Monorepo for the nibling.run platform
README.md

@nibling/lexicons #

The lexicon documents nibling reads and writes, and the generated TypeScript types and validators over them.

Layout #

lexicons/dev/nibling/**/*.json are the lexicons nibling defines (project, feed.like, feed.comment, feed.getRecent, feed.getTrending, feed.defs, graph.follow, actor.profile, actor.getKnown). lexicons/org/tangled/**/*.json vendors the four org.tangled.* lexicons nibling consumes (repo.declaration, repo.defs, repo.manifest, actor.defs, and graph.follow), fetched from tangled's own published com.atproto.lexicon.schema records so generating types here needs no network access; @atcute/tangled already ships sh.tangled.graph.follow as a dependency, so that one isn't vendored. Neither vendored set is published by this package; publish.ts only writes dev.nibling.* records, since tangled publishes its own.

src/lexicons/ is @atcute/lex-cli's generated output (types plus runtime validators) and is committed. src/index.ts re-exports it and lists the record collections nibling writes in collections.

Regenerating #

pnpm generate runs lex-cli generate per lex.config.js and overwrites src/lexicons/. Run it after adding or editing a lexicon JSON file, then commit the result.

Drift check #

pnpm check (also run by pnpm test) regenerates the lexicons into a scratch temp directory and diffs that output against the committed src/lexicons/, failing if they differ. It never writes inside the repo, so a clean run leaves nothing behind; a failing run tells you to run pnpm generate and commit.

Publishing #

node scripts/publish.ts publishes every dev.nibling.* lexicon as a com.atproto.lexicon.schema record (rkey = the lexicon's own NSID), per the atproto lexicon publishing guide and the lexicon spec's resolution section.

Default is a dry run: it resolves NIB_LEXICON_HANDLE to a DID (no network call if you pass a did: directly), prints the exact record body it would write for each lexicon, and prints the DNS TXT records an operator needs to add. Pass --write to publish for real, which additionally needs NIB_LEXICON_APP_PASSWORD and authenticates via com.atproto.server.createSession. Reruns are safe: each lexicon is read back with getRecord first and putRecord only runs when the content differs from what is already published.

DNS resolution is per NSID authority, not per package. An authority is the NSID minus its final segment, reversed into a domain: dev.nibling.project's authority is dev.nibling, so it resolves under _lexicon.nibling.dev, but dev.nibling.actor.getKnown's authority is dev.nibling.actor, resolving under the different name _lexicon.actor.nibling.dev. docs/VISION.md D19 names only _lexicon.nibling.dev; that covers the three-segment NSIDs (dev.nibling.project) but not the four-segment ones (everything under actor.*, feed.*, graph.*), which each need their own TXT record. The script derives and prints every authority the current lexicon set actually needs, so D19's open question is: publish one record per authority (what this script assumes), or flatten the deeper lexicons so they all share the dev.nibling authority.