diff --git a/.agent/agent.md b/.agent/agent.md index 0bc8cf1..e9afc18 100644 --- a/.agent/agent.md +++ b/.agent/agent.md @@ -50,12 +50,12 @@ schemas ← core ← react ← apps/web ## Key invariants - `generateLearningPath()` is pure: no async, no network, no side effects -- `LearningPathInput` shape is the public API contract — do not change without a major version bump -- `packages/react` has no Tailwind dependency — CSS custom properties only -- All TypeScript types in packages are inferred from Zod schemas — no manual type duplication -- The demo at /demo runs entirely on @learnkit-ai/core — zero backend required +- `LearningPathInput` shape is the public API contract - do not change without a major version bump +- `packages/react` has no Tailwind dependency - CSS custom properties only +- All TypeScript types in packages are inferred from Zod schemas - no manual type duplication +- The demo at /demo runs entirely on @learnkit-ai/core - zero backend required -## Public API — @learnkit-ai/core +## Public API - @learnkit-ai/core ```typescript function generateLearningPath(input: LearningPathInput): LearningPath @@ -76,7 +76,7 @@ Input type (LearningPathInput): } ``` -## Component API — @learnkit-ai/react +## Component API - @learnkit-ai/react ```tsx @@ -97,16 +97,16 @@ useLearnKit(input: LearningPathInput): { path, loading, error } No fake social proof: no customer logos, no testimonials, no GitHub star counts, no compliance badges (SOC 2, HIPAA, GDPR), no user or revenue metrics. -## Out of scope (project is pure OSS — no hosted SaaS) +## Out of scope (project is pure OSS - no hosted SaaS) - Any backend server (NestJS, Express, Hono, or any HTTP server) - Any database (Prisma, Postgres, SQLite, or any persistence layer) - Authentication of any kind -- Billing or pricing of any kind — Apache-2.0, no paid tier, ever +- Billing or pricing of any kind - Apache-2.0, no paid tier, ever - Real LLM API calls (Anthropic, OpenAI, Gemini, or any LLM provider) - Docker or docker-compose - Team dashboard, HR analytics, SSO, SCIM -- A hosted REST API (`apps/api`) — the engine is client-side only +- A hosted REST API (`apps/api`) - the engine is client-side only - Tracking, analytics, telemetry, phone-home ## Rules @@ -114,19 +114,19 @@ no compliance badges (SOC 2, HIPAA, GDPR), no user or revenue metrics. See `.agent/rules/` for full conventions. Short version: - No `any` without an explanatory comment -- Named exports only from packages — no `export default` in packages/ +- Named exports only from packages - no `export default` in packages/ - Co-locate tests: `foo.ts` → `__tests__/foo.test.ts` -- No mocking internal packages in tests — only mock at system boundaries +- No mocking internal packages in tests - only mock at system boundaries - All Zod schemas live in packages/schemas -- Stage files by name — never `git add .` or `git add -A` +- Stage files by name - never `git add .` or `git add -A` - Commit messages: imperative mood, no AI co-author lines, no file lists ## Do not touch - `pnpm-lock.yaml` -- `packages/schemas/src/index.ts` types once stabilized — they are the public API contract +- `packages/schemas/src/index.ts` types once stabilized - they are the public API contract - `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.windsurfrules`, `GEMINI.md`, `CONVENTIONS.md` - — these are generated from this file; edit here and re-sync + - these are generated from this file; edit here and re-sync ## Agent config sync diff --git a/.agent/agents/code-reviewer.md b/.agent/agents/code-reviewer.md index e8f6393..39c533d 100644 --- a/.agent/agents/code-reviewer.md +++ b/.agent/agents/code-reviewer.md @@ -4,26 +4,26 @@ You are a senior TypeScript engineer reviewing a LearnKit AI pull request. ## Behavior -- Be direct and specific — point to exact file paths and line numbers +- Be direct and specific - point to exact file paths and line numbers - Explain why something is wrong, not just that it is - Distinguish blocking issues from warnings from nitpicks -- Do not praise — assume the author is competent +- Do not praise - assume the author is competent ## Focus areas -1. **Correctness** — does it do what it claims? Are edge cases handled? -2. **API contract** — is `LearningPathInput` shape preserved? -3. **Purity** — is `generateLearningPath()` still pure and synchronous? -4. **Types** — no `any`, types inferred from Zod, no manual duplicates -5. **Brand** — no "Olé", no fake social proof, no wrong domain/scope -6. **Scope** — no backend, database, auth, or LLM calls sneaking in -7. **Tests** — new logic has coverage, no internal mocks -8. **Security** — no secrets, no `dangerouslySetInnerHTML`, no `eval` +1. **Correctness** - does it do what it claims? Are edge cases handled? +2. **API contract** - is `LearningPathInput` shape preserved? +3. **Purity** - is `generateLearningPath()` still pure and synchronous? +4. **Types** - no `any`, types inferred from Zod, no manual duplicates +5. **Brand** - no "Olé", no fake social proof, no wrong domain/scope +6. **Scope** - no backend, database, auth, or LLM calls sneaking in +7. **Tests** - new logic has coverage, no internal mocks +8. **Security** - no secrets, no `dangerouslySetInnerHTML`, no `eval` ## Output format ``` -[BLOCKING] path/to/file.ts:42 — description. required action. -[WARNING] path/to/file.ts:88 — description. should fix before merge. -[NITPICK] path/to/file.ts:101 — optional improvement. +[BLOCKING] path/to/file.ts:42 - description. required action. +[WARNING] path/to/file.ts:88 - description. should fix before merge. +[NITPICK] path/to/file.ts:101 - optional improvement. ``` diff --git a/.agent/agents/security-auditor.md b/.agent/agents/security-auditor.md index a2a98ef..4b9f698 100644 --- a/.agent/agents/security-auditor.md +++ b/.agent/agents/security-auditor.md @@ -7,16 +7,16 @@ You are a security engineer auditing LearnKit AI for vulnerabilities. - Assume hostile input at every external boundary - Flag anything suspicious even if not confirmed vulnerable - Reference OWASP categories where relevant -- Only suggest real mitigations — no security theater +- Only suggest real mitigations - no security theater ## v0 attack surface v0 has no backend, no auth, no database. Focus on: -1. **Supply chain** — new npm dependencies with known CVEs or suspicious provenance -2. **XSS** — React rendering of user-supplied content unsafely -3. **Secret leakage** — API keys, tokens, or credentials in source or .env files -4. **Code injection** — `eval()`, `new Function()`, dynamic `require()` with user data +1. **Supply chain** - new npm dependencies with known CVEs or suspicious provenance +2. **XSS** - React rendering of user-supplied content unsafely +3. **Secret leakage** - API keys, tokens, or credentials in source or .env files +4. **Code injection** - `eval()`, `new Function()`, dynamic `require()` with user data ## What to look for @@ -29,7 +29,7 @@ v0 has no backend, no auth, no database. Focus on: ## Output format ``` -[CRITICAL] path/to/file.ts:14 — description. required action. -[HIGH] path/to/file.ts:88 — description. -[MEDIUM] path/to/file.ts:32 — description. +[CRITICAL] path/to/file.ts:14 - description. required action. +[HIGH] path/to/file.ts:88 - description. +[MEDIUM] path/to/file.ts:32 - description. ``` diff --git a/.agent/commands/fix-issue.md b/.agent/commands/fix-issue.md index 7db5026..35bd87d 100644 --- a/.agent/commands/fix-issue.md +++ b/.agent/commands/fix-issue.md @@ -1,13 +1,13 @@ Fix the issue: $ARGUMENTS -1. **Understand** — restate the problem in one sentence before touching any code -2. **Locate** — find the relevant code by searching for symbols, not by guessing paths -3. **Reproduce** — write a failing Vitest test that demonstrates the bug -4. **Fix** — change only what is needed to make the test pass -5. **Verify** — run `pnpm test` and `pnpm typecheck` — both must be clean -6. **Check scope** — confirm the fix does not add backend, database, auth, or LLM calls -7. **Stage** — add only the changed files by name: `git add path/to/file.ts` -8. **Commit message** — imperative mood, one sentence, no AI co-author lines +1. **Understand** - restate the problem in one sentence before touching any code +2. **Locate** - find the relevant code by searching for symbols, not by guessing paths +3. **Reproduce** - write a failing Vitest test that demonstrates the bug +4. **Fix** - change only what is needed to make the test pass +5. **Verify** - run `pnpm test` and `pnpm typecheck` - both must be clean +6. **Check scope** - confirm the fix does not add backend, database, auth, or LLM calls +7. **Stage** - add only the changed files by name: `git add path/to/file.ts` +8. **Commit message** - imperative mood, one sentence, no AI co-author lines Do not refactor unrelated code while fixing. Do not change `LearningPathInput` shape unless the issue explicitly requires it. diff --git a/.agent/commands/review.md b/.agent/commands/review.md index a37e19e..c536cc3 100644 --- a/.agent/commands/review.md +++ b/.agent/commands/review.md @@ -5,11 +5,11 @@ Check each category. Reference exact file paths and line numbers. **1. Correctness** - Does the code do what it claims? - Are edge cases handled (empty arrays, undefined inputs, unsupported roles)? -- Does `generateLearningPath()` remain pure — no async, no side effects? +- Does `generateLearningPath()` remain pure - no async, no side effects? **2. Types** - No `any` without an explanatory comment -- All types inferred from Zod schemas — no manual duplicates +- All types inferred from Zod schemas - no manual duplicates - No type assertions (`as Foo`) that could hide runtime errors **3. Brand** @@ -44,12 +44,12 @@ Check each category. Reference exact file paths and line numbers. - No `export default` from `packages/` - Files co-located with their tests -Output format — one line per finding: +Output format - one line per finding: ``` -[BLOCKING] path/to/file.ts:42 — problem description. required action. -[WARNING] path/to/file.ts:88 — problem description. should fix before merge. -[NITPICK] path/to/file.ts:101 — optional suggestion. +[BLOCKING] path/to/file.ts:42 - problem description. required action. +[WARNING] path/to/file.ts:88 - problem description. should fix before merge. +[NITPICK] path/to/file.ts:101 - optional suggestion. ``` Do not summarize what the code does. Do not praise. Be specific. diff --git a/.agent/rules/api-conventions.md b/.agent/rules/api-conventions.md index cc4e142..0e9fa55 100644 --- a/.agent/rules/api-conventions.md +++ b/.agent/rules/api-conventions.md @@ -15,7 +15,7 @@ may change freely. `LearningPathInput` is locked for v0: -- Do not add required fields — it is a breaking change +- Do not add required fields - it is a breaking change - Optional fields (`companyContext?`) may be added in minor versions - Renaming, removing, or changing the type of any field is a major version bump - Do not change the output shape of `generateLearningPath()` without a major bump @@ -35,7 +35,7 @@ export type { LearningPath, LearningPathInput, Lesson } export default function generateLearningPath(...) ``` -Exception: Next.js App Router page components require `export default` — this +Exception: Next.js App Router page components require `export default` - this applies only inside `apps/web/app/`. ## Zod schemas @@ -49,10 +49,10 @@ applies only inside `apps/web/app/`. ## Error handling - `generateLearningPath()` never throws for input that passes Zod validation -- Unknown or unsupported roles return a valid generic LearningPath — documented fallback, +- Unknown or unsupported roles return a valid generic LearningPath - documented fallback, not an exception -- Invalid input that fails Zod parse surfaces as `ZodError` — callers can catch it -- No `console.error` in packages — surface errors to the caller +- Invalid input that fails Zod parse surfaces as `ZodError` - callers can catch it +- No `console.error` in packages - surface errors to the caller ## Versioning diff --git a/.agent/rules/code-style.md b/.agent/rules/code-style.md index be67e35..48b85c6 100644 --- a/.agent/rules/code-style.md +++ b/.agent/rules/code-style.md @@ -2,12 +2,12 @@ ## TypeScript -- Strict mode everywhere — `tsconfig.base.json` sets `"strict": true` +- Strict mode everywhere - `tsconfig.base.json` sets `"strict": true` - No `any` without a comment explaining why it cannot be avoided -- Named exports only from packages — no `export default` inside `packages/` +- Named exports only from packages - no `export default` inside `packages/` - Prefer `type` over `interface` for data shapes; use `interface` only for extension points that consumers are expected to augment -- Infer types from Zod schemas — do not write matching manual types alongside them +- Infer types from Zod schemas - do not write matching manual types alongside them - `const` over `let`, never `var` - Arrow functions for callbacks and inline expressions - `async`/`await` over `.then()` chains @@ -23,24 +23,24 @@ ## File size -- Aim for ~100 lines per file — split when longer +- Aim for ~100 lines per file - split when longer - One primary export per file - No barrel re-export chains deeper than one level (`index.ts` re-exports direct sources) -- No circular imports — dependency graph must be a DAG +- No circular imports - dependency graph must be a DAG ## Comments -- No comments explaining what the code does — use clear names instead +- No comments explaining what the code does - use clear names instead - Comments only for: non-obvious constraints, invariants, or bug workarounds -- No `// TODO` committed to main — open a GitHub issue instead +- No `// TODO` committed to main - open a GitHub issue instead ## React - Functional components only - Props typed with `type`, not `interface`, unless explicitly designed for extension - No prop spreading except when forwarding to a native HTML element -- No inline `style` objects — use CSS custom properties (`--lk-*`) or Tailwind classes -- `packages/react` must not import Tailwind — CSS custom properties only +- No inline `style` objects - use CSS custom properties (`--lk-*`) or Tailwind classes +- `packages/react` must not import Tailwind - CSS custom properties only ## Formatting diff --git a/.agent/rules/security.md b/.agent/rules/security.md index 6562ab5..2bbd96c 100644 --- a/.agent/rules/security.md +++ b/.agent/rules/security.md @@ -2,9 +2,9 @@ ## Secrets -- No API keys, tokens, passwords, or secrets in source code — ever +- No API keys, tokens, passwords, or secrets in source code - ever - `.env.example` must contain only placeholder values: `SOME_KEY=your_key_here` -- `.env` and `.env.local` are gitignored — verify before every commit +- `.env` and `.env.local` are gitignored - verify before every commit - Run `git diff --staged` and scan for secrets before committing ## Input validation @@ -17,14 +17,14 @@ ## React output -- No `dangerouslySetInnerHTML` — render all text as React children +- No `dangerouslySetInnerHTML` - render all text as React children - No user-supplied strings injected into CSS custom properties at runtime - All external links (`` to third-party domains): add `rel="noopener noreferrer"` - Images from external URLs: validate domain allowlist if added in future ## Dependencies -- Review every new dependency before adding — prefer small, audited, well-maintained packages +- Review every new dependency before adding - prefer small, audited, well-maintained packages - Run `pnpm audit` before merging any PR that changes `pnpm-lock.yaml` - Do not add packages with known critical CVEs - Prefer packages with TypeScript types built-in or `@types/*` available @@ -34,9 +34,9 @@ v0 has no backend, no auth, no database, no user accounts. Main risks in scope: -1. **Supply chain** — malicious or compromised npm packages -2. **XSS** — unsafe React rendering of user-supplied content -3. **Secret leakage** — accidentally committed `.env` or API keys +1. **Supply chain** - malicious or compromised npm packages +2. **XSS** - unsafe React rendering of user-supplied content +3. **Secret leakage** - accidentally committed `.env` or API keys Do not add attack surface in v0. If a feature requires auth, a server, -or data persistence — it belongs in v1, not here. +or data persistence - it belongs in v1, not here. diff --git a/.agent/rules/testing.md b/.agent/rules/testing.md index 795203e..34808b5 100644 --- a/.agent/rules/testing.md +++ b/.agent/rules/testing.md @@ -15,22 +15,22 @@ packages/core/src/__tests__/generator.test.ts ## Writing tests -- Test behavior, not implementation — assert what a function returns, not how it works internally +- Test behavior, not implementation - assert what a function returns, not how it works internally - One logical assertion per test where possible - Test names describe the scenario in plain English: `it('returns a fallback path for an unsupported role')` - No `describe` nesting deeper than two levels -- Prefer independent tests — avoid shared mutable state between tests +- Prefer independent tests - avoid shared mutable state between tests - No `beforeAll`/`afterAll` unless there is no reasonable alternative ## Mocking - Mock only at system boundaries: HTTP, filesystem, clocks, external APIs -- Never mock internal packages — import and use the real implementation +- Never mock internal packages - import and use the real implementation - Never mock `@learnkit-ai/core` inside `@learnkit-ai/react` tests - Never mock `@learnkit-ai/schemas` anywhere -## Required coverage — packages/core +## Required coverage - packages/core These scenarios must have explicit tests: @@ -42,7 +42,7 @@ These scenarios must have explicit tests: - Unknown/unsupported role returns a valid LearningPath (no throw, no undefined) - Output validates against `learningPathSchema` from @learnkit-ai/schemas -## Required coverage — packages/schemas +## Required coverage - packages/schemas - Each Zod schema accepts a known-valid object without error - Each Zod schema rejects a known-invalid object with a ZodError diff --git a/.agent/tasks/STATUS.md b/.agent/tasks/STATUS.md index 44b7544..720968e 100644 --- a/.agent/tasks/STATUS.md +++ b/.agent/tasks/STATUS.md @@ -1,26 +1,26 @@ -# LearnKit AI v0 — Implementation Status +# LearnKit AI v0 - Implementation Status Last updated: 2026-05-03 ## Done -- [x] `.agent/` — Agent Anatomy universal config +- [x] `.agent/` - Agent Anatomy universal config - `agent.md` (source of truth) - - `commands/` — review, fix-issue, ship - - `rules/` — code-style, testing, security, api-conventions - - `agents/` — code-reviewer, security-auditor - - `tasks/` — v0-scaffold.md, v0-landing-demo.md, v0.txt + - `commands/` - review, fix-issue, ship + - `rules/` - code-style, testing, security, api-conventions + - `agents/` - code-reviewer, security-auditor + - `tasks/` - v0-scaffold.md, v0-landing-demo.md, v0.txt - `settings.json`, local override examples -- [x] `CLAUDE.md` — generated from agent.md -- [x] `AGENTS.md` — generated from agent.md -- [x] `.github/copilot-instructions.md` — generated from agent.md +- [x] `CLAUDE.md` - generated from agent.md +- [x] `AGENTS.md` - generated from agent.md +- [x] `.github/copilot-instructions.md` - generated from agent.md - [x] `.gitignore` ## In progress - [ ] Monorepo scaffold (pnpm + Turborepo + TypeScript) -## Next — implement in this order +## Next - implement in this order ### 1. Monorepo root - `pnpm-workspace.yaml` @@ -31,29 +31,29 @@ Last updated: 2026-05-03 - `.eslintrc.js` (root, shared) - `prettier.config.js` -### 2. packages/schemas — `@learnkit-ai/schemas` +### 2. packages/schemas - `@learnkit-ai/schemas` - Zod schemas: `levelSchema`, `lessonSchema`, `learningPathSchema`, `learningPathInputSchema` - Inferred TS types (no manual types) - Vitest tests -### 3. packages/core — `@learnkit-ai/core` -- `generateLearningPath()` — pure, deterministic, no LLM +### 3. packages/core - `@learnkit-ai/core` +- `generateLearningPath()` - pure, deterministic, no LLM - 5 role templates: Product Manager, Software Engineer, Designer, Marketer, Data Analyst - `getSupportedRoles()`, `getSupportedTools()`, `isRoleSupported()` - Vitest tests (all roles, determinism, fallback) -### 4. packages/react — `@learnkit-ai/react` -- `tokens.css` — CSS custom properties, warm theme + midnight theme +### 4. packages/react - `@learnkit-ai/react` +- `tokens.css` - CSS custom properties, warm theme + midnight theme - `` component - `` component - `` component - `useLearnKit()` hook - Named exports from `src/index.ts` -### 5. apps/web — Next.js App Router -- Landing page (`/`) — 7 sections, no fake proof -- Demo page (`/demo`) — role → tools → goal → path, zero backend -- Docs page (`/docs`) — placeholder with API reference +### 5. apps/web - Next.js App Router +- Landing page (`/`) - 7 sections, no fake proof +- Demo page (`/demo`) - role → tools → goal → path, zero backend +- Docs page (`/docs`) - placeholder with API reference ### 6. examples/nextjs-basic - Standalone Next.js app diff --git a/.agent/tasks/v0-landing-demo.md b/.agent/tasks/v0-landing-demo.md index 52aacac..2f4f53f 100644 --- a/.agent/tasks/v0-landing-demo.md +++ b/.agent/tasks/v0-landing-demo.md @@ -12,7 +12,7 @@ user input with zero backend. `examples/nextjs-basic` runs standalone. Task 2 of 2. Depends on `v0-scaffold` completing first. `apps/web` imports `@learnkit-ai/react` and `@learnkit-ai/core` from the workspace. -The demo runs entirely on `generateLearningPath()` — no API routes, no fetch calls. +The demo runs entirely on `generateLearningPath()` - no API routes, no fetch calls. Read `.agent/agent.md` and `.agent/rules/` before starting. @@ -46,13 +46,13 @@ const config = { export default config ``` -**`app/layout.tsx`** — import Google Fonts (Newsreader, Inter, JetBrains Mono), +**`app/layout.tsx`** - import Google Fonts (Newsreader, Inter, JetBrains Mono), import `@learnkit-ai/react/tokens.css`, import `globals.css`. -**`tailwind.config.ts`** — content includes `./app/**/*.tsx`, `./components/**/*.tsx`, +**`tailwind.config.ts`** - content includes `./app/**/*.tsx`, `./components/**/*.tsx`, and `../../packages/react/src/**/*.tsx`. -### 2. Landing page — app/page.tsx +### 2. Landing page - app/page.tsx Section order: @@ -64,12 +64,12 @@ Section order: **Hero** - Headline (serif, large): e.g. "Learning paths for your product, in minutes." - Sub-headline: one sentence describing what `generateLearningPath()` does -- Embedded `` component — live path preview, no interaction required +- Embedded `` component - live path preview, no interaction required **What it is** - Two-column layout -- Left: "A typed function" — code block showing `generateLearningPath()` call + return shape -- Right: "A React component" — code block showing `` usage +- Left: "A typed function" - code block showing `generateLearningPath()` call + return shape +- Right: "A React component" - code block showing `` usage **How it works** - 3-step grid: "Define the learner" → "Engine generates a path" → "Render with one component" @@ -95,12 +95,12 @@ Brand rules to enforce: - "AI Guide" not "Olé" if the AI feedback component is mentioned - No fake logos, testimonials, compliance badges, or metric claims -### 3. Demo page — app/demo/page.tsx +### 3. Demo page - app/demo/page.tsx Three-step interactive flow. All state is client-side (`'use client'`). No API routes. No fetch calls. Result is instant. -**Step 1 — Role** +**Step 1 - Role** Five clickable cards: - Product Manager - Software Engineer @@ -108,22 +108,22 @@ Five clickable cards: - Marketer - Data Analyst -**Step 2 — Tools** +**Step 2 - Tools** Multi-select chips (at least one required): - Cursor, Claude, ChatGPT, GitHub Copilot, Figma, Notion, Slack, HubSpot -**Step 3 — Goal** +**Step 3 - Goal** Single text input: "What do you want to achieve?" Placeholder: "e.g. ship AI features faster" **Submit** -Button: "Generate my path" — calls `generateLearningPath()` from `@learnkit-ai/core` +Button: "Generate my path" - calls `generateLearningPath()` from `@learnkit-ai/core` and renders `` from `@learnkit-ai/react` directly below. -No fake loading state. The call is synchronous — render the result immediately. +No fake loading state. The call is synchronous - render the result immediately. Show a "Start over" button after the result renders. -### 4. Docs page — app/docs/page.tsx +### 4. Docs page - app/docs/page.tsx Placeholder only. Static content: @@ -174,7 +174,7 @@ export default function Page() { **`examples/nextjs-basic/README.md`** must contain exactly: ```markdown -# LearnKit AI — Next.js basic example +# LearnKit AI - Next.js basic example Minimal integration showing `` in a Next.js app. diff --git a/.agent/tasks/v0-scaffold.md b/.agent/tasks/v0-scaffold.md index b76d0a5..5b606a0 100644 --- a/.agent/tasks/v0-scaffold.md +++ b/.agent/tasks/v0-scaffold.md @@ -11,7 +11,7 @@ Bootstrap the monorepo and implement `packages/schemas`, `packages/core`, and `p Task 1 of 2. `v0-landing-demo` depends on this completing first. Stabilize types in `packages/schemas` before writing `packages/core`. -The `LearningPathInput` shape is the public API contract — do not change it +The `LearningPathInput` shape is the public API contract - do not change it after tests pass without opening a discussion. Read `.agent/agent.md` and `.agent/rules/` before starting. @@ -30,7 +30,7 @@ packages: - 'examples/*' ``` -**`turbo.json`** — pipelines for `dev`, `build`, `lint`, `typecheck`, `test` +**`turbo.json`** - pipelines for `dev`, `build`, `lint`, `typecheck`, `test` with correct dependency ordering (`build` depends on upstream `build`, etc.) **`tsconfig.base.json`** @@ -50,7 +50,7 @@ with correct dependency ordering (`build` depends on upstream `build`, etc.) } ``` -**`package.json`** — root scripts: +**`package.json`** - root scripts: ```json { "scripts": { @@ -63,7 +63,7 @@ with correct dependency ordering (`build` depends on upstream `build`, etc.) } ``` -**`.env.example`** — single comment: `# No environment variables required for v0` +**`.env.example`** - single comment: `# No environment variables required for v0` ### 2. packages/schemas @@ -121,7 +121,7 @@ Add `src/__tests__/schemas.test.ts`: Package name: `@learnkit-ai/core` Dependencies: `@learnkit-ai/schemas` -**`src/templates.ts`** — define 5 role templates. +**`src/templates.ts`** - define 5 role templates. Each template is a function `(input: LearningPathInput) => { title, summary, durationDays, lessons, outcomes }`. Use `input.tools` to mention actual tools in lesson copy. Use `input.level` to adjust difficulty labels and practice complexity. @@ -134,7 +134,7 @@ Supported roles (case-insensitive match): - `data analyst` Each template must produce at least 4 lessons. -Fallback for unknown roles: return a generic "AI Fundamentals" path — no throw. +Fallback for unknown roles: return a generic "AI Fundamentals" path - no throw. **`src/generator.ts`** @@ -156,8 +156,8 @@ export function getSupportedTools(): string[] { ... } export function isRoleSupported(role: string): boolean { ... } ``` -`deterministicId`: hash of `role + tools.sort().join() + goal + level` — no random, no uuid. -Use a simple deterministic hash (e.g. djb2) — no crypto dependency needed. +`deterministicId`: hash of `role + tools.sort().join() + goal + level` - no random, no uuid. +Use a simple deterministic hash (e.g. djb2) - no crypto dependency needed. **`src/__tests__/generator.test.ts`** must cover: - `generateLearningPath()` returns a valid `LearningPath` for all 5 roles @@ -173,7 +173,7 @@ Package name: `@learnkit-ai/react` Peer dependencies: `react >=18`, `react-dom >=18` Dependencies: `@learnkit-ai/core`, `@learnkit-ai/schemas` -**`src/tokens.css`** — CSS custom properties, warm theme: +**`src/tokens.css`** - CSS custom properties, warm theme: ```css :root { @@ -208,19 +208,19 @@ Dependencies: `@learnkit-ai/core`, `@learnkit-ai/schemas` **Components:** `` -— calls `generateLearningPath(input)` internally, renders path title, summary, +- calls `generateLearningPath(input)` internally, renders path title, summary, outcomes list, and a `` for each lesson. `` -— renders lesson title, duration, difficulty badge, why, and practice prompt. +- renders lesson title, duration, difficulty badge, why, and practice prompt. `status` controls a visual indicator: `pending` | `active` | `complete`. `` -— avatar + message bubble. Avatar is a small circle with warm gradient +- avatar + message bubble. Avatar is a small circle with warm gradient and a subtle face glyph (SVG). No "Olé" text anywhere. `useLearnKit(input: LearningPathInput)` -— calls `generateLearningPath(input)` synchronously, wraps in state. +- calls `generateLearningPath(input)` synchronously, wraps in state. Returns `{ path: LearningPath | null, loading: boolean, error: Error | null }`. `loading` is always `false` in v0 (synchronous call). @@ -243,7 +243,7 @@ Styling rules: - [ ] `pnpm install` completes without errors - [ ] `pnpm typecheck` clean across all packages -- [ ] `pnpm test` passes — all Vitest tests green +- [ ] `pnpm test` passes - all Vitest tests green - [ ] `generateLearningPath({ role: 'Product Manager', tools: ['Cursor'], goal: 'ship AI features', level: 'beginner' })` returns a typed `LearningPath` at runtime - [ ] Output of above call validates against `learningPathSchema.parse()` - [ ] `grep -r "any" packages/core/src packages/schemas/src` shows zero untagged `any` types @@ -256,6 +256,6 @@ Styling rules: - Add `async` to `generateLearningPath()` - Add any LLM API calls - Add Tailwind to `packages/react` -- Write manual TypeScript types — infer from Zod schemas only -- Use `uuid` or `crypto.randomUUID()` for IDs — use deterministic hash +- Write manual TypeScript types - infer from Zod schemas only +- Use `uuid` or `crypto.randomUUID()` for IDs - use deterministic hash - Change `LearningPathInput` shape after tests pass diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f5a6c85..90c9395 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,4 +1,4 @@ - # LearnKit AI @@ -53,12 +53,12 @@ schemas ← core ← react ← apps/web ## Key invariants - `generateLearningPath()` is pure: no async, no network, no side effects -- `LearningPathInput` shape is the public API contract — do not change without a major version bump -- `packages/react` has no Tailwind dependency — CSS custom properties only -- All TypeScript types in packages are inferred from Zod schemas — no manual type duplication -- The demo at /demo runs entirely on @learnkit-ai/core — zero backend required +- `LearningPathInput` shape is the public API contract - do not change without a major version bump +- `packages/react` has no Tailwind dependency - CSS custom properties only +- All TypeScript types in packages are inferred from Zod schemas - no manual type duplication +- The demo at /demo runs entirely on @learnkit-ai/core - zero backend required -## Public API — @learnkit-ai/core +## Public API - @learnkit-ai/core ```typescript function generateLearningPath(input: LearningPathInput): LearningPath @@ -79,7 +79,7 @@ Input type (LearningPathInput): } ``` -## Component API — @learnkit-ai/react +## Component API - @learnkit-ai/react ```tsx @@ -114,16 +114,16 @@ no compliance badges (SOC 2, HIPAA, GDPR), no user or revenue metrics. ## Rules - No `any` without an explanatory comment -- Named exports only from packages — no `export default` in packages/ +- Named exports only from packages - no `export default` in packages/ - Co-locate tests: `foo.ts` → `__tests__/foo.test.ts` -- No mocking internal packages in tests — only mock at system boundaries +- No mocking internal packages in tests - only mock at system boundaries - All Zod schemas live in packages/schemas -- Stage files by name — never `git add .` or `git add -A` +- Stage files by name - never `git add .` or `git add -A` - Commit messages: imperative mood, no AI co-author lines, no file lists ## Do not touch - `pnpm-lock.yaml` -- `packages/schemas/src/index.ts` types once stabilized — public API contract +- `packages/schemas/src/index.ts` types once stabilized - public API contract - `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.windsurfrules`, `GEMINI.md`, `CONVENTIONS.md` - — generated from `.agent/agent.md`; edit there and re-sync + - generated from `.agent/agent.md`; edit there and re-sync diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9acdd8e..ee361ac 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,7 +2,7 @@ Thanks for the PR! A few quick checks before submitting: - Read CONTRIBUTING.md if you haven't already -- One logical change per PR — split unrelated work into separate PRs +- One logical change per PR - split unrelated work into separate PRs - pnpm typecheck, pnpm test, pnpm lint should all pass locally --> diff --git a/AGENTS.md b/AGENTS.md index f5a6c85..90c9395 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ - # LearnKit AI @@ -53,12 +53,12 @@ schemas ← core ← react ← apps/web ## Key invariants - `generateLearningPath()` is pure: no async, no network, no side effects -- `LearningPathInput` shape is the public API contract — do not change without a major version bump -- `packages/react` has no Tailwind dependency — CSS custom properties only -- All TypeScript types in packages are inferred from Zod schemas — no manual type duplication -- The demo at /demo runs entirely on @learnkit-ai/core — zero backend required +- `LearningPathInput` shape is the public API contract - do not change without a major version bump +- `packages/react` has no Tailwind dependency - CSS custom properties only +- All TypeScript types in packages are inferred from Zod schemas - no manual type duplication +- The demo at /demo runs entirely on @learnkit-ai/core - zero backend required -## Public API — @learnkit-ai/core +## Public API - @learnkit-ai/core ```typescript function generateLearningPath(input: LearningPathInput): LearningPath @@ -79,7 +79,7 @@ Input type (LearningPathInput): } ``` -## Component API — @learnkit-ai/react +## Component API - @learnkit-ai/react ```tsx @@ -114,16 +114,16 @@ no compliance badges (SOC 2, HIPAA, GDPR), no user or revenue metrics. ## Rules - No `any` without an explanatory comment -- Named exports only from packages — no `export default` in packages/ +- Named exports only from packages - no `export default` in packages/ - Co-locate tests: `foo.ts` → `__tests__/foo.test.ts` -- No mocking internal packages in tests — only mock at system boundaries +- No mocking internal packages in tests - only mock at system boundaries - All Zod schemas live in packages/schemas -- Stage files by name — never `git add .` or `git add -A` +- Stage files by name - never `git add .` or `git add -A` - Commit messages: imperative mood, no AI co-author lines, no file lists ## Do not touch - `pnpm-lock.yaml` -- `packages/schemas/src/index.ts` types once stabilized — public API contract +- `packages/schemas/src/index.ts` types once stabilized - public API contract - `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.windsurfrules`, `GEMINI.md`, `CONVENTIONS.md` - — generated from `.agent/agent.md`; edit there and re-sync + - generated from `.agent/agent.md`; edit there and re-sync diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dd6268..b25f53b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,39 +7,39 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] ### Added -- `/teams` page — OSS-framed guide for embedding LearnKit AI across an org: role-mapped embed pattern, before/after comparison, 3-step quickstart -- `/docs` page — full API reference with sticky sidebar, active-section highlighting, quickstart, theming, and self-hosting guide -- `DocsSidebar` client component — `IntersectionObserver`-based active section tracking for the docs page +- `/teams` page - OSS-framed guide for embedding LearnKit AI across an org: role-mapped embed pattern, before/after comparison, 3-step quickstart +- `/docs` page - full API reference with sticky sidebar, active-section highlighting, quickstart, theming, and self-hosting guide +- `DocsSidebar` client component - `IntersectionObserver`-based active section tracking for the docs page - 3 new engineering blog posts: "Why generateLearningPath() makes zero LLM calls", "How to fork and customize LearnKit AI", "Embedding AI learning paths in your SaaS onboarding flow" -- `tsup` build for all packages — ESM + CJS + `.d.ts` output; conditional exports map (`"source"` for monorepo dev, `"import"` for npm consumers) -- 21 React component tests — ``, ``, ``, `useLearnKit()` using `@testing-library/react` and `happy-dom` -- Per-role lesson curricula for Software Engineer, Product Manager, Designer, and Data Analyst — distinct week titles and lesson content per role -- `vitest.config.ts` with `resolve.alias` in core and react packages — resolves workspace deps to TypeScript source without requiring a pre-build -- `"source"` custom export condition across all packages — prevents vitest from resolving to non-existent dist files in CI +- `tsup` build for all packages - ESM + CJS + `.d.ts` output; conditional exports map (`"source"` for monorepo dev, `"import"` for npm consumers) +- 21 React component tests - ``, ``, ``, `useLearnKit()` using `@testing-library/react` and `happy-dom` +- Per-role lesson curricula for Software Engineer, Product Manager, Designer, and Data Analyst - distinct week titles and lesson content per role +- `vitest.config.ts` with `resolve.alias` in core and react packages - resolves workspace deps to TypeScript source without requiring a pre-build +- `"source"` custom export condition across all packages - prevents vitest from resolving to non-existent dist files in CI ### Changed -- `/developers` page — rewrote to show the real package API surface (`generateLearningPath()`, `getSupportedRoles()`, `getSupportedTools()`, React components) instead of fabricated REST endpoints -- `UseItYourWay` section — replaced pricing cards with OSS install/embed/self-host options; no dollar amounts anywhere -- `Proof` section — replaced fake testimonials and social proof with real OSS facts (Apache-2.0, TypeScript strict, 0 tracking pixels) -- Nav — updated links: "For teams" → `/teams`, added "Docs" → `/docs` -- CI — added `@learnkit-ai/react` to the test step; added package build step (schemas → core → react) before web build -- `packageManager` field added to root `package.json` — fixes `turbo dev` workspace resolution +- `/developers` page - rewrote to show the real package API surface (`generateLearningPath()`, `getSupportedRoles()`, `getSupportedTools()`, React components) instead of fabricated REST endpoints +- `UseItYourWay` section - replaced pricing cards with OSS install/embed/self-host options; no dollar amounts anywhere +- `Proof` section - replaced fake testimonials and social proof with real OSS facts (Apache-2.0, TypeScript strict, 0 tracking pixels) +- Nav - updated links: "For teams" → `/teams`, added "Docs" → `/docs` +- CI - added `@learnkit-ai/react` to the test step; added package build step (schemas → core → react) before web build +- `packageManager` field added to root `package.json` - fixes `turbo dev` workspace resolution ### Fixed - `getSupportedRoles()` comment in docs now shows the actual return value - `next-env.d.ts` added to `.gitignore` -- CI pnpm version conflict — removed hardcoded `version: 10` from `pnpm/action-setup@v4`; version read from `packageManager` field only +- CI pnpm version conflict - removed hardcoded `version: 10` from `pnpm/action-setup@v4`; version read from `packageManager` field only --- -## [0.0.1] — 2026-05-01 (initial scaffold) +## [0.0.1] - 2026-05-01 (initial scaffold) ### Added -- `@learnkit-ai/schemas` — Zod schemas for `LearningPathInput`, `LearningPath`, `Lesson`, `Week`, and `Level`, with inferred TypeScript types -- `@learnkit-ai/core` — deterministic `generateLearningPath()` engine with 9 covered tests, plus role/tool normalization helpers -- `@learnkit-ai/react` — ``, ``, ``, and the `useLearnKit()` hook with three built-in themes -- `apps/web` — full marketing site with landing, demo flow, developers, tools, roles, and blog routes -- Programmatic SEO surface — 8 tool pages, 8 role pages, sitemap, robots, OG image +- `@learnkit-ai/schemas` - Zod schemas for `LearningPathInput`, `LearningPath`, `Lesson`, `Week`, and `Level`, with inferred TypeScript types +- `@learnkit-ai/core` - deterministic `generateLearningPath()` engine with 9 covered tests, plus role/tool normalization helpers +- `@learnkit-ai/react` - ``, ``, ``, and the `useLearnKit()` hook with three built-in themes +- `apps/web` - full marketing site with landing, demo flow, developers, tools, roles, and blog routes +- Programmatic SEO surface - 8 tool pages, 8 role pages, sitemap, robots, OG image - Responsive layer covering desktop, tablet, and mobile breakpoints -- OSS hygiene — LICENSE (Apache-2.0), CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, issue/PR templates +- OSS hygiene - LICENSE (Apache-2.0), CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, issue/PR templates - CI workflow on GitHub Actions running lint, typecheck, and test on every PR diff --git a/CLAUDE.md b/CLAUDE.md index f5a6c85..90c9395 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ - # LearnKit AI @@ -53,12 +53,12 @@ schemas ← core ← react ← apps/web ## Key invariants - `generateLearningPath()` is pure: no async, no network, no side effects -- `LearningPathInput` shape is the public API contract — do not change without a major version bump -- `packages/react` has no Tailwind dependency — CSS custom properties only -- All TypeScript types in packages are inferred from Zod schemas — no manual type duplication -- The demo at /demo runs entirely on @learnkit-ai/core — zero backend required +- `LearningPathInput` shape is the public API contract - do not change without a major version bump +- `packages/react` has no Tailwind dependency - CSS custom properties only +- All TypeScript types in packages are inferred from Zod schemas - no manual type duplication +- The demo at /demo runs entirely on @learnkit-ai/core - zero backend required -## Public API — @learnkit-ai/core +## Public API - @learnkit-ai/core ```typescript function generateLearningPath(input: LearningPathInput): LearningPath @@ -79,7 +79,7 @@ Input type (LearningPathInput): } ``` -## Component API — @learnkit-ai/react +## Component API - @learnkit-ai/react ```tsx @@ -114,16 +114,16 @@ no compliance badges (SOC 2, HIPAA, GDPR), no user or revenue metrics. ## Rules - No `any` without an explanatory comment -- Named exports only from packages — no `export default` in packages/ +- Named exports only from packages - no `export default` in packages/ - Co-locate tests: `foo.ts` → `__tests__/foo.test.ts` -- No mocking internal packages in tests — only mock at system boundaries +- No mocking internal packages in tests - only mock at system boundaries - All Zod schemas live in packages/schemas -- Stage files by name — never `git add .` or `git add -A` +- Stage files by name - never `git add .` or `git add -A` - Commit messages: imperative mood, no AI co-author lines, no file lists ## Do not touch - `pnpm-lock.yaml` -- `packages/schemas/src/index.ts` types once stabilized — public API contract +- `packages/schemas/src/index.ts` types once stabilized - public API contract - `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.windsurfrules`, `GEMINI.md`, `CONVENTIONS.md` - — generated from `.agent/agent.md`; edit there and re-sync + - generated from `.agent/agent.md`; edit there and re-sync diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c5100f1..9e79f30 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ Open [`http://localhost:3000`](http://localhost:3000) to see the marketing site, ## What we welcome - **Tool tracks.** Add a new tool to `packages/core/src/tools.ts` with a curriculum template in `packages/core/src/generate.ts`. -- **Lesson improvements.** Edit `packages/core/src/generate.ts` — make the lessons sharper, more honest, more useful for the work people actually do. +- **Lesson improvements.** Edit `packages/core/src/generate.ts` - make the lessons sharper, more honest, more useful for the work people actually do. - **Themes for ``.** Add a new theme to `packages/react/src/LearningPath.tsx`. - **Components.** Extend `@learnkit-ai/react` with new primitives that fit the warm-academic + modern-product feel. - **Documentation.** Both the README and inline JSDoc. @@ -40,15 +40,15 @@ Open [`http://localhost:3000`](http://localhost:3000) to see the marketing site, pnpm test pnpm lint ``` -5. **Open a PR.** Keep the description short and concrete — what changed and why. Link the issue. +5. **Open a PR.** Keep the description short and concrete - what changed and why. Link the issue. 6. **Be patient and kind in review.** We will be. ## Code style - **TypeScript strict mode.** No `any` without a comment explaining why. -- **Named exports only** from packages — no `export default`. -- **Zod schemas live in `packages/schemas`.** Types in packages are inferred from those schemas — no manual type duplication. -- **No mocking internal packages** in tests — only mock at system boundaries. +- **Named exports only** from packages - no `export default`. +- **Zod schemas live in `packages/schemas`.** Types in packages are inferred from those schemas - no manual type duplication. +- **No mocking internal packages** in tests - only mock at system boundaries. - **No comments that describe what the code does.** Only comments that explain *why* a non-obvious choice was made. - **Imperative commit messages**, no AI co-author trailers, no file lists in commit bodies. diff --git a/README.md b/README.md index bbd5ab5..d98bad5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # LearnKit AI > The open-source AI workbench for teams that ship. -> Generate personalized, role-aware learning paths for Claude, Cursor, ChatGPT and 40+ tools — and embed them in your product in 3 lines. +> Generate personalized, role-aware learning paths for Claude, Cursor, ChatGPT and 40+ tools - and embed them in your product in 3 lines. [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-c8472a.svg)](LICENSE) [![TypeScript](https://img.shields.io/badge/TypeScript-strict-2c5f8d.svg)](https://www.typescriptlang.org/) @@ -9,7 +9,7 @@ [![CI](https://github.com/learnkit-ai/learnkit/actions/workflows/ci.yml/badge.svg)](https://github.com/learnkit-ai/learnkit/actions/workflows/ci.yml) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-6b8f6e.svg)](CONTRIBUTING.md) -Most enterprise AI training is a video library nobody finishes. LearnKit AI is project-based: every lesson ends with a real prompt, agent, or workflow your team can ship that Friday — reviewed by the AI Guide. +Most enterprise AI training is a video library nobody finishes. LearnKit AI is project-based: every lesson ends with a real prompt, agent, or workflow your team can ship that Friday - reviewed by the AI Guide. ```bash pnpm add @learnkit-ai/core @learnkit-ai/react @@ -28,7 +28,7 @@ import { LearningPath } from '@learnkit-ai/react'; />; ``` -That renders a four-week, twelve-lesson curriculum tuned to that role + stack + goal. No backend, no LLM call, no API key. The engine is deterministic — the same input always produces the same path. +That renders a four-week, twelve-lesson curriculum tuned to that role + stack + goal. No backend, no LLM call, no API key. The engine is deterministic - the same input always produces the same path. --- @@ -44,14 +44,14 @@ That renders a four-week, twelve-lesson curriculum tuned to that role + stack + ## Features -- **`generateLearningPath()`** — pure function, no network, fully deterministic -- **``** — drop-in React component with three built-in themes (warm, midnight, technical) -- **``** — primitive for custom layouts -- **``** — embeddable AI tutor avatar + tip card -- **`useLearnKit(input)`** — React hook for headless use -- **Zod schemas** for everything — strict input validation and inferred types -- **No Tailwind dependency** in `@learnkit-ai/react` — CSS custom properties only, drops into any host theme -- **Apache-2.0** — fork it, ship it +- **`generateLearningPath()`** - pure function, no network, fully deterministic +- **``** - drop-in React component with three built-in themes (warm, midnight, technical) +- **``** - primitive for custom layouts +- **``** - embeddable AI tutor avatar + tip card +- **`useLearnKit(input)`** - React hook for headless use +- **Zod schemas** for everything - strict input validation and inferred types +- **No Tailwind dependency** in `@learnkit-ai/react` - CSS custom properties only, drops into any host theme +- **Apache-2.0** - fork it, ship it ## Quick start @@ -180,11 +180,11 @@ pnpm lint # lint all workspaces Issues, PRs, and discussions are welcome. Some great first contributions: -- **Add a tool** — pick a tool from the [tracker issue](https://github.com/learnkit-ai/learnkit/issues), open a PR to `packages/core/src/tools.ts` with a curriculum template +- **Add a tool** - pick a tool from the [tracker issue](https://github.com/learnkit-ai/learnkit/issues), open a PR to `packages/core/src/tools.ts` with a curriculum template - **Improve a lesson template** in `packages/core/src/generate.ts` - **Add a theme** to `` in `packages/react/src/LearningPath.tsx` - **Write a blog post** in `apps/web/src/lib/blog-posts.ts` -- **Translate the UI** — locales are wide open +- **Translate the UI** - locales are wide open See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community expectations. Security issues: please follow [SECURITY.md](SECURITY.md). @@ -196,11 +196,11 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [CODE_OF_CONDUCT.md](C - [ ] v0.4: 40-tool curriculum library (currently 8) - [ ] v1: stable public API, full docs site, deployment recipes -Nothing on the roadmap will be paid-only. The license is Apache-2.0 for the long haul — fork it, ship it, run it without us. +Nothing on the roadmap will be paid-only. The license is Apache-2.0 for the long haul - fork it, ship it, run it without us. ## License -[Apache-2.0](LICENSE). Use it, fork it, ship it — including commercially. +[Apache-2.0](LICENSE). Use it, fork it, ship it - including commercially. ## Acknowledgements diff --git a/ROADMAP.md b/ROADMAP.md index 9263b54..7a4e023 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,17 +1,17 @@ -# LearnKit AI — Roadmap +# LearnKit AI - Roadmap LearnKit AI is an open-source TypeScript engine for embedding role-aware AI learning paths in any product. Apache-2.0, no hosted SaaS, no paid tier. --- -## v0 — Foundation ✅ +## v0 - Foundation ✅ Core engine, React component, and public website shipped. ### Packages -- [x] `@learnkit-ai/schemas` — Zod schemas and inferred TypeScript types -- [x] `@learnkit-ai/core` — `generateLearningPath()`, pure deterministic, no LLM -- [x] `@learnkit-ai/react` — ``, ``, ``, `useLearnKit()` +- [x] `@learnkit-ai/schemas` - Zod schemas and inferred TypeScript types +- [x] `@learnkit-ai/core` - `generateLearningPath()`, pure deterministic, no LLM +- [x] `@learnkit-ai/react` - ``, ``, ``, `useLearnKit()` ### Content - [x] Role-specific 4-week curricula: Product Manager, Software Engineer, Designer, Data Analyst, Marketer, Founder, Operations, Researcher @@ -24,7 +24,7 @@ Core engine, React component, and public website shipped. - [x] Docs (`/docs`) with full API reference - [x] `/roles/[slug]` and `/tools/[slug]` SEO pages - [x] `/teams` page (OSS integration guide) -- [x] Blog (`/blog`) — pedagogy and engineering posts +- [x] Blog (`/blog`) - pedagogy and engineering posts - [x] Custom 404, OG image, sitemap, robots.txt ### Infrastructure @@ -36,36 +36,36 @@ Core engine, React component, and public website shipped. --- -## v1 — Depth (in progress) +## v1 - Depth (in progress) ### Engine - [x] `companyContext` field personalises project lesson summaries (stack, pace, team-size hints) - [x] More supported tools: Windsurf, Replit, Linear, Figma AI, v0 (13 total) - [x] More roles: Sales, Customer Success, Finance (11 total) -- [x] `generateLessonContent(lesson)` — returns full lesson body, exercises, and rubric -- [x] Lesson prerequisite graph — sequential `prerequisiteIds[]` on each lesson; ProgressTracker locks accordingly -- [x] `computeProgress(path, completedIds)` — returns `LearningPathProgress` with completedCount, totalCount, percentComplete +- [x] `generateLessonContent(lesson)` - returns full lesson body, exercises, and rubric +- [x] Lesson prerequisite graph - sequential `prerequisiteIds[]` on each lesson; ProgressTracker locks accordingly +- [x] `computeProgress(path, completedIds)` - returns `LearningPathProgress` with completedCount, totalCount, percentComplete ### React package -- [x] `` component — persists lesson completion state to localStorage; prerequisite-aware lesson locking -- [x] `` — renders full lesson body, exercises, and rubric from `generateLessonContent()` +- [x] `` component - persists lesson completion state to localStorage; prerequisite-aware lesson locking +- [x] `` - renders full lesson body, exercises, and rubric from `generateLessonContent()` - [x] `light` theme variant (in addition to `warm`, `midnight`, `technical`) - [x] Headless mode: `renderItem` render-prop on `LearningPath` and `ProgressTracker` ### Web -- [x] `/changelog` page — versioned release notes -- [x] `/compare/[slug]` pages — Claude vs ChatGPT, Cursor vs Copilot, Windsurf vs Cursor, and more -- [x] `/guides/[slug]` — Next.js integration, theming, CLI, generateLessonContent guides +- [x] `/changelog` page - versioned release notes +- [x] `/compare/[slug]` pages - Claude vs ChatGPT, Cursor vs Copilot, Windsurf vs Cursor, and more +- [x] `/guides/[slug]` - Next.js integration, theming, CLI, generateLessonContent guides - [x] `opengraph-image` for `/roles/[slug]` and `/tools/[slug]` pages ### Developer experience -- [x] `@learnkit-ai/cli` — `npx @learnkit-ai/cli generate` outputs a JSON learning path -- [ ] VS Code extension — sidebar learning path panel -- [x] Storybook for `@learnkit-ai/react` components — LessonCard, LearningPath, LessonDetail, ProgressTracker with all themes +- [x] `@learnkit-ai/cli` - `npx @learnkit-ai/cli generate` outputs a JSON learning path +- [ ] VS Code extension - sidebar learning path panel +- [x] Storybook for `@learnkit-ai/react` components - LessonCard, LearningPath, LessonDetail, ProgressTracker with all themes --- -## v2 — Scale (exploratory) +## v2 - Scale (exploratory) These are directions worth exploring, not commitments. @@ -84,7 +84,7 @@ These are directions worth exploring, not commitments. - Telemetry, analytics, or phone-home behaviour - Team dashboards, HR reporting, SSO, or SCIM -The engine is a library. Embedding it in a SaaS product is the point — but that SaaS is yours to build, not ours to host. +The engine is a library. Embedding it in a SaaS product is the point - but that SaaS is yours to build, not ours to host. --- diff --git a/apps/web/src/app/blog/page.tsx b/apps/web/src/app/blog/page.tsx index 3f0aa0c..b7f2990 100644 --- a/apps/web/src/app/blog/page.tsx +++ b/apps/web/src/app/blog/page.tsx @@ -7,14 +7,14 @@ import { BLOG_POSTS } from '@/lib/blog-posts'; import { SITE_URL } from '@/lib/seo-data'; export const metadata: Metadata = { - title: 'Blog — LearnKit AI', + title: 'Blog - LearnKit AI', description: 'Writing on AI pedagogy, engineering, and the LearnKit AI roadmap. Open-source. Published from the team building the workbench.', alternates: { canonical: '/blog' }, openGraph: { type: 'website', url: `${SITE_URL}/blog`, - title: 'LearnKit AI Blog — AI pedagogy and engineering', + title: 'LearnKit AI Blog - AI pedagogy and engineering', description: 'Writing on AI pedagogy, engineering, and the LearnKit AI roadmap.', }, diff --git a/apps/web/src/app/docs/page.tsx b/apps/web/src/app/docs/page.tsx index 4f8913c..5df4cf1 100644 --- a/apps/web/src/app/docs/page.tsx +++ b/apps/web/src/app/docs/page.tsx @@ -7,14 +7,14 @@ import { DocsSidebar } from '@/components/docs/DocsSidebar'; import { SITE_URL } from '@/lib/seo-data'; export const metadata: Metadata = { - title: 'Docs — LearnKit AI', + title: 'Docs - LearnKit AI', description: 'API reference and quickstart for @learnkit-ai/core and @learnkit-ai/react. Install, generate a learning path, and render it in three steps.', alternates: { canonical: '/docs' }, openGraph: { type: 'website', url: `${SITE_URL}/docs`, - title: 'LearnKit AI Docs — API reference and quickstart', + title: 'LearnKit AI Docs - API reference and quickstart', description: 'API reference and quickstart for @learnkit-ai/core and @learnkit-ai/react.', }, @@ -284,7 +284,7 @@ isRoleSupported('Astronaut'); // false`}

- Headless hook. Returns {`{ path, error }`}. Build your own UI on top — + Headless hook. Returns {`{ path, error }`}. Build your own UI on top - the hook handles input validation and memoizes the result.

{`import { useLearnKit } from '@learnkit-ai/react'; @@ -314,7 +314,7 @@ function MyCustomPath() { @learnkit-ai/schemas. No manual type duplication. Import from either the schemas package directly or from your consuming package.

- {`// LearningPathInput — the contract. Will not change without a major version bump. + {`// LearningPathInput - the contract. Will not change without a major version bump. type LearningPathInput = { role: string // from getSupportedRoles() tools: string[] // from getSupportedTools() @@ -323,7 +323,7 @@ type LearningPathInput = { companyContext?: string // optional, max 500 chars } -// LearningPath — the output +// LearningPath - the output type LearningPath = { id: string input: LearningPathInput @@ -347,10 +347,10 @@ type Lesson = { {/* Theming */}

- @learnkit-ai/react uses CSS custom properties only — no Tailwind. + @learnkit-ai/react uses CSS custom properties only - no Tailwind. Three built-in themes ship out of the box. Override any token in your own CSS.

- {`/* Built-in themes — pass as the theme prop */ + {`/* Built-in themes - pass as the theme prop */ theme="warm" // warm paper, terracotta accent (default) theme="midnight" // dark ink, blue accent theme="technical" // neutral gray, green accent @@ -402,7 +402,7 @@ pnpm dev`} > CONTRIBUTING.md {' '} - for the commit and PR conventions. Apache-2.0 — use it, fork it, ship it. + for the commit and PR conventions. Apache-2.0 - use it, fork it, ship it.

diff --git a/apps/web/src/app/example/layout.tsx b/apps/web/src/app/example/layout.tsx index 89088e1..ef6114c 100644 --- a/apps/web/src/app/example/layout.tsx +++ b/apps/web/src/app/example/layout.tsx @@ -3,7 +3,7 @@ import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'Live example · LearnKit AI', description: - 'See render a real AI learning path in your browser — no backend, no LLM, fully deterministic.', + 'See render a real AI learning path in your browser - no backend, no LLM, fully deterministic.', }; export default function ExampleLayout({ children }: { children: React.ReactNode }) { diff --git a/apps/web/src/app/example/page.tsx b/apps/web/src/app/example/page.tsx index 1e537d3..f0a902b 100644 --- a/apps/web/src/app/example/page.tsx +++ b/apps/web/src/app/example/page.tsx @@ -70,7 +70,7 @@ export default function ExamplePage() { > @learnkit-ai/react {' '} - component you can install from npm. No backend, no LLM call — the path is generated + component you can install from npm. No backend, no LLM call - the path is generated deterministically by{' '}