AI Persona Generation Community
Find Your Guide
Quick Reference
# Start local dev
./scripts/dev.sh
# Run quality checks
./scripts/quality.sh
# List all components
./scripts/discover.sh
Critical Rules
- Handler pattern: All handlers return
error, wrapped with app.Wrap(). HTTPErrors map to status codes; raw errors become 500.
- Request binding: Always use
app.Bind() or app.BindAndValidate(). Never use raw json.NewDecoder.
- URL parameters: Use brace syntax
{param} for chi URL parameters. NEVER use colon syntax :param - it won't work and will cause 404s. Extract with chi.URLParam(r, "param").
- Error types: Use
httperror.BadRequest, httperror.NotFound, etc. Never bare http.Error().
- Response envelope: Use
httpresponse.OK, httpresponse.Created, httpresponse.NoContent. All responses use {data, meta} envelope.
- Auth middleware: Auth is opt-in. Use
auth.Middleware() in route groups for protected endpoints.
- OpenAPI first: Document endpoints in
spec.go using openapi.* helpers. Mount with application.EnableDocs(spec).
- CSS variables: All UI components use CSS custom properties (
var(--background), var(--accent), etc.). Never hardcode colors.
- Monorepo imports: Go packages from
git.threesix.ai/jordan/persona-community-1/pkg/*, TypeScript from @persona-community-1/*.
- Database: Production uses CockroachDB (provisioned by the platform). Local dev uses PostgreSQL via docker-compose. Both are wire-compatible via
lib/pq. Write SQL compatible with both — avoid PostgreSQL-only features (advisory locks, listen/notify, tsvector).
- NO WEBSOCKETS. EVER. All real-time communication uses HTTP2 + SSE. User → server is HTTP2 POST. Server → user is SSE. This includes chat, notifications, progress, everything.
- Event flow:
POST → Service (enqueue) → Queue → Worker (generate) → Redis pub/sub → Service SSE subscriber → User. Service is thin, worker does AI work.
- Channel naming:
user:<id> = events for a specific user. channel:<id> = events for a topic/room/resource. Document all channels in ./docs/channels.md.
- Media uploads: POST returns job ID immediately. Progress and result come via SSE events. Never wait synchronously.
- Media generation: Same pattern - POST queues job, returns ID, results via SSE. Video takes 2-5 min; never block HTTP. Text generation streams
ai_chat_chunk events token-by-token.
- Media storage: Backend returns complete URLs. Never construct storage paths in frontend. Variants (thumbnail, optimized) auto-generated.
- No fake progress: Never simulate progress with timers. Real progress comes from real events.
- Auth tokens: 15-minute access tokens with embedded session ID (
sid). Refresh via POST /auth/refresh. Session revocation invalidates all tokens for that session.
- Passwords: Bcrypt cost 12, min 8 chars, max 72. Hashing lives in
pkg/auth/password.go. Never store plaintext.
- Auth codes: OTP/magic link/reset codes are single-use and time-limited. In standalone dev mode (no
DATABASE_URL), the code is always logged to stdout as [DEV] auth code created — use this code to log in code=XXXXXX — check the server terminal to get it. This works even when NOTIFY_URL is set. In production (with DATABASE_URL), emails go through the notify service (NOTIFY_URL/NOTIFY_API_KEY/NOTIFY_HOST/NOTIFY_FROM).
- Dev user: Set
DEV_USER_EMAIL=you@example.com (and optionally DEV_USER_PASSWORD) to seed your account into the in-memory store on startup so it survives restarts without re-registering.
Architecture
persona-community-1/
├── services/ # Go API services (port 8001+)
├── workers/ # Background workers (no port)
├── apps/ # Frontend applications (port 3001+)
├── cli/ # CLI tools (no port)
├── packages/ # Shared TypeScript packages
│ ├── ui/ # UI components (@persona-community-1/ui)
│ ├── layout/ # Dashboard layout (@persona-community-1/layout)
│ ├── auth/ # Auth provider (@persona-community-1/auth)
│ ├── api-client/ # Typed API client (@persona-community-1/api-client)
│ └── logger/ # HTTP/console logger (@persona-community-1/logger)
├── pkg/ # Shared Go packages
│ ├── app/ # Service bootstrapper (Wrap, Bind, Health)
│ ├── chassis/ # Facade re-exporting app types
│ ├── openapi/ # OpenAPI 3.0 spec builder + Scalar docs
│ ├── httperror/ # Typed HTTP errors
│ ├── httpresponse/ # Response envelope helpers
│ ├── httpvalidation/ # Struct validation
│ ├── middleware/ # RequestID, CORS, Recovery, Logger
│ ├── auth/ # JWT, API key, middleware
│ ├── config/ # Viper-based configuration
│ ├── httpclient/ # Resilient HTTP client
│ └── logging/ # slog wrapper
└── scripts/ # Development & CI scripts
| Slot |
Language |
Port Range |
Purpose |
| services/ |
Go |
8001+ |
REST APIs, backend services |
| workers/ |
Go |
none |
Background jobs, queue consumers |
| apps/ |
TypeScript |
3001+ |
React, Next.js, Astro frontends |
| cli/ |
Go |
none |
CLI tools, scripts |
| packages/ |
TypeScript |
none |
Shared frontend packages |
| pkg/ |
Go |
none |
Shared backend packages |
Components
| Component |
Type |
Path |
| persona-api |
API service |
services/persona-api/ |
| media-worker |
Background worker |
workers/media-worker/ |
| creator-ui |
React app |
apps/creator-ui/ |