learning_ai_common_plat/docs/BEST_PRACTICES/README.md
2026-02-28 20:50:12 -08:00

773 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ByteLyst Platform — Best Practices & New Product Playbook
> **For:** Founders, engineers, and AI coding agents building products on the ByteLyst shared platform.
>
> **Last updated:** 2026-02-28 · **Ecosystem:** 5 products, 16 shared packages, 43 platform modules, 1100+ service tests.
---
## Table of Contents
1. [Platform Philosophy](#1-platform-philosophy)
2. [What You Get for Free](#2-what-you-get-for-free)
3. [New Product Playbook — Step by Step](#3-new-product-playbook--step-by-step)
4. [Expected Velocity](#4-expected-velocity)
5. [Architecture Best Practices](#5-architecture-best-practices)
6. [Coding Conventions](#6-coding-conventions)
7. [Data & Cosmos DB Practices](#7-data--cosmos-db-practices)
8. [Auth & Security Practices](#8-auth--security-practices)
9. [Testing Practices](#9-testing-practices)
10. [Deployment & CI Practices](#10-deployment--ci-practices)
11. [AI Agent Collaboration](#11-ai-agent-collaboration)
12. [Anti-Patterns to Avoid](#12-anti-patterns-to-avoid)
13. [Real-World Examples](#13-real-world-examples)
---
## 1. Platform Philosophy
The ByteLyst platform follows a **"build once, ship five"** model:
- **Product-agnostic core** — every shared package and service works for any product via the `productId` field
- **Thin product shells** — product repos contain only UI and product-specific logic; all infrastructure is shared
- **Convention over configuration** — follow the patterns, get auth/billing/telemetry/flags/audit for free
- **Offline-first** — clients work without connectivity and sync when online
### The Three Layers
```
┌─────────────────────────────────────────────────────────────┐
│ PRODUCT REPO UI + product-specific logic only │
│ (your new app) Next.js / SwiftUI / Compose / RN │
└────────────────────────────┬────────────────────────────────┘
│ file: refs / REST API
┌────────────────────────────┴────────────────────────────────┐
│ COMMON PLATFORM @bytelyst/* packages │
│ (learning_ai_common_plat) platform-service (port 4003) │
│ extraction-service (port 4005) │
└────────────────────────────┬────────────────────────────────┘
┌────────────────────────────┴────────────────────────────────┐
│ AZURE INFRASTRUCTURE Cosmos DB · Blob · Key Vault │
│ Speech · OpenAI · Stripe │
└─────────────────────────────────────────────────────────────┘
```
---
## 2. What You Get for Free
### 2.1 Shared Packages (16)
Every package is `npm install`-able via `file:` refs to the sibling common-plat repo.
| Package | What It Does | You Write |
| ------------------------------ | ------------------------------------------------------ | ------------------------ |
| **@bytelyst/auth** | JWT sign/verify, password hash, auth middleware | Nothing — just call it |
| **@bytelyst/auth-client** | Client-side auth (login, register, token refresh, SSO) | Wire to your login UI |
| **@bytelyst/cosmos** | Cosmos DB client singleton, container registry | Register your containers |
| **@bytelyst/config** | Zod env loader, product identity, Key Vault resolver | Your product's `.env` |
| **@bytelyst/api-client** | Fetch wrapper with auth injection, timeout, retry | Your service URLs |
| **@bytelyst/errors** | Typed HTTP errors (400429) | Throw them |
| **@bytelyst/fastify-core** | `createServiceApp()` + `startService()` factory | Your route plugins |
| **@bytelyst/react-auth** | `createAuthContext()` → typed Provider + useAuth hook | Wrap your app |
| **@bytelyst/logger** | Pino-based structured logging | `req.log.info(...)` |
| **@bytelyst/events** | Typed in-memory event bus with error isolation | Emit/subscribe |
| **@bytelyst/blob** | Azure Blob Storage client + SAS token helpers | Your container names |
| **@bytelyst/extraction** | AI text extraction client | Your extraction tasks |
| **@bytelyst/monitoring** | Health-check utilities, Loki/Grafana helpers | Your service name |
| **@bytelyst/telemetry-client** | Browser/RN telemetry SDK (queue, flush, beacon) | `trackEvent()` |
| **@bytelyst/design-tokens** | JSON → CSS/TS/Kotlin/Swift token generator | Your color overrides |
| **@bytelyst/testing** | Shared test mocks, Fastify inject helpers | Import in tests |
### 2.2 Platform Service Modules (43)
The consolidated platform-service (port 4003) provides REST endpoints for:
| Category | Modules | What You Get |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- |
| **Identity** | auth, sessions | JWT auth, login/register, SSO, password reset, email verification, device sessions |
| **Billing** | subscriptions, plans, licenses, stripe, promos | Stripe integration, plan management, promo codes, license keys |
| **Growth** | invitations, referrals | Invite links, referral tracking, reward attribution |
| **Ops** | flags, maintenance, status, ip-rules, ratelimit, jobs | Feature flags with rollout %, maintenance mode, public status page, scheduled jobs |
| **Data** | audit, exports, settings, notifications, delivery, push-triggers | Audit log, GDPR export, user preferences, email/push delivery with templates |
| **Content** | items, comments, votes, public, changelog, feedback | Tracker/roadmap items, comments, voting, public roadmap, in-app feedback |
| **Telemetry** | telemetry, analytics, experiments | Event ingestion, error clustering, geo distribution, A/B experiments |
| **Storage** | blob, products | Blob SAS tokens, product registry/cache |
| **Impersonation** | impersonation | Admin user impersonation for debugging |
| **Product-specific** | timers, routines, shared-timers, households (CM), fasting-sessions, fasting-protocols, body-stages, social-fasting, meal-log (NG), brains, memory, reflections, daily-briefs, streaks (ML) | Domain CRUD — each scoped by `productId` |
### 2.3 Dashboards (Product-Agnostic)
| Dashboard | Port | What It Does |
| --------------- | ---- | ---------------------------------------------------------------------------------------------- |
| **admin-web** | 3001 | User management, audit logs, feature flags, telemetry viewer, secrets manager, mission control |
| **tracker-web** | 3003 | Issue tracker, public roadmap, voting, changelog |
Both work for any product — they read `productId` from env and filter accordingly.
### 2.4 Infrastructure
- **Azure Cosmos DB** — multi-tenant via `productId` partition
- **Azure Blob Storage** — 6 containers (audio, transcripts, attachments, avatars, releases, backups)
- **Azure Key Vault** — secrets resolution at startup via `@bytelyst/config`
- **Docker Compose** — full stack with Traefik, Loki, Grafana
- **GitHub Actions** — CI templates (lint, test, typecheck, build)
- **Husky + lint-staged** — pre-commit secret scanning, linting
---
## 3. New Product Playbook — Step by Step
### Day 0: Identity & Repo Setup (1 hour)
```bash
# 1. Create your product repo
mkdir learning_ai_<codename>
cd learning_ai_<codename>
git init
# 2. Choose your product identity
PRODUCT_ID="yourapp" # lowercase, no hyphens (e.g. "nomgap", "chronomind")
BUNDLE_ID="com.saravana.${PRODUCT_ID}"
DOMAIN="${PRODUCT_ID}.app"
```
Create the scaffolding:
```
learning_ai_<codename>/
├── docs/
│ ├── PRD.md # Product requirements
│ └── roadmap.md # Implementation roadmap
├── scripts/
│ └── docker-prep.sh # Copy from any existing product repo
├── AGENTS.md # AI agent instructions (copy + customize template)
├── CLAUDE.md # Symlink or copy of AGENTS.md
├── .cursorrules # Symlink or copy of AGENTS.md
├── .windsurfrules # Symlink or copy of AGENTS.md
├── .gitignore
├── .env.example
└── README.md
```
### Day 0: Register Product in Platform (30 minutes)
1. **Add product to platform-service products module:**
```
POST /products
{
"id": "<PRODUCT_ID>",
"name": "Your App Name",
"description": "One-liner",
"domain": "yourapp.app",
"bundleId": "com.saravana.yourapp"
}
```
2. **Seed default feature flags** — already automatic (see `flags/seed.ts`), just add your product's flags to the seed file.
3. **Add to backup/push workflows** — update `scripts/backup-main.sh` and `.windsurf/workflows/repo_*.md` to include the new repo.
### Day 1: Web App (Next.js) — 24 hours
```bash
mkdir web && cd web
npx create-next-app@latest . --app --typescript --tailwind --eslint
npm install zustand zod date-fns recharts
```
Wire the shared packages:
```json
// package.json — add file: refs
{
"dependencies": {
"@bytelyst/api-client": "file:../../learning_ai_common_plat/packages/api-client",
"@bytelyst/auth-client": "file:../../learning_ai_common_plat/packages/auth-client",
"@bytelyst/config": "file:../../learning_ai_common_plat/packages/config",
"@bytelyst/cosmos": "file:../../learning_ai_common_plat/packages/cosmos",
"@bytelyst/react-auth": "file:../../learning_ai_common_plat/packages/react-auth",
"@bytelyst/telemetry-client": "file:../../learning_ai_common_plat/packages/telemetry-client",
"@bytelyst/errors": "file:../../learning_ai_common_plat/packages/errors"
}
}
```
Create the standard `src/lib/` wiring files (copy from any existing product):
| File | Purpose | Source Package |
| ------------------------ | ------------------------------- | ---------------------------- |
| `lib/cosmos.ts` | Register Cosmos containers | `@bytelyst/cosmos` |
| `lib/auth-server.ts` | JWT utils for API routes | `@bytelyst/auth` |
| `lib/product-config.ts` | Product identity | `@bytelyst/config` |
| `lib/platform-client.ts` | API client for platform-service | `@bytelyst/api-client` |
| `lib/telemetry.ts` | Client telemetry init | `@bytelyst/telemetry-client` |
| `app/providers.tsx` | AuthProvider + telemetry init | `@bytelyst/react-auth` |
**What you DON'T write:** auth flows, JWT handling, token refresh, Cosmos client setup, error types, API client with retry/timeout, telemetry pipeline, feature flag polling.
### Day 1: Native App (choose your framework) — 48 hours
| Option | Best For | Stack |
| ------------------------- | --------------------------------- | ------------------------------------------ |
| **Expo (React Native)** | Fast cross-platform, JS ecosystem | Expo SDK, expo-router, Zustand + MMKV |
| **KMP + SwiftUI/Compose** | Maximum native performance | Shared Kotlin, native UI shells |
| **Pure Native** | Single platform focus | SwiftUI (iOS) or Jetpack Compose (Android) |
For any native app:
1. Copy `TelemetryService` from an existing product (Swift or Kotlin)
2. Copy `PlatformApiClient` / `PlatformSyncManager` for sync
3. Wire `@bytelyst/auth-client` (or native equivalent) for auth
4. Use design tokens from `@bytelyst/design-tokens`
### Day 2: Product-Specific Backend Modules (24 hours per module)
Each domain module follows the same pattern:
```
services/platform-service/src/modules/<your-module>/
├── types.ts # Zod schemas + TypeScript interfaces
├── repository.ts # Cosmos DB CRUD (query, create, update, delete)
├── routes.ts # Fastify REST endpoints
└── <module>.test.ts # Vitest tests
```
**Template (types.ts):**
```typescript
import { z } from 'zod';
export interface YourDoc {
id: string;
productId: string; // REQUIRED — always
userId: string;
// ... your fields
createdAt: string;
updatedAt: string;
}
export const CreateYourDocSchema = z.object({
// ... your validation
});
```
**Template (repository.ts):**
```typescript
import { getContainer } from '../../lib/cosmos.js';
import type { YourDoc } from './types.js';
function container() {
return getContainer('your_collection');
}
export async function list(productId: string, userId: string): Promise<YourDoc[]> {
const { resources } = await container()
.items.query<YourDoc>({
query: 'SELECT * FROM c WHERE c.productId = @pid AND c.userId = @uid',
parameters: [
{ name: '@pid', value: productId },
{ name: '@uid', value: userId },
],
})
.fetchAll();
return resources;
}
// ... create, update, delete
```
**Template (routes.ts):**
```typescript
import type { FastifyInstance } from 'fastify';
import { getRequestProductId } from '../../lib/request-context.js';
import { BadRequestError, NotFoundError } from '../../lib/errors.js';
import * as repo from './repository.js';
import { CreateYourDocSchema } from './types.js';
export async function yourRoutes(app: FastifyInstance) {
app.get('/your-resource', async req => {
const productId = getRequestProductId(req);
return { items: await repo.list(productId, req.user!.userId) };
});
// ... POST, PUT, DELETE
}
```
Register in `server.ts`:
```typescript
import { yourRoutes } from './modules/your-module/routes.js';
// ... inside route registration block:
await app.register(yourRoutes);
```
### Day 3: User Dashboard (optional) — 46 hours
If your product needs a user-facing web portal, create a Next.js app in your product repo:
```
your-product/
└── user-dashboard-web/
├── src/
│ ├── app/ # App Router pages
│ ├── lib/ # Standard wiring files (copy pattern)
│ └── components/ # shadcn/ui + custom
├── package.json # file: refs to @bytelyst/*
└── .env.example
```
The admin dashboard and tracker dashboard are **already built and product-agnostic** — just point them at your productId.
---
## 4. Expected Velocity
### What Took Months, Now Takes Days
Based on actual delivery across 5 products (LysnrAI, MindLyst, ChronoMind, NomGap, and the platform itself):
| Capability | Without Platform | With Platform | Savings |
| ------------------------------------------------ | ---------------- | --------------------------- | ------- |
| Auth (JWT, login, register, SSO, password reset) | 23 weeks | 0 days (already built) | 100% |
| Billing (Stripe, plans, subscriptions) | 23 weeks | 0 days | 100% |
| Feature flags with rollout | 1 week | 0 days | 100% |
| Telemetry pipeline | 12 weeks | 1 hour (wire client) | 95% |
| Admin dashboard | 34 weeks | 0 days (shared) | 100% |
| Audit logging | 35 days | 0 days | 100% |
| GDPR data export | 35 days | 0 days | 100% |
| Email delivery (templates, SendGrid) | 1 week | 0 days | 100% |
| Rate limiting + IP rules | 35 days | 0 days | 100% |
| Blob storage (uploads, SAS tokens) | 1 week | 0 days | 100% |
| Public roadmap + issue tracker | 2 weeks | 0 days | 100% |
| Client offline sync queue | 1 week | 2 hours (copy pattern) | 90% |
| Design system (tokens across platforms) | 12 weeks | 1 hour (add product colors) | 90% |
| **New product-specific CRUD module** | — | **24 hours** | — |
| **Full MVP (web + mobile shell)** | 610 weeks | **35 days** | ~85% |
### Realistic Timeline for a New Product
| Day | Milestone |
| --------- | --------------------------------------------------------------------- |
| **Day 0** | Repo created, product registered, AGENTS.md written |
| **Day 1** | Web app scaffolded with auth, telemetry, feature flags wired |
| **Day 2** | 23 product-specific backend modules, Cosmos containers registered |
| **Day 3** | Core UI screens built, offline sync queue, user dashboard (if needed) |
| **Day 4** | Native app shells (iOS/Android) with auth + sync wired |
| **Day 5** | Polish, tests, CI, first deploy |
**By Day 5 you have:** a fully authenticated, multi-platform app with billing, telemetry, feature flags, admin dashboard, audit logging, GDPR export, public roadmap, and offline sync — all production-grade.
---
## 5. Architecture Best Practices
### 5.1 Product Repo Structure
```
your-product/
├── web/ # Next.js (App Router) or Expo
│ ├── src/
│ │ ├── app/ # Pages + API routes
│ │ ├── components/ # UI components
│ │ └── lib/ # Engine logic (pure TS, no framework imports)
│ └── package.json # file: refs to @bytelyst/*
├── ios/ # SwiftUI (if native)
├── android/ # Jetpack Compose (if native)
├── docs/ # PRD, roadmap, research
├── scripts/ # Build/deploy scripts
├── AGENTS.md # AI agent instructions
└── .env.example
```
### 5.2 Engine Logic Separation
**Critical rule:** Keep business logic in pure TypeScript/Kotlin/Swift files with zero framework dependencies.
```
✅ web/src/lib/fasting-timer.ts → pure TS, testable without DOM
✅ web/src/lib/body-stages.ts → pure TS, imported by components
❌ web/src/components/Timer.tsx → business logic mixed with React
❌ web/src/lib/timer.ts → imports from 'react'
```
This enables:
- Unit testing without mocking React/RN
- Sharing logic between web and native (via ports)
- AI agents can modify engine logic confidently
### 5.3 Sync Architecture
Every client follows the same offline-first pattern:
```
Local Store (Zustand/MMKV/UserDefaults)
├── Immediate: update local state
├── Fire-and-forget: POST/PUT to platform-service
└── On failure: enqueue to offline queue
└── On next online: flush queue → pull remote → merge
```
**Key files to copy from existing products:**
- `offline-queue.ts` (NomGap) — MMKV-backed queue with retry + exponential backoff
- `platform-sync.ts` (ChronoMind) — full bidirectional sync with conflict detection
- `PlatformSyncManager.kt/swift` (MindLyst) — native sync managers
---
## 6. Coding Conventions
### Must Follow
| Rule | Why |
| ---------------------------------------------- | --------------------------------------- |
| Every Cosmos document includes `productId` | Multi-tenant isolation |
| Every REST endpoint validates with Zod schemas | Type safety + auto documentation |
| Every service propagates `x-request-id` | Distributed tracing |
| Use `req.log` / `app.log` in Fastify | Structured logging with request context |
| Use `structlog` in Python | Same — never `print()` |
| Use theme tokens, never hardcode colors | Cross-platform consistency |
| Commit messages: `type(scope): description` | Changelog generation |
| Imports always at top of file | Code style consistency |
### Must Not Do
| Anti-Pattern | Do Instead |
| -------------------------------- | -------------------------------------- |
| `console.log` in production | `req.log.info(...)` or analytics stub |
| `any` type in TypeScript | Zod inference or explicit types |
| Hardcode secrets | `@bytelyst/config` + Key Vault |
| Hardcode API URLs | Environment variables |
| `Math.random()` for IDs in loops | `crypto.randomUUID()` or include index |
| Modify tests to make them pass | Fix the actual code |
| `npm` in common-plat | `pnpm` (workspace) |
---
## 7. Data & Cosmos DB Practices
### Container Naming
```
✅ fasting_sessions (snake_case, plural)
✅ feature_flags
❌ FastingSessions (no PascalCase)
❌ fasting-session (no hyphens, no singular)
```
### Document Shape
Every document must include:
```typescript
{
id: string; // Unique ID (e.g. "session_1709234567890")
productId: string; // ALWAYS — multi-tenant key
// ... your fields
createdAt: string; // ISO 8601
updatedAt: string; // ISO 8601
}
```
### Partition Key Strategy
- Use `productId` as partition key for shared collections
- Use `id` as partition key for product-specific collections with low cross-product queries
- For high-volume telemetry: composite key like `productId:yyyyMM:platform`
### Query Patterns
```typescript
// ✅ Always filter by productId first
'SELECT * FROM c WHERE c.productId = @pid AND c.userId = @uid ORDER BY c.createdAt DESC';
// ❌ Full scan — never do this
'SELECT * FROM c';
```
---
## 8. Auth & Security Practices
### JWT Flow
```
Client → POST /auth/login → platform-service → JWT (access + refresh)
Client → Authorization: Bearer <jwt> → platform-service validates
Client → 401 → silent refresh via refresh token → retry
```
### Server-Side (Next.js API Routes)
```typescript
// lib/auth-server.ts — copy from existing product
import { createJwtUtils } from '@bytelyst/auth';
export const { verifyToken, signToken, hashPassword, verifyPassword } = createJwtUtils({
secret: process.env.JWT_SECRET!,
});
```
### Client-Side
```typescript
// lib/auth-client.ts — copy from existing product
import { createAuthClient } from '@bytelyst/auth-client';
export const authClient = createAuthClient({
baseUrl: process.env.NEXT_PUBLIC_PLATFORM_URL!,
storage: { getItem, setItem, removeItem }, // localStorage or MMKV
});
```
### Security Checklist
- [ ] Husky pre-commit: secret scan (`scripts/secret-scan-staged.sh`)
- [ ] Husky pre-push: full repo scan (`scripts/secret-scan-repo.sh`)
- [ ] No secrets in `.env.example` — only placeholder keys
- [ ] All real secrets in Azure Key Vault
- [ ] `@bytelyst/config` resolves secrets at startup
- [ ] Rate limiting on all public endpoints
- [ ] Edge middleware blocks unauthenticated API requests
---
## 9. Testing Practices
### Test Structure
```
# Service tests (Vitest)
services/platform-service/src/modules/<module>/<module>.test.ts
# Web engine tests (Vitest)
web/src/lib/<module>.test.ts
# Native tests
ios/<Project>Tests/ # XCTest
android/app/src/test/ # JUnit5
# E2E tests (Playwright)
web/e2e/
```
### Testing Rules
1. **Engine logic gets unit tests** — pure functions, no mocking needed
2. **API routes get integration tests** — use `@bytelyst/testing` Fastify inject helpers
3. **Never modify tests to make them pass** — fix the code
4. **Test the module pattern**`types.ts` (schema validation), `repository.ts` (CRUD), `routes.ts` (HTTP)
5. **Mock external services** — Cosmos, Stripe, SendGrid
6. **Run all tests before pushing:**
```bash
# Common platform
cd learning_ai_common_plat && pnpm test
# Your product web
cd your-product/web && npm test
# Typecheck
cd your-product/web && npx tsc --noEmit
```
### Current Test Counts (for reference)
| Repo | Tests | Test Files |
| ------------------ | ----- | ---------- |
| Platform-service | 1,141 | 84 |
| ChronoMind web | 394 | 17 |
| NomGap | 430 | 15 |
| ChronoMind iOS | 129 | 8 |
| ChronoMind Android | 30 | — |
---
## 10. Deployment & CI Practices
### Local Development
```bash
# Start platform-service (required for all products)
cd learning_ai_common_plat/services/platform-service
npm run dev # port 4003
# Start your product
cd your-product/web
npm run dev # port 3000 (or custom)
```
### Docker / CI Builds
Product repos use `file:` refs to `@bytelyst/*` packages. These break in Docker/CI where the sibling repo isn't available. Use the tarball prep workflow:
```bash
# 1. Build packages
cd learning_ai_common_plat && pnpm build
# 2. Pack tarballs + rewrite package.json
./scripts/docker-prep.sh
# 3. Now Docker build works (no sibling repo needed)
docker build your-product/web/
# 4. Restore original package.json
./scripts/docker-prep.sh --restore
```
### Environment Variables
```bash
# Required for every product
COSMOS_ENDPOINT=https://your-cosmos.documents.azure.com:443
COSMOS_KEY=...
JWT_SECRET=...
PRODUCT_ID=yourapp
# Platform-service URL (for client API calls)
PLATFORM_SERVICE_URL=http://localhost:4003
NEXT_PUBLIC_PLATFORM_URL=http://localhost:4003
# Optional but recommended
AZURE_BLOB_CONNECTION_STRING=...
STRIPE_SECRET_KEY=...
```
---
## 11. AI Agent Collaboration
### AGENTS.md Is Your Contract
Every product repo MUST have an `AGENTS.md` at root. This is the onboarding doc for all AI coding agents (Claude, Cursor, Copilot, Windsurf, Codex). Include:
1. **Project identity** — product name, ID, bundle ID, repo name
2. **Repo layout** — directory tree with descriptions
3. **Tech stack** — frameworks, versions, patterns
4. **Coding conventions** — must-follow and must-not-do rules
5. **File ownership map** — which files to touch for which domain
6. **Build & test commands** — copy-pastable verification steps
7. **Common pitfalls** — things agents frequently get wrong
### Windsurf Workflows
Create `.windsurf/workflows/` for repeatable multi-step tasks:
```yaml
---
description: Build and deploy the app
---
1. Run tests
// turbo
2. Build the app
// turbo
3. Deploy to staging
```
### Key Agent Rules
- Agents should **read AGENTS.md first** before making any changes
- Agents should **never modify tests to make them pass**
- Agents should **use `req.log` not `console.log`**
- Agents should **always include `productId`** in Cosmos documents
- Agents should **run typecheck + tests** after making changes
---
## 12. Anti-Patterns to Avoid
### Architecture Anti-Patterns
| Don't | Do Instead |
| --------------------------------------------- | ------------------------------------------------------- |
| Build a custom auth system | Use `@bytelyst/auth` + `@bytelyst/auth-client` |
| Create a new microservice for each feature | Add a module to platform-service |
| Inline `fetch()` wrappers in dashboard code | Use `@bytelyst/api-client` factory |
| Put business logic in React components | Pure TS in `src/lib/`, React in `src/components/` |
| Create a separate Cosmos database per product | Share one database, partition by `productId` |
| Write your own feature flag system | Use `flags/poll` endpoint + existing polling client |
| Skip offline queue | Copy `offline-queue.ts` pattern — users will be offline |
### Code Anti-Patterns
| Don't | Do Instead |
| ------------------------------------------------------ | ----------------------------------------------- |
| `import { something } from '../../../common_plat/...'` | `import { something } from '@bytelyst/package'` |
| `const id = Math.random().toString()` | `const id = crypto.randomUUID()` |
| `catch (e: any)` | `catch (e: unknown)` with type narrowing |
| `if (process.env.NODE_ENV === 'production')` | Feature flags via `flags/poll` |
| Copy-paste an entire module and rename | Use the module template pattern in §3 |
### Process Anti-Patterns
| Don't | Do Instead |
| -------------------------------------------------- | -------------------------------------------- |
| Make a giant PR across 5 repos | Commit incrementally per repo, push in order |
| Skip typecheck before pushing | `npx tsc --noEmit` is mandatory |
| Forget to update AGENTS.md | Keep it current — it's the agent contract |
| Use `npm` in common-plat | `pnpm` — workspace protocol requires it |
| Forget `pnpm build` before dashboard `npm install` | Always build packages first |
---
## 13. Real-World Examples
### Example: How NomGap Was Built
NomGap (fasting visualization app) was built on this platform in ~1 week:
1. **Day 0:** Created `learning_ai_fastgap`, wrote PRD, wrote AGENTS.md
2. **Day 1:** Expo (React Native) app scaffolded with:
- Zustand + MMKV for state
- `@bytelyst/auth-client` for auth
- `@bytelyst/telemetry-client` for telemetry
- Feature flag polling from platform-service
3. **Day 2:** Pure engine modules in `src/lib/` — fasting timer, body stages, autophagy meter, safety checks, gamification (283 tests)
4. **Day 3:** Platform-service modules added — `fasting-sessions`, `fasting-protocols`, `body-stages`, `social-fasting`, `meal-log`
5. **Day 4:** Offline queue, sync, native extensions (widgets, watch app stubs)
6. **Day 5:** Store assets, CI, polish
**What was NOT built from scratch:** Auth, billing, telemetry, feature flags, admin dashboard, audit logging, rate limiting, email delivery — all inherited from the platform.
### Example: How ChronoMind Was Built
ChronoMind (AI clock/timer) spans web (Next.js PWA), iOS (SwiftUI), Android (Compose), watchOS, macOS:
1. **Web:** Next.js 16 + Zustand + Serwist (PWA). 16 pure engine modules in `web/src/lib/`, 12 React components, 394 tests
2. **iOS:** SwiftUI with 20+ shared modules in `ios/ChronoMind/Shared/`, WidgetKit, Live Activities, Siri Shortcuts
3. **Android:** Jetpack Compose + Room + Hilt, Glance widgets, foreground service
4. **Backend:** 4 modules in platform-service (timers, routines, shared-timers, households)
5. **Sync:** Bidirectional sync with offline queue, conflict detection
**Total platform-service modules added:** 4. Everything else (auth, billing, flags, telemetry, admin, tracker) was inherited.
---
## Quick Reference: Copy-Paste Checklist for New Products
```
□ Create repo: learning_ai_<codename>
□ Write AGENTS.md (copy template, customize)
□ Create .env.example with required vars
□ Register product: POST /products to platform-service
□ Add flags to services/platform-service/src/modules/flags/seed.ts
□ Add design tokens to packages/design-tokens/ (optional)
□ Scaffold web app with file: refs to @bytelyst/*
□ Create lib/ wiring: cosmos.ts, auth-server.ts, product-config.ts, platform-client.ts
□ Create 13 backend modules in platform-service
□ Register Cosmos containers in cosmos-init.ts
□ Wire telemetry client
□ Wire feature flag polling
□ Add offline queue for sync
□ Write tests for engine logic
□ Run typecheck + tests
□ Add to backup/push workflows
□ Push to origin
```