@cogito.ai/cli 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/registry.json +3 -13
- package/dist/templates/web-nextjs/.github/copilot-instructions.md +36 -14
- package/dist/templates/web-nextjs/AGENTS.md +14 -11
- package/dist/templates/web-nextjs/README.md +37 -30
- package/dist/templates/web-nextjs/apps/docs/.source/browser.ts +12 -0
- package/dist/templates/web-nextjs/apps/docs/.source/dynamic.ts +8 -0
- package/dist/templates/web-nextjs/apps/docs/.source/server.ts +19 -0
- package/dist/templates/web-nextjs/apps/docs/.source/source.config.mjs +10 -0
- package/dist/templates/web-nextjs/apps/docs/app/(home)/page.tsx +5 -0
- package/dist/templates/web-nextjs/apps/docs/app/api/search/route.ts +4 -0
- package/dist/templates/web-nextjs/apps/docs/app/docs/[[...slug]]/page.tsx +41 -0
- package/dist/templates/web-nextjs/apps/docs/app/docs/layout.tsx +14 -0
- package/dist/templates/web-nextjs/apps/docs/app/global.css +3 -0
- package/dist/templates/web-nextjs/apps/docs/app/layout.tsx +13 -0
- package/dist/templates/web-nextjs/apps/docs/app/llms-full.txt/route.ts +11 -0
- package/dist/templates/web-nextjs/apps/docs/app/llms.txt/route.ts +8 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/changelog/.gitkeep +2 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/changelog/index.mdx +9 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/changelog/meta.json +3 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/decisions/.gitkeep +0 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/decisions/meta.json +4 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/features/hello.mdx +29 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/features/meta.json +4 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/index.mdx +6 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/meta.json +4 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/roadmap/.gitkeep +2 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/roadmap/index.mdx +29 -0
- package/dist/templates/web-nextjs/apps/docs/content/docs/roadmap/meta.json +3 -0
- package/dist/templates/web-nextjs/apps/docs/eslint.config.js +10 -0
- package/dist/templates/web-nextjs/apps/docs/lib/source.ts +7 -0
- package/dist/templates/web-nextjs/apps/docs/next.config.ts +14 -0
- package/dist/templates/web-nextjs/apps/docs/package.json +38 -0
- package/dist/templates/web-nextjs/apps/docs/postcss.config.mjs +8 -0
- package/dist/templates/web-nextjs/apps/docs/source.config.ts +7 -0
- package/dist/templates/web-nextjs/apps/docs/tsconfig.json +26 -0
- package/dist/templates/web-nextjs/apps/web/.github/copilot-instructions.md +65 -0
- package/dist/templates/web-nextjs/apps/web/next-env.d.ts +6 -0
- package/dist/templates/web-nextjs/{next.config.ts → apps/web/next.config.ts} +6 -1
- package/dist/templates/web-nextjs/apps/web/package.json +33 -0
- package/dist/templates/web-nextjs/openspec/config.yaml +20 -7
- package/dist/templates/web-nextjs/openspec/roadmap.yaml +31 -0
- package/dist/templates/web-nextjs/package.json +10 -21
- package/dist/templates/web-nextjs/packages/eslint-config/CHANGELOG.md +7 -0
- package/dist/templates/web-nextjs/packages/eslint-config/base.js +34 -0
- package/dist/templates/web-nextjs/packages/eslint-config/features.js +86 -0
- package/dist/templates/web-nextjs/packages/eslint-config/next.js +24 -0
- package/dist/templates/web-nextjs/packages/eslint-config/package.json +22 -0
- package/dist/templates/web-nextjs/packages/openspec-docs-sync/package.json +24 -0
- package/dist/templates/web-nextjs/packages/openspec-docs-sync/src/index.ts +290 -0
- package/dist/templates/web-nextjs/packages/openspec-docs-sync/tsconfig.json +17 -0
- package/dist/templates/web-nextjs/packages/tsconfig/CHANGELOG.md +7 -0
- package/dist/templates/web-nextjs/packages/tsconfig/base.json +11 -0
- package/dist/templates/web-nextjs/packages/tsconfig/package.json +10 -0
- package/dist/templates/web-nextjs/pnpm-lock.yaml +6722 -0
- package/dist/templates/web-nextjs/pnpm-workspace.yaml +3 -0
- package/dist/templates/web-nextjs/roadmap.yaml +31 -0
- package/dist/templates/web-nextjs/turbo.json +18 -0
- package/package.json +1 -1
- /package/dist/templates/web-nextjs/{next-env.d.ts → apps/docs/next-env.d.ts} +0 -0
- /package/dist/templates/web-nextjs/{eslint.config.js → apps/web/eslint.config.js} +0 -0
- /package/dist/templates/web-nextjs/{messages → apps/web/messages}/en.json +0 -0
- /package/dist/templates/web-nextjs/{messages → apps/web/messages}/zh.json +0 -0
- /package/dist/templates/web-nextjs/{middleware.ts → apps/web/middleware.ts} +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/app/[locale]/globals.css +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/app/[locale]/hello/page.tsx +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/app/[locale]/layout.tsx +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/app/[locale]/page.tsx +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/core/repositories/.gitkeep +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/core/repositories/IGreetingRepository.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/core/types/.gitkeep +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/core/types/greeting.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/features/_experiments/.gitkeep +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/features/hello/__contract__.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/features/hello/hello.test.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/features/hello/index.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/features/hello/service.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/i18n/request.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/infra/db/.gitkeep +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/infra/db/SupabaseGreetingRepository.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/infra/db/client.ts +0 -0
- /package/dist/templates/web-nextjs/{src → apps/web/src}/infra/db/schema.ts +0 -0
- /package/dist/templates/web-nextjs/{tailwind.config.ts → apps/web/tailwind.config.ts} +0 -0
- /package/dist/templates/web-nextjs/{tsconfig.json → apps/web/tsconfig.json} +0 -0
- /package/dist/templates/web-nextjs/{vitest.config.ts → apps/web/vitest.config.ts} +0 -0
package/dist/registry.json
CHANGED
|
@@ -4,22 +4,12 @@
|
|
|
4
4
|
{
|
|
5
5
|
"id": "web-nextjs",
|
|
6
6
|
"name": "@cogito.ai/template-web-nextjs",
|
|
7
|
-
"description": "Full-stack Next.js 16 starter with Supabase, next-intl, Tailwind CSS and
|
|
7
|
+
"description": "Full-stack Next.js 16 monorepo starter with Supabase, next-intl, Tailwind CSS, Vitest and built-in Fumadocs docs site",
|
|
8
8
|
"minCliVersion": "0.1.0",
|
|
9
9
|
"source": "templates/web-nextjs",
|
|
10
10
|
"resolvedDependencies": {
|
|
11
|
-
"@
|
|
12
|
-
"
|
|
13
|
-
"next-intl": "^4.13.0",
|
|
14
|
-
"react": "19",
|
|
15
|
-
"react-dom": "19",
|
|
16
|
-
"@vitejs/plugin-react": "^6.0.2",
|
|
17
|
-
"tailwindcss": "^4.3.0",
|
|
18
|
-
"typescript": "^6.0.3",
|
|
19
|
-
"vitest": "^4.1.8",
|
|
20
|
-
"@cogito.ai/eslint-config": "^0.2.0",
|
|
21
|
-
"@cogito.ai/tsconfig": "^0.2.0",
|
|
22
|
-
"@fission-ai/openspec": "^1.3.1"
|
|
11
|
+
"@fission-ai/openspec": "^1.3.1",
|
|
12
|
+
"turbo": "latest"
|
|
23
13
|
}
|
|
24
14
|
}
|
|
25
15
|
]
|
|
@@ -2,25 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
> Applies to: GitHub Copilot (chat + completions) in any project generated from this template.
|
|
4
4
|
|
|
5
|
+
## Monorepo Structure
|
|
6
|
+
|
|
7
|
+
This project is a turborepo + pnpm monorepo with two applications:
|
|
8
|
+
|
|
9
|
+
| Directory | Purpose |
|
|
10
|
+
| ------------ | -------------------------------------------------------------------- |
|
|
11
|
+
| `apps/web/` | Main Next.js 16 application (four-layer contract, features, i18n) |
|
|
12
|
+
| `apps/docs/` | Fumadocs documentation site (features, decisions, changelog, roadmap)|
|
|
13
|
+
| `packages/` | Shared tooling packages (eslint-config, tsconfig) |
|
|
14
|
+
|
|
15
|
+
Run all commands from the monorepo root: `pnpm build`, `pnpm lint`, `pnpm test`, `pnpm check-types`.
|
|
16
|
+
|
|
5
17
|
## Directory Contract
|
|
6
18
|
|
|
7
|
-
This project enforces a four-layer directory contract
|
|
19
|
+
This project enforces a four-layer directory contract inside `apps/web/`. **Before placing any code**, confirm which layer it belongs to:
|
|
8
20
|
|
|
9
|
-
| Layer | Path
|
|
10
|
-
| --------------- |
|
|
11
|
-
| **core** | `src/core/` | Stable domain layer — types, repository interfaces, pure logic | No framework imports, no DB clients, read-only |
|
|
12
|
-
| **features** | `src/features/` | AI coding zone — business features | Must have `__contract__.ts`; no direct DB access; no cross-feature imports |
|
|
13
|
-
| **infra** | `src/infra/` | Infrastructure — Supabase clients, third-party SDKs | Requires approval; only `core/repositories` implementations live here |
|
|
14
|
-
| **experiments** | `src/features/_experiments/` | Sandbox | Never imported by non-experimental features |
|
|
21
|
+
| Layer | Path | Purpose | Rules |
|
|
22
|
+
| --------------- | ------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
23
|
+
| **core** | `apps/web/src/core/` | Stable domain layer — types, repository interfaces, pure logic | No framework imports, no DB clients, read-only |
|
|
24
|
+
| **features** | `apps/web/src/features/` | AI coding zone — business features | Must have `__contract__.ts`; no direct DB access; no cross-feature imports |
|
|
25
|
+
| **infra** | `apps/web/src/infra/` | Infrastructure — Supabase clients, third-party SDKs | Requires approval; only `core/repositories` implementations live here |
|
|
26
|
+
| **experiments** | `apps/web/src/features/_experiments/` | Sandbox | Never imported by non-experimental features |
|
|
15
27
|
|
|
16
28
|
## Layer 2 Architecture Rules (error-level, enforced by ESLint)
|
|
17
29
|
|
|
18
|
-
Four rules are enforced at `error` severity in `src/features/**`. Violations fail `pnpm lint`.
|
|
30
|
+
Four rules are enforced at `error` severity in `apps/web/src/features/**`. Violations fail `pnpm lint`.
|
|
19
31
|
|
|
20
|
-
1. **`no-direct-db-in-features`** — Features must not import from `infra/db`. Use repository interfaces from `src/core/repositories/` instead.
|
|
32
|
+
1. **`no-direct-db-in-features`** — Features must not import from `infra/db`. Use repository interfaces from `apps/web/src/core/repositories/` instead.
|
|
21
33
|
2. **`require-feature-contract`** — Every feature subdirectory must contain `__contract__.ts` declaring its public API boundary.
|
|
22
34
|
3. **`no-cross-feature`** — Features must not directly import from sibling feature internals. Import through the feature's `index.ts` only.
|
|
23
|
-
4. **`no-core-mutation`** — `src/core/` is read-only. Features and infra must not modify core types or interfaces in-place.
|
|
35
|
+
4. **`no-core-mutation`** — `apps/web/src/core/` is read-only. Features and infra must not modify core types or interfaces in-place.
|
|
36
|
+
|
|
37
|
+
## Docs Co-evolution
|
|
38
|
+
|
|
39
|
+
Documentation lives alongside the application and grows with it:
|
|
40
|
+
|
|
41
|
+
- **Feature docs**: When adding a new feature, create `apps/docs/content/docs/features/<name>.mdx` documenting its purpose, API, and architecture notes.
|
|
42
|
+
- **Architecture decisions**: Record significant decisions in `apps/docs/content/docs/decisions/<adr-id>.mdx` (e.g., `001-database-choice.mdx`).
|
|
43
|
+
- **Changelog & Roadmap**: After archiving a change in `openspec/`, run `pnpm docs:sync` from the monorepo root to auto-generate changelog and roadmap pages in `apps/docs/`.
|
|
24
44
|
|
|
25
45
|
## Hard Rules
|
|
26
46
|
|
|
@@ -28,16 +48,18 @@ Four rules are enforced at `error` severity in `src/features/**`. Violations fai
|
|
|
28
48
|
2. **TypeScript strict** — `strict: true` enforced. No `any`, no `// @ts-ignore` without explanation.
|
|
29
49
|
3. **Conventional commits** — `type(scope): summary` format required.
|
|
30
50
|
4. **pnpm only** — Do not use `npm install` or `yarn`. Always `pnpm add`.
|
|
31
|
-
5. **ESLint config** — Architecture rules come from `packages/eslint-config/features.js
|
|
51
|
+
5. **ESLint config** — Architecture rules come from `packages/eslint-config/features.js`.
|
|
32
52
|
|
|
33
53
|
## Feature Development Pattern
|
|
34
54
|
|
|
35
|
-
When adding a new feature `src/features/<name>/`:
|
|
55
|
+
When adding a new feature `apps/web/src/features/<name>/`:
|
|
36
56
|
|
|
37
57
|
1. Create `__contract__.ts` first — declare input/output types and public API.
|
|
38
58
|
2. Create `service.ts` — pure business logic, no side effects.
|
|
39
59
|
3. Create `index.ts` — only export what `__contract__.ts` declares.
|
|
40
60
|
4. Create `<name>.test.ts` — Vitest unit tests.
|
|
41
|
-
5. Create page/component in `src/app/[locale]/` to consume the feature.
|
|
61
|
+
5. Create page/component in `apps/web/src/app/[locale]/` to consume the feature.
|
|
62
|
+
6. Create `apps/docs/content/docs/features/<name>.mdx` — feature documentation.
|
|
63
|
+
|
|
64
|
+
Reference implementation: `apps/web/src/features/hello/`.
|
|
42
65
|
|
|
43
|
-
Reference implementation: `src/features/hello/`.
|
|
@@ -11,36 +11,39 @@
|
|
|
11
11
|
|
|
12
12
|
### May execute autonomously
|
|
13
13
|
|
|
14
|
-
- `pnpm install`, `pnpm build`, `pnpm check-types`, `pnpm lint`, `pnpm test`
|
|
14
|
+
- `pnpm install`, `pnpm build`, `pnpm check-types`, `pnpm lint`, `pnpm test`, `pnpm docs:sync`
|
|
15
15
|
- Creating / editing files within the current task scope
|
|
16
|
-
- Adding new features inside `src/features/` (following the contract pattern)
|
|
17
|
-
- Adding repository interfaces to `src/core/repositories/`
|
|
18
|
-
- Updating translations in `messages/`
|
|
19
|
-
- Writing or updating tests in `src/**/*.test.ts`
|
|
16
|
+
- Adding new features inside `apps/web/src/features/` (following the contract pattern)
|
|
17
|
+
- Adding repository interfaces to `apps/web/src/core/repositories/`
|
|
18
|
+
- Updating translations in `apps/web/messages/`
|
|
19
|
+
- Writing or updating tests in `apps/web/src/**/*.test.ts`
|
|
20
|
+
- Creating / updating MDX documentation in `apps/docs/content/` (feature docs, ADRs)
|
|
20
21
|
- Running `openspec` CLI commands (read-only: `list`, `status`, `instructions`, `validate`)
|
|
21
22
|
|
|
22
23
|
### Must pause and confirm
|
|
23
24
|
|
|
24
25
|
- Any `git push`, `git push --force`, or publishing to a registry
|
|
25
26
|
- Deleting files (including tracked files)
|
|
26
|
-
- Adding new **top-level** directories outside the
|
|
27
|
-
- Adding new
|
|
27
|
+
- Adding new **top-level** directories outside the monorepo contract (`apps/`, `packages/`)
|
|
28
|
+
- Adding new directories outside the four-layer contract inside `apps/web/src/` (`core/`, `features/`, `infra/`, `app/`)
|
|
29
|
+
- Adding new `dependencies` or `devDependencies` to any `package.json`
|
|
28
30
|
- Any change to `openspec/config.yaml`
|
|
29
|
-
- Modifying `middleware.ts` (affects routing for all locales)
|
|
31
|
+
- Modifying `apps/web/middleware.ts` (affects routing for all locales)
|
|
30
32
|
|
|
31
33
|
### Prohibited
|
|
32
34
|
|
|
33
35
|
- Writing real secrets, API keys, or credentials anywhere
|
|
34
36
|
- Running `rm -rf` on tracked directories
|
|
35
37
|
- Bypassing git hooks with `--no-verify`
|
|
36
|
-
- Importing from `src/infra/db/` inside `src/features/**` (violates Layer 2 rules)
|
|
38
|
+
- Importing from `apps/web/src/infra/db/` inside `apps/web/src/features/**` (violates Layer 2 rules)
|
|
37
39
|
- Creating features without `__contract__.ts` (violates require-feature-contract)
|
|
38
40
|
|
|
39
41
|
## Acceptance Criteria (before marking a task done)
|
|
40
42
|
|
|
41
|
-
1. `pnpm lint` — exits 0, no Layer 2 violations in `src/features/`
|
|
43
|
+
1. `pnpm lint` — exits 0, no Layer 2 violations in `apps/web/src/features/`
|
|
42
44
|
2. ESLint ignores build artifacts (at minimum `.next/**`) so generated files are never linted.
|
|
43
45
|
3. `pnpm build && pnpm lint` — both exit 0 (lint remains stable after a build).
|
|
44
46
|
4. `pnpm test` — all unit tests pass
|
|
45
|
-
5. `pnpm check-types` — TypeScript strict mode, no errors
|
|
47
|
+
5. `pnpm check-types` — TypeScript strict mode, no errors in `apps/web` and `apps/docs`
|
|
46
48
|
6. New features include `__contract__.ts`, `index.ts`, and at least one test
|
|
49
|
+
7. New features have a corresponding `apps/docs/content/docs/features/<name>.mdx`
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> Generated from the [AgentDock](https://github.com/CogitoTech/agentdock) `web-nextjs` template.
|
|
4
4
|
|
|
5
|
-
Full-stack Next.js 16 starter with Supabase, i18n, Tailwind CSS
|
|
5
|
+
Full-stack Next.js 16 monorepo starter with Supabase, i18n, Tailwind CSS, strict TypeScript,
|
|
6
|
+
and a built-in Fumadocs documentation site.
|
|
6
7
|
Designed for both human developers and AI coding agents.
|
|
7
8
|
|
|
8
9
|
## Tech Stack
|
|
@@ -18,20 +19,24 @@ Designed for both human developers and AI coding agents.
|
|
|
18
19
|
| Package manager | [pnpm](https://pnpm.io) ≥ 9 |
|
|
19
20
|
| Runtime | Node.js ≥ 18 |
|
|
20
21
|
| Governance | [OpenSpec](https://github.com/fission-ai/openspec) (`@fission-ai/openspec`) |
|
|
22
|
+
| Monorepo | [Turborepo](https://turbo.build/repo) + pnpm workspaces |
|
|
21
23
|
|
|
22
24
|
## Directory Structure
|
|
23
25
|
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
├──
|
|
27
|
-
├──
|
|
28
|
-
├──
|
|
29
|
-
│
|
|
30
|
-
├──
|
|
31
|
-
│
|
|
32
|
-
└── i18n/
|
|
33
|
-
messages/
|
|
34
|
-
|
|
26
|
+
```text
|
|
27
|
+
apps/
|
|
28
|
+
├── web/
|
|
29
|
+
│ ├── src/
|
|
30
|
+
│ │ ├── app/ # Next.js App Router — pages and layouts (per-locale)
|
|
31
|
+
│ │ ├── core/ # Domain types + repository interfaces (no framework deps)
|
|
32
|
+
│ │ ├── features/ # AI coding zone — one directory per feature
|
|
33
|
+
│ │ ├── infra/ # Supabase implementations (requires human review to edit)
|
|
34
|
+
│ │ └── i18n/ # next-intl request configuration
|
|
35
|
+
│ ├── messages/ # Translation files (en.json, zh.json)
|
|
36
|
+
│ └── middleware.ts # Locale routing guard + next-intl middleware
|
|
37
|
+
├── docs/ # Fumadocs site (features, decisions, changelog, roadmap)
|
|
38
|
+
packages/ # Shared tooling packages (eslint-config, tsconfig, docs sync)
|
|
39
|
+
openspec/ # Project governance — changes and specs
|
|
35
40
|
```
|
|
36
41
|
|
|
37
42
|
> **Four-layer contract** is enforced by ESLint Layer 2 rules.
|
|
@@ -72,48 +77,50 @@ Open `.env.local` and fill in your values:
|
|
|
72
77
|
pnpm dev
|
|
73
78
|
```
|
|
74
79
|
|
|
75
|
-
Open [http://localhost:3000](http://localhost:3000)
|
|
80
|
+
Open [http://localhost:3000](http://localhost:3000) for the app and
|
|
81
|
+
[http://localhost:3001](http://localhost:3001) for docs.
|
|
76
82
|
|
|
77
83
|
## Development
|
|
78
84
|
|
|
79
85
|
### Common commands
|
|
80
86
|
|
|
81
87
|
```bash
|
|
82
|
-
pnpm dev # Start dev
|
|
83
|
-
pnpm build #
|
|
84
|
-
pnpm
|
|
85
|
-
pnpm
|
|
86
|
-
pnpm check-types # TypeScript type check (no emit)
|
|
88
|
+
pnpm dev # Start all workspace dev tasks
|
|
89
|
+
pnpm build # Build all workspace packages/apps
|
|
90
|
+
pnpm test # Run tests (currently apps/web Vitest)
|
|
91
|
+
pnpm check-types # TypeScript check across apps/web and apps/docs
|
|
87
92
|
pnpm lint # ESLint (includes Layer 2 architectural rules)
|
|
93
|
+
pnpm docs:sync # Generate changelog/roadmap docs from openspec archive
|
|
88
94
|
```
|
|
89
95
|
|
|
90
96
|
### Adding a new feature
|
|
91
97
|
|
|
92
|
-
Features live in `src/features/`. Follow the reference implementation in `src/features/hello/`:
|
|
98
|
+
Features live in `apps/web/src/features/`. Follow the reference implementation in `apps/web/src/features/hello/`:
|
|
93
99
|
|
|
94
100
|
```
|
|
95
|
-
src/features/<your-feature>/
|
|
101
|
+
apps/web/src/features/<your-feature>/
|
|
96
102
|
├── __contract__.ts # Public API surface (required — export types and functions)
|
|
97
103
|
├── index.ts # Re-exports from __contract__.ts
|
|
98
104
|
└── *.test.ts # Vitest unit tests
|
|
99
105
|
```
|
|
100
106
|
|
|
101
107
|
Rules:
|
|
102
|
-
- Features import from `src/core/` (domain interfaces) — never from `src/infra/` directly.
|
|
108
|
+
- Features import from `apps/web/src/core/` (domain interfaces) — never from `apps/web/src/infra/` directly.
|
|
103
109
|
- Every feature directory **must** have `__contract__.ts` (ESLint enforces this).
|
|
104
|
-
- Add translations to `messages/en.json` and `messages/zh.json`.
|
|
110
|
+
- Add translations to `apps/web/messages/en.json` and `apps/web/messages/zh.json`.
|
|
105
111
|
|
|
106
112
|
### Adding a language
|
|
107
113
|
|
|
108
|
-
1. Add locale to `
|
|
109
|
-
2. Create `messages/<locale>.json` with translated keys.
|
|
114
|
+
1. Add locale to `apps/web/middleware.ts` routing config.
|
|
115
|
+
2. Create `apps/web/messages/<locale>.json` with translated keys.
|
|
116
|
+
3. Ensure `apps/web/src/i18n/request.ts` can load the new locale JSON.
|
|
110
117
|
|
|
111
118
|
### Running tests
|
|
112
119
|
|
|
113
120
|
```bash
|
|
114
121
|
pnpm test # Run all tests once
|
|
115
|
-
pnpm test --watch # Watch mode
|
|
116
|
-
pnpm test --coverage # With coverage report
|
|
122
|
+
pnpm --filter @cogito.ai/web test --watch # Watch mode
|
|
123
|
+
pnpm --filter @cogito.ai/web test --coverage # With coverage report
|
|
117
124
|
```
|
|
118
125
|
|
|
119
126
|
## Deployment
|
|
@@ -129,7 +136,7 @@ pnpm test --coverage # With coverage report
|
|
|
129
136
|
|
|
130
137
|
```bash
|
|
131
138
|
pnpm build
|
|
132
|
-
pnpm start
|
|
139
|
+
pnpm --filter @cogito.ai/web start
|
|
133
140
|
```
|
|
134
141
|
|
|
135
142
|
Ensure all `NEXT_PUBLIC_*` variables are set at **build time** (they are inlined by Next.js).
|
|
@@ -178,16 +185,16 @@ See `openspec/config.yaml` for project-specific governance rules.
|
|
|
178
185
|
A: The `@cogito.ai/tsconfig` and `@cogito.ai/eslint-config` packages must be published to npm before use. If you generated this project before the packages were published, run `pnpm install` again after they are live at [npmjs.com/@agentdock](https://www.npmjs.com/org/cogito.ai).
|
|
179
186
|
|
|
180
187
|
**Q: How do I add a new Supabase table?**
|
|
181
|
-
A: Create the table in the Supabase Dashboard, then add a repository interface to `src/core/repositories/` and implement it in `src/infra/db/`. Do not call Supabase directly from `src/features/` — use the interface.
|
|
188
|
+
A: Create the table in the Supabase Dashboard, then add a repository interface to `apps/web/src/core/repositories/` and implement it in `apps/web/src/infra/db/`. Do not call Supabase directly from `apps/web/src/features/` — use the interface.
|
|
182
189
|
|
|
183
190
|
**Q: How do I disable i18n and use a single language?**
|
|
184
|
-
A: Set a single locale in `
|
|
191
|
+
A: Set a single locale in `apps/web/middleware.ts` and simplify locale segment handling there. Keep `apps/web/messages/en.json` and remove unused locale files.
|
|
185
192
|
|
|
186
193
|
**Q: TypeScript is strict — how do I handle `!` assertions?**
|
|
187
194
|
A: Prefer explicit checks (`if (!value) throw new Error(...)`) over `!` assertions. If you must use one, add a comment explaining why the value is guaranteed non-null.
|
|
188
195
|
|
|
189
196
|
**Q: Can AI agents work in this project?**
|
|
190
|
-
A: Yes. See `AGENTS.md` for the autonomy boundary contract. AI agents may freely edit `src/features/` but must pause for human review before editing `src/infra/` or `middleware.ts`.
|
|
197
|
+
A: Yes. See `AGENTS.md` for the autonomy boundary contract. AI agents may freely edit `apps/web/src/features/` but must pause for human review before editing `apps/web/src/infra/` or `apps/web/middleware.ts`.
|
|
191
198
|
|
|
192
199
|
## Contributing
|
|
193
200
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { browser } from 'fumadocs-mdx/runtime/browser';
|
|
3
|
+
import type * as Config from '../source.config';
|
|
4
|
+
|
|
5
|
+
const create = browser<typeof Config, import("fumadocs-mdx/runtime/types").InternalTypeConfig & {
|
|
6
|
+
DocData: {
|
|
7
|
+
}
|
|
8
|
+
}>();
|
|
9
|
+
const browserCollections = {
|
|
10
|
+
docs: create.doc("docs", {"index.mdx": () => import("../content/docs/index.mdx?collection=docs"), "changelog/index.mdx": () => import("../content/docs/changelog/index.mdx?collection=docs"), "features/hello.mdx": () => import("../content/docs/features/hello.mdx?collection=docs"), "roadmap/index.mdx": () => import("../content/docs/roadmap/index.mdx?collection=docs"), }),
|
|
11
|
+
};
|
|
12
|
+
export default browserCollections;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { dynamic } from 'fumadocs-mdx/runtime/dynamic';
|
|
3
|
+
import * as Config from '../source.config';
|
|
4
|
+
|
|
5
|
+
const create = await dynamic<typeof Config, import("fumadocs-mdx/runtime/types").InternalTypeConfig & {
|
|
6
|
+
DocData: {
|
|
7
|
+
}
|
|
8
|
+
}>(Config, {"configPath":"source.config.ts","environment":"next","outDir":".source"}, {"doc":{"passthroughs":["extractedReferences"]}});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import * as __fd_glob_8 from "../content/docs/roadmap/index.mdx?collection=docs"
|
|
3
|
+
import * as __fd_glob_7 from "../content/docs/features/hello.mdx?collection=docs"
|
|
4
|
+
import * as __fd_glob_6 from "../content/docs/changelog/index.mdx?collection=docs"
|
|
5
|
+
import * as __fd_glob_5 from "../content/docs/index.mdx?collection=docs"
|
|
6
|
+
import { default as __fd_glob_4 } from "../content/docs/roadmap/meta.json?collection=docs"
|
|
7
|
+
import { default as __fd_glob_3 } from "../content/docs/features/meta.json?collection=docs"
|
|
8
|
+
import { default as __fd_glob_2 } from "../content/docs/decisions/meta.json?collection=docs"
|
|
9
|
+
import { default as __fd_glob_1 } from "../content/docs/changelog/meta.json?collection=docs"
|
|
10
|
+
import { default as __fd_glob_0 } from "../content/docs/meta.json?collection=docs"
|
|
11
|
+
import { server } from 'fumadocs-mdx/runtime/server';
|
|
12
|
+
import type * as Config from '../source.config';
|
|
13
|
+
|
|
14
|
+
const create = server<typeof Config, import("fumadocs-mdx/runtime/types").InternalTypeConfig & {
|
|
15
|
+
DocData: {
|
|
16
|
+
}
|
|
17
|
+
}>({"doc":{"passthroughs":["extractedReferences"]}});
|
|
18
|
+
|
|
19
|
+
export const docs = await create.docs("docs", "content/docs", {"meta.json": __fd_glob_0, "changelog/meta.json": __fd_glob_1, "decisions/meta.json": __fd_glob_2, "features/meta.json": __fd_glob_3, "roadmap/meta.json": __fd_glob_4, }, {"index.mdx": __fd_glob_5, "changelog/index.mdx": __fd_glob_6, "features/hello.mdx": __fd_glob_7, "roadmap/index.mdx": __fd_glob_8, });
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { source } from '@/lib/source'
|
|
2
|
+
import {
|
|
3
|
+
DocsBody,
|
|
4
|
+
DocsDescription,
|
|
5
|
+
DocsPage,
|
|
6
|
+
DocsTitle,
|
|
7
|
+
} from 'fumadocs-ui/layouts/docs/page'
|
|
8
|
+
import { notFound } from 'next/navigation'
|
|
9
|
+
|
|
10
|
+
export default async function Page(props: { params: Promise<{ slug?: string[] }> }) {
|
|
11
|
+
const params = await props.params
|
|
12
|
+
const page = source.getPage(params.slug)
|
|
13
|
+
if (!page) notFound()
|
|
14
|
+
|
|
15
|
+
const MDX = page.data.body
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<DocsPage toc={page.data.toc}>
|
|
19
|
+
<DocsTitle>{page.data.title}</DocsTitle>
|
|
20
|
+
<DocsDescription>{page.data.description}</DocsDescription>
|
|
21
|
+
<DocsBody>
|
|
22
|
+
<MDX />
|
|
23
|
+
</DocsBody>
|
|
24
|
+
</DocsPage>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function generateStaticParams() {
|
|
29
|
+
return source.generateParams()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function generateMetadata(props: { params: Promise<{ slug?: string[] }> }) {
|
|
33
|
+
const params = await props.params
|
|
34
|
+
const page = source.getPage(params.slug)
|
|
35
|
+
if (!page) notFound()
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
title: page.data.title,
|
|
39
|
+
description: page.data.description,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { source } from '@/lib/source'
|
|
2
|
+
import { DocsLayout } from 'fumadocs-ui/layouts/docs'
|
|
3
|
+
import type { ReactNode } from 'react'
|
|
4
|
+
|
|
5
|
+
export default function Layout({ children }: { children: ReactNode }) {
|
|
6
|
+
return (
|
|
7
|
+
<DocsLayout
|
|
8
|
+
tree={source.getPageTree()}
|
|
9
|
+
nav={{ title: 'Docs' }}
|
|
10
|
+
>
|
|
11
|
+
{children}
|
|
12
|
+
</DocsLayout>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RootProvider } from 'fumadocs-ui/provider/next'
|
|
2
|
+
import './global.css'
|
|
3
|
+
import type { ReactNode } from 'react'
|
|
4
|
+
|
|
5
|
+
export default function Layout({ children }: { children: ReactNode }) {
|
|
6
|
+
return (
|
|
7
|
+
<html lang="en" suppressHydrationWarning>
|
|
8
|
+
<body>
|
|
9
|
+
<RootProvider>{children}</RootProvider>
|
|
10
|
+
</body>
|
|
11
|
+
</html>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { source } from '@/lib/source'
|
|
2
|
+
|
|
3
|
+
export const revalidate = false
|
|
4
|
+
|
|
5
|
+
export async function GET() {
|
|
6
|
+
const pages = source.getPages()
|
|
7
|
+
const texts = await Promise.all(
|
|
8
|
+
pages.map(async (page) => `# ${page.data.title} (${page.url})\n\n${page.data.description ?? ''}`)
|
|
9
|
+
)
|
|
10
|
+
return new Response(texts.join('\n\n'))
|
|
11
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Hello Feature"
|
|
3
|
+
description: "Reference implementation of the feature contract pattern."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The `hello` feature demonstrates the four-layer directory contract in practice:
|
|
9
|
+
|
|
10
|
+
- `__contract__.ts` — declares input/output types and public API
|
|
11
|
+
- `service.ts` — pure business logic, no side effects
|
|
12
|
+
- `index.ts` — exports only what the contract declares
|
|
13
|
+
- `hello.test.ts` — Vitest unit tests
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { getGreeting } from '@/features/hello'
|
|
19
|
+
|
|
20
|
+
const result = getGreeting({ name: 'World' })
|
|
21
|
+
// { message: 'Hello, World!' }
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Architecture Notes
|
|
25
|
+
|
|
26
|
+
This feature follows Layer 2 rules:
|
|
27
|
+
- No direct database access (uses repository interfaces from `core/`)
|
|
28
|
+
- No cross-feature imports
|
|
29
|
+
- Contract-first design
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Roadmap"
|
|
3
|
+
description: "Current platform roadmap — four-bucket view (Now / Next / Later / Won't)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
{/* <!-- AUTO-GENERATED by openspec-docs-sync. Do not edit manually. --> */}
|
|
7
|
+
|
|
8
|
+
> Auto-generated from `roadmap.yaml`. To update, edit the YAML and re-run `pnpm docs:sync`.
|
|
9
|
+
|
|
10
|
+
## Now
|
|
11
|
+
|
|
12
|
+
- 🔄 **Web Next.js built-in suite (monorepo + docs + auth + payments)** `web-nextjs-builtin-suite`
|
|
13
|
+
Status: in-progress · Owner: @team
|
|
14
|
+
|
|
15
|
+
## Next
|
|
16
|
+
|
|
17
|
+
- 📋 **Add authentication feature (Supabase Auth)** `web-nextjs-auth`
|
|
18
|
+
Status: planned · Owner: @team
|
|
19
|
+
- 📋 **Add payments feature (Stripe)** `web-nextjs-payments`
|
|
20
|
+
Status: planned · Owner: @team
|
|
21
|
+
|
|
22
|
+
## Later
|
|
23
|
+
|
|
24
|
+
- 📋 **Add analytics feature** `web-nextjs-analytics`
|
|
25
|
+
Status: planned · Owner: @team
|
|
26
|
+
|
|
27
|
+
## Won't
|
|
28
|
+
|
|
29
|
+
_No items._
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createMDX } from 'fumadocs-mdx/next'
|
|
2
|
+
import type { NextConfig } from 'next'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
const withMDX = createMDX()
|
|
6
|
+
|
|
7
|
+
const config: NextConfig = {
|
|
8
|
+
reactStrictMode: true,
|
|
9
|
+
turbopack: {
|
|
10
|
+
root: path.resolve(process.cwd(), '../..'),
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default withMDX(config)
|