WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

atBB Monorepo#

atBB is a decentralized BB-style forum built on the AT Protocol. Users own their posts on their own PDS; the forum's AppView indexes and serves them. Lexicon namespace: space.atbb.* (domain atbb.space is owned). License: AGPL-3.0.

The master project plan with MVP phases and progress tracking lives at docs/atproto-forum-plan.md.

Packages#

Package Description Port
@atbb/lexicon AT Proto lexicon definitions (YAML) + generated TypeScript types
@atbb/appview Hono JSON API server — indexes forum data, serves API 3000
@atbb/web Hono JSX + HTMX server-rendered web UI — calls appview API 3001
@atbb/spike PDS read/write test script for validating AT Proto operations

Dependency chain: @atbb/lexicon builds first (generates types), then @atbb/appview and @atbb/web build in parallel. Turbo handles this via ^build.

Development#

Setup#

devenv shell                    # enter Nix dev shell (Node.js, pnpm, turbo)
pnpm install                    # install all workspace dependencies
cp .env.example .env            # configure environment variables

Commands#

pnpm build                      # build all packages (lexicon → appview + web)
pnpm dev                        # start all dev servers with hot reload
pnpm clean                      # remove all dist/ directories
devenv up                       # start appview + web servers via process manager
pnpm --filter @atbb/appview dev # run a single package
pnpm --filter @atbb/spike spike # run the PDS spike script

Environment Variables#

See .env.example. Key variables:

  • PORT — server port (appview: 3000, web: 3001)
  • FORUM_DID — the forum's AT Proto DID
  • PDS_URL — URL of the forum's PDS
  • APPVIEW_URL — URL the web package uses to reach the appview API
  • FORUM_HANDLE, FORUM_PASSWORD — forum service account credentials (for spike/writes)

Lexicon Conventions#

  • Source of truth is YAML in packages/lexicon/lexicons/. Never edit generated JSON or TypeScript.
  • Build pipeline: YAML → JSON (scripts/build.ts) → TypeScript (@atproto/lex-cli gen-api).
  • Adding a new lexicon: Create a .yaml file under lexicons/space/atbb/, run pnpm --filter @atbb/lexicon build.
  • Record keys: Use key: tid for collections (multiple records per repo). Use key: literal:self for singletons.
  • References: Use com.atproto.repo.strongRef wrapped in named defs (e.g., forumRef, subjectRef).
  • Extensible fields: Use knownValues (not enum) for strings that may grow (permissions, reaction types, mod actions).
  • Record ownership:
    • Forum DID owns: forum.forum, forum.category, forum.role, modAction
    • User DID owns: post, membership, reaction

AT Protocol Conventions#

  • Unified post model: There is no separate "topic" type. A space.atbb.post without a reply ref is a topic starter; one with a reply ref is a reply.
  • Reply chains: replyRef has both root (thread starter) and parent (direct parent) — same pattern as app.bsky.feed.post.
  • MVP trust model: The AppView holds the Forum DID's signing keys directly and writes forum-level records on behalf of admins/mods after verifying their role. This will be replaced by AT Protocol privilege delegation post-MVP.

TypeScript / Hono Gotchas#

  • @types/node is required as a devDependency in every package that uses process.env or other Node APIs. tsx doesn't need it at runtime, but tsc builds will fail without it.
  • Hono JSX children: Use PropsWithChildren<T> from hono/jsx for components that accept children. Unlike React, Hono's FC<T> does not include children implicitly.
  • HTMX attributes in JSX: The typed-htmx package provides types for hx-* attributes. See packages/web/src/global.d.ts for the augmentation.
  • Glob expansion in npm scripts: @atproto/lex-cli needs file paths, not globs. Use bash -c 'shopt -s globstar && ...' to expand **/*.json in npm scripts.
  • .env loading: Dev and spike scripts use Node's --env-file=../../.env flag to load the root .env file. No dotenv dependency needed.

Git Conventions#

  • Do not include Co-Authored-By lines in commit messages.
  • prior-art/ contains git submodules (Rust AppView, original lexicons, delegation spec) — reference material only, not used at build time.
  • Worktrees with submodules need submodule deinit --all -f then worktree remove --force to clean up.