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

@hypercerts-org/lexicon

v0.10.0-beta.13

Published

ATProto lexicon definitions and TypeScript types for the Hypercerts protocol

Readme

Hypercerts Lexicon Documentation

This repository contains ATProto lexicon definitions for the Hypercerts protocol. Each lexicon defines a record type that can be stored on the ATProto network.

Entity Relationship Diagram

The following diagrams show the relationship between:

  • data classes represented by ATProto lexicons, which model the data sets relating to hypercerts

  • contributors to activity records (modelled/identified by ATProto DIDs rather than lexicons)

  • hypercerts protocol tokens which are onchain representations of activity records in ATProto

Note that contributors and tokens do not require lexicons.

To distinguish these in the diagrams, each class has one of the following icons:

  • "D" means "data class"
  • "E" means "entity"
  • "P" means "protocol"

Hypercert ERD

Hypercert ERD with fields

Installation

npm install @hypercerts-org/lexicon

Usage

Basic Import

import {
  HYPERCERTS_SCHEMAS,
  ACTIVITY_NSID,
  validate,
} from "@hypercerts-org/lexicon";

// Use with AT Protocol Agent
import { Agent } from "@atproto/api";

const agent = new Agent({ service: "https://bsky.social" });

// Register lexicons with the agent
agent.api.lex.add(...HYPERCERTS_SCHEMAS);

// Create a record
const activityRecord = {
  $type: ACTIVITY_NSID,
  title: "My Impact Work",
  shortDescription: "Description here",
  // workScope can be a strongRef to a work-scope record:
  workScope: {
    uri: "at://did:plc:alice/org.hypercerts.helper.workScopeTag/abc123",
    cid: "...",
  },
  // OR a simple string: workScope: "Environmental conservation",
  startDate: "2023-01-01T00:00:00Z",
  endDate: "2023-12-31T23:59:59Z",
  createdAt: new Date().toISOString(),
};

// Validate before creating
const validation = validate(ACTIVITY_NSID, activityRecord);
if (!validation.valid) {
  console.error("Validation failed:", validation.errors);
}

await agent.api.com.atproto.repo.createRecord({
  repo: agent.session?.did,
  collection: ACTIVITY_NSID,
  record: activityRecord,
});

Creating Location Records

Location records (app.certified.location) specify where work was performed using geographic coordinates or other location formats. They can be referenced by activities, collections, attachments, measurements, and evaluations.

import { LOCATION_NSID } from "@hypercerts-org/lexicon";

const locationRecord = {
  $type: LOCATION_NSID,
  lpVersion: "1.0", // Location Protocol version
  srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84", // Spatial Reference System
  locationType: "coordinate-decimal", // or "geojson-point"
  location: {
    uri: "https://example.com/location-data.geojson",
  },
  // Optional fields
  name: "Project Site A",
  description: "Primary research facility in the Amazon rainforest",
  createdAt: new Date().toISOString(),
};
  • lpVersion (required): Version of the Location Protocol specification
  • srs (required): Spatial Reference System URI defining the coordinate system
  • locationType (required): Format identifier (e.g., "coordinate-decimal", "geojson-point")
  • location (required): Location data as URI, blob, or string
  • name (optional): Human-readable name for the location
  • description (optional): Additional context about the location
  • createdAt (required): Timestamp when the record was created

Location data formats:

The location field accepts three formats:

  1. URI reference: { uri: "https://..." } - Link to external location data
  2. Small blob: Embedded location data (up to 10MB)
  3. Location string: Inline string wrapped in an object, containing coordinates or GeoJSON
// Example with embedded blob
const locationWithBlob = {
  $type: LOCATION_NSID,
  lpVersion: "1.0",
  srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
  locationType: "geojson-point",
  location: {
    blob: {
      $type: "blob",
      ref: {
        $link: "bafyrei...", // CID of the uploaded blob
      },
      mimeType: "application/geo+json",
      size: 123,
    },
  },
  name: "Amazon Research Station",
  createdAt: new Date().toISOString(),
};

// Example with inline string (coordinates)
const locationWithCoordinates = {
  $type: LOCATION_NSID,
  lpVersion: "1.0",
  srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
  locationType: "coordinate-decimal",
  location: {
    string: "-3.4653, -62.2159", // lat, lon
  },
  name: "Amazon Research Site",
  description: "Field station coordinates",
  createdAt: new Date().toISOString(),
};

// Example with inline GeoJSON string
const locationWithGeoJSON = {
  $type: LOCATION_NSID,
  lpVersion: "1.0",
  srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
  locationType: "geojson-point",
  location: {
    string: '{"type":"Point","coordinates":[-62.2159,-3.4653]}',
  },
  name: "Research Station Alpha",
  createdAt: new Date().toISOString(),
};

Accessing NSIDs (Lexicon IDs)

Recommended: Use individual NSID constants for cleaner, more readable code:

import { ACTIVITY_NSID, COLLECTION_NSID } from "@hypercerts-org/lexicon";

// Clean and explicit
const record = {
  $type: ACTIVITY_NSID,
  // ...
};

Alternative: Use the semantic NSID object when you need multiple NSIDs:

import { HYPERCERTS_NSIDS } from "@hypercerts-org/lexicon";

// Access via semantic keys
const activityId = HYPERCERTS_NSIDS.ACTIVITY;
const collectionId = HYPERCERTS_NSIDS.COLLECTION;
const rightsId = HYPERCERTS_NSIDS.RIGHTS;

Type-based mapping: If you need to map TypeScript type namespaces to NSIDs:

import { HYPERCERTS_NSIDS_BY_TYPE } from "@hypercerts-org/lexicon";

// Access via type namespace names
const activityId = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsClaimActivity;
const collectionId = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsClaimCollection;

Lightweight Bundle: Import from /lexicons for runtime validation without TypeScript types (smaller bundle size):

import { schemas, validate, ids } from "@hypercerts-org/lexicon/lexicons";

// Lighter bundle, type-based namespace access
const result = validate(ids.OrgHypercertsClaimActivity, record);

Note: Individual constants (e.g., ACTIVITY_NSID) are the recommended approach for most use cases as they provide the best developer experience with clear, concise naming.

TypeScript Types

All lexicon types are exported as namespaces:

import { OrgHypercertsClaimActivity } from "@hypercerts-org/lexicon";

// Use the Main type
const activity: OrgHypercertsClaimActivity.Main = {
  $type: "org.hypercerts.claim.activity",
  title: "My Impact Work",
  // ... other fields
};

Individual Lexicon Imports

Each lexicon is available in two forms as individual constants:

import {
  // Raw JSON (untyped) - direct import from JSON files
  ACTIVITY_LEXICON_JSON,
  RIGHTS_LEXICON_JSON,

  // Typed LexiconDoc - from lexicons.get() at module initialization
  ACTIVITY_LEXICON_DOC,
  RIGHTS_LEXICON_DOC,
} from "@hypercerts-org/lexicon";

| Suffix | Type | Source | Use Case | | ------- | -------------------- | ------------------------- | ------------------------------ | | _JSON | Untyped JSON | Direct JSON import | Raw schema data | | _DOC | LexiconDoc (typed) | lexicons.get() instance | Type-safe lexicon manipulation |

Or access all lexicons via semantic mapping objects:

import {
  HYPERCERTS_LEXICON_JSON,
  HYPERCERTS_LEXICON_DOC,
} from "@hypercerts-org/lexicon";

// Access via semantic keys (same keys as HYPERCERTS_NSIDS)
const activityJSON = HYPERCERTS_LEXICON_JSON.ACTIVITY;
const activityDoc = HYPERCERTS_LEXICON_DOC.ACTIVITY;
const rightsJSON = HYPERCERTS_LEXICON_JSON.RIGHTS;
const rightsDoc = HYPERCERTS_LEXICON_DOC.RIGHTS;

Schema Documentation

For complete schema documentation with all lexicon definitions and property tables, see SCHEMAS.md.

Examples

Creating a Collection with Nested Items

import { TID } from "@atproto/common";

const collectionRecord = {
  $type: "org.hypercerts.claim.collection",
  title: "Climate Action Projects",
  shortDescription:
    "A collection of climate-related activities and sub-collections",
  items: [
    // Reference to an activity
    {
      uri: "at://did:plc:alice/org.hypercerts.claim.activity/3k2abc",
      cid: "...",
    },
    // Reference to another activity
    {
      uri: "at://did:plc:bob/org.hypercerts.claim.activity/7x9def",
      cid: "...",
    },
    // Reference to another collection (recursive!)
    {
      uri: "at://did:plc:carol/org.hypercerts.claim.collection/4m5ghi",
      cid: "...",
    },
  ],
  createdAt: new Date().toISOString(),
};

Creating a Project

Projects are collections with a type field set to "project" and can include rich-text descriptions:

const projectRecord = {
  $type: "org.hypercerts.claim.collection",
  type: "project",
  title: "Carbon Offset Initiative",
  shortDescription: "A project focused on carbon reduction and reforestation",
  description: {
    uri: "at://did:plc:alice/pub.leaflet.pages.linearDocument/abc123",
    cid: "...",
  },
  items: [
    {
      uri: "at://did:plc:alice/org.hypercerts.claim.activity/3k2abc",
      cid: "...",
    },
    {
      uri: "at://did:plc:bob/org.hypercerts.claim.activity/7x9def",
      cid: "...",
    },
  ],
  createdAt: new Date().toISOString(),
};

Note: The type field is optional and can be set to "project", "favorites", or any other collection type. The description field supports rich-text via Leaflet linear documents.

Adding Visual Representation to Collections

Collections can include avatar and banner fields for visual representation:

import { COLLECTION_NSID } from "@hypercerts-org/lexicon";

const collectionRecord = {
  $type: COLLECTION_NSID,
  title: "Climate Action Projects",
  avatar: {
    image: blobRef, // or { uri: "https://..." }
  },
  banner: {
    image: largeBlobRef, // or { uri: "https://..." }
  },
  items: [
    // ... collection items
  ],
  createdAt: new Date().toISOString(),
};

Note: Both avatar (up to 5MB) and banner (up to 10MB) fields are optional and support either embedded image blobs or URI references to external images.

Adding Locations to Activities

The locations field in activity records is an array of strong references (com.atproto.repo.strongRef) pointing to app.certified.location records. Each strong reference contains two required fields:

  • uri: The ATProto URI of the location record (e.g., at://did:plc:alice/app.certified.location/abc123)
  • cid: The content identifier (CID) of the location record, ensuring referential integrity

Validation and Expectations:

  • All location records referenced in the locations array must conform to the app.certified.location lexicon schema
  • The uri field must be a valid ATProto URI pointing to an existing location record
  • The cid field must match the current CID of the referenced location record
  • The locations field is optional; activities can be created without location data

Adding Location to Collections

Collections can include an optional location field to specify where the collection's activities were performed:

const collectionRecord = {
  $type: "org.hypercerts.claim.collection",
  title: "Climate Action Projects",
  shortDescription: "A collection of climate-related activities",
  location: {
    uri: "at://did:plc:alice/app.certified.location/xyz789",
    cid: "...",
  },
  items: [
    // ... collection items
  ],
  createdAt: new Date().toISOString(),
};

The location field is a strong reference to an app.certified.location record containing the same uri and cid fields as described above for activities.

Creating Attachments

Attachments provide commentary, context, evidence, or documentary material related to hypercert records. They can be linked to activities, evaluations, measurements, or even other attachments:

import { ATTACHMENT_NSID } from "@hypercerts-org/lexicon";

const attachmentRecord = {
  $type: ATTACHMENT_NSID,
  title: "Field Survey Report",
  subjects: [
    {
      uri: "at://did:plc:alice/org.hypercerts.claim.activity/abc123",
      cid: "...",
    },
  ],
  contentType: "report",
  content: [
    { uri: "https://example.com/reports/survey-2024.pdf" },
    { uri: "ipfs://Qm..." },
  ],
  shortDescription: "Quarterly field survey documenting project progress",
  createdAt: new Date().toISOString(),
};

Key fields:

  • title (required): String title for the attachment
  • shortDescription/description: Support rich text via facet annotations
  • subjects (optional): Array of strong references to records this attachment relates to
  • contentType (optional): Type descriptor (e.g., "report", "audit", "evidence", "testimonial")
  • content (required): Array of URIs or blobs containing the attachment files
  • location (optional): Strong reference to an app.certified.location record
  • createdAt (required): Timestamp when the attachment was created

Adding Location to Attachments:

const attachmentWithLocation = {
  $type: ATTACHMENT_NSID,
  title: "Site Inspection Photos",
  content: [{ uri: "https://..." }],
  location: {
    uri: "at://did:plc:alice/app.certified.location/loc123",
    cid: "...",
  },
  createdAt: new Date().toISOString(),
};