Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
1478365
J2: CRUD forms (db schema, API routes, admin UI)
miracleweasel Jan 23, 2026
54e215a
Merge branch 'step/J2-crud-forms'
miracleweasel Jan 23, 2026
72b8ca7
J3: public form + submissions (db/api/ui)
miracleweasel Jan 23, 2026
adfc109
J3: public form + submissions (db/api/ui)
miracleweasel Jan 23, 2026
b4cd18b
Merge branch 'step/J3-public-submit'
miracleweasel Jan 23, 2026
0ce6d03
J4: admin submissions page with cursor pagination and load more
miracleweasel Jan 23, 2026
446eedc
J5: export CSV submissions
miracleweasel Jan 24, 2026
1f81433
add more csv
miracleweasel Jan 24, 2026
3782176
add search
miracleweasel Jan 24, 2026
bb5ece2
J6B: add time range filters for submissions
miracleweasel Jan 24, 2026
6d1db89
J6C: align drizzle defaults + updatedAt onUpdate + submissions UX polish
miracleweasel Jan 24, 2026
20f43f2
J6A-J6C: submissions filters (email+range), sticky toolbar + counters…
miracleweasel Jan 24, 2026
ed20087
J7A: fix login suspense boundary for useSearchParams
miracleweasel Jan 24, 2026
fc12bd6
7A
miracleweasel Jan 24, 2026
a4eff8f
J7B: Lemon Squeezy billing (subscriptions table + checkout + webhook)
miracleweasel Jan 25, 2026
3302a65
J7C: show subscription status on /billing
miracleweasel Jan 25, 2026
b1c3d81
J7C: standardize JSON errors
miracleweasel Jan 29, 2026
0b4fa2c
J7C: harden submissions query + standard errors
miracleweasel Jan 29, 2026
b5a58f5
J7C: protect billing checkout + add node:test script
miracleweasel Jan 29, 2026
5eef1bd
J7C: harden billing webhook payload handling
miracleweasel Jan 29, 2026
a611f68
J7C: add node:test coverage for submissions query parsing
miracleweasel Jan 29, 2026
e8ed544
J7C: add zod validation for create form
miracleweasel Jan 29, 2026
cd35773
J7C: add best-effort rate limiting (checkout)
miracleweasel Jan 29, 2026
8cf26e7
J7C: add best-effort rate limiting (login)
miracleweasel Jan 29, 2026
d4463ba
J7C: protect dashboard pages via server layout guard
miracleweasel Jan 29, 2026
f237167
feat(backlog): add integration tables (connection + form settings)
miracleweasel Feb 1, 2026
105580c
feat(backlog): admin config endpoints + form settings + test connection
miracleweasel Feb 1, 2026
209974f
test: load env for node tests + add backlog unit tests
miracleweasel Feb 1, 2026
733d8f7
feat(backlog): create issue on public submit (non-blocking)
miracleweasel Feb 1, 2026
035d90e
test: stabilize node test env and isolate runner
miracleweasel Feb 1, 2026
785064c
api: guard backlog form settings with getAdminEmail
miracleweasel Feb 1, 2026
63e2124
fix(auth): await getAdminEmail everywhere + fix backlog submit async
miracleweasel Feb 1, 2026
487cbf4
merge: J8-2 backlog submit + admin guards
miracleweasel Feb 1, 2026
13a1f90
refactor(auth): use SESSION_COOKIE_NAME constant and simplify email c…
miracleweasel Feb 2, 2026
6efc5fe
fix(security): critical auth fixes + webhook signature verification
miracleweasel Feb 2, 2026
fd36c69
fix(security): encrypt Backlog API key + rate limit public submit
miracleweasel Feb 2, 2026
646cf85
refactor(auth): centralize requireAdmin and getCookieValue
miracleweasel Feb 2, 2026
d0d4b48
test(auth): add comprehensive tests for getCookieValue and requireAdm…
miracleweasel Feb 2, 2026
dccf11e
test(security): add tests for crypto and rate limiting (Phase 1 cover…
miracleweasel Feb 2, 2026
0004b52
feat(i18n): add centralized i18n with Japanese translations + future …
miracleweasel Feb 3, 2026
2a148b7
feat(ui): add dashboard header with navigation and logout
miracleweasel Feb 3, 2026
6d501f4
feat(ui): add "Powered by FormGate" branding to public forms
miracleweasel Feb 3, 2026
1e08800
feat(ui): implement design system + landing page redesign
miracleweasel Feb 3, 2026
e24199e
style(ui): apply design system to all dashboard pages
miracleweasel Feb 4, 2026
39c41d4
security: add password hashing, Backlog rate limiting, fix error logging
miracleweasel Feb 4, 2026
366696d
fix(security): enhance crypto KDF and add security headers
miracleweasel Feb 5, 2026
4f89f66
feat(forms): add custom fields support
miracleweasel Feb 5, 2026
4e8fb53
fix(config): correct drizzle schema path
miracleweasel Feb 5, 2026
2f07c28
docs: comprehensive README with technical state and resume instructions
miracleweasel Feb 5, 2026
11637c4
docs(claude): add mandatory README update instruction
miracleweasel Feb 5, 2026
aebdf33
feat(backlog): add field mapping + security hardening
miracleweasel Feb 5, 2026
a7c3fbc
feat(forms): add admin field builder UI
miracleweasel Feb 9, 2026
1f8bf47
style(ui): redesign UI inspired by Fillout.com
miracleweasel Feb 10, 2026
07ade75
feat(security,billing,legal): production hardening
miracleweasel Feb 16, 2026
726b766
perf: subscription cache, direct DB query, server-only guard
miracleweasel Feb 16, 2026
0239997
style(ui): redesign all pages with Fillout.com-inspired aesthetic
miracleweasel Feb 17, 2026
df311f4
docs: update README with UI/UX redesign status
miracleweasel Feb 17, 2026
b329bd4
feat(onboarding,settings,monitoring): onboarding flow, settings page,…
miracleweasel Feb 18, 2026
61f7ab9
fix(deploy): require Node >= 20.9.0 for Next.js 16
miracleweasel Feb 18, 2026
4e5c32f
fix(deploy): copy static assets into standalone output for Railway
miracleweasel Feb 18, 2026
76a246c
feat(auth): replace password auth with magic link + multi-user support
miracleweasel Feb 19, 2026
48a3ee0
feat(landing,email,docs): landing page polish, email template, SEO me…
miracleweasel Feb 20, 2026
5d7d747
fix(billing): pass Date as ISO string in raw SQL queries
miracleweasel Feb 20, 2026
874e845
style(ux): show full public URL with copy button on form detail page
miracleweasel Feb 26, 2026
99b2854
feat: submission email notifications, welcome email, help page, copyw…
miracleweasel Feb 26, 2026
d511bd8
feat: submission detail view, magic link cleanup, Railway prep, docs …
miracleweasel Feb 26, 2026
62a5b5f
chore: cleanup dead files, trigger Railway redeploy
miracleweasel Feb 26, 2026
2c5128a
fix(deploy): copy static assets into standalone output
miracleweasel Feb 26, 2026
0c54167
fix(deploy): use Dockerfile instead of Nixpacks for Railway
miracleweasel Feb 26, 2026
84f2ab9
fix(deploy): remove standalone mode, use standard next start
miracleweasel Feb 26, 2026
4ea72d9
fix(deploy): simplify Dockerfile for non-standalone mode
miracleweasel Feb 26, 2026
482fdd4
chore: cleanup defaults, add FormGate favicon
miracleweasel Feb 26, 2026
7467b01
feat(seo): add robots.txt, sitemap, OG image for social sharing
miracleweasel Feb 26, 2026
a2a4fe5
feat(fields): add 5 new field types and 6 form templates
miracleweasel Feb 27, 2026
00f0847
docs: update README with new field types, templates, recent commits
miracleweasel Feb 27, 2026
ab709f9
feat(backlog): add auto-assign, sub-tasks, and file attachments
miracleweasel Mar 1, 2026
4ca7c69
fix(build): declare runtime directly in twitter-image instead of re-e…
miracleweasel Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"permissions": {
"allow": [
"Bash(npm test:*)",
"Bash(npm run build:*)",
"Bash(timeout 10 npm run dev:*)",
"Bash(git add:*)",
"Bash(git commit -m \"$\\(cat <<''EOF''\nrefactor\\(auth\\): use SESSION_COOKIE_NAME constant and simplify email check\n\nUse exported constant instead of hardcoded cookie name, simplify\nemail comparison with toLowerCase\\(\\), and add test coverage.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
"Bash(pnpm test:*)",
"Bash(pnpm build:*)",
"Bash(git push:*)",
"Bash(pnpm add:*)",
"Bash(findstr:*)",
"Bash(git commit:*)",
"WebFetch(domain:www.fillout.com)",
"Bash(ls:*)",
"Bash(railway status:*)",
"Bash(railway whoami:*)",
"Bash(railway list:*)",
"Bash(railway init:*)",
"Bash(railway service:*)",
"Bash(railway add --help:*)",
"Bash(railway add:*)",
"Bash(railway variables set:*)",
"Bash(railway variables:*)",
"Bash(railway up:*)",
"Bash(railway domain:*)",
"Bash(railway logs:*)",
"WebFetch(domain:formgate-web-production.up.railway.app)",
"Bash(git -C \"C:\\\\Users\\\\anthony\\\\Desktop\\\\dev\\\\projets\\\\formgate\" log --oneline -5)",
"Bash(git -C \"C:\\\\Users\\\\anthony\\\\Desktop\\\\dev\\\\projets\\\\formgate\" add .env.example \"app/\\(dashboard\\)/forms/page.tsx\" \"app/\\(dashboard\\)/layout.tsx\" \"app/\\(dashboard\\)/settings/page.tsx\" \"app/api/auth/login/route.ts\" \"app/api/auth/verify/route.ts\" \"app/api/billing/checkout/route.ts\" \"app/api/billing/portal/route.ts\" \"app/api/billing/status/route.ts\" \"app/api/billing/webhook/route.ts\" \"app/api/forms/[id]/integrations/backlog/route.ts\" \"app/api/forms/[id]/route.ts\" \"app/api/forms/[id]/submissions/export/route.ts\" \"app/api/forms/[id]/submissions/route.ts\" \"app/api/forms/route.ts\" \"app/api/integrations/backlog/project-meta/route.ts\" \"app/api/integrations/backlog/route.ts\" \"app/api/integrations/backlog/test/route.ts\" \"app/api/public/forms/[slug]/submit/route.ts\" \"app/f/[slug]/page.tsx\" \"app/login/LoginClient.tsx\" lib/auth/admin.ts lib/auth/cookies.ts lib/auth/getSessionEmail.ts lib/auth/magicLink.ts lib/auth/password.ts lib/auth/requireAdmin.ts lib/auth/requireUser.ts lib/backlog/form-settings-handlers.ts lib/billing/planLimits.ts lib/db/schema.ts lib/email/send.ts lib/env.ts lib/i18n/en.ts lib/i18n/ja.ts lib/i18n/types.ts package.json pnpm-lock.yaml scripts/hash-password.ts scripts/test-setup.mjs \"drizzle/0006_magic_link_auth.sql\" test/api.backlog-form-settings.handlers.test.ts test/architecture.test.ts test/auth.requireAdminFromRequest.test.ts test/auth.requireUser.test.ts test/i18n.test.ts test/password.test.ts test/security.api-auth.test.ts test/security.comprehensive.test.ts)"
]
}
}
25 changes: 24 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
DATABASE_URL="postgres://USER:PASSWORD@HOST:5432/DB"
APP_ENC_KEY="CHANGE_ME_LONG_RANDOM"
APP_ENC_KEY="CHANGE_ME_LONG_RANDOM_32_CHARS"
APP_URL="http://localhost:3000"

# Auth
AUTH_SECRET="CHANGE_ME_LONG_RANDOM_32_CHARS"

# Email (Resend) — required for magic link auth
RESEND_API_KEY="re_CHANGE_ME"
EMAIL_FROM="onboarding@resend.dev"

# Proxy (set to 1 on Railway/Vercel/any reverse proxy)
TRUSTED_PROXY="1"

# LemonSqueezy billing (optional — required for paid plans)
LEMONSQUEEZY_API_KEY=""
LEMONSQUEEZY_STORE_ID=""
LEMONSQUEEZY_VARIANT_ID=""
LEMONSQUEEZY_WEBHOOK_SECRET=""

# Sentry error monitoring (optional, leave empty to disable)
NEXT_PUBLIC_SENTRY_DSN=""

# Plausible analytics (optional, leave empty to disable)
# Set to your domain, e.g. "formgate.jp"
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=""
279 changes: 279 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
# FormGate - Brief CTO Complet

## PRODUIT

**Nom:** FormGate
**Concept:** Formulaires publics → Tickets Backlog automatiquement via API officielle
**Problème:** Formulaire → Mail → Copier → Backlog = perte de temps, erreurs, pas de traçabilité
**Solution:** Formulaire → Ticket direct dans Backlog
**Cible:** PME japonaises, équipes IT/support, utilisateurs Backlog (Nulab)
**Valeur:** Gain temps, 0 erreur, traçabilité, sécurité, conformité API officielle

---

## STACK TECHNIQUE

- Next.js 16
- TypeScript
- Drizzle ORM
- PostgreSQL (Supabase)
- Zod validation
- pnpm
- node:test

---

## CONTRAINTES STRICTES

- API officielle Backlog uniquement (PAS de scraping)
- Stockage minimal données
- JST timezone aware (Japon)
- Sécurité stricte : session cookie httpOnly/secure, guards, CSRF
- Pas de secrets côté client

---

## MODE CTO HARDCORE (PERMANENT)

### Rôle Claude
- Développeur senior + stratège marketing
- Responsable : qualité, sécurité, scalabilité, maintenabilité, commercialisation
- Aucun hack non documenté
- Aucune solution fragile
- Aucun compromis sécurité
- Toujours penser long terme + valeur revente

### Priorités (ordre strict)
1. **Sécurité** — non négociable
2. **Stabilité** — ça doit marcher
3. **Simplicité** — code lisible, maintenable
4. **UX** — onboarding < 5 min
5. **Business** — conversion, pricing
6. **Scaling** — prêt pour 1000 clients

### Philosophie
- Court terme : survivre (MVP fonctionnel, sécurisé, premiers clients)
- Moyen terme : stabiliser (rentabilité, processus, qualité)
- Long terme : dominer (scale, acquisition, ou exit)

---

## RISQUES TECHNIQUES IDENTIFIÉS

| Risque | Mitigation |
|--------|------------|
| Rate limit API Backlog (600 req/h) | Queue Bull, documenter limites, plan Pro |
| Échec API Backlog | Fallback email + retry 3x + logs DB |
| Spam formulaire public | Rate limit IP (10/min) + CAPTCHA optionnel + Zod strict |
| RGPD/JP compliance | Mention consentement, stockage 30j max |

---

## AUDIT RÉALISÉ

### Phase 1 : Sécurité (CRITIQUE) ✅ COMPLÉTÉ
- [x] Auth/Session : magic link auth, cookie httpOnly/secure/sameSite=lax, guards via requireUserFromRequest
- [x] Magic Link : SHA-256 token hash, 15min expiry, single-use, rate limited 3/email/10min (lib/auth/magicLink.ts)
- [x] API Backlog : token storage AES-256-GCM encrypted (PBKDF2 key derivation), rate limit 500 req/h
- [x] Formulaire public : validation Zod stricte, rate limit IP (10/min), max 50 champs, primitives only
- [x] Secrets : .env sécurisé, APP_ENC_KEY pour encryption, pas de secrets côté client
- [x] Logs : sanitized - pas de données sensibles loggées (erreurs sans stack traces)
- [x] Security headers : CSP, X-Frame-Options DENY, X-Content-Type-Options nosniff, etc. (proxy.ts)
- [x] Multi-user isolation : user_email scoping sur forms, submissions, billing, integrations
- [x] Tests sécurité : 279 tests passant, attack simulations (SQL injection, XSS, path traversal, IP spoofing, CSRF, billing bypass)
- [x] CSRF protection : Origin/Referer validation sur toutes les mutations (proxy.ts)
- [x] Billing enforcement : limites form count + submissions/mois côté serveur (lib/billing/planLimits.ts)
- [x] IP extraction hardened : proxy headers ignorés sans TRUSTED_PROXY=1 (anti-spoofing)
- [x] Middleware coverage : /api/integrations/* et /api/billing/* protégés auth
- [x] Public form GET rate limited (30/min anti-enumeration)

### Phase 2 : MVP Features ✅ COMPLÉTÉ
- [x] Custom Fields : champs dynamiques (text, email, number, textarea, select, url, phone, date, checkbox, radio, file)
- lib/validation/fields.ts - schémas Zod pour définition des champs (11 types dont file)
- lib/db/schema.ts - colonne `fields` JSONB sur table forms
- Validation dynamique côté serveur avec buildSubmissionSchema()
- Rendu dynamique dans public-form-client.tsx
- Backward compatible: DEFAULT_FIELDS (email + message) si pas de champs définis
- [x] Field Mapping Backlog : mapper les champs vers Backlog custom fields
- lib/validation/backlogMapping.ts - schémas Zod pour mapping + assignmentRule + subTasks
- lib/backlog/issue.ts - buildMappedIssue() avec templates
- app/api/integrations/backlog/project-meta/route.ts - metadata Backlog (issueTypes, priorities, customFields, members)
- BacklogSettingsClient.tsx - UI complète pour configurer le mapping, assignation, sous-tâches
- drizzle/0005_add_backlog_field_mapping.sql - migration field_mapping JSONB
- 47 tests unitaires (test/backlog.mapping.test.ts)
- [x] Auto-assignation Backlog : règles statiques ou conditionnelles (field_match)
- lib/validation/backlogMapping.ts - AssignmentRuleSchema, evaluateAssignmentRule()
- BacklogSettingsClient.tsx - UI radio none/static/field_match, dropdown membres
- [x] Sous-tâches automatiques : templates de sous-tâches (max 5) après création ticket parent
- lib/backlog/client.ts - createBacklogSubTasks()
- lib/validation/backlogMapping.ts - SubTaskTemplateSchema
- BacklogSettingsClient.tsx - UI liste éditable avec assignee optionnel
- [x] Pièces jointes : upload fichiers vers Backlog (file field type)
- lib/validation/fields.ts - FileFieldSchema (accept, maxFileSize)
- lib/backlog/client.ts - backlogUploadAttachment() multipart
- app/api/public/forms/[slug]/submit/route.ts - FormData parsing, validation (10MB, 3 files, MIME)
- app/f/[slug]/public-form-client.tsx - input file + FormData submission
- Sécurité: validation taille, type MIME, pas de stockage local (stream vers Backlog)
- [x] Admin Field Builder UI : interface pour configurer les champs
- components/field-builder/ - Composants UI (FormEditClient, FieldList, FieldEditor, SelectOptionsEditor, FormPreview)
- app/(dashboard)/forms/[id]/edit/page.tsx - Page d'édition
- lib/i18n/types.ts, ja.ts, en.ts - Traductions fieldBuilder
- test/fieldBuilder.test.ts - Tests client-side validation
- Fonctionnalités: add/remove/reorder fields, type-specific options, live preview, validation temps réel

### Phase 2 : Architecture
- [x] Structure code : séparation, réutilisabilité, testabilité
- [x] Database : indexes, relations, migrations propres (drizzle/0004_add_form_fields.sql)
- [x] Race conditions : transactions atomiques pour forms + submissions (planLimits.ts)
- [x] Branding serveur : vérification subscription côté serveur (app/f/[slug]/page.tsx)
- [x] Billing env validation : 503 clair si LemonSqueezy pas configuré
- [x] Pages légales : CGU + Politique de confidentialité (app/terms/, app/privacy/)
- [x] SEO metadata : titre JP, description, lang="ja" (app/layout.tsx)
- [x] Error pages : 404 + 500 en japonais (app/error.tsx, app/not-found.tsx)
- [x] Billing UI : comparaison plans, barres d'usage, portail client (app/(dashboard)/billing/)
- [x] Dead code cleanup : lib/db.ts supprimé, pg désinstallé
- [x] Performance : subscription cache 60s, direct DB query submissions, server-only guard
- [ ] Scalabilité : prêt 100/1000 clients, bottlenecks identifiés

### Phase 3 : Produit/UX
- [ ] UI japonaise : conventions JP, terminologie, layout culturel
- [x] Onboarding : checklist 3 étapes sur /forms, inline Backlog config, dismiss localStorage
- components/onboarding/OnboardingChecklist.tsx - Checklist dashboard (hasForms/hasBacklog/hasSubmissions)
- components/backlog/BacklogConnectionForm.tsx - Formulaire réutilisable connexion Backlog
- app/(dashboard)/settings/page.tsx + SettingsClient.tsx - Page settings dédiée
- proxy.ts - /settings protégé auth
- DashboardHeader.tsx - nav "Settings" ajouté
- i18n: sections onboarding + settings (JA/EN)
- [ ] Copywriting : messages clairs JP, erreurs compréhensibles, CTAs efficaces
- [x] Analytics : Plausible script conditionnel (NEXT_PUBLIC_PLAUSIBLE_DOMAIN)

### Phase 4 : Observabilité & Lancement
- [x] Sentry : @sentry/nextjs, client/server/edge configs, global-error.tsx, beforeSend sanitization
- sentry.client.config.ts, sentry.server.config.ts, sentry.edge.config.ts
- app/global-error.tsx - capture + affichage erreur globale
- app/error.tsx - capture Sentry ajoutée
- next.config.ts - withSentryConfig conditionnel
- CSP mise à jour (connect-src: *.ingest.sentry.io)
- [x] Analytics : Plausible script conditionnel dans app/layout.tsx
- CSP mise à jour (script-src + connect-src: plausible.io)
- .env.example mis à jour (NEXT_PUBLIC_SENTRY_DSN, NEXT_PUBLIC_PLAUSIBLE_DOMAIN)
- [x] Documentation JP : guide utilisateur /help (app/(dashboard)/help/page.tsx)
- [x] Email templates : notification soumission + welcome email (lib/email/send.ts)
- [x] Copywriting polish : CTAs, messages d'erreur, empty states (lib/i18n/ja.ts, en.ts)
- [x] Magic link cleanup : auto-nettoyage tokens expirés (lib/auth/magicLink.ts)
- [x] Submission detail view : click-to-expand dans la liste des soumissions
- [ ] LemonSqueezy finalization : STORE_ID, VARIANT_ID, webhook, deploy
- [ ] Performance testing : load test, métriques < 3s
- [ ] Backups DB automatiques (Supabase PITR)
- [ ] Support email : channel dédié
- [ ] Scalabilité audit : bottlenecks 100/1000 clients

---

## BUSINESS MODEL

### Pricing
| Plan | Limites | Prix |
|------|---------|------|
| Free | 1 form, 50 sub/mois, branding | 0¥ |
| Starter | 5 forms, 500 sub/mois, sans branding | 2,980¥/mois (~18€) |
| Pro | Illimité, 5000 sub/mois, support prioritaire | 9,800¥/mois (~60€) |
| Enterprise | Custom, SLA, onboarding | 30,000¥+ (~180€+) |

### Marché
- TAM : 52,500 utilisateurs Backlog estimés
- SAM : 3,150 ont besoin intégration + prêts payer
- SOM An 1 : 31 clients = 6,700€ ARR (1% pénétration)

### Différenciateurs vs Zapier/Make
- Setup < 5 min (vs 20-30 min)
- Support japonais natif
- Spécialisé Backlog (pas généraliste)
- UI/UX japonaise
- Prix compétitif

---

## GO-TO-MARKET (Budget 0€)

1. **Partenariat Nulab** — devenir partenaire officiel, App Marketplace
2. **Content SEO JP** — Qiita, Note.com ("Backlog連携", "フォーム自動化")
3. **Community** — Nulab forums, Facebook groups PME JP
4. **Freemium viral** — watermark "Powered by FormGate"
5. **Outreach direct** — 20 emails/semaine ciblés

---

## PROJECTIONS (Side project 1-2h/jour)

### Timeline
- Mois 1-2 : Dev MVP (40-80h)
- Mois 3-4 : Validation marché (50-100 signups free)
- Mois 5-6 : Premiers payants (5-10 clients)
- Mois 7-12 : Croissance organique (20-50 clients)

### Seuils de décision
| Mois | Stop/Pivot | Continuer | Accélérer |
|------|------------|-----------|-----------|
| 6 | < 3 clients | 5-10 clients | > 15 clients |
| 12 | < 500€ MRR | 500-1,500€ MRR | > 2,000€ MRR |

---

## CHECKLIST PRÉ-LANCEMENT

### Technique
- [x] Tests sécurité passés (279 tests, attack simulations, attacker-perspective tests)
- [x] Magic link auth + multi-user (lib/auth/magicLink.ts, lib/auth/requireUser.ts)
- [x] Rate limiting actif (IP 10/min submit, 30/min read, Backlog API 500/h)
- [x] CSRF protection (proxy.ts)
- [x] Billing enforcement server-side (lib/billing/planLimits.ts)
- [x] Error monitoring (Sentry) — @sentry/nextjs, client+server+edge configs, global-error.tsx
- [ ] Backups DB automatiques
- [ ] SSL/HTTPS
- [ ] Performance < 3s load

### Produit
- [x] Onboarding : checklist 3 étapes + settings page + inline Backlog form
- [x] Documentation JP : guide utilisateur /help
- [x] FAQ : section landing page + guide
- [x] Email templates : magic link, notification soumission, welcome
- [x] Terms of Service JP (app/terms/)
- [x] Privacy Policy (app/privacy/)

### Business
- [ ] LemonSqueezy finalisé (STORE_ID, VARIANT_ID, webhook, deploy)
- [ ] Invoicing automatique
- [ ] Support email
- [x] Analytics (Plausible) — script conditionnel via NEXT_PUBLIC_PLAUSIBLE_DOMAIN
- [x] Landing page SEO : metadata, pain points, FAQ, CTAs optimisés

---

## WORKFLOW GIT

- Branches : `main` (prod), `dev` (développement), `feature/*` (features)
- Commits : messages clairs en anglais, format conventionnel
- PR : documentées, review avant merge
- Push : après chaque feature/fix complète

---

## INSTRUCTIONS CLAUDE CODE

1. Lis ce fichier + README.md en entier avant toute action
2. Fais un audit complet avant de modifier
3. Priorise sécurité > stabilité > reste
4. Commit + push chaque changement significatif
5. Messages commit clairs : `fix(security): ...`, `feat(form): ...`, `refactor(api): ...`
6. Si doute → demande avant d'agir
7. **OBLIGATOIRE : Mettre à jour README.md à chaque changement significatif** avec :
- État actuel (features implémentées/en cours)
- Derniers commits (hash + description)
- Fichiers modifiés (avec leur rôle)
- Prochaines tâches (priorité + fichiers concernés)
- Prompts de reprise pour Claude (copy-paste ready)

---

*Dernière mise à jour : 19 février 2026*
Loading