npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@offline-protocol/id-react

v0.2.0

Published

Offline ID for React and Next.js: email OTP sign-in, profiles and connections.

Downloads

1,067

Readme

@offline-protocol/id-react

Offline ID for React / Next.js: email/OTP authentication, profiles, and connections via OfflineAppProvider and hooks. Location proofs live in @offline-protocol/pol.

License

MIT — free to use in open-source and proprietary apps.

Install

npm install @offline-protocol/id-react

Quick start

import { OfflineAppProvider, useAuth } from '@offline-protocol/id-react';

export function App({ children }: { children: React.ReactNode }) {
  return (
    <OfflineAppProvider appId="app_xxxxxxxx">
      {children}
    </OfflineAppProvider>
  );
}

Replace app_xxxxxxxx with an app ID from your organization on dev.offlineprotocol.com.

projectId is still accepted as a deprecated alias for appId.

Connections and location sharing

import { useConnections } from '@offline-protocol/id-react';

function Friends() {
  const { connections, setLocationSharing } = useConnections();

  return (
    <ul>
      {connections.map((c) => (
        <li key={c.id}>
          {c.peer}
          {c.sharingLocationWithMe && ' shares location with you'}
          <label>
            <input
              type="checkbox"
              checked={c.sharingLocationWithThem}
              onChange={(e) => setLocationSharing(c.id, e.target.checked)}
            />
            Share my location
          </label>
        </li>
      ))}
    </ul>
  );
}

Each item in connections is seen from the signed-in user's side:

| Field | Meaning | | ----- | ------- | | id | Connection ID | | peer | The other profile's username | | sharingLocationWithThem | You share your location with peer | | sharingLocationWithMe | peer shares their location with you |

Location sharing is per connection and one way, and it is off by default, including for connections made before it existed. A peer's location is only returned to you (GET /connections/{username}/locations) once they turn sharing on for your connection.

setLocationSharing(connectionId, share) turns sharing of your own location with that peer on or off. It is idempotent and never changes the peer's side. The connections list updates at once. If several updates to one connection overlap (a quickly toggled checkbox), they are sent one at a time in the order you made them, and the last one decides what the list shows. One that a later update replaces before it is sent is not sent at all.

It resolves to what became of the update:

| status | Meaning | connections shows | | -------- | ------- | ------------------- | | applied | The server took it. connection is the updated connection, or null if the server returned none. | The new value | | rejected | It was not applied: the server turned it down (a 4xx), or nobody is signed in. | What the server last confirmed | | unknown | No usable answer (a timeout, a dropped connection, a 5xx), and the one automatic retry was not applied either. It may or may not have been applied. | Sharing as on, if it may be on | | superseded | You made a later update to the same connection before this one was sent. | Whatever the later one settles to |

const result = await setLocationSharing(c.id, false);
if (result.status === 'unknown') {
  // Tell the user it could not be confirmed, and let them try again.
}

While what the server holds is unknown, the list shows sharing as on rather than risk saying "not sharing" while your location is shared. It stays that way until the server answers: call setLocationSharing again (always safe), or let the list reload on the next sign-in.

One case the SDK cannot rule out: a request that timed out can still reach the server later, after a newer update to the same connection was confirmed. The API has no version to refuse the late one with, so after an unknown result, treat the setting as unconfirmed until an update to it is applied.

Without the hook, call the API directly: PUT /connections/by-id/{id}/location-sharing with { "share": true, "username": "<your profile in the connection>" }. username is optional unless you own both profiles in the connection.