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.

refactor: reorganize monorepo into apps/ and packages/ directories

Move server applications (appview, web) into apps/ and keep shared
libraries (lexicon, spike) in packages/. Update pnpm workspace config,
documentation (CLAUDE.md, README.md, project plan, schema design doc)
to reflect the new structure.

https://claude.ai/code/session_014iuD1gNMNFLYgouQ5RhkJX

Claude 99aad8ce 30d024c1

+75 -56
+17 -6
CLAUDE.md
··· 4 4 5 5 The master project plan with MVP phases and progress tracking lives at `docs/atproto-forum-plan.md`. 6 6 7 - ## Packages 7 + ## Apps & Packages 8 + 9 + ### Apps (`apps/`) 10 + 11 + Servers and applications that are deployed or run as services. 8 12 9 - | Package | Description | Port | 10 - |---------|-------------|------| 11 - | `@atbb/lexicon` | AT Proto lexicon definitions (YAML) + generated TypeScript types | — | 13 + | App | Description | Port | 14 + |-----|-------------|------| 12 15 | `@atbb/appview` | Hono JSON API server — indexes forum data, serves API | 3000 | 13 16 | `@atbb/web` | Hono JSX + HTMX server-rendered web UI — calls appview API | 3001 | 14 - | `@atbb/spike` | PDS read/write test script for validating AT Proto operations | — | 17 + 18 + ### Packages (`packages/`) 19 + 20 + Shared libraries, tools, and utilities consumed by apps or used standalone. 21 + 22 + | Package | Description | 23 + |---------|-------------| 24 + | `@atbb/lexicon` | AT Proto lexicon definitions (YAML) + generated TypeScript types | 25 + | `@atbb/spike` | PDS read/write test script for validating AT Proto operations | 15 26 16 27 **Dependency chain:** `@atbb/lexicon` builds first (generates types), then `@atbb/appview` and `@atbb/web` build in parallel. Turbo handles this via `^build`. 17 28 ··· 68 79 69 80 - **`@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. 70 81 - **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. 71 - - **HTMX attributes in JSX:** The `typed-htmx` package provides types for `hx-*` attributes. See `packages/web/src/global.d.ts` for the augmentation. 82 + - **HTMX attributes in JSX:** The `typed-htmx` package provides types for `hx-*` attributes. See `apps/web/src/global.d.ts` for the augmentation. 72 83 - **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. 73 84 - **`.env` loading:** Dev and spike scripts use Node's `--env-file=../../.env` flag to load the root `.env` file. No `dotenv` dependency needed. 74 85
+10 -3
README.md
··· 26 26 27 27 User-generated content (posts, reactions, memberships) lives on each user's PDS. Forum metadata (categories, roles, mod actions) lives on a dedicated Forum Service Account. The AppView indexes both into a unified view. 28 28 29 - ## Packages 29 + ## Apps & Packages 30 30 31 31 This is a [Turborepo](https://turbo.build/) monorepo with [pnpm](https://pnpm.io/) workspaces. 32 32 33 + ### Apps (`apps/`) 34 + 35 + | App | Description | 36 + |-----|-------------| 37 + | [`apps/appview`](apps/appview) | Hono-based JSON API server | 38 + | [`apps/web`](apps/web) | Server-rendered web UI (Hono JSX + HTMX) | 39 + 40 + ### Packages (`packages/`) 41 + 33 42 | Package | Description | 34 43 |---------|-------------| 35 44 | [`packages/lexicon`](packages/lexicon) | AT Proto lexicon schemas (YAML) and generated TypeScript types | 36 - | [`packages/appview`](packages/appview) | Hono-based JSON API server | 37 - | [`packages/web`](packages/web) | Server-rendered web UI (Hono JSX + HTMX) | 38 45 | [`packages/spike`](packages/spike) | PDS read/write test script | 39 46 40 47 ## Getting Started
+1 -1
docs/atproto-forum-plan.md
··· 139 139 - [x] Audit existing `space.atbb.*` lexicons — **Result:** 2 existing (`forum.forum`, `post`), 5 new needed for MVP. No separate topic type; unified post model with reply refs. 140 140 - [x] Review prior Rust AppView — **Result:** Axum/SQLx scaffold with jetstream-oxide firehose, minimal DB schema. Reference for route structure and Docker setup; MVP will be Node/TS rewrite. 141 141 - [x] Define new lexicons in YAML: `forum.category`, `forum.role`, `membership`, `reaction`, `modAction` — **Result:** All 5 defined in `packages/lexicon/lexicons/`, with YAML→JSON→TypeScript build pipeline via `@atproto/lex-cli`. 142 - - [x] Set up project scaffolding: monorepo with `packages/lexicon`, `packages/appview`, `packages/web` — **Result:** Turborepo + pnpm workspaces, devenv for Nix toolchain. AppView (Hono JSON API, port 3000), Web (Hono JSX + HTMX, port 3001), plus `packages/spike` for PDS testing. 142 + - [x] Set up project scaffolding: monorepo with `packages/lexicon`, `apps/appview`, `apps/web` — **Result:** Turborepo + pnpm workspaces, devenv for Nix toolchain. AppView (Hono JSON API, port 3000), Web (Hono JSX + HTMX, port 3001), plus `packages/spike` for PDS testing. Apps live in `apps/`, shared libraries in `packages/`. 143 143 - [ ] Create Forum Service Account (generate DID, set up PDS or use existing hosting) 144 144 - [ ] Spike: write a test record to a PDS, read it back via AT Proto API — **Note:** Script written in `packages/spike`, ready to run once PDS credentials are configured in `.env`. 145 145
+22 -22
docs/plans/2026-02-06-database-schema-design.md
··· 13 13 ### Task 1: Install Drizzle dependencies 14 14 15 15 **Files:** 16 - - Modify: `packages/appview/package.json` 16 + - Modify: `apps/appview/package.json` 17 17 18 18 **Step 1: Add runtime dependencies** 19 19 ··· 46 46 **Step 4: Commit** 47 47 48 48 ```bash 49 - git add packages/appview/package.json pnpm-lock.yaml 49 + git add apps/appview/package.json pnpm-lock.yaml 50 50 git commit -m "feat(appview): add drizzle-orm and postgres dependencies" 51 51 ``` 52 52 ··· 55 55 ### Task 2: Define the database schema 56 56 57 57 **Files:** 58 - - Create: `packages/appview/src/db/schema.ts` 58 + - Create: `apps/appview/src/db/schema.ts` 59 59 60 60 **Step 1: Create the schema file** 61 61 62 - Create `packages/appview/src/db/schema.ts` with the full schema: 62 + Create `apps/appview/src/db/schema.ts` with the full schema: 63 63 64 64 ```typescript 65 65 import { ··· 223 223 **Step 3: Commit** 224 224 225 225 ```bash 226 - git add packages/appview/src/db/schema.ts 226 + git add apps/appview/src/db/schema.ts 227 227 git commit -m "feat(appview): define database schema for all 6 tables" 228 228 ``` 229 229 ··· 232 232 ### Task 3: Create the database connection module 233 233 234 234 **Files:** 235 - - Create: `packages/appview/src/db/index.ts` 236 - - Modify: `packages/appview/src/lib/config.ts` 235 + - Create: `apps/appview/src/db/index.ts` 236 + - Modify: `apps/appview/src/lib/config.ts` 237 237 238 238 **Step 1: Add DATABASE_URL to config** 239 239 240 - Modify `packages/appview/src/lib/config.ts` to add `databaseUrl`: 240 + Modify `apps/appview/src/lib/config.ts` to add `databaseUrl`: 241 241 242 242 ```typescript 243 243 export interface AppConfig { ··· 259 259 260 260 **Step 2: Create the database connection module** 261 261 262 - Create `packages/appview/src/db/index.ts`: 262 + Create `apps/appview/src/db/index.ts`: 263 263 264 264 ```typescript 265 265 import { drizzle } from "drizzle-orm/postgres-js"; ··· 287 287 **Step 4: Commit** 288 288 289 289 ```bash 290 - git add packages/appview/src/db/index.ts packages/appview/src/lib/config.ts 290 + git add apps/appview/src/db/index.ts apps/appview/src/lib/config.ts 291 291 git commit -m "feat(appview): add database connection module and DATABASE_URL config" 292 292 ``` 293 293 ··· 296 296 ### Task 4: Configure drizzle-kit and generate migrations 297 297 298 298 **Files:** 299 - - Create: `packages/appview/drizzle.config.ts` 299 + - Create: `apps/appview/drizzle.config.ts` 300 300 301 301 **Step 1: Create drizzle-kit config** 302 302 303 - Create `packages/appview/drizzle.config.ts`: 303 + Create `apps/appview/drizzle.config.ts`: 304 304 305 305 ```typescript 306 306 import { defineConfig } from "drizzle-kit"; ··· 314 314 315 315 **Step 2: Add migration scripts to package.json** 316 316 317 - Add to `packages/appview/package.json` scripts: 317 + Add to `apps/appview/package.json` scripts: 318 318 319 319 ```json 320 320 { ··· 331 331 pnpm --filter @atbb/appview db:generate 332 332 ``` 333 333 334 - Expected: a migration SQL file appears in `packages/appview/drizzle/` with CREATE TABLE statements for all 6 tables. 334 + Expected: a migration SQL file appears in `apps/appview/drizzle/` with CREATE TABLE statements for all 6 tables. 335 335 336 336 **Step 4: Inspect the generated SQL** 337 337 338 - Read the generated `.sql` file in `packages/appview/drizzle/` and verify it contains: 338 + Read the generated `.sql` file in `apps/appview/drizzle/` and verify it contains: 339 339 - 6 CREATE TABLE statements (forums, categories, users, memberships, posts, mod_actions) 340 340 - All UNIQUE indexes on (did, rkey) 341 341 - All additional indexes (posts.forum_uri, posts.root_post_id, memberships.did) ··· 344 344 **Step 5: Commit** 345 345 346 346 ```bash 347 - git add packages/appview/drizzle.config.ts packages/appview/drizzle/ packages/appview/package.json 347 + git add apps/appview/drizzle.config.ts apps/appview/drizzle/ apps/appview/package.json 348 348 git commit -m "feat(appview): add drizzle-kit config and generate initial migration" 349 349 ``` 350 350 ··· 446 446 447 447 | Action | File | 448 448 |--------|------| 449 - | Modify | `packages/appview/package.json` (deps + scripts) | 450 - | Create | `packages/appview/src/db/schema.ts` | 451 - | Create | `packages/appview/src/db/index.ts` | 452 - | Modify | `packages/appview/src/lib/config.ts` | 453 - | Create | `packages/appview/drizzle.config.ts` | 454 - | Create | `packages/appview/drizzle/*.sql` (generated) | 449 + | Modify | `apps/appview/package.json` (deps + scripts) | 450 + | Create | `apps/appview/src/db/schema.ts` | 451 + | Create | `apps/appview/src/db/index.ts` | 452 + | Modify | `apps/appview/src/lib/config.ts` | 453 + | Create | `apps/appview/drizzle.config.ts` | 454 + | Create | `apps/appview/drizzle/*.sql` (generated) | 455 455 | Modify | `.env.example` | 456 456 | Create | `docs/plans/2026-02-06-database-schema-design.md` |
packages/appview/drizzle.config.ts apps/appview/drizzle.config.ts
packages/appview/drizzle/0000_lovely_roland_deschain.sql apps/appview/drizzle/0000_lovely_roland_deschain.sql
packages/appview/drizzle/meta/0000_snapshot.json apps/appview/drizzle/meta/0000_snapshot.json
packages/appview/drizzle/meta/_journal.json apps/appview/drizzle/meta/_journal.json
packages/appview/package.json apps/appview/package.json
packages/appview/src/db/index.ts apps/appview/src/db/index.ts
packages/appview/src/db/schema.ts apps/appview/src/db/schema.ts
packages/appview/src/index.ts apps/appview/src/index.ts
packages/appview/src/lib/atproto.ts apps/appview/src/lib/atproto.ts
packages/appview/src/lib/config.ts apps/appview/src/lib/config.ts
packages/appview/src/routes/categories.ts apps/appview/src/routes/categories.ts
packages/appview/src/routes/forum.ts apps/appview/src/routes/forum.ts
packages/appview/src/routes/health.ts apps/appview/src/routes/health.ts
packages/appview/src/routes/index.ts apps/appview/src/routes/index.ts
packages/appview/src/routes/posts.ts apps/appview/src/routes/posts.ts
packages/appview/src/routes/topics.ts apps/appview/src/routes/topics.ts
packages/appview/tsconfig.json apps/appview/tsconfig.json
packages/web/package.json apps/web/package.json
packages/web/src/global.d.ts apps/web/src/global.d.ts
packages/web/src/index.ts apps/web/src/index.ts
packages/web/src/layouts/base.tsx apps/web/src/layouts/base.tsx
packages/web/src/lib/api.ts apps/web/src/lib/api.ts
packages/web/src/lib/config.ts apps/web/src/lib/config.ts
packages/web/src/routes/home.tsx apps/web/src/routes/home.tsx
packages/web/src/routes/index.ts apps/web/src/routes/index.ts
packages/web/tsconfig.json apps/web/tsconfig.json
+24 -24
pnpm-lock.yaml
··· 15 15 specifier: ^5.7.0 16 16 version: 5.9.3 17 17 18 - packages/appview: 18 + apps/appview: 19 19 dependencies: 20 20 '@atbb/lexicon': 21 21 specifier: workspace:* 22 - version: link:../lexicon 22 + version: link:../../packages/lexicon 23 23 '@atproto/api': 24 24 specifier: ^0.15.0 25 25 version: 0.15.27 ··· 52 52 specifier: ^5.7.0 53 53 version: 5.9.3 54 54 55 + apps/web: 56 + dependencies: 57 + '@hono/node-server': 58 + specifier: ^1.14.0 59 + version: 1.19.9(hono@4.11.8) 60 + hono: 61 + specifier: ^4.7.0 62 + version: 4.11.8 63 + devDependencies: 64 + '@types/node': 65 + specifier: ^22.0.0 66 + version: 22.19.9 67 + tsx: 68 + specifier: ^4.0.0 69 + version: 4.21.0 70 + typed-htmx: 71 + specifier: ^0.3.0 72 + version: 0.3.1 73 + typescript: 74 + specifier: ^5.7.0 75 + version: 5.9.3 76 + 55 77 packages/lexicon: 56 78 devDependencies: 57 79 '@atproto/lex-cli': ··· 85 107 tsx: 86 108 specifier: ^4.0.0 87 109 version: 4.21.0 88 - typescript: 89 - specifier: ^5.7.0 90 - version: 5.9.3 91 - 92 - packages/web: 93 - dependencies: 94 - '@hono/node-server': 95 - specifier: ^1.14.0 96 - version: 1.19.9(hono@4.11.8) 97 - hono: 98 - specifier: ^4.7.0 99 - version: 4.11.8 100 - devDependencies: 101 - '@types/node': 102 - specifier: ^22.0.0 103 - version: 22.19.9 104 - tsx: 105 - specifier: ^4.0.0 106 - version: 4.21.0 107 - typed-htmx: 108 - specifier: ^0.3.0 109 - version: 0.3.1 110 110 typescript: 111 111 specifier: ^5.7.0 112 112 version: 5.9.3
+1
pnpm-workspace.yaml
··· 1 1 packages: 2 + - "apps/*" 2 3 - "packages/*"