chore: update chat history archive + design-tokens tarball
This commit is contained in:
parent
23d5ef44f3
commit
de13a08a98
@ -1,9 +1,9 @@
|
|||||||
Last refresh: 2026-03-29T06:00:06Z (2026-03-28 23:00:06 PDT)
|
Last refresh: 2026-03-31T06:00:05Z (2026-03-30 23:00:05 PDT)
|
||||||
Cascade conversations: 50 (424M)
|
Cascade conversations: 50 (366M)
|
||||||
Memories: 104
|
Memories: 106
|
||||||
Implicit context: 20
|
Implicit context: 20
|
||||||
Code tracker dirs: 77
|
Code tracker dirs: 43
|
||||||
File edit history: 3881 entries
|
File edit history: 4014 entries
|
||||||
Workspace storage: 34 workspaces
|
Workspace storage: 34 workspaces
|
||||||
Repo docs: 7 files across 2 repos
|
Repo docs: 7 files across 2 repos
|
||||||
Repo workflows: 49 files across 11 repos
|
Repo workflows: 54 files across 12 repos
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
# Effo Rise AI — Windsurf Workflows
|
||||||
|
|
||||||
|
This directory contains Windsurf workflow definitions for the Effo Rise AI project.
|
||||||
|
|
||||||
|
## Available Workflows
|
||||||
|
|
||||||
|
| Workflow | Description |
|
||||||
|
| ----------------------- | ----------------------------------------- |
|
||||||
|
| `/refresh-chat-history` | Refresh the Windsurf chat history archive |
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
description: Refresh the Windsurf chat history archive
|
||||||
|
---
|
||||||
|
|
||||||
|
# Refresh Chat History
|
||||||
|
|
||||||
|
This workflow is a placeholder for the Effo Rise AI project. Since this repo does not currently have a chat-history archive directory, this workflow is minimal.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
1. Confirm the repo is clean or commit pending changes first.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/sd9235/code/mygh/learning_ai_efforise && git status --short
|
||||||
|
```
|
||||||
|
|
||||||
|
2. No chat-history symlinks or archives to refresh for this repo at this time.
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
---
|
||||||
|
description: 'Window 1: Phase 0 scaffolding + Manus cleanup (RUN FIRST — other windows depend on this)'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Window 1: Phase 0 Scaffolding + Manus Cleanup
|
||||||
|
|
||||||
|
> **MUST complete before starting Window 2 or Window 3.**
|
||||||
|
> **Scope:** Root files, `shared/`, `vite.config.ts`, config files. Do NOT create `backend/` or `mobile/`.
|
||||||
|
> **Reference:** `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md` Sections 4 (Phase 0), 5, and 6.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
This repo (`learning_ai_efforise`) is a Vite + React 19 SPA built by Manus.computer. It needs ecosystem scaffolding before any feature work. The product is **EffoRise** — an identity-based habit tracker. Product ID: `efforise`, backend port: 4020, web port: 3080.
|
||||||
|
|
||||||
|
## Step 1: Create Product Identity
|
||||||
|
|
||||||
|
Create `shared/product.json` following the ecosystem pattern. Use NoteLett (`../learning_ai_notes/shared/product.json`) or ActionTrail (`../learning_ai_trails/shared/product.json`) as reference. Key fields:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"productId": "efforise",
|
||||||
|
"productName": "EffoRise",
|
||||||
|
"displayName": "EffoRise",
|
||||||
|
"description": "Identity-based habit tracker — rise with efforts",
|
||||||
|
"domain": "efforise.app",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"ports": {
|
||||||
|
"backend": 4020,
|
||||||
|
"web": 3080
|
||||||
|
},
|
||||||
|
"bundleIds": {
|
||||||
|
"ios": "com.saravana.efforise",
|
||||||
|
"android": "com.saravana.efforise"
|
||||||
|
},
|
||||||
|
"platforms": ["web", "mobile"],
|
||||||
|
"tokenPrefix": "--er-",
|
||||||
|
"ecosystem": "bytelyst"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 2: Create Agent Config Files (8 files)
|
||||||
|
|
||||||
|
Create all 8 agent config files matching ecosystem standard. Copy structure from `../learning_ai_notes/` or `../learning_ai_trails/`:
|
||||||
|
|
||||||
|
1. `AGENTS.md` — AI agent onboarding guide (customize for efforise: Vite SPA + Fastify backend, productId efforise, port 4020, --er-\* tokens)
|
||||||
|
2. `CLAUDE.md` — Claude Code instructions (short version pointing to AGENTS.md)
|
||||||
|
3. `.windsurfrules` — Windsurf rules (short version pointing to AGENTS.md)
|
||||||
|
4. `.cursorrules` — Cursor rules (short version pointing to AGENTS.md)
|
||||||
|
5. `.clinerules` — Cline rules (short version pointing to AGENTS.md)
|
||||||
|
6. `.aider.conf.yml` — Aider config
|
||||||
|
7. `.editorconfig` — Copy from any ecosystem repo
|
||||||
|
8. `.github/copilot-instructions.md` — GitHub Copilot rules
|
||||||
|
|
||||||
|
## Step 3: Create Root Config Files
|
||||||
|
|
||||||
|
1. Add `.nvmrc` with content `22`
|
||||||
|
2. Update `packageManager` in `package.json` to `"pnpm@10.6.5"`
|
||||||
|
3. Add `.npmrc` — copy from `../learning_ai_notes/.npmrc` (Gitea registry config)
|
||||||
|
4. Add `.npmrc.docker` — copy from `../learning_ai_notes/.npmrc.docker`
|
||||||
|
5. Add `pnpm-workspace.yaml`:
|
||||||
|
```yaml
|
||||||
|
packages:
|
||||||
|
- backend
|
||||||
|
```
|
||||||
|
6. Add `.husky/pre-commit` and `.husky/pre-push` — copy from `../learning_ai_notes/.husky/`
|
||||||
|
7. Add `scripts/secret-scan-repo.sh` and `scripts/secret-scan-staged.sh` — copy from `../learning_ai_notes/scripts/`
|
||||||
|
8. Add `.dockerignore` — copy from `../learning_ai_notes/.dockerignore`
|
||||||
|
9. Add `eslint.config.js` at root — ESLint 9 flat config
|
||||||
|
|
||||||
|
## Step 4: Manus Artifact Cleanup
|
||||||
|
|
||||||
|
### 4a. Clean `vite.config.ts`
|
||||||
|
|
||||||
|
- Remove `vite-plugin-manus-runtime` plugin
|
||||||
|
- Remove `vite-plugin-manus-debug-collector` plugin + all LOG_DIR code
|
||||||
|
- Remove `@builder.io/vite-plugin-jsx-loc` plugin
|
||||||
|
- Replace `allowedHosts: [".manuspre.computer", ...]` with `allowedHosts: ["localhost"]`
|
||||||
|
|
||||||
|
### 4b. Delete Manus Files
|
||||||
|
|
||||||
|
- Delete `client/src/components/ManusDialog.tsx`
|
||||||
|
- Delete `client/src/components/Map.tsx` (Google Maps boilerplate, 156 lines)
|
||||||
|
- Delete `client/public/__manus__/` directory (contains `debug-collector.js`)
|
||||||
|
- Delete `client/public/images/` (empty dir, referenced `identity-tree.png` never existed)
|
||||||
|
- Delete `report.txt` (root — Manus project report)
|
||||||
|
- Delete `server/` directory entirely (Express static server — replaced by backend/ in Phase 1)
|
||||||
|
- Delete `shared/const.ts` (Manus OAuth constants — `COOKIE_NAME`, `ONE_YEAR_MS`)
|
||||||
|
- Delete `patches/wouter@3.7.1.patch` (evaluate first — remove if not critical)
|
||||||
|
|
||||||
|
### 4c. Clean `client/index.html`
|
||||||
|
|
||||||
|
- Remove `VITE_ANALYTICS_ENDPOINT` / `VITE_ANALYTICS_WEBSITE_ID` script references
|
||||||
|
|
||||||
|
### 4d. Dependency Cleanup in `package.json`
|
||||||
|
|
||||||
|
- **Downgrade** `zod` from `^4.1.12` → `^3.24.2` (CRITICAL — Zod 4 breaks @bytelyst/\* integration)
|
||||||
|
- **Upgrade** `typescript` from `5.6.3` → `^5.7.3`
|
||||||
|
- **Remove:** `streamdown`, `cmdk`, `add` (devDep), `@types/google.maps` (devDep), `next-themes`
|
||||||
|
- **Remove:** `express`, `@types/express` (server/ is deleted)
|
||||||
|
- **Remove** Manus vite plugins from devDeps: `vite-plugin-manus-runtime`, `@builder.io/vite-plugin-jsx-loc`
|
||||||
|
|
||||||
|
### 4e. Move Files
|
||||||
|
|
||||||
|
- Move `ideas.md` → `docs/ideas.md`
|
||||||
|
|
||||||
|
## Step 5: Create README.md
|
||||||
|
|
||||||
|
Write a proper README.md with:
|
||||||
|
|
||||||
|
- Product name + description
|
||||||
|
- Tech stack (Vite + React 19 SPA, Fastify 5 backend planned)
|
||||||
|
- Setup instructions (`pnpm install`, `pnpm dev`)
|
||||||
|
- Port assignments (backend: 4020, web: 3080)
|
||||||
|
- Link to `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md`
|
||||||
|
|
||||||
|
## Step 6: Verify
|
||||||
|
|
||||||
|
- Run `pnpm install` to verify lock file generates cleanly
|
||||||
|
- Run `pnpm dev` to verify the Vite SPA still works after cleanup
|
||||||
|
- Commit: `chore(scaffold): Phase 0 product identity + ecosystem scaffolding`
|
||||||
|
- Commit: `chore(cleanup): remove Manus artifacts and fix dependencies`
|
||||||
|
|
||||||
|
## Done Signal
|
||||||
|
|
||||||
|
When complete, tell the user: **"Window 1 complete. You can now start Window 2 (backend) and Window 3 (web) in parallel."**
|
||||||
@ -0,0 +1,255 @@
|
|||||||
|
---
|
||||||
|
description: 'Window 2: Backend scaffold + domain modules (Phase 1 + Phase 3 — start AFTER Window 1 completes)'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Window 2: Backend Scaffold + Domain Modules
|
||||||
|
|
||||||
|
> **Prerequisites:** Window 1 must be complete (product identity, pnpm-workspace, .npmrc exist).
|
||||||
|
> **Scope:** `backend/` directory ONLY. Do NOT modify `client/`, `mobile/`, root config files, or `shared/`.
|
||||||
|
> **Reference:** `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md` Sections 4 (Phase 1, Phase 3).
|
||||||
|
> **Scaffold reference repos:** `../learning_ai_notes/backend/`, `../learning_ai_trails/backend/`, `../learning_ai_flowmonk/backend/`
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
EffoRise is an identity-based habit tracker. Product ID: `efforise`, backend port: 4020. The backend follows the standard ByteLyst product-backend pattern: Fastify 5 + TypeScript ESM + `@bytelyst/*` shared packages + Zod validation.
|
||||||
|
|
||||||
|
All `@bytelyst/*` packages come from the Gitea npm registry (configured in root `.npmrc`). Use `@bytelyst/datastore` with `DB_PROVIDER=memory` for local dev (no Cosmos needed).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: Backend Scaffold
|
||||||
|
|
||||||
|
### Step 1: Create `backend/package.json`
|
||||||
|
|
||||||
|
Copy structure from `../learning_ai_notes/backend/package.json`. Key deps:
|
||||||
|
|
||||||
|
**dependencies:**
|
||||||
|
|
||||||
|
- `@bytelyst/fastify-core`, `@bytelyst/config`, `@bytelyst/errors`, `@bytelyst/datastore`
|
||||||
|
- `@bytelyst/cosmos`, `@bytelyst/auth`, `@bytelyst/fastify-auth`, `@bytelyst/backend-config`
|
||||||
|
- `@bytelyst/backend-telemetry`, `@bytelyst/backend-flags`, `@bytelyst/field-encrypt`
|
||||||
|
- `@bytelyst/logger`, `fastify`, `zod` (^3.24.2), `jose`
|
||||||
|
|
||||||
|
**devDependencies:**
|
||||||
|
|
||||||
|
- `typescript` (^5.7.3), `tsx`, `vitest`, `eslint` (^9.0.0), `@bytelyst/testing`
|
||||||
|
|
||||||
|
**scripts:**
|
||||||
|
|
||||||
|
- `"dev": "tsx watch src/server.ts"`
|
||||||
|
- `"build": "tsc"`
|
||||||
|
- `"typecheck": "tsc --noEmit"`
|
||||||
|
- `"test": "vitest run"`
|
||||||
|
- `"start": "node dist/server.js"`
|
||||||
|
|
||||||
|
### Step 2: Create `backend/tsconfig.json`
|
||||||
|
|
||||||
|
Extend `../../tsconfig.base.json` if available, otherwise use ecosystem standard:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"outDir": "dist",
|
||||||
|
"rootDir": "src",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"declaration": true,
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"exclude": ["src/**/*.test.ts", "dist"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Create `backend/src/lib/` Files
|
||||||
|
|
||||||
|
Create these standard lib files (copy patterns from `../learning_ai_notes/backend/src/lib/`):
|
||||||
|
|
||||||
|
1. **`product-config.ts`** — Read `../../shared/product.json`, export `productConfig`, `PRODUCT_ID`
|
||||||
|
2. **`config.ts`** — Zod env schema (PORT=4020, HOST, NODE_ENV, DB_PROVIDER, JWT_SECRET, CORS_ORIGIN, COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE)
|
||||||
|
3. **`auth.ts`** — Re-export JWT extraction from `@bytelyst/auth` or `@bytelyst/fastify-auth`
|
||||||
|
4. **`request-context.ts`** — `getUserId(req)`, `getRequestProductId(req)` helpers
|
||||||
|
5. **`errors.ts`** — Re-export from `@bytelyst/errors`
|
||||||
|
6. **`datastore.ts`** — `@bytelyst/datastore` provider init (Cosmos or memory via `DB_PROVIDER`)
|
||||||
|
7. **`cosmos-init.ts`** — Register all Cosmos containers on startup (effo_identities, effo_efforts, effo_habits, effo_streaks, effo_insights)
|
||||||
|
8. **`field-encrypt.ts`** — Field encryption singleton from `@bytelyst/field-encrypt`
|
||||||
|
9. **`telemetry.ts`** — Telemetry event buffer stub from `@bytelyst/backend-telemetry`
|
||||||
|
10. **`feature-flags.ts`** — Feature flag registry stub from `@bytelyst/backend-flags`
|
||||||
|
|
||||||
|
### Step 4: Create `backend/src/server.ts`
|
||||||
|
|
||||||
|
Fastify entrypoint using `createServiceApp()` from `@bytelyst/fastify-core`:
|
||||||
|
|
||||||
|
- Register CORS, auth, health endpoint
|
||||||
|
- Register cosmos-init on startup
|
||||||
|
- Register route modules (added in Phase 3)
|
||||||
|
- `startService()` on port 4020
|
||||||
|
|
||||||
|
### Step 5: Create `backend/src/diagnostics.test.ts`
|
||||||
|
|
||||||
|
Standard diagnostic health-check test (copy from any ecosystem backend).
|
||||||
|
|
||||||
|
### Step 6: Create Config Files
|
||||||
|
|
||||||
|
- `backend/.env.example` — All env vars with defaults
|
||||||
|
- `backend/.gitignore` — `dist/`, `node_modules/`, `.env`
|
||||||
|
- `backend/eslint.config.js` — ESLint 9 flat config (copy from `../learning_ai_notes/backend/`)
|
||||||
|
- `backend/vitest.config.ts` — Vitest config
|
||||||
|
- `backend/Dockerfile` — Multi-stage Fastify build (copy from `../learning_ai_notes/backend/Dockerfile`)
|
||||||
|
|
||||||
|
### Step 7: Add Vite Proxy
|
||||||
|
|
||||||
|
Add to `vite.config.ts` (in the root, this is the ONE root file you may touch):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
'/api': 'http://localhost:4020'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 8: Verify Phase 1
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend && pnpm install && pnpm run typecheck && pnpm run build && pnpm test
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit: `feat(backend): Phase 1 backend scaffold with Fastify 5 + @bytelyst/* packages`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: Domain Modules
|
||||||
|
|
||||||
|
### Module Pattern
|
||||||
|
|
||||||
|
Each module lives in `backend/src/modules/<name>/` with three files:
|
||||||
|
|
||||||
|
- `types.ts` — Zod schemas + TypeScript types, Cosmos doc shape
|
||||||
|
- `repository.ts` — CRUD operations via `@bytelyst/datastore` `getCollection()`
|
||||||
|
- `routes.ts` — Fastify route handlers with Zod validation
|
||||||
|
- `routes.test.ts` — Vitest tests using `buildTestApp()` pattern
|
||||||
|
|
||||||
|
Every Cosmos document MUST include `productId: "efforise"`.
|
||||||
|
|
||||||
|
### Module 1: `identities`
|
||||||
|
|
||||||
|
Container: `effo_identities`, partition: `/userId`
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
| ----------- | ---------- | ------------------------- |
|
||||||
|
| id | string | UUID |
|
||||||
|
| userId | string | Owner |
|
||||||
|
| productId | "efforise" | Required |
|
||||||
|
| name | string | "Writer", "Athlete", etc. |
|
||||||
|
| parentId | string? | For tree structure |
|
||||||
|
| description | string | What this identity means |
|
||||||
|
| color | string | Accent color |
|
||||||
|
| icon | string | Emoji or icon key |
|
||||||
|
| order | number | Sort order |
|
||||||
|
| createdAt | string | ISO timestamp |
|
||||||
|
| updatedAt | string | ISO timestamp |
|
||||||
|
|
||||||
|
Routes: GET /api/identities, POST /api/identities, GET /api/identities/:id, PATCH /api/identities/:id, DELETE /api/identities/:id, PATCH /api/identities/:id/reorder
|
||||||
|
|
||||||
|
### Module 2: `efforts`
|
||||||
|
|
||||||
|
Container: `effo_efforts`, partition: `/userId`
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
| --------------- | ----------------------------- | ----------------------------------- |
|
||||||
|
| id | string | UUID |
|
||||||
|
| userId | string | Owner |
|
||||||
|
| productId | "efforise" | Required |
|
||||||
|
| identityId | string | Which identity this effort supports |
|
||||||
|
| habitId | string? | Optional link to habit |
|
||||||
|
| type | "micro" \| "medium" \| "deep" | Effort depth |
|
||||||
|
| description | string | What was done |
|
||||||
|
| durationMinutes | number? | Optional duration |
|
||||||
|
| loggedAt | string | When the effort happened |
|
||||||
|
| createdAt | string | ISO timestamp |
|
||||||
|
|
||||||
|
Routes: GET /api/efforts, POST /api/efforts, GET /api/efforts/:id, PATCH /api/efforts/:id, DELETE /api/efforts/:id, GET /api/efforts/stats (aggregation)
|
||||||
|
|
||||||
|
### Module 3: `habits`
|
||||||
|
|
||||||
|
Container: `effo_habits`, partition: `/userId`
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
| ------------ | ------------------------------- | ------------------------------------- |
|
||||||
|
| id | string | UUID |
|
||||||
|
| userId | string | Owner |
|
||||||
|
| productId | "efforise" | Required |
|
||||||
|
| identityId | string | Which identity this habit supports |
|
||||||
|
| name | string | "Write 500 words", "Run 3 miles" |
|
||||||
|
| frequency | "daily" \| "weekly" \| "custom" | How often |
|
||||||
|
| customDays | number[]? | If frequency=custom, which days (0-6) |
|
||||||
|
| targetCount | number | Times per period |
|
||||||
|
| reminderTime | string? | HH:MM for push notification |
|
||||||
|
| isActive | boolean | Can be paused |
|
||||||
|
| createdAt | string | ISO timestamp |
|
||||||
|
| updatedAt | string | ISO timestamp |
|
||||||
|
|
||||||
|
Routes: GET /api/habits, POST /api/habits, GET /api/habits/:id, PATCH /api/habits/:id, DELETE /api/habits/:id
|
||||||
|
|
||||||
|
### Module 4: `streaks`
|
||||||
|
|
||||||
|
Container: `effo_streaks`, partition: `/userId`
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
| ---------------- | ---------- | ------------------------ |
|
||||||
|
| id | string | UUID |
|
||||||
|
| userId | string | Owner |
|
||||||
|
| productId | "efforise" | Required |
|
||||||
|
| habitId | string | Which habit |
|
||||||
|
| currentStreak | number | Current consecutive days |
|
||||||
|
| longestStreak | number | All-time record |
|
||||||
|
| lastLogDate | string | YYYY-MM-DD |
|
||||||
|
| totalCompletions | number | All-time count |
|
||||||
|
| updatedAt | string | ISO timestamp |
|
||||||
|
|
||||||
|
Routes: GET /api/streaks, GET /api/streaks/:habitId, POST /api/streaks/:habitId/log (increment)
|
||||||
|
|
||||||
|
### Module 5: `insights`
|
||||||
|
|
||||||
|
Container: `effo_insights`, partition: `/userId`
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
| ------------------ | --------------------------------------------- | -------------------------- |
|
||||||
|
| id | string | UUID |
|
||||||
|
| userId | string | Owner |
|
||||||
|
| productId | "efforise" | Required |
|
||||||
|
| type | "weekly_summary" \| "coaching" \| "milestone" | Insight type |
|
||||||
|
| title | string | Display title |
|
||||||
|
| body | string | Insight content (markdown) |
|
||||||
|
| relatedIdentityIds | string[] | Referenced identities |
|
||||||
|
| generatedAt | string | ISO timestamp |
|
||||||
|
| dismissedAt | string? | If user dismissed |
|
||||||
|
|
||||||
|
Routes: GET /api/insights, GET /api/insights/:id, POST /api/insights/:id/dismiss
|
||||||
|
|
||||||
|
### Step: Register All Modules
|
||||||
|
|
||||||
|
Update `server.ts` to register all 5 route modules. Update `cosmos-init.ts` to register all 5 containers.
|
||||||
|
|
||||||
|
### Step: Create `backend/src/test-helpers.ts`
|
||||||
|
|
||||||
|
Standard `buildTestApp()` helper for Vitest (copy pattern from `../learning_ai_notes/backend/src/test-helpers.ts`).
|
||||||
|
|
||||||
|
### Verify Phase 3
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend && pnpm run typecheck && pnpm test && pnpm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit: `feat(backend): Phase 3 domain modules — identities, efforts, habits, streaks, insights`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Done Signal
|
||||||
|
|
||||||
|
When complete, tell the user: **"Window 2 complete. Backend with 5 domain modules is ready. Window 3 can now build web screens against these APIs. Window 5 (mobile) can also start."**
|
||||||
@ -0,0 +1,278 @@
|
|||||||
|
---
|
||||||
|
description: 'Window 3: Web frontend + design tokens + platform integration + DevOps (Phase 2 + 4 + 5 + 6 — start AFTER Window 1 completes)'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Window 3: Web Frontend + DevOps
|
||||||
|
|
||||||
|
> **Prerequisites:** Window 1 must be complete (Manus artifacts removed, deps cleaned, scaffolding in place).
|
||||||
|
> **Scope:** `client/` directory, root DevOps files (`Dockerfile`, `docker-compose.yml`, `.gitea/`, `scripts/docker-prep.sh`). Do NOT modify `backend/` or `mobile/`.
|
||||||
|
> **Reference:** `docs/ECOSYSTEM_ADAPTATION_ROADMAP.md` Sections 4 (Phase 2, 4, 5, 6).
|
||||||
|
> **Scaffold reference repos:** `../learning_ai_fastgap/web/` (NomGap), `../learning_ai_notes/web/` (NoteLett)
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
EffoRise is an identity-based habit tracker. The web frontend is a Vite + React 19 SPA in `client/`. Currently only a landing page exists (`client/src/pages/Home.tsx`). The backend (Window 2) exposes APIs on port 4020. Vite proxy is configured to forward `/api` → `http://localhost:4020`.
|
||||||
|
|
||||||
|
Product design direction: "Modern Gradient Minimalism" with emerald green branding and glassmorphic UI elements (see `docs/ideas.md`). CSS token prefix: `--er-*`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: Design Token Alignment
|
||||||
|
|
||||||
|
### Step 1: Define `--er-*` CSS Custom Properties
|
||||||
|
|
||||||
|
Update `client/src/index.css` to use `--er-*` prefixed tokens. Map existing unprefixed vars to the new namespace:
|
||||||
|
|
||||||
|
```css
|
||||||
|
:root {
|
||||||
|
/* EffoRise design tokens (--er-* namespace) */
|
||||||
|
--er-bg-primary: #ffffff;
|
||||||
|
--er-bg-secondary: #f8fafc;
|
||||||
|
--er-bg-surface: #ffffff;
|
||||||
|
--er-text-primary: #0f172a;
|
||||||
|
--er-text-secondary: #475569;
|
||||||
|
--er-text-muted: #94a3b8;
|
||||||
|
--er-accent-primary: #059669; /* emerald-600 */
|
||||||
|
--er-accent-secondary: #0d9488; /* teal-600 */
|
||||||
|
--er-accent-gradient: linear-gradient(to right, #059669, #0d9488);
|
||||||
|
--er-border-default: #e2e8f0;
|
||||||
|
--er-border-subtle: #f1f5f9;
|
||||||
|
--er-radius-sm: 0.375rem;
|
||||||
|
--er-radius-md: 0.5rem;
|
||||||
|
--er-radius-lg: 0.75rem;
|
||||||
|
--er-radius-xl: 1rem;
|
||||||
|
/* ... dark mode overrides in .dark {} */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep the existing shadcn/ui CSS variable layer (--background, --foreground, etc.) but wire them to reference `--er-*` tokens underneath so the app can gradually migrate.
|
||||||
|
|
||||||
|
### Step 2: Integrate `@bytelyst/design-tokens`
|
||||||
|
|
||||||
|
Add `@bytelyst/design-tokens` to root `package.json` (devDep). This provides the canonical token source. The `--er-*` tokens should align with the generated values where possible.
|
||||||
|
|
||||||
|
### Step 3: Wire `@bytelyst/ui` Components
|
||||||
|
|
||||||
|
Add `@bytelyst/ui` to root `package.json`. Audit existing `client/src/components/ui/` — replace local shadcn copies where `@bytelyst/ui` equivalents exist (Button, Card, Badge, Toast, etc.). Keep app-specific components local.
|
||||||
|
|
||||||
|
Commit: `feat(web): Phase 2 design tokens — --er-* namespace + @bytelyst/design-tokens`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Web App Screens
|
||||||
|
|
||||||
|
### Step 1: Create App Layout
|
||||||
|
|
||||||
|
Create a sidebar-based app layout (matching ecosystem pattern). Reference `../learning_ai_fastgap/web/src/components/Sidebar.tsx`.
|
||||||
|
|
||||||
|
The app should have two modes:
|
||||||
|
|
||||||
|
- **Marketing:** Landing page at `/` (existing `Home.tsx`)
|
||||||
|
- **App:** Sidebar layout at `/app/*` routes (new)
|
||||||
|
|
||||||
|
For Vite SPA with wouter:
|
||||||
|
|
||||||
|
- `/` → Landing page (existing)
|
||||||
|
- `/app` → Dashboard
|
||||||
|
- `/app/identity` → Identity tree builder
|
||||||
|
- `/app/log` → Effort logging
|
||||||
|
- `/app/insights` → Progress charts
|
||||||
|
- `/app/settings` → Account settings
|
||||||
|
|
||||||
|
### Step 2: Create API Client
|
||||||
|
|
||||||
|
Create `client/src/lib/api-client.ts` — typed fetch wrapper for backend API:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const API_BASE = '/api'; // Vite proxy handles forwarding to :4020
|
||||||
|
|
||||||
|
export async function fetchApi<T>(path: string, options?: RequestInit): Promise<T> {
|
||||||
|
const res = await fetch(`${API_BASE}${path}`, {
|
||||||
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create typed clients: `identity-client.ts`, `effort-client.ts`, `habit-client.ts`, `streak-client.ts`, `insight-client.ts`.
|
||||||
|
|
||||||
|
### Step 3: Create Zustand Store
|
||||||
|
|
||||||
|
Create `client/src/lib/store.ts` — app state store:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { create } from 'zustand';
|
||||||
|
// Identity, effort, habit, streak state + actions
|
||||||
|
// Wire to API clients for fetch/create/update/delete
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Build Screens
|
||||||
|
|
||||||
|
Build each screen as a component in `client/src/pages/app/`:
|
||||||
|
|
||||||
|
1. **Dashboard** (`Dashboard.tsx`)
|
||||||
|
- Identity tree summary cards
|
||||||
|
- Today's habits checklist
|
||||||
|
- Current streaks display
|
||||||
|
- Quick-log effort button
|
||||||
|
- Recent insights
|
||||||
|
|
||||||
|
2. **Identity Builder** (`Identity.tsx`)
|
||||||
|
- Tree view of identities (parent/child)
|
||||||
|
- Create/edit identity modal
|
||||||
|
- Drag-and-drop reorder
|
||||||
|
- Color + icon picker
|
||||||
|
|
||||||
|
3. **Effort Logger** (`Log.tsx`)
|
||||||
|
- Quick-tap effort buttons (micro/medium/deep)
|
||||||
|
- Select identity + optional habit
|
||||||
|
- Description + duration
|
||||||
|
- Recent efforts timeline
|
||||||
|
|
||||||
|
4. **Insights** (`Insights.tsx`)
|
||||||
|
- Weekly effort chart (Recharts)
|
||||||
|
- Streak leaderboard
|
||||||
|
- AI coaching cards
|
||||||
|
- Milestone celebrations
|
||||||
|
|
||||||
|
5. **Settings** (`Settings.tsx`)
|
||||||
|
- Account info (placeholder until auth)
|
||||||
|
- Theme toggle (already exists via ThemeContext)
|
||||||
|
- Notification preferences (placeholder)
|
||||||
|
- Data export
|
||||||
|
|
||||||
|
### Step 5: Verify Phase 4
|
||||||
|
|
||||||
|
- All screens render without errors
|
||||||
|
- API calls work through Vite proxy to backend (if Window 2 is running)
|
||||||
|
- Navigation works between all routes
|
||||||
|
|
||||||
|
Commit: `feat(web): Phase 4 app screens — dashboard, identity, log, insights, settings`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5: Platform Integration
|
||||||
|
|
||||||
|
### Step 1: Add Platform Client Packages
|
||||||
|
|
||||||
|
Add to root `package.json`:
|
||||||
|
|
||||||
|
- `@bytelyst/react-auth` — Auth context + provider
|
||||||
|
- `@bytelyst/api-client` — Typed fetch wrapper (can replace manual api-client.ts)
|
||||||
|
- `@bytelyst/telemetry-client` — Browser telemetry
|
||||||
|
- `@bytelyst/diagnostics-client` — Diagnostic reporter
|
||||||
|
- `@bytelyst/feature-flag-client` — Feature flags
|
||||||
|
- `@bytelyst/kill-switch-client` — Kill switch
|
||||||
|
- `@bytelyst/platform-client` — Platform service client
|
||||||
|
|
||||||
|
### Step 2: Wire Auth
|
||||||
|
|
||||||
|
Create `client/src/lib/auth.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createAuthContext } from '@bytelyst/react-auth';
|
||||||
|
export const { AuthProvider, useAuth } = createAuthContext({
|
||||||
|
platformUrl: 'http://localhost:4003',
|
||||||
|
productId: 'efforise',
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Wrap app in `<AuthProvider>` in `App.tsx`.
|
||||||
|
|
||||||
|
### Step 3: Wire Telemetry + Diagnostics
|
||||||
|
|
||||||
|
Create `client/src/lib/telemetry.ts` and `client/src/lib/diagnostics.ts`. Initialize in app root.
|
||||||
|
|
||||||
|
### Step 4: Wire Feature Flags + Kill Switch
|
||||||
|
|
||||||
|
Create `client/src/lib/feature-flags.ts` and `client/src/lib/kill-switch.ts`. Use for gating unreleased features.
|
||||||
|
|
||||||
|
### Step 5: Create Product Config
|
||||||
|
|
||||||
|
Create `client/src/lib/product-config.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import productJson from '../../../shared/product.json';
|
||||||
|
export const PRODUCT_ID = productJson.productId;
|
||||||
|
export const PRODUCT_NAME = productJson.productName;
|
||||||
|
// etc.
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit: `feat(web): Phase 5 platform integration — auth, telemetry, flags, kill switch`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6: DevOps
|
||||||
|
|
||||||
|
### Step 1: Docker
|
||||||
|
|
||||||
|
- Create `client/Dockerfile` — multi-stage Vite build (or copy from NomGap `../learning_ai_fastgap/web/Dockerfile` and adapt for Vite)
|
||||||
|
- Create `docker-compose.yml` at root:
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build: ./backend
|
||||||
|
ports: ['4020:4020']
|
||||||
|
env_file: backend/.env
|
||||||
|
web:
|
||||||
|
build: ./client
|
||||||
|
ports: ['3080:3080']
|
||||||
|
```
|
||||||
|
- Create `scripts/docker-prep.sh` — Pack @bytelyst/\* tarballs for Docker builds (copy from `../learning_ai_notes/scripts/docker-prep.sh`)
|
||||||
|
|
||||||
|
### Step 2: CI
|
||||||
|
|
||||||
|
Create `.gitea/workflows/ci.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: CI
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
backend:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with: { node-version: 22 }
|
||||||
|
- run: pnpm install --frozen-lockfile
|
||||||
|
- run: cd backend && pnpm run typecheck
|
||||||
|
- run: cd backend && pnpm test
|
||||||
|
- run: cd backend && pnpm run build
|
||||||
|
web:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with: { node-version: 22 }
|
||||||
|
- run: pnpm install --frozen-lockfile
|
||||||
|
- run: cd client && npx tsc --noEmit
|
||||||
|
- run: pnpm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Playwright E2E
|
||||||
|
|
||||||
|
Create `client/e2e/` directory with:
|
||||||
|
|
||||||
|
- `playwright.config.ts` — config targeting `http://localhost:3080`
|
||||||
|
- `accessibility.spec.ts` — axe-core accessibility checks on all pages
|
||||||
|
- `navigation.spec.ts` — verify all routes load
|
||||||
|
|
||||||
|
### Step 4: Register in Ecosystem
|
||||||
|
|
||||||
|
Tell user to add to `../learning_ai_common_plat/`:
|
||||||
|
|
||||||
|
- `docker-compose.ecosystem.yml`: efforise-backend :4020, efforise-web :3080
|
||||||
|
- `.env.ecosystem.example`: Effo Rise env vars
|
||||||
|
- `products/efforise/product.json`: Product registry entry
|
||||||
|
|
||||||
|
Commit: `chore(devops): Phase 6 — Docker, CI, Playwright E2E, docker-prep`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Done Signal
|
||||||
|
|
||||||
|
When complete, tell the user: **"Window 3 complete. Web app with 5 screens, platform integration, Docker, CI, and Playwright E2E are ready."**
|
||||||
BIN
packages/design-tokens/bytelyst-design-tokens-0.1.0.tgz
Normal file
BIN
packages/design-tokens/bytelyst-design-tokens-0.1.0.tgz
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user