773 lines
35 KiB
Markdown
773 lines
35 KiB
Markdown
# 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 (400–429) | 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) — 2–4 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) — 4–8 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 (2–4 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) — 4–6 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) | 2–3 weeks | 0 days (already built) | 100% |
|
||
| Billing (Stripe, plans, subscriptions) | 2–3 weeks | 0 days | 100% |
|
||
| Feature flags with rollout | 1 week | 0 days | 100% |
|
||
| Telemetry pipeline | 1–2 weeks | 1 hour (wire client) | 95% |
|
||
| Admin dashboard | 3–4 weeks | 0 days (shared) | 100% |
|
||
| Audit logging | 3–5 days | 0 days | 100% |
|
||
| GDPR data export | 3–5 days | 0 days | 100% |
|
||
| Email delivery (templates, SendGrid) | 1 week | 0 days | 100% |
|
||
| Rate limiting + IP rules | 3–5 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) | 1–2 weeks | 1 hour (add product colors) | 90% |
|
||
| **New product-specific CRUD module** | — | **2–4 hours** | — |
|
||
| **Full MVP (web + mobile shell)** | 6–10 weeks | **3–5 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** | 2–3 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 1–3 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
|
||
```
|