commits
Extract three focused classes to separate concerns in FirehoseService:
- CursorManager: manages firehose cursor persistence in database
- Handles loading/saving cursor state
- Provides rewind utility for safety margin
- CircuitBreaker: implements circuit breaker pattern
- Tracks consecutive operation failures
- Triggers callback when failure threshold exceeded
- Prevents cascading failures
- ReconnectionManager: handles reconnection with exponential backoff
- Implements backoff strategy: baseDelay * 2^(attempt - 1)
- Enforces max attempt limit
- Provides attempt count for monitoring
Benefits:
- Single Responsibility Principle: each class has one well-defined purpose
- Testability: classes can be tested in isolation with unit tests
- Reusability: helper classes can be reused in other services
- Maintainability: easier to understand, modify, and debug
- Monitoring: exposes failure/attempt counts for health checks
FirehoseService now delegates cursor, circuit breaker, and reconnection
concerns to these helper classes while focusing on WebSocket management
and event routing.
Replace module-level state in indexer with class-based architecture:
- Convert all handler functions to methods on new Indexer class
- Database instance passed to constructor, not module-level variable
- Remove initIndexer() function in favor of instantiation
- Update FirehoseService to create and use Indexer instance
- Update all tests to instantiate Indexer with test database
- Add TxOrDb type alias for cleaner transaction/database parameter types
Benefits:
- Explicit dependencies - database requirement visible in constructor
- Testability - no shared module state between tests
- Flexibility - can create multiple indexer instances if needed
- Type safety - transaction parameters properly typed
Extract Transaction and DbOrTransaction types from inline definitions
in the indexer to shared type exports in @atbb/db package.
This improves code clarity and reusability by:
- Eliminating complex inline type expressions
- Providing a single source of truth for transaction types
- Adding comprehensive documentation with usage examples
- Making these types available to all consumers of @atbb/db
The Transaction type extracts the transaction callback parameter type
from Drizzle's database instance. The DbOrTransaction union type is
useful for helper functions that can work with either a database
instance or an active transaction context.
After discovering drift between codebase reality and project tracking
(ATB-10 was complete but marked as Backlog), established a clear
workflow for keeping these synchronized:
- docs/atproto-forum-plan.md (master plan with phase checklist)
- Linear issues (task tracker)
New section explains when and how to update both sources of truth
when completing work, with commit prefix convention for plan updates.
Also updated MEMORY.md with critical reminder about doc sync.
Marked Phase 0 and Phase 1 items as complete based on codebase audit:
Phase 0 (Foundation):
- Forum Service Account setup (ATB-5)
- PDS spike script validation (ATB-6)
Phase 1 (AppView Core):
- Database schema with 7 tables (ATB-7)
- Firehose subscription with Jetstream (ATB-9)
- Record indexer for all types (ATB-10)
- Read/Write API scaffolding (ATB-11, ATB-12 - in progress)
Linear issues ATB-10 and ATB-11 updated to match reality.
ATB-9: Add Jetstream firehose integration for real-time event indexing
Addresses two critical issues from PR #7 code review:
1. Lookup functions now participate in transactions
- Added dbOrTx parameter to getForumIdByUri, getForumIdByDid, and getPostIdByUri
- Updated all handlers to pass transaction context to lookups
- Ensures lookups see uncommitted writes within the same transaction
- Fixes reply chain resolution when parent and child arrive in the same batch
2. Test mocks now support transactions
- Added transaction method to createMockDb() that executes callbacks
- Prevents TypeError: mockDb.transaction is not a function in tests
Additional improvements:
- Wrapped all multi-step handlers in transactions for atomicity
- handleCategoryCreate/Update, handleMembershipUpdate, handleModActionUpdate now use transactions
All tests pass (42/42).
Address all 7 blocking issues identified in comprehensive PR review:
1. parseAtUri: Replace URL constructor with regex for at:// scheme support
2. Collection names: Use full lexicon IDs (space.atbb.forum.forum, space.atbb.forum.category)
3. Forum resolution: Add getForumIdByDid() for category/modAction records owned by Forum DID
4. ModAction subject: Access record.subject.post.uri and record.subject.did correctly
5. Circuit breaker: Track consecutive failures (max 100), stop firehose on threshold
6. Transactions: Wrap ensureUser + insert operations in db.transaction()
7. Reconnection state: Set isRunning=false on exhaustion, add health check methods
Additional improvements:
- Propagate errors from all handlers to circuit breaker
- Update test collection names and add type assertions
- Enhance error logging with event context
Added comprehensive test coverage for the firehose subscription system:
Indexer tests (indexer.test.ts):
- Post handlers: creation, updates, deletion, forum refs, reply refs
- Forum handlers: create, update, delete
- Category handlers: creation with/without forum lookup
Firehose service tests (firehose.test.ts):
- Construction and initialization
- Lifecycle management (start, stop, already running check)
- Cursor management (resume from saved, start fresh)
Test coverage:
- 42 total tests passing
- Validates event transformation logic
- Confirms proper database interaction patterns
- Tests error handling and edge cases
All tests use vitest with mocked database instances to verify
behavior without requiring actual database connections.
Resolved merge conflicts from monorepo reorganization and updated firehose
implementation to work with extracted packages:
Database layer refactoring:
- Removed singleton db export from @atbb/db package
- Added db instance injection to FirehoseService constructor
- Created initIndexer() function to initialize indexer with db instance
- Added drizzle-orm to appview dependencies for type imports
Schema alignment fixes:
- Updated post handlers to use correct column names (text not content,
rootPostId/parentPostId not replyRootId/replyParentId, deleted boolean
not deletedAt timestamp)
- Removed forumId from posts table (only forumUri exists)
- Fixed forum handlers (removed displayName and createdAt fields)
- Fixed category handlers (removed forumUri and displayName, added slug)
- Fixed membership handlers (replaced status with role/roleUri/joinedAt)
- Fixed modAction handlers (removed forumUri, use subjectPostUri not
subjectPostId, added createdBy and expiresAt)
Lexicon type fixes:
- Corrected nested ref structure (record.forum.forum.uri not
record.forumRef.uri)
- Corrected reply refs (record.reply not record.replyRef)
- Added type assertions for unknown types from Jetstream events
- Added @atproto/lexicon and multiformats dependencies to lexicon package
Note: TypeScript errors remain in generated lexicon code due to missing .js
extensions and type guard issues, but these don't affect runtime behavior.
Resolved conflicts from monorepo reorganization:
- Moved firehose implementation files to apps/appview
- Consolidated database dependencies in @atbb/db package
- Removed duplicate drizzle-orm and postgres dependencies from appview
- Added @skyware/jetstream dependency for Jetstream integration
- Updated lockfile with pnpm install
docs: analyze test coverage gaps and propose testing strategy
- Add @types/node and typescript to lexicon package devDependencies
- Add missing columns to schema tests (cid, description, indexedAt on all AT Proto record tables)
- Replace defensive if with explicit toBeDefined() in modAction test
Set up vitest as the monorepo test framework with workspace support
and turbo task integration. Added tests across all three packages:
- appview: route handler tests (health, forum, categories, topics,
posts, routing), config loading, and database schema assertions
- lexicon: contract tests validating YAML structure, lexicon IDs,
record key conventions, knownValues usage, and strongRef fields
- web: fetchApi client tests (URL construction, error handling)
and config loading tests
Tests also document two config gaps where ?? doesn't catch empty
strings, causing NaN ports and empty URLs.
https://claude.ai/code/session_01MffppURah8kTTYS3SUZu5e
The monorepo currently has zero test infrastructure and 0% coverage
across ~530 lines of source code. This document catalogs every
untested module, recommends vitest as the framework, and provides a
prioritized implementation plan with concrete code examples.
https://claude.ai/code/session_01MffppURah8kTTYS3SUZu5e
refactor: reorganize monorepo into apps/ and packages/ directories
- Add explicit types exports using conditional exports format
- Remove unused barrel file apps/appview/src/db/index.ts
- Add @types/node to @atbb/db devDependencies per project convention
All three suggestions from PR #5 code review implemented.
docs: add mobile apps plan (React Native + Expo)
Fix critical issues:
- Fix OAuth architecture: remove appview mediation endpoints, rewrite auth
flow to have mobile app exchange tokens directly with user's PDS and
present DPoP-bound tokens to appview (preserves AT Proto decentralization)
- Update iOS PWA claim: reflect iOS 16.4+ Web Push support with accurate
constraints (requires add-to-home-screen, constrained UX)
- Add missing reactions endpoints to API inventory with note about DB/lexicon
gaps
- Remove premature API versioning: defer /api/v1/* until post-v1 to avoid
breaking changes while API still evolving
Improvements per review suggestions:
- Elevate DPoP key management to dedicated Authentication subsection with
mobile-specific secure storage details (secure enclave/keystore)
- Clarify devices table is local/appview-managed, not AT Proto record
- Clarify mobile build pipeline: Metro bundler (expo/eas build) vs Turborepo
(lexicon types used at dev/typecheck only)
- Reframe component sharing question: web and mobile paradigms fundamentally
different, share types/contracts not UI components
docs: add comprehensive phpBB research and gap analysis
Critical fixes:
- Add note confirming Jetstream wildcard syntax is supported
Important fixes:
- Correct post grapheme limit (300, not 3000 chars)
- Acknowledge that limit may need revisiting for forum posts
- Fix categoryId schema mismatch (posts use forumUri)
- Update event routing to use forumUri with implementation note
- Fix Hono JSX rendering API (use JSX directly in streamSSE, not renderToString)
- Clarify "zero custom client-side JS" (HTMX itself is ~14KB)
- Update AT Proto record description (supports updates via putRecord)
- Fix empty <tr> sentinel by moving SSE attributes to <tbody>
All changes address feedback from PR review to ensure technical
accuracy before merge.
Add theming system design plan
Fix lexicon convention issues identified in code review:
- Use knownValues (not implicit enum) for colorScheme field
- Wrap theme references with strongRef for CID integrity checks
- Separate themePolicy into its own singleton to prevent forum record bloat
- Note that forum.theme must be added to CLAUDE.md ownership list
Add missing implementation details:
- Elevate CSS sanitization from open question to mandatory Phase 3 gate
- Document cache key must include resolved color scheme
- Constrain fontUrls to HTTPS with allowlist consideration
- Add database schema notes for themes and memberships tables
- Clarify AppView endpoints are REST, not XRPC
Updates theme resolution waterfall to show CID integrity checks via strongRef.
Implemented a complete firehose subscription system that connects to AT Proto Jetstream,
filters for space.atbb.* records, and indexes them into the PostgreSQL database.
Key Changes:
**Firehose Service** (packages/appview/src/lib/firehose.ts):
- Created FirehoseService class using @skyware/jetstream client
- Subscribes to space.atbb.post, space.atbb.forum, space.atbb.category,
space.atbb.membership, space.atbb.modAction, and space.atbb.reaction collections
- Implements connection lifecycle with automatic reconnection and exponential backoff
- Tracks cursor position in database for resume-from-last-position functionality
- Handles create, update, and delete events for all record types
**Record Indexer** (packages/appview/src/lib/indexer.ts):
- Implements database operations for all space.atbb.* record types
- Handles posts (topics and replies) with forum references and reply chains
- Creates users on-the-fly when new records are encountered
- Implements soft delete for posts (sets deleted flag)
- Parses AT Proto URIs to resolve foreign key references
- Handles forum, category, membership, and moderation action records
**Database Schema**:
- Added firehose_cursor table to track Jetstream event position
- Supports resuming from last known cursor after restarts
- Migration generated: drizzle/0001_daily_power_pack.sql
**Configuration**:
- Added JETSTREAM_URL environment variable
- Defaults to wss://jetstream2.us-east.bsky.network/subscribe
- Integrated firehose service with appview server startup
- Implements graceful shutdown to properly close WebSocket connections
**Dependencies**:
- Added @skyware/jetstream v0.2.5 to appview
- Added @atproto/api, @atproto/xrpc, @atproto/lexicon, multiformats to lexicon package
- Updated package exports to support direct type imports
**Integration**:
- Firehose starts automatically when appview server starts
- Handles SIGTERM and SIGINT for graceful shutdown
- Logs all record operations (create/update/delete) for debugging
Note: TypeScript build currently has issues with generated lexicon types missing .js
extensions. Runtime execution with tsx works correctly. This will be addressed in a
future update to the lexicon generation process.
Resolves ATB-9
https://claude.ai/code/session_01PaA43d9Q2ztwuRS8BRzJEL
Move the Drizzle ORM schema and connection factory into packages/db
so the database layer can be shared by future consumers (firehose
consumer, admin CLI, seed scripts). Appview now depends on @atbb/db
instead of owning drizzle-orm/postgres directly. Drizzle-kit config
stays in appview (migrations are app-level concerns).
https://claude.ai/code/session_014iuD1gNMNFLYgouQ5RhkJX
Outlines strategy for iOS/Android apps consuming the existing appview
JSON API. Covers technology choice (React Native + Expo), AT Proto OAuth
on mobile, push notifications architecture, offline support, and a
4-phase implementation roadmap. Also adds mobile apps section to the
main project plan's future roadmap.
https://claude.ai/code/session_013mSCQhwArU9acUKZYweD8L
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
Detailed architectural research on connecting the AT Proto Jetstream
firehose to the browser via Server-Sent Events and HTMX's declarative
SSE extension. Covers all three layers:
1. Jetstream consumer (@skyware/jetstream with space.atbb.* filter)
2. In-process EventEmitter → Hono SSE streaming endpoints
3. HTMX sse-swap attributes for zero-JS live DOM updates
Includes concrete code sketches, scaling considerations (EventEmitter
→ Redis Pub/Sub → PostgreSQL LISTEN/NOTIFY), implementation roadmap,
and comparison showing why this is atBB's strongest architectural
differentiator over phpBB/Discourse/Flarum/NodeBB.
https://claude.ai/code/session_012nLGUeocmDKttJz1VYFPPA
Replace the single active-theme model with a full theme policy system:
- Admin curates available themes with separate light/dark defaults
- Users can pick their own theme from the available list
- Theme resolution waterfall: user pref → color scheme → forum default → fallback
- New themePolicy on forum.forum, preferredTheme on membership
- AppView API endpoints for theme CRUD and user preference
- Updated presets to ship light+dark variants
- 5-phase implementation plan reflecting new scope
https://claude.ai/code/session_01Y3xoFe9ty2gduA4KHVKeYx
Deep research into phpBB's feature set, common complaints, decline
reasons, and lessons from modern competitors (Discourse, Flarum,
XenForo). Includes prioritized gap analysis comparing atBB's current
feature set against phpBB's, with actionable recommendations.
Key findings:
- AT Proto identity is atBB's biggest advantage (spam resistance,
portable identity, data ownership)
- Critical missing features: rich text/markdown, unread tracking,
notifications, search, post reporting
- phpBB's permission complexity is a cautionary tale — keep it simple
- Discourse's trust levels are worth adopting in simplified form
- Real-time updates via firehose + HTMX SSE would be a differentiator
https://claude.ai/code/session_012nLGUeocmDKttJz1VYFPPA
Plan for a phpBB-inspired admin-customizable theme system with a
neobrutal default. Covers CSS custom property architecture, design
token schema, lexicon for theme storage on Forum DID, admin editor
workflow, and built-in preset themes. Scoped as post-MVP work.
https://claude.ai/code/session_01Y3xoFe9ty2gduA4KHVKeYx
Two options for running Postgres locally:
1. Docker Compose: `docker compose up -d` starts a PostgreSQL 17
container on port 5432 with persistent volume storage.
2. Devenv: `devenv up` now also starts a managed PostgreSQL 17 service
alongside the appview and web dev servers.
Both use the same credentials (atbb/atbb) and database name (atbb),
matching the existing DATABASE_URL in .env.example.
https://claude.ai/code/session_01T1qT4qo8eoui9X7f32PVt4
Use Node 22+ native --env-file=../../.env in dev/spike scripts so
packages pick up root .env variables without a dotenv dependency.
Also add devenv, direnv, and pre-commit entries to .gitignore.
Documents architecture, dev setup, lexicon conventions, AT Protocol
patterns, TypeScript/Hono gotchas, and git conventions.
Mark lexicon definitions and project scaffolding as complete, with
result notes. Spike script is written but awaiting PDS credentials.
Set up Turborepo monorepo with pnpm workspaces and devenv for the atBB
decentralized forum project. Defines 5 new AT Proto lexicon schemas
(category, role, membership, reaction, modAction) alongside the 3
existing ones, with a YAML→JSON→TypeScript build pipeline. Scaffolds
the Hono AppView API server, HTMX web UI server, and PDS spike script.
Extract three focused classes to separate concerns in FirehoseService:
- CursorManager: manages firehose cursor persistence in database
- Handles loading/saving cursor state
- Provides rewind utility for safety margin
- CircuitBreaker: implements circuit breaker pattern
- Tracks consecutive operation failures
- Triggers callback when failure threshold exceeded
- Prevents cascading failures
- ReconnectionManager: handles reconnection with exponential backoff
- Implements backoff strategy: baseDelay * 2^(attempt - 1)
- Enforces max attempt limit
- Provides attempt count for monitoring
Benefits:
- Single Responsibility Principle: each class has one well-defined purpose
- Testability: classes can be tested in isolation with unit tests
- Reusability: helper classes can be reused in other services
- Maintainability: easier to understand, modify, and debug
- Monitoring: exposes failure/attempt counts for health checks
FirehoseService now delegates cursor, circuit breaker, and reconnection
concerns to these helper classes while focusing on WebSocket management
and event routing.
Replace module-level state in indexer with class-based architecture:
- Convert all handler functions to methods on new Indexer class
- Database instance passed to constructor, not module-level variable
- Remove initIndexer() function in favor of instantiation
- Update FirehoseService to create and use Indexer instance
- Update all tests to instantiate Indexer with test database
- Add TxOrDb type alias for cleaner transaction/database parameter types
Benefits:
- Explicit dependencies - database requirement visible in constructor
- Testability - no shared module state between tests
- Flexibility - can create multiple indexer instances if needed
- Type safety - transaction parameters properly typed
Extract Transaction and DbOrTransaction types from inline definitions
in the indexer to shared type exports in @atbb/db package.
This improves code clarity and reusability by:
- Eliminating complex inline type expressions
- Providing a single source of truth for transaction types
- Adding comprehensive documentation with usage examples
- Making these types available to all consumers of @atbb/db
The Transaction type extracts the transaction callback parameter type
from Drizzle's database instance. The DbOrTransaction union type is
useful for helper functions that can work with either a database
instance or an active transaction context.
After discovering drift between codebase reality and project tracking
(ATB-10 was complete but marked as Backlog), established a clear
workflow for keeping these synchronized:
- docs/atproto-forum-plan.md (master plan with phase checklist)
- Linear issues (task tracker)
New section explains when and how to update both sources of truth
when completing work, with commit prefix convention for plan updates.
Also updated MEMORY.md with critical reminder about doc sync.
Marked Phase 0 and Phase 1 items as complete based on codebase audit:
Phase 0 (Foundation):
- Forum Service Account setup (ATB-5)
- PDS spike script validation (ATB-6)
Phase 1 (AppView Core):
- Database schema with 7 tables (ATB-7)
- Firehose subscription with Jetstream (ATB-9)
- Record indexer for all types (ATB-10)
- Read/Write API scaffolding (ATB-11, ATB-12 - in progress)
Linear issues ATB-10 and ATB-11 updated to match reality.
Addresses two critical issues from PR #7 code review:
1. Lookup functions now participate in transactions
- Added dbOrTx parameter to getForumIdByUri, getForumIdByDid, and getPostIdByUri
- Updated all handlers to pass transaction context to lookups
- Ensures lookups see uncommitted writes within the same transaction
- Fixes reply chain resolution when parent and child arrive in the same batch
2. Test mocks now support transactions
- Added transaction method to createMockDb() that executes callbacks
- Prevents TypeError: mockDb.transaction is not a function in tests
Additional improvements:
- Wrapped all multi-step handlers in transactions for atomicity
- handleCategoryCreate/Update, handleMembershipUpdate, handleModActionUpdate now use transactions
All tests pass (42/42).
Address all 7 blocking issues identified in comprehensive PR review:
1. parseAtUri: Replace URL constructor with regex for at:// scheme support
2. Collection names: Use full lexicon IDs (space.atbb.forum.forum, space.atbb.forum.category)
3. Forum resolution: Add getForumIdByDid() for category/modAction records owned by Forum DID
4. ModAction subject: Access record.subject.post.uri and record.subject.did correctly
5. Circuit breaker: Track consecutive failures (max 100), stop firehose on threshold
6. Transactions: Wrap ensureUser + insert operations in db.transaction()
7. Reconnection state: Set isRunning=false on exhaustion, add health check methods
Additional improvements:
- Propagate errors from all handlers to circuit breaker
- Update test collection names and add type assertions
- Enhance error logging with event context
Added comprehensive test coverage for the firehose subscription system:
Indexer tests (indexer.test.ts):
- Post handlers: creation, updates, deletion, forum refs, reply refs
- Forum handlers: create, update, delete
- Category handlers: creation with/without forum lookup
Firehose service tests (firehose.test.ts):
- Construction and initialization
- Lifecycle management (start, stop, already running check)
- Cursor management (resume from saved, start fresh)
Test coverage:
- 42 total tests passing
- Validates event transformation logic
- Confirms proper database interaction patterns
- Tests error handling and edge cases
All tests use vitest with mocked database instances to verify
behavior without requiring actual database connections.
Resolved merge conflicts from monorepo reorganization and updated firehose
implementation to work with extracted packages:
Database layer refactoring:
- Removed singleton db export from @atbb/db package
- Added db instance injection to FirehoseService constructor
- Created initIndexer() function to initialize indexer with db instance
- Added drizzle-orm to appview dependencies for type imports
Schema alignment fixes:
- Updated post handlers to use correct column names (text not content,
rootPostId/parentPostId not replyRootId/replyParentId, deleted boolean
not deletedAt timestamp)
- Removed forumId from posts table (only forumUri exists)
- Fixed forum handlers (removed displayName and createdAt fields)
- Fixed category handlers (removed forumUri and displayName, added slug)
- Fixed membership handlers (replaced status with role/roleUri/joinedAt)
- Fixed modAction handlers (removed forumUri, use subjectPostUri not
subjectPostId, added createdBy and expiresAt)
Lexicon type fixes:
- Corrected nested ref structure (record.forum.forum.uri not
record.forumRef.uri)
- Corrected reply refs (record.reply not record.replyRef)
- Added type assertions for unknown types from Jetstream events
- Added @atproto/lexicon and multiformats dependencies to lexicon package
Note: TypeScript errors remain in generated lexicon code due to missing .js
extensions and type guard issues, but these don't affect runtime behavior.
Resolved conflicts from monorepo reorganization:
- Moved firehose implementation files to apps/appview
- Consolidated database dependencies in @atbb/db package
- Removed duplicate drizzle-orm and postgres dependencies from appview
- Added @skyware/jetstream dependency for Jetstream integration
- Updated lockfile with pnpm install
Set up vitest as the monorepo test framework with workspace support
and turbo task integration. Added tests across all three packages:
- appview: route handler tests (health, forum, categories, topics,
posts, routing), config loading, and database schema assertions
- lexicon: contract tests validating YAML structure, lexicon IDs,
record key conventions, knownValues usage, and strongRef fields
- web: fetchApi client tests (URL construction, error handling)
and config loading tests
Tests also document two config gaps where ?? doesn't catch empty
strings, causing NaN ports and empty URLs.
https://claude.ai/code/session_01MffppURah8kTTYS3SUZu5e
The monorepo currently has zero test infrastructure and 0% coverage
across ~530 lines of source code. This document catalogs every
untested module, recommends vitest as the framework, and provides a
prioritized implementation plan with concrete code examples.
https://claude.ai/code/session_01MffppURah8kTTYS3SUZu5e
Fix critical issues:
- Fix OAuth architecture: remove appview mediation endpoints, rewrite auth
flow to have mobile app exchange tokens directly with user's PDS and
present DPoP-bound tokens to appview (preserves AT Proto decentralization)
- Update iOS PWA claim: reflect iOS 16.4+ Web Push support with accurate
constraints (requires add-to-home-screen, constrained UX)
- Add missing reactions endpoints to API inventory with note about DB/lexicon
gaps
- Remove premature API versioning: defer /api/v1/* until post-v1 to avoid
breaking changes while API still evolving
Improvements per review suggestions:
- Elevate DPoP key management to dedicated Authentication subsection with
mobile-specific secure storage details (secure enclave/keystore)
- Clarify devices table is local/appview-managed, not AT Proto record
- Clarify mobile build pipeline: Metro bundler (expo/eas build) vs Turborepo
(lexicon types used at dev/typecheck only)
- Reframe component sharing question: web and mobile paradigms fundamentally
different, share types/contracts not UI components
Critical fixes:
- Add note confirming Jetstream wildcard syntax is supported
Important fixes:
- Correct post grapheme limit (300, not 3000 chars)
- Acknowledge that limit may need revisiting for forum posts
- Fix categoryId schema mismatch (posts use forumUri)
- Update event routing to use forumUri with implementation note
- Fix Hono JSX rendering API (use JSX directly in streamSSE, not renderToString)
- Clarify "zero custom client-side JS" (HTMX itself is ~14KB)
- Update AT Proto record description (supports updates via putRecord)
- Fix empty <tr> sentinel by moving SSE attributes to <tbody>
All changes address feedback from PR review to ensure technical
accuracy before merge.
Fix lexicon convention issues identified in code review:
- Use knownValues (not implicit enum) for colorScheme field
- Wrap theme references with strongRef for CID integrity checks
- Separate themePolicy into its own singleton to prevent forum record bloat
- Note that forum.theme must be added to CLAUDE.md ownership list
Add missing implementation details:
- Elevate CSS sanitization from open question to mandatory Phase 3 gate
- Document cache key must include resolved color scheme
- Constrain fontUrls to HTTPS with allowlist consideration
- Add database schema notes for themes and memberships tables
- Clarify AppView endpoints are REST, not XRPC
Updates theme resolution waterfall to show CID integrity checks via strongRef.
Implemented a complete firehose subscription system that connects to AT Proto Jetstream,
filters for space.atbb.* records, and indexes them into the PostgreSQL database.
Key Changes:
**Firehose Service** (packages/appview/src/lib/firehose.ts):
- Created FirehoseService class using @skyware/jetstream client
- Subscribes to space.atbb.post, space.atbb.forum, space.atbb.category,
space.atbb.membership, space.atbb.modAction, and space.atbb.reaction collections
- Implements connection lifecycle with automatic reconnection and exponential backoff
- Tracks cursor position in database for resume-from-last-position functionality
- Handles create, update, and delete events for all record types
**Record Indexer** (packages/appview/src/lib/indexer.ts):
- Implements database operations for all space.atbb.* record types
- Handles posts (topics and replies) with forum references and reply chains
- Creates users on-the-fly when new records are encountered
- Implements soft delete for posts (sets deleted flag)
- Parses AT Proto URIs to resolve foreign key references
- Handles forum, category, membership, and moderation action records
**Database Schema**:
- Added firehose_cursor table to track Jetstream event position
- Supports resuming from last known cursor after restarts
- Migration generated: drizzle/0001_daily_power_pack.sql
**Configuration**:
- Added JETSTREAM_URL environment variable
- Defaults to wss://jetstream2.us-east.bsky.network/subscribe
- Integrated firehose service with appview server startup
- Implements graceful shutdown to properly close WebSocket connections
**Dependencies**:
- Added @skyware/jetstream v0.2.5 to appview
- Added @atproto/api, @atproto/xrpc, @atproto/lexicon, multiformats to lexicon package
- Updated package exports to support direct type imports
**Integration**:
- Firehose starts automatically when appview server starts
- Handles SIGTERM and SIGINT for graceful shutdown
- Logs all record operations (create/update/delete) for debugging
Note: TypeScript build currently has issues with generated lexicon types missing .js
extensions. Runtime execution with tsx works correctly. This will be addressed in a
future update to the lexicon generation process.
Resolves ATB-9
https://claude.ai/code/session_01PaA43d9Q2ztwuRS8BRzJEL
Move the Drizzle ORM schema and connection factory into packages/db
so the database layer can be shared by future consumers (firehose
consumer, admin CLI, seed scripts). Appview now depends on @atbb/db
instead of owning drizzle-orm/postgres directly. Drizzle-kit config
stays in appview (migrations are app-level concerns).
https://claude.ai/code/session_014iuD1gNMNFLYgouQ5RhkJX
Outlines strategy for iOS/Android apps consuming the existing appview
JSON API. Covers technology choice (React Native + Expo), AT Proto OAuth
on mobile, push notifications architecture, offline support, and a
4-phase implementation roadmap. Also adds mobile apps section to the
main project plan's future roadmap.
https://claude.ai/code/session_013mSCQhwArU9acUKZYweD8L
Detailed architectural research on connecting the AT Proto Jetstream
firehose to the browser via Server-Sent Events and HTMX's declarative
SSE extension. Covers all three layers:
1. Jetstream consumer (@skyware/jetstream with space.atbb.* filter)
2. In-process EventEmitter → Hono SSE streaming endpoints
3. HTMX sse-swap attributes for zero-JS live DOM updates
Includes concrete code sketches, scaling considerations (EventEmitter
→ Redis Pub/Sub → PostgreSQL LISTEN/NOTIFY), implementation roadmap,
and comparison showing why this is atBB's strongest architectural
differentiator over phpBB/Discourse/Flarum/NodeBB.
https://claude.ai/code/session_012nLGUeocmDKttJz1VYFPPA
Replace the single active-theme model with a full theme policy system:
- Admin curates available themes with separate light/dark defaults
- Users can pick their own theme from the available list
- Theme resolution waterfall: user pref → color scheme → forum default → fallback
- New themePolicy on forum.forum, preferredTheme on membership
- AppView API endpoints for theme CRUD and user preference
- Updated presets to ship light+dark variants
- 5-phase implementation plan reflecting new scope
https://claude.ai/code/session_01Y3xoFe9ty2gduA4KHVKeYx
Deep research into phpBB's feature set, common complaints, decline
reasons, and lessons from modern competitors (Discourse, Flarum,
XenForo). Includes prioritized gap analysis comparing atBB's current
feature set against phpBB's, with actionable recommendations.
Key findings:
- AT Proto identity is atBB's biggest advantage (spam resistance,
portable identity, data ownership)
- Critical missing features: rich text/markdown, unread tracking,
notifications, search, post reporting
- phpBB's permission complexity is a cautionary tale — keep it simple
- Discourse's trust levels are worth adopting in simplified form
- Real-time updates via firehose + HTMX SSE would be a differentiator
https://claude.ai/code/session_012nLGUeocmDKttJz1VYFPPA
Plan for a phpBB-inspired admin-customizable theme system with a
neobrutal default. Covers CSS custom property architecture, design
token schema, lexicon for theme storage on Forum DID, admin editor
workflow, and built-in preset themes. Scoped as post-MVP work.
https://claude.ai/code/session_01Y3xoFe9ty2gduA4KHVKeYx
Two options for running Postgres locally:
1. Docker Compose: `docker compose up -d` starts a PostgreSQL 17
container on port 5432 with persistent volume storage.
2. Devenv: `devenv up` now also starts a managed PostgreSQL 17 service
alongside the appview and web dev servers.
Both use the same credentials (atbb/atbb) and database name (atbb),
matching the existing DATABASE_URL in .env.example.
https://claude.ai/code/session_01T1qT4qo8eoui9X7f32PVt4
Set up Turborepo monorepo with pnpm workspaces and devenv for the atBB
decentralized forum project. Defines 5 new AT Proto lexicon schemas
(category, role, membership, reaction, modAction) alongside the 3
existing ones, with a YAML→JSON→TypeScript build pipeline. Scaffolds
the Hono AppView API server, HTMX web UI server, and PDS spike script.