···4455The master project plan with MVP phases and progress tracking lives at `docs/atproto-forum-plan.md`.
6677-## Packages
77+## Apps & Packages
8899-| Package | Description | Port |
1010-|---------|-------------|------|
1111-| `@atbb/lexicon` | AT Proto lexicon definitions (YAML) + generated TypeScript types | — |
99+### Apps (`apps/`)
1010+1111+Servers and applications that are deployed or run as services.
1212+1313+| App | Description | Port |
1414+|-----|-------------|------|
1215| `@atbb/appview` | Hono JSON API server — indexes forum data, serves API | 3000 |
1316| `@atbb/web` | Hono JSX + HTMX server-rendered web UI — calls appview API | 3001 |
1414-| `@atbb/spike` | PDS read/write test script for validating AT Proto operations | — |
15171616-**Dependency chain:** `@atbb/lexicon` builds first (generates types), then `@atbb/appview` and `@atbb/web` build in parallel. Turbo handles this via `^build`.
1818+### Packages (`packages/`)
1919+2020+Shared libraries, tools, and utilities consumed by apps or used standalone.
2121+2222+| Package | Description |
2323+|---------|-------------|
2424+| `@atbb/db` | Drizzle ORM schema and connection factory for PostgreSQL |
2525+| `@atbb/lexicon` | AT Proto lexicon definitions (YAML) + generated TypeScript types |
2626+| `@atbb/spike` | PDS read/write test script for validating AT Proto operations |
2727+2828+**Dependency chain:** `@atbb/lexicon` and `@atbb/db` build first, then `@atbb/appview` and `@atbb/web` build in parallel. Turbo handles this via `^build`.
17291830## Development
1931···68806981- **`@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.
7082- **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.
7171-- **HTMX attributes in JSX:** The `typed-htmx` package provides types for `hx-*` attributes. See `packages/web/src/global.d.ts` for the augmentation.
8383+- **HTMX attributes in JSX:** The `typed-htmx` package provides types for `hx-*` attributes. See `apps/web/src/global.d.ts` for the augmentation.
7284- **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.
7385- **`.env` loading:** Dev and spike scripts use Node's `--env-file=../../.env` flag to load the root `.env` file. No `dotenv` dependency needed.
7486
+11-3
README.md
···26262727User-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.
28282929-## Packages
2929+## Apps & Packages
30303131This is a [Turborepo](https://turbo.build/) monorepo with [pnpm](https://pnpm.io/) workspaces.
32323333+### Apps (`apps/`)
3434+3535+| App | Description |
3636+|-----|-------------|
3737+| [`apps/appview`](apps/appview) | Hono-based JSON API server |
3838+| [`apps/web`](apps/web) | Server-rendered web UI (Hono JSX + HTMX) |
3939+4040+### Packages (`packages/`)
4141+3342| Package | Description |
3443|---------|-------------|
4444+| [`packages/db`](packages/db) | Drizzle ORM schema and connection factory for PostgreSQL |
3545| [`packages/lexicon`](packages/lexicon) | AT Proto lexicon schemas (YAML) and generated TypeScript types |
3636-| [`packages/appview`](packages/appview) | Hono-based JSON API server |
3737-| [`packages/web`](packages/web) | Server-rendered web UI (Hono JSX + HTMX) |
3846| [`packages/spike`](packages/spike) | PDS read/write test script |
39474048## Getting Started
+1-1
docs/atproto-forum-plan.md
···139139- [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.
140140- [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.
141141- [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`.
142142-- [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.
142142+- [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/`.
143143- [ ] Create Forum Service Account (generate DID, set up PDS or use existing hosting)
144144- [ ] 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`.
145145
+22-22
docs/plans/2026-02-06-database-schema-design.md
···1313### Task 1: Install Drizzle dependencies
14141515**Files:**
1616-- Modify: `packages/appview/package.json`
1616+- Modify: `apps/appview/package.json`
17171818**Step 1: Add runtime dependencies**
1919···4646**Step 4: Commit**
47474848```bash
4949-git add packages/appview/package.json pnpm-lock.yaml
4949+git add apps/appview/package.json pnpm-lock.yaml
5050git commit -m "feat(appview): add drizzle-orm and postgres dependencies"
5151```
5252···5555### Task 2: Define the database schema
56565757**Files:**
5858-- Create: `packages/appview/src/db/schema.ts`
5858+- Create: `apps/appview/src/db/schema.ts`
59596060**Step 1: Create the schema file**
61616262-Create `packages/appview/src/db/schema.ts` with the full schema:
6262+Create `apps/appview/src/db/schema.ts` with the full schema:
63636464```typescript
6565import {
···223223**Step 3: Commit**
224224225225```bash
226226-git add packages/appview/src/db/schema.ts
226226+git add apps/appview/src/db/schema.ts
227227git commit -m "feat(appview): define database schema for all 6 tables"
228228```
229229···232232### Task 3: Create the database connection module
233233234234**Files:**
235235-- Create: `packages/appview/src/db/index.ts`
236236-- Modify: `packages/appview/src/lib/config.ts`
235235+- Create: `apps/appview/src/db/index.ts`
236236+- Modify: `apps/appview/src/lib/config.ts`
237237238238**Step 1: Add DATABASE_URL to config**
239239240240-Modify `packages/appview/src/lib/config.ts` to add `databaseUrl`:
240240+Modify `apps/appview/src/lib/config.ts` to add `databaseUrl`:
241241242242```typescript
243243export interface AppConfig {
···259259260260**Step 2: Create the database connection module**
261261262262-Create `packages/appview/src/db/index.ts`:
262262+Create `apps/appview/src/db/index.ts`:
263263264264```typescript
265265import { drizzle } from "drizzle-orm/postgres-js";
···287287**Step 4: Commit**
288288289289```bash
290290-git add packages/appview/src/db/index.ts packages/appview/src/lib/config.ts
290290+git add apps/appview/src/db/index.ts apps/appview/src/lib/config.ts
291291git commit -m "feat(appview): add database connection module and DATABASE_URL config"
292292```
293293···296296### Task 4: Configure drizzle-kit and generate migrations
297297298298**Files:**
299299-- Create: `packages/appview/drizzle.config.ts`
299299+- Create: `apps/appview/drizzle.config.ts`
300300301301**Step 1: Create drizzle-kit config**
302302303303-Create `packages/appview/drizzle.config.ts`:
303303+Create `apps/appview/drizzle.config.ts`:
304304305305```typescript
306306import { defineConfig } from "drizzle-kit";
···314314315315**Step 2: Add migration scripts to package.json**
316316317317-Add to `packages/appview/package.json` scripts:
317317+Add to `apps/appview/package.json` scripts:
318318319319```json
320320{
···331331pnpm --filter @atbb/appview db:generate
332332```
333333334334-Expected: a migration SQL file appears in `packages/appview/drizzle/` with CREATE TABLE statements for all 6 tables.
334334+Expected: a migration SQL file appears in `apps/appview/drizzle/` with CREATE TABLE statements for all 6 tables.
335335336336**Step 4: Inspect the generated SQL**
337337338338-Read the generated `.sql` file in `packages/appview/drizzle/` and verify it contains:
338338+Read the generated `.sql` file in `apps/appview/drizzle/` and verify it contains:
339339- 6 CREATE TABLE statements (forums, categories, users, memberships, posts, mod_actions)
340340- All UNIQUE indexes on (did, rkey)
341341- All additional indexes (posts.forum_uri, posts.root_post_id, memberships.did)
···344344**Step 5: Commit**
345345346346```bash
347347-git add packages/appview/drizzle.config.ts packages/appview/drizzle/ packages/appview/package.json
347347+git add apps/appview/drizzle.config.ts apps/appview/drizzle/ apps/appview/package.json
348348git commit -m "feat(appview): add drizzle-kit config and generate initial migration"
349349```
350350···446446447447| Action | File |
448448|--------|------|
449449-| Modify | `packages/appview/package.json` (deps + scripts) |
450450-| Create | `packages/appview/src/db/schema.ts` |
451451-| Create | `packages/appview/src/db/index.ts` |
452452-| Modify | `packages/appview/src/lib/config.ts` |
453453-| Create | `packages/appview/drizzle.config.ts` |
454454-| Create | `packages/appview/drizzle/*.sql` (generated) |
449449+| Modify | `apps/appview/package.json` (deps + scripts) |
450450+| Create | `apps/appview/src/db/schema.ts` |
451451+| Create | `apps/appview/src/db/index.ts` |
452452+| Modify | `apps/appview/src/lib/config.ts` |
453453+| Create | `apps/appview/drizzle.config.ts` |
454454+| Create | `apps/appview/drizzle/*.sql` (generated) |
455455| Modify | `.env.example` |
456456| Create | `docs/plans/2026-02-06-database-schema-design.md` |