tillerhand 3.43.0 → 3.47.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/.claude/agents/board-chair.md +20 -20
- package/.claude/agents/code-reviewer.md +20 -20
- package/.claude/agents/council-advisor.md +14 -14
- package/.claude/agents/security-auditor.md +30 -30
- package/.claude/agents/test-writer.md +22 -22
- package/.claude/board/board-ai.md +25 -25
- package/.claude/board/board-api.md +25 -25
- package/.claude/board/board-architect.md +28 -28
- package/.claude/board/board-devops.md +25 -25
- package/.claude/board/board-mobile.md +25 -25
- package/.claude/board/board-performance.md +24 -24
- package/.claude/board/board-privacy.md +25 -25
- package/.claude/board/board-product.md +26 -26
- package/.claude/board/board-qa.md +28 -28
- package/.claude/board/board-ux.md +26 -26
- package/.claude/board/council.md +76 -76
- package/.claude/board/rules.md +61 -61
- package/.claude/claude-security-guidance.md +10 -10
- package/.claude/commands/adopt.md +70 -69
- package/.claude/commands/ask-mode.md +9 -9
- package/.claude/commands/board.md +15 -15
- package/.claude/commands/build.md +47 -47
- package/.claude/commands/dashboard.md +17 -17
- package/.claude/commands/design.md +31 -31
- package/.claude/commands/findings-all.md +14 -14
- package/.claude/commands/findings-business.md +7 -7
- package/.claude/commands/findings-legal.md +7 -7
- package/.claude/commands/findings-perf.md +7 -7
- package/.claude/commands/findings-security.md +9 -9
- package/.claude/commands/findings-tech.md +7 -7
- package/.claude/commands/findings-ux.md +7 -7
- package/.claude/commands/fix-bug.md +15 -15
- package/.claude/commands/freeze.md +8 -8
- package/.claude/commands/handoff.md +38 -38
- package/.claude/commands/kit-update.md +17 -14
- package/.claude/commands/language.md +13 -0
- package/.claude/commands/maintain.md +19 -19
- package/.claude/commands/plan-task.md +32 -32
- package/.claude/commands/qa.md +17 -17
- package/.claude/commands/release.md +40 -40
- package/.claude/commands/research.md +31 -31
- package/.claude/commands/retro.md +32 -32
- package/.claude/commands/review-changes.md +15 -15
- package/.claude/commands/rollback.md +24 -24
- package/.claude/commands/start.md +116 -113
- package/.claude/commands/tools.md +11 -11
- package/.claude/commands/user-feedback.md +11 -11
- package/.claude/commands/wrap-up.md +18 -18
- package/.claude/findings/lenses/business.md +24 -24
- package/.claude/findings/lenses/legal.md +29 -29
- package/.claude/findings/lenses/perf.md +19 -19
- package/.claude/findings/lenses/security.md +30 -30
- package/.claude/findings/lenses/tech.md +23 -23
- package/.claude/findings/lenses/ux.md +19 -19
- package/.claude/findings/protocol.md +54 -54
- package/.claude/findings/report-template.md +30 -30
- package/.claude/hooks/budget.mjs +7 -7
- package/.claude/hooks/checkpoint.mjs +12 -12
- package/.claude/hooks/commit-gate.mjs +38 -37
- package/.claude/hooks/cost.mjs +2 -2
- package/.claude/hooks/council.mjs +3 -3
- package/.claude/hooks/dashboard-data.mjs +4 -3
- package/.claude/hooks/dashboard.mjs +164 -149
- package/.claude/hooks/destructive-guard.mjs +74 -64
- package/.claude/hooks/edit-rounds.mjs +3 -3
- package/.claude/hooks/flow.mjs +10 -10
- package/.claude/hooks/freeze-guard.mjs +27 -23
- package/.claude/hooks/gate.mjs +25 -25
- package/.claude/hooks/guard-secrets.mjs +11 -11
- package/.claude/hooks/lang.mjs +114 -0
- package/.claude/hooks/messages.mjs +495 -0
- package/.claude/hooks/models.mjs +14 -11
- package/.claude/hooks/notify.mjs +3 -2
- package/.claude/hooks/package-gate.mjs +17 -15
- package/.claude/hooks/plugins-sync.mjs +9 -9
- package/.claude/hooks/prefs.mjs +19 -19
- package/.claude/hooks/preview.mjs +11 -11
- package/.claude/hooks/progress.mjs +14 -14
- package/.claude/hooks/qa-report.mjs +11 -10
- package/.claude/hooks/reminder.mjs +6 -3
- package/.claude/hooks/session-start.mjs +23 -17
- package/.claude/hooks/shared.mjs +1 -1
- package/.claude/hooks/status-read.mjs +5 -4
- package/.claude/hooks/statusline.mjs +14 -11
- package/.claude/hooks/structure-guard.mjs +9 -9
- package/.claude/hooks/test-guard.mjs +12 -12
- package/.claude/hooks/tools.mjs +28 -29
- package/.claude/hooks/usage.mjs +18 -15
- package/.claude/output-styles/anlatici.md +28 -28
- package/.claude/security-patterns.json +3 -3
- package/.claude/settings.json +2 -0
- package/.claude/skills/logo-design/SKILL.md +42 -42
- package/.claude/skills/motion-video/SKILL.md +52 -52
- package/.claude/skills/source-research/SKILL.md +35 -35
- package/.claude/skills/ui-motion/SKILL.md +38 -38
- package/.github/workflows/kit-tests.yml +7 -7
- package/.github/workflows/npm-publish.yml +16 -16
- package/AGENTS.md +56 -56
- package/CHANGELOG.md +7 -7
- package/CLAUDE.md +5 -5
- package/README.md +199 -172
- package/README.tr.md +292 -0
- package/docs/architecture/overview.md +31 -31
- package/docs/architecture/stack.md +2 -2
- package/docs/archive/README.md +4 -4
- package/docs/decisions/adr-template.md +14 -14
- package/docs/decisions/log.md +10 -10
- package/docs/findings/README.md +13 -13
- package/docs/findings/config.md +13 -13
- package/docs/legal/privacy-kvkk.md +1 -1
- package/docs/operations/accounts.md +25 -25
- package/docs/operations/deploy-setup.md +64 -64
- package/docs/operations/feature-flags.md +17 -17
- package/docs/operations/maintenance.md +48 -48
- package/docs/operations/release-checklist.md +61 -61
- package/docs/operations/spend-alarms.md +28 -28
- package/docs/product/feedback.md +9 -8
- package/docs/product/glossary.md +16 -16
- package/docs/product/launch.md +28 -28
- package/docs/product/prd.md +43 -42
- package/docs/product/roadmap.md +31 -30
- package/docs/product/specs/_template.md +13 -12
- package/docs/product/unit-economics.md +23 -22
- package/docs/quality/metrics.md +14 -14
- package/docs/quality/retros.md +11 -11
- package/docs/quality/test-plan.md +48 -48
- package/docs/security/checklist.md +57 -57
- package/docs/workflow/board.md +7 -7
- package/docs/workflow/cost-log.md +4 -4
- package/docs/workflow/decision-protocol.md +70 -70
- package/docs/workflow/learning.md +4 -4
- package/docs/workflow/mcp-catalog.md +31 -31
- package/docs/workflow/models.md +35 -35
- package/docs/workflow/progress.md +7 -7
- package/docs/workflow/skills.md +108 -108
- package/docs/workflow/usage-limits.md +62 -62
- package/kit/CHANGELOG.md +882 -841
- package/kit/VERSION +1 -1
- package/kit/guide.html +713 -477
- package/kit/guide.tr.html +1328 -0
- package/kit/kit.mjs +56 -54
- package/kit/project/README.md +29 -29
- package/kit/project/gitignore +12 -12
- package/kit/templates/addons/ai/.env.example.append +5 -5
- package/kit/templates/addons/ai/ai/evals/README.md +11 -11
- package/kit/templates/addons/ai/ai/evals/cases.jsonl +2 -2
- package/kit/templates/addons/ai/ai/prompts/README.md +8 -8
- package/kit/templates/addons/ai/docs/ai/guide.md +56 -56
- package/kit/templates/backend/.claude/hooks/format.mjs +1 -1
- package/kit/templates/backend/.claude/structure.json +1 -1
- package/kit/templates/backend/.env.example +6 -6
- package/kit/templates/backend/.github/dependabot.yml +1 -1
- package/kit/templates/backend/.github/workflows/ci.yml +13 -13
- package/kit/templates/backend/.github/workflows/claude-ci-fix.yml +19 -19
- package/kit/templates/backend/.github/workflows/claude-maintenance.yml +18 -18
- package/kit/templates/backend/.github/workflows/live-monitoring.yml +14 -14
- package/kit/templates/backend/.pre-commit-config.yaml +3 -3
- package/kit/templates/backend/docs/architecture/stack.md +98 -98
- package/kit/templates/backend/docs/architecture/structure.md +34 -34
- package/kit/templates/mobile/.claude/structure.json +1 -1
- package/kit/templates/mobile/.env.example +6 -6
- package/kit/templates/mobile/.github/dependabot.yml +2 -2
- package/kit/templates/mobile/.github/workflows/ci.yml +18 -18
- package/kit/templates/mobile/.github/workflows/claude-ci-fix.yml +19 -19
- package/kit/templates/mobile/.github/workflows/claude-maintenance.yml +18 -18
- package/kit/templates/mobile/.gitignore.append +2 -2
- package/kit/templates/mobile/docs/architecture/stack.md +113 -113
- package/kit/templates/mobile/docs/architecture/structure.md +33 -33
- package/kit/templates/mobile/docs/design/design-guide.md +37 -37
- package/kit/templates/mobile/tests/security/rls.mjs +22 -22
- package/kit/templates/web-saas/.claude/structure.json +1 -1
- package/kit/templates/web-saas/.env.example +11 -11
- package/kit/templates/web-saas/.github/dependabot.yml +3 -3
- package/kit/templates/web-saas/.github/workflows/ci.yml +20 -20
- package/kit/templates/web-saas/.github/workflows/claude-ci-fix.yml +19 -19
- package/kit/templates/web-saas/.github/workflows/claude-maintenance.yml +18 -18
- package/kit/templates/web-saas/.github/workflows/live-monitoring.yml +12 -12
- package/kit/templates/web-saas/docs/architecture/stack.md +116 -116
- package/kit/templates/web-saas/docs/architecture/structure.md +44 -44
- package/kit/templates/web-saas/docs/design/design-guide.md +38 -38
- package/kit/templates/web-saas/tests/live/smoke.spec.ts +4 -4
- package/kit/templates/web-saas/tests/security/rls.mjs +22 -22
- package/kit/tools/codex/.codex/hooks.json +1 -1
- package/package.json +2 -2
- package/README.en.md +0 -267
|
@@ -1,169 +1,169 @@
|
|
|
1
|
-
# Stack: Web
|
|
1
|
+
# Stack: Web App / SaaS
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> This file is loaded into the AI every session. If you made a different choice in the project, update it here
|
|
4
|
+
> and write the reason in `docs/decisions/log.md`.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Decision points
|
|
7
7
|
|
|
8
|
-
`/start`
|
|
8
|
+
`/start` asks these decisions in order (`docs/workflow/decision-protocol.md`). For each decision, offer the 2-4 options that best fit this project. The **recommended** label is the default, but if another option fits the PRD better, recommend that one and say why. If a claim that can change (price, free tier, limit) carries a `(kaynak: <adres>, YYYY-AA-GG)` note newer than 90 days, do not research it again.
|
|
9
9
|
|
|
10
|
-
| # |
|
|
10
|
+
| # | Decision | Options (when each is better) |
|
|
11
11
|
|---|---|---|
|
|
12
|
-
| 1 | Framework | **Next.js** (
|
|
13
|
-
| 2 |
|
|
14
|
-
| 3 |
|
|
15
|
-
| 4 |
|
|
16
|
-
| 5 | UI
|
|
17
|
-
| 6 |
|
|
18
|
-
| 7 |
|
|
19
|
-
| 8 |
|
|
20
|
-
| 9 |
|
|
21
|
-
| 10 |
|
|
22
|
-
| 11 |
|
|
23
|
-
| 12 | Test | **Vitest + Playwright** (
|
|
12
|
+
| 1 | Framework | **Next.js** (recommended: SEO + dashboard + API in one project, the ecosystem the AI knows best) · Astro (content/landing-page heavy, fastest pages) · SvelteKit (less code, fast; smaller ecosystem) · React + Vite SPA (app only behind login, no SEO need, simplest hosting) |
|
|
13
|
+
| 2 | Language | **TypeScript** (recommended: catches AI mistakes at compile time) · JavaScript (only for a very small prototype) |
|
|
14
|
+
| 3 | Database + identity | **Supabase** (recommended: Postgres + Auth + Storage + RLS in one place; free tier has 2 active projects, 500 MB database per project, a project idle for 1 week is paused (kaynak: https://supabase.com/pricing, 2026-10-26)) · Neon + Better Auth (more control, less provider lock-in) · Firebase (realtime, NoSQL, shared backend with mobile) · Clerk + Postgres (ready-made, polished identity UI; first 50,000 monthly returning users free, then per-user fee (kaynak: https://clerk.com/billing, 2026-10-26)) |
|
|
15
|
+
| 4 | Data access | **Supabase client + RLS** (if Supabase is chosen) · Drizzle ORM (type-safe SQL, provider-independent) · Prisma (mature, schema-driven; heavier) |
|
|
16
|
+
| 5 | UI components | **shadcn/ui + Tailwind** (recommended: code lives in the project, fully customizable, works with the design skills) · Tailwind + own components (fully original design) · Mantine (rich ready-made components, dashboard heavy) |
|
|
17
|
+
| 6 | Payment | None (free in the first release) · **iyzico** (Turkish cards, installments, TRY) · Stripe (customers abroad; may be restricted for a Turkish company: Turkey does not appear in the supported-country list (kaynak: https://stripe.com/global, 2026-10-26)) · Paddle / Lemon Squeezy (merchant of record: they handle tax and invoicing; subscriptions sold abroad) |
|
|
18
|
+
| 7 | Hosting | **Vercel** (recommended for Next.js: zero config, preview environments; the free Hobby plan is for personal, non-commercial use only, a product that takes payments or shows ads needs Pro (kaynak: https://vercel.com/docs/limits/fair-use-guidelines, 2026-10-26)) · Cloudflare (cheap and fast; free Workers are limited to 100,000 requests per day and 10 ms CPU per request (kaynak: https://developers.cloudflare.com/workers/platform/limits/, 2026-10-26)) · Netlify · Your own server + Coolify (fixed cost, maintenance is yours) |
|
|
19
|
+
| 8 | Email | **Resend** (recommended: developer friendly, React email templates; free plan gives 3,000 emails per month, 100 per day (kaynak: https://resend.com/pricing, 2026-10-26)) · Postmark (very high deliverability) · Amazon SES (cheapest, hard to set up) |
|
|
20
|
+
| 9 | Analytics | **Plausible** (cookieless, KVKK friendly; no free plan, starts at 9 dollars per month, 30-day trial (kaynak: https://plausible.io/docs/billing, 2026-10-26)) · PostHog (product analytics, funnels, feature flags) · Umami (self-host, free) · None |
|
|
21
|
+
| 10 | Error tracking | **Sentry** (recommended) · Highlight / Better Stack |
|
|
22
|
+
| 11 | Language support | **Turkish only** (recommended for the MVP) · Turkish + English (next-intl; setting it up from the start is cheaper than adding it later) |
|
|
23
|
+
| 12 | Test | **Vitest + Playwright** (recommended) · Playwright only (little logic, mostly UI) |
|
|
24
24
|
|
|
25
25
|
## Seçilen teknolojiler
|
|
26
26
|
|
|
27
|
-
> `/start`
|
|
28
|
-
>
|
|
27
|
+
> `/start` fills this in at Step 4 from the decision points. The table below is the **recommended** stack and counts as a proposal until approved.
|
|
28
|
+
> If the choice differs, rewrite the commands, folder, rules, verification and checks sections of this file to match the choice.
|
|
29
29
|
|
|
30
|
-
|
|
|
30
|
+
| Layer | Choice | Note |
|
|
31
31
|
|---|---|---|
|
|
32
32
|
| Framework | Next.js (App Router) + TypeScript (strict) | |
|
|
33
|
-
| UI | Tailwind CSS + shadcn/ui |
|
|
34
|
-
| DB + Auth +
|
|
35
|
-
| ORM /
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
33
|
+
| UI | Tailwind CSS + shadcn/ui | Before writing a new component, check whether shadcn has it |
|
|
34
|
+
| DB + Auth + Storage | Supabase (Postgres) | Alternative: Neon + Auth.js |
|
|
35
|
+
| ORM / query | Supabase client or Drizzle | Use only the one the project already has |
|
|
36
|
+
| Validation | Zod | For both forms and the server |
|
|
37
|
+
| Payment | Stripe / iyzico / Paddle | Stripe may be restricted for a Turkish company, check |
|
|
38
|
+
| Email | Resend | Domain verification is required |
|
|
39
39
|
| Hosting | Vercel | |
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
| Test | Vitest (
|
|
40
|
+
| Error tracking | Sentry | |
|
|
41
|
+
| Analytics | Plausible / PostHog | Watch cookie consent |
|
|
42
|
+
| Test | Vitest (unit), Playwright (e2e) | |
|
|
43
43
|
|
|
44
|
-
## Komutlar
|
|
44
|
+
## Komutlar (commands)
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
npm run dev #
|
|
48
|
-
npm run build #
|
|
47
|
+
npm run dev # development
|
|
48
|
+
npm run build # production build (always before deploy)
|
|
49
49
|
npm run lint
|
|
50
|
-
npx tsc --noEmit #
|
|
50
|
+
npx tsc --noEmit # type check
|
|
51
51
|
npm run test # vitest
|
|
52
52
|
npx playwright test # e2e
|
|
53
|
-
npx supabase migration new [ad] #
|
|
53
|
+
npx supabase migration new [ad] # new migration
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
##
|
|
56
|
+
## Folder structure
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Feature-based structure and rules: `docs/architecture/structure.md`. Map: `.claude/structure.json` (writing outside it is asked about, CI checks it).
|
|
59
59
|
```
|
|
60
60
|
src/
|
|
61
|
-
├── app/ #
|
|
62
|
-
│ ├── (marketing)/ #
|
|
63
|
-
│ ├── (auth)/ #
|
|
64
|
-
│ ├── (app)/ #
|
|
65
|
-
│ └── api/ # webhook
|
|
61
|
+
├── app/ # ONLY routes: page, layout, loading, error, route handler. No business logic.
|
|
62
|
+
│ ├── (marketing)/ # landing, pricing, blog
|
|
63
|
+
│ ├── (auth)/ # sign in, sign up, password reset
|
|
64
|
+
│ ├── (app)/ # the app that needs login
|
|
65
|
+
│ └── api/ # webhook and external API endpoints
|
|
66
66
|
├── features/
|
|
67
|
-
│ └──
|
|
68
|
-
│ ├── components/ #
|
|
69
|
-
│ ├── hooks/ #
|
|
70
|
-
│ ├── server/ # server actions,
|
|
71
|
-
│ ├── lib/ #
|
|
72
|
-
│ ├── __tests__/ #
|
|
73
|
-
│ ├── schemas.ts # Zod
|
|
67
|
+
│ └── <feature>/ # e.g. invoice/
|
|
68
|
+
│ ├── components/ # components of this feature only
|
|
69
|
+
│ ├── hooks/ # client hooks
|
|
70
|
+
│ ├── server/ # server actions, queries, services (run on the server)
|
|
71
|
+
│ ├── lib/ # feature-specific helpers
|
|
72
|
+
│ ├── __tests__/ # unit and integration tests
|
|
73
|
+
│ ├── schemas.ts # Zod schemas
|
|
74
74
|
│ ├── types.ts
|
|
75
|
-
│ └── index.ts #
|
|
75
|
+
│ └── index.ts # the only gate the feature exposes
|
|
76
76
|
├── components/
|
|
77
|
-
│ └── ui/ # shadcn/ui
|
|
78
|
-
├── hooks/ #
|
|
79
|
-
├── lib/ #
|
|
80
|
-
├── config/ #
|
|
81
|
-
├── styles/ # global
|
|
82
|
-
├── types/ # global
|
|
77
|
+
│ └── ui/ # shadcn/ui and shared presentational components
|
|
78
|
+
├── hooks/ # hooks used by more than one feature
|
|
79
|
+
├── lib/ # infrastructure clients: supabase/, stripe/, email/, sentry
|
|
80
|
+
├── config/ # environment variable validation (env.ts), constants
|
|
81
|
+
├── styles/ # global styles, design tokens (from DESIGN.md)
|
|
82
|
+
├── types/ # global types
|
|
83
83
|
└── middleware.ts
|
|
84
|
-
public/ #
|
|
84
|
+
public/ # static files
|
|
85
85
|
tests/
|
|
86
|
-
├── e2e/ # Playwright
|
|
87
|
-
└── live/ #
|
|
88
|
-
supabase/migrations/ #
|
|
86
|
+
├── e2e/ # Playwright acceptance tests (Ö-01.1 ...)
|
|
87
|
+
└── live/ # live monitoring tests (that delete no data)
|
|
88
|
+
supabase/migrations/ # database changes ONLY here
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
##
|
|
91
|
+
## Coding rules
|
|
92
92
|
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
- `NEXT_PUBLIC_`
|
|
96
|
-
- Supabase
|
|
97
|
-
- DB
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
- UI
|
|
93
|
+
- Default to **Server Component**. `"use client"` only when interaction is needed, and in the lowest component.
|
|
94
|
+
- Writing data: Server Action or route handler. In each: Zod validation → session check → permission check → operation.
|
|
95
|
+
- Variables with the `NEXT_PUBLIC_` prefix go to the browser. A secret is never `NEXT_PUBLIC_`.
|
|
96
|
+
- The Supabase secret key (`SUPABASE_SECRET_KEY`, `sb_secret_…`; old name `service_role`) only on the server and only when really needed (it bypasses RLS).
|
|
97
|
+
- DB schema changes only through a migration file (`npx supabase migration new [ad]`). No manual DDL from the dashboard or MCP; the `supabase-dev` MCP is for trying data in dev.
|
|
98
|
+
- Every new table has RLS on, a written policy, and an entry in the `tests/security/rls.mjs` → `TABLES` list (the `rls` job in CI turns red on an unregistered table).
|
|
99
|
+
- On every page, think about `loading.tsx` / empty state / `error.tsx`.
|
|
100
|
+
- Images with `next/image`, links with `next/link`.
|
|
101
|
+
- Texts are in Turkish; format date/money with `Intl` and `tr-TR`.
|
|
102
|
+
- Before UI work, read `DESIGN.md` and `docs/design/design-guide.md`; do not go outside the tokens and rules. If a new design decision is needed, use `/design`.
|
|
103
103
|
|
|
104
|
-
##
|
|
104
|
+
## Verification (evidence before a task is done)
|
|
105
105
|
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
-
|
|
106
|
+
- UI: `node .claude/hooks/preview.mjs <task id>` takes a desktop (1440) and mobile (390) screenshot (the `geliştirme:` and `önizleme:` lines in `AGENTS.md`). To try scenarios, with `npm run dev` running, open the page with the Playwright CLI (`npx -y @playwright/cli@0.1.22 open http://localhost:3000`, then `snapshot`, `console`, `screenshot`) or with Claude's browser, and try the main scenario and one error scenario.
|
|
107
|
+
- Proving acceptance criteria in the browser: `/qa` (one Playwright test per criterion, report in `docs/quality/qa/`).
|
|
108
|
+
- Authorization: with a second test user, try to reach the first user's record; it must fail.
|
|
109
|
+
- No errors/warnings in the console.
|
|
110
110
|
|
|
111
|
-
##
|
|
111
|
+
## Automatic checks
|
|
112
112
|
|
|
113
|
-
|
|
|
113
|
+
| Layer | What it does | Setup |
|
|
114
114
|
|---|---|---|
|
|
115
|
-
| Claude
|
|
116
|
-
| Pre-commit | lint-staged (ESLint + Prettier) +
|
|
117
|
-
| CI (+ Semgrep,
|
|
118
|
-
| Dependabot |
|
|
119
|
-
| MCP | Supabase (
|
|
115
|
+
| Claude hooks | Block writing secrets; format the edited file with Prettier | Ready (`.claude/settings.json`). Prettier must be installed in the project |
|
|
116
|
+
| Pre-commit | lint-staged (ESLint + Prettier) + secret scan | `npm i -D husky lint-staged prettier` → `npm pkg set scripts.prepare="husky"` → `npx husky` |
|
|
117
|
+
| CI (+ Semgrep, duplicate code, complexity budget) | Lint, types, test, build, vulnerability scan, gitleaks, complexity budget on changed files (function complexity 15, function 80, file 400 lines; `node .claude/hooks/budget.mjs --check`) | `.github/workflows/ci.yml` is ready. Add the `NEXT_PUBLIC_*` values to GitHub > Settings > Variables |
|
|
118
|
+
| Dependabot | Weekly small updates in a single PR | `.github/dependabot.yml` is ready |
|
|
119
|
+
| MCP | Supabase (read-only), Sentry, Context7 · when needed: Playwright, Chrome DevTools, Supabase dev (`docs/workflow/mcp-catalog.md`) | `.mcp.json`: fill in `DEV_REF` (read-only, the **development** project; the prod ref is not written into the AI environment). The write-enabled Supabase MCP only for the **development** project (`supabase-dev`) |
|
|
120
120
|
|
|
121
|
-
##
|
|
121
|
+
## Acceptance tests and feature flags
|
|
122
122
|
|
|
123
|
-
**
|
|
123
|
+
**Acceptance tests** (`docs/quality/test-plan.md` §1a): The test name carries the criterion id (`test('Ö-01.1 ...')`). The dashboard reads the JUnit report:
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
126
|
PLAYWRIGHT_JUNIT_OUTPUT_NAME=test-results/junit.xml npx playwright test --reporter=list,junit
|
|
127
127
|
npx vitest run --reporter=default --reporter=junit --outputFile.junit=test-results/junit-unit.xml
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
- PostHog
|
|
132
|
-
-
|
|
133
|
-
-
|
|
130
|
+
**Feature flags** (`docs/operations/feature-flags.md`): Emergency shutdown must not need a deploy. So use a source read at runtime, not an environment variable:
|
|
131
|
+
- PostHog feature flags if PostHog is chosen; otherwise
|
|
132
|
+
- A `feature_flags` table in Supabase (`ad`, `acik`, `yuzde`) + a 60 s cache on the server. Reading goes through one helper: `lib/bayrak.ts` → `bayrakAcik('ad', kullanici)`.
|
|
133
|
+
- The flag check runs on the server; the client only sees the result.
|
|
134
134
|
|
|
135
|
-
##
|
|
135
|
+
## Common AI mistakes (watch for these)
|
|
136
136
|
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
- RLS
|
|
141
|
-
-
|
|
142
|
-
-
|
|
137
|
+
- Writing an absolute path specific to this machine into code, a test or a setting (`C:\Users\<ad>\…`, `/home/<ad>/…`, the full path of the project folder): it does not work on another machine. Derive the path with `import.meta.url` / `__dirname`, `path.join(process.cwd(), …)` or `os.tmpdir()`. The deterministic gate catches this.
|
|
138
|
+
- Using the Supabase admin client or a secret inside a client component.
|
|
139
|
+
- Protecting the page with middleware but leaving the server action unprotected.
|
|
140
|
+
- Turning RLS off because it "does not work".
|
|
141
|
+
- Mixing old Pages Router patterns (`getServerSideProps`) into the App Router.
|
|
142
|
+
- Not verifying the signature on a webhook; processing a webhook twice when it arrives twice (idempotency).
|
|
143
143
|
|
|
144
|
-
##
|
|
144
|
+
## Security (extra)
|
|
145
145
|
|
|
146
|
-
- [ ]
|
|
147
|
-
- [ ]
|
|
148
|
-
- [ ]
|
|
149
|
-
- [ ]
|
|
146
|
+
- [ ] RLS is on in all tables and every table is in the adversarial test: `tests/security/rls.mjs` (CI `rls` job green). Locally: `npx -y supabase@2.120.0 start`, then the commands at the top of the file.
|
|
147
|
+
- [ ] Another user and an anonymous user cannot read, change or delete the user's row (same test).
|
|
148
|
+
- [ ] Security headers (CSP, X-Frame-Options etc.) in `next.config` or middleware.
|
|
149
|
+
- [ ] Rate limit on auth endpoints (Supabase settings + Upstash if needed).
|
|
150
150
|
|
|
151
|
-
##
|
|
151
|
+
## Go live (extra)
|
|
152
152
|
|
|
153
|
-
- [ ] Vercel prod
|
|
154
|
-
- [ ] Supabase prod
|
|
155
|
-
- [ ] Supabase
|
|
156
|
-
- [ ]
|
|
157
|
-
- [ ] SEO: `metadata` (title, description), Open Graph
|
|
158
|
-
- [ ] Lighthouse (
|
|
153
|
+
- [ ] Vercel prod environment variables entered (Preview and Production separate)
|
|
154
|
+
- [ ] Supabase prod project is separate; prod domain and redirect URLs in Auth → URL Configuration
|
|
155
|
+
- [ ] Supabase email templates in Turkish and a custom SMTP (the default SMTP limit is very low)
|
|
156
|
+
- [ ] Payment: live keys, live webhook endpoint and signing secret
|
|
157
|
+
- [ ] SEO: `metadata` (title, description), Open Graph image, `sitemap.ts`, `robots.ts`, favicon
|
|
158
|
+
- [ ] Lighthouse (mobile): Performance ≥ 90, Accessibility ≥ 90, SEO ≥ 90
|
|
159
159
|
- [ ] Core Web Vitals: LCP < 2.5s, CLS < 0.1, INP < 200ms
|
|
160
|
-
- [ ] `not-found.tsx`
|
|
161
|
-
- [ ]
|
|
162
|
-
- [ ] Sentry
|
|
160
|
+
- [ ] `not-found.tsx` and `error.tsx` customized
|
|
161
|
+
- [ ] Domain + `www` redirect + SSL (Vercel automatic)
|
|
162
|
+
- [ ] Sentry source maps are uploaded
|
|
163
163
|
|
|
164
|
-
##
|
|
164
|
+
## Maintenance (extra)
|
|
165
165
|
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
-
|
|
166
|
+
- Weekly: Vercel usage (bandwidth, function duration), Supabase usage (DB size, MAU).
|
|
167
|
+
- Monthly: `npm outdated`, `npm audit`, rerun Lighthouse.
|
|
168
|
+
- Quarterly: Next.js / Supabase major version notes; Supabase backups (no PITR on the free tier, take your own backup: `supabase db dump`).
|
|
169
|
+
- A free Supabase project can be paused when idle; on a live project move to a paid plan or watch this.
|
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Project structure: Web / SaaS (Next.js App Router)
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> This file is the human explanation of the `.claude/structure.json` map; the two are updated together.
|
|
4
|
+
> Following the structure is mandatory: the hook checks at write time, CI on every PR, the board Architect and `/findings-tech` review it.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Code
|
|
7
7
|
|
|
8
8
|
```
|
|
9
9
|
src/
|
|
10
|
-
├── app/ #
|
|
11
|
-
│ ├── (marketing)/ #
|
|
12
|
-
│ ├── (auth)/ #
|
|
13
|
-
│ ├── (app)/ #
|
|
14
|
-
│ └── api/ # webhook
|
|
10
|
+
├── app/ # ONLY routes: page, layout, loading, error, route handler. No business logic.
|
|
11
|
+
│ ├── (marketing)/ # landing, pricing, blog
|
|
12
|
+
│ ├── (auth)/ # sign in, sign up, password reset
|
|
13
|
+
│ ├── (app)/ # the app that needs login
|
|
14
|
+
│ └── api/ # webhook and external API endpoints
|
|
15
15
|
├── features/
|
|
16
|
-
│ └──
|
|
17
|
-
│ ├── components/ #
|
|
18
|
-
│ ├── hooks/ #
|
|
19
|
-
│ ├── server/ # server actions,
|
|
20
|
-
│ ├── lib/ #
|
|
21
|
-
│ ├── __tests__/ #
|
|
22
|
-
│ ├── schemas.ts # Zod
|
|
16
|
+
│ └── <feature>/ # e.g. invoice/
|
|
17
|
+
│ ├── components/ # components of this feature only
|
|
18
|
+
│ ├── hooks/ # client hooks
|
|
19
|
+
│ ├── server/ # server actions, queries, services (run on the server)
|
|
20
|
+
│ ├── lib/ # feature-specific helpers
|
|
21
|
+
│ ├── __tests__/ # unit and integration tests
|
|
22
|
+
│ ├── schemas.ts # Zod schemas
|
|
23
23
|
│ ├── types.ts
|
|
24
|
-
│ └── index.ts #
|
|
24
|
+
│ └── index.ts # the only gate the feature exposes
|
|
25
25
|
├── components/
|
|
26
|
-
│ └── ui/ # shadcn/ui
|
|
27
|
-
├── hooks/ #
|
|
28
|
-
├── lib/ #
|
|
29
|
-
├── config/ #
|
|
30
|
-
├── styles/ # global
|
|
31
|
-
├── types/ # global
|
|
26
|
+
│ └── ui/ # shadcn/ui and shared presentational components
|
|
27
|
+
├── hooks/ # hooks used by more than one feature
|
|
28
|
+
├── lib/ # infrastructure clients: supabase/, stripe/, email/, sentry
|
|
29
|
+
├── config/ # environment variable validation (env.ts), constants
|
|
30
|
+
├── styles/ # global styles, design tokens (from DESIGN.md)
|
|
31
|
+
├── types/ # global types
|
|
32
32
|
└── middleware.ts
|
|
33
|
-
public/ #
|
|
33
|
+
public/ # static files
|
|
34
34
|
tests/
|
|
35
|
-
├── e2e/ # Playwright
|
|
36
|
-
└── live/ #
|
|
37
|
-
supabase/migrations/ #
|
|
35
|
+
├── e2e/ # Playwright acceptance tests (Ö-01.1 ...)
|
|
36
|
+
└── live/ # live monitoring tests (that delete no data)
|
|
37
|
+
supabase/migrations/ # database changes ONLY here
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
##
|
|
40
|
+
## Common to every project
|
|
41
41
|
|
|
42
42
|
```
|
|
43
43
|
.
|
|
44
|
-
├── .claude/ # Claude Code:
|
|
45
|
-
├── .github/ # CI, Dependabot,
|
|
44
|
+
├── .claude/ # Claude Code: commands, agents, hooks, board, findings, structure.json
|
|
45
|
+
├── .github/ # CI, Dependabot, cloud agents
|
|
46
46
|
├── docs/
|
|
47
47
|
│ ├── product/ # prd, roadmap, glossary, launch, feedback, unit-economics
|
|
48
|
-
│ ├── architecture/ # overview, stack, structure (
|
|
49
|
-
│ ├── design/ # design-guide (
|
|
50
|
-
│ ├── decisions/ # log.md (
|
|
48
|
+
│ ├── architecture/ # overview, stack, structure (this file)
|
|
49
|
+
│ ├── design/ # design-guide (if there is a UI)
|
|
50
|
+
│ ├── decisions/ # log.md (decision log) + adr-NNNN-*.md (detailed decisions)
|
|
51
51
|
│ ├── quality/ # test-plan, metrics, retros
|
|
52
52
|
│ ├── security/ # checklist
|
|
53
53
|
│ ├── legal/ # privacy-kvkk
|
|
54
54
|
│ ├── operations/ # release-checklist, maintenance, accounts, feature-flags
|
|
55
55
|
│ ├── workflow/ # progress, decision-protocol, skills, board, usage-limits, cost-log
|
|
56
|
-
│ ├── findings/ # /findings-*
|
|
57
|
-
│ └── archive/ #
|
|
58
|
-
├── sandbox/ #
|
|
56
|
+
│ ├── findings/ # /findings-* reports (type/date.md, latest.md)
|
|
57
|
+
│ └── archive/ # documents that are no longer valid but are kept
|
|
58
|
+
├── sandbox/ # trials, exploration code, temporary scripts (not committed to git)
|
|
59
59
|
├── AGENTS.md CLAUDE.md README.md CHANGELOG.md
|
|
60
60
|
└── .env.example
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
##
|
|
63
|
+
## Rules
|
|
64
64
|
|
|
65
|
-
1. **
|
|
66
|
-
2.
|
|
67
|
-
3.
|
|
68
|
-
4. **
|
|
69
|
-
5. **
|
|
70
|
-
6. **
|
|
71
|
-
7. **
|
|
65
|
+
1. **A new file goes to its place in the map.** Writing outside the `.claude/structure.json` map is asked about; clutter patterns (`*.bak`, `*-old.*`, `* copy*`, `temp/`, `deneme*`) are blocked. CI checks the whole repo on every PR.
|
|
66
|
+
2. **By feature.** Everything that belongs to a feature (component, logic, test) stays under `features/<feature>/`. When a piece of code starts to be used by two features, it moves to the shared layer (`components/`, `lib/`, `shared/`).
|
|
67
|
+
3. **Features do not reach into each other.** `features/a` does not import the internal files of another feature; it uses only what that feature exposes from its `index` file.
|
|
68
|
+
4. **Naming:** Folders and files use `kebab-case`. React component files may use `PascalCase.tsx`; Python modules use `snake_case.py`. A feature folder name is singular and English (`invoice`, `customer`).
|
|
69
|
+
5. **Temporary and unrelated work** goes under `sandbox/`. If something useful comes out, it moves to the right place; `sandbox/` is cleaned regularly.
|
|
70
|
+
6. **Old documents** are not deleted; they move under `docs/archive/` with a line at the top saying why they were archived.
|
|
71
|
+
7. **Changing the map** (a new top-level folder, a new layer) is a `teknik` decision: ask the user, record it under `docs/decisions/`, then update `.claude/structure.json` and this file.
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Design
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
> - `PRODUCT.md`:
|
|
5
|
-
> - `DESIGN.md`:
|
|
6
|
-
> -
|
|
3
|
+
> The interface has three sources of truth:
|
|
4
|
+
> - `PRODUCT.md`: product context (who, for what). Written with Impeccable `init`, fed from the PRD.
|
|
5
|
+
> - `DESIGN.md`: visual world and design tokens (color, type, spacing, corners, shadow, motion). Impeccable writes it; components use only these tokens.
|
|
6
|
+
> - This file: the chosen direction, the design decision log and the lasting rules that apply on every screen.
|
|
7
7
|
>
|
|
8
|
-
>
|
|
9
|
-
>
|
|
8
|
+
> Decisions are made with `/design` using **visual previews** (`docs/workflow/decision-protocol.md` §5). If a new color, size or component
|
|
9
|
+
> is needed, it is asked as a decision first, then added to DESIGN.md. No raw colors or arbitrary sizes in code.
|
|
10
10
|
|
|
11
|
-
## 1. Seçilen yön
|
|
11
|
+
## 1. Seçilen yön (Chosen direction)
|
|
12
12
|
|
|
13
|
-
|
|
|
13
|
+
| Area | Choice | Skill | Preview | Date |
|
|
14
14
|
|---|---|---|---|---|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
15
|
+
| Style direction | [e.g. Premium / Apple style] | [e.g. taste-skill:high-end-visual-design] | `.previews/01-stil/b.html` | |
|
|
16
|
+
| Color palette | | ui-ux-pro-max | | |
|
|
17
|
+
| Font pair | | ui-ux-pro-max | | |
|
|
18
|
+
| Corners / shadow / motion | | | | |
|
|
19
|
+
| Dark theme | | | | |
|
|
20
|
+
| Form of address (informal/formal) | | | | |
|
|
21
21
|
|
|
22
|
-
## 2.
|
|
22
|
+
## 2. Design decision log
|
|
23
23
|
|
|
24
|
-
| # |
|
|
24
|
+
| # | Date | Screen/scope | Question | Chosen | Preview |
|
|
25
25
|
|---|---|---|---|---|---|
|
|
26
26
|
|
|
27
|
-
## 3.
|
|
27
|
+
## 3. Components
|
|
28
28
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- Form:
|
|
32
|
-
-
|
|
33
|
-
-
|
|
29
|
+
- First check whether it exists in `components/ui/` (shadcn); if it does, use it, do not copy and change it.
|
|
30
|
+
- Button variants: `default` (at most 1 main action per page), `secondary`, `outline`, `ghost`, `destructive`.
|
|
31
|
+
- Form: the label is always visible (not only a placeholder), the error message sits under the field, the button is disabled + loading while submitting.
|
|
32
|
+
- Table/list: an empty-state component + a loading skeleton are required.
|
|
33
|
+
- Icons: [lucide-react], a single set.
|
|
34
34
|
|
|
35
|
-
## 4.
|
|
35
|
+
## 4. States (on every screen)
|
|
36
36
|
|
|
37
|
-
|
|
|
37
|
+
| State | How it looks |
|
|
38
38
|
|---|---|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
39
|
+
| Loading | Skeleton; nothing for loads shorter than 300 ms |
|
|
40
|
+
| Empty | One sentence saying what will be here + a first-step button |
|
|
41
|
+
| Error | What happened + what the user can do (retry / support); no technical detail |
|
|
42
|
+
| Successful action | Short notification (toast), 3-4 s |
|
|
43
43
|
|
|
44
|
-
## 5.
|
|
44
|
+
## 5. Accessibility
|
|
45
45
|
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
46
|
+
- Text contrast at least 4.5:1 (large text 3:1); in both themes.
|
|
47
|
+
- Everything is reachable by keyboard, the focus ring is visible.
|
|
48
|
+
- `alt` on images, `aria-label` on icon buttons.
|
|
49
|
+
- No horizontal scroll at mobile width (375 px), touch target at least 44 px.
|
|
50
50
|
|
|
51
|
-
## 6.
|
|
51
|
+
## 6. Copy language
|
|
52
52
|
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
53
|
+
- Form of address: [informal/formal] (same as `docs/product/glossary.md`).
|
|
54
|
+
- Buttons are verbs: "Save", "Create invoice"; not vague ones like "OK", "Submit".
|
|
55
|
+
- An error message does not blame the user and says the fix: "The email address is not valid. Example: name@domain.com".
|
|
@@ -6,14 +6,14 @@ import { test, expect } from '@playwright/test';
|
|
|
6
6
|
const BASE = process.env.BASE_URL ?? 'http://localhost:3000';
|
|
7
7
|
const MAX_MS = Number(process.env.LIVE_MAX_MS ?? 3000);
|
|
8
8
|
|
|
9
|
-
test('
|
|
9
|
+
test('live: home page opens, response time within the limit, no console errors',async ({ page }) => {
|
|
10
10
|
const errors: string[] = [];
|
|
11
11
|
page.on('console', (m) => { if (m.type() === 'error') errors.push(m.text()); });
|
|
12
12
|
page.on('pageerror', (e) => errors.push(e.message));
|
|
13
13
|
const start = Date.now();
|
|
14
14
|
const response = await page.goto(BASE, { waitUntil: 'domcontentloaded' });
|
|
15
15
|
const ms = Date.now() - start;
|
|
16
|
-
expect(response?.ok(), `
|
|
17
|
-
expect(ms, `
|
|
18
|
-
expect(errors, `
|
|
16
|
+
expect(response?.ok(), `status code ${response?.status()}`).toBe(true);
|
|
17
|
+
expect(ms, `home page ${ms} ms (limit ${MAX_MS} ms)`).toBeLessThan(MAX_MS);
|
|
18
|
+
expect(errors, `console error: ${errors[0] ?? ''}`).toEqual([]);
|
|
19
19
|
});
|