You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
4.**SEO-first**- every public page has JSON-LD, OG metadata, sitemap entries.
32
32
33
33
## ISR revalidation (required for all marketing pages)
34
34
@@ -38,7 +38,7 @@ Every `app/(marketing)/**/page.tsx` that calls any API fetch **must** export:
38
38
exportconst revalidate =3600;
39
39
```
40
40
41
-
Without this, pages are pure dynamic SSR — every request hits the API live. On Vercel, a slow or cold API response causes a function timeout → error page. With `revalidate`, Vercel pre-renders at build time and serves cached HTML, revalidating in the background. Reload-fixes-it is the symptom of a missing `revalidate`.
41
+
Without this, pages are pure dynamic SSR - every request hits the API live. On Vercel, a slow or cold API response causes a function timeout → error page. With `revalidate`, Vercel pre-renders at build time and serves cached HTML, revalidating in the background. Reload-fixes-it is the symptom of a missing `revalidate`.
42
42
43
43
## Breadcrumbs
44
44
@@ -65,8 +65,8 @@ Pages currently missing breadcrumbs (add when touching): `dieu-khoan`, `docs`, `
65
65
See `@.claude/docs/layout.md` for container conventions and CSS/typography rules.
66
66
67
67
## API authentication
68
-
- Always use `apiFetch()` from `lib/api.ts`— auto-injects `X-OpenWallet-Key` header.
69
-
- Never use `NEXT_PUBLIC_` prefix for `OPENWALLET_API_KEY`— server-only build secret.
68
+
- Always use `apiFetch()` from `lib/api.ts`- auto-injects `X-OpenWallet-Key` header.
69
+
- Never use `NEXT_PUBLIC_` prefix for `OPENWALLET_API_KEY`- server-only build secret.
70
70
- Never use raw `fetch()` for API calls. Pass only path: `apiFetch('/api/v1/cards')`.
71
71
72
72
## Blog content rules
@@ -76,44 +76,44 @@ See `@.claude/docs/layout.md` for container conventions and CSS/typography rules
-**No em dashes (—):** Never use em dashes in any page content or metadata. Replace with a comma, colon, parentheses, or restructure the sentence. Em dashes are a visible AI writing signal.
79
+
-**No em dashes (-):** Never use em dashes in any page content or metadata. Replace with a comma, colon, parentheses, or restructure the sentence. Em dashes are a visible AI writing signal.
80
80
-**Tone for public pages:** Professional and honest, not corporate or casual. Use "chúng tôi" consistently. Avoid overly informal phrasing.
81
81
82
82
## Feature gate status
83
83
84
-
### Wallet app (`/app/*`) — FROZEN
84
+
### Wallet app (`/app/*`) - FROZEN
85
85
- Routes return 404 unless `WALLET_ENABLED=true` env var is set.
86
86
- Gate is in `app/app/layout.tsx` (server component) → calls `notFound()`.
87
87
- Shell code lives in `app/app/app-shell.tsx` (client component, untouched).
88
-
-`WalletNavButton` component exists but is not used anywhere — do not add it to nav.
88
+
-`WalletNavButton` component exists but is not used anywhere - do not add it to nav.
89
89
- Do not delete wallet code. May revive later. ROI currently too low vs competitors.
90
90
-`public/robots.txt` has `Disallow: /app`. Keep this.
91
91
92
92
### Chat (`/chat`, `openwallet-chat`)
93
-
-**Chat button hidden**—`ChatToggleButton` removed from `components/layout/header.tsx` (both desktop + mobile). Do not re-add unless explicitly requested.
93
+
-**Chat button hidden**-`ChatToggleButton` removed from `components/layout/header.tsx` (both desktop + mobile). Do not re-add unless explicitly requested.
94
94
- Not ready for public release. Needs evals + system prompt iteration first.
95
-
-See `evals/` folder for eval harness.
95
+
-**Full chat docs (arch, logging, Langfuse, evals, dev plan):**`.claude/docs/chat.md`
96
96
97
97
### `so-sanh-404-redirect`
98
98
- Active. Handles legacy `/card-battle/X-vs-Y` URLs → redirects to `/card-battle?compare=X,Y`.
99
99
- Lives in `components/layout/so-sanh-404-redirect.tsx`, used in `app/not-found.tsx`. Do not remove.
100
100
101
101
## Card ranking
102
102
103
-
**Architecture SSOT: `../api/.claude/docs/card-recommendation-architecture.md`**— authoritative doc for intent model, intent groups, ranking rules, and data quality requirements. Read this before touching any ranking or recommendation code.
103
+
**Architecture SSOT: `../api/.claude/docs/card-recommendation-architecture.md`**- authoritative doc for intent model, intent groups, ranking rules, and data quality requirements. Read this before touching any ranking or recommendation code.
104
104
105
105
**Ranking logic lives in the API repo.** The web repo only consumes results:
106
-
-`lib/cashback-calc.ts`— cashback estimation (mirrors API logic for display)
107
-
-`lib/card-ranker.ts`— sort order only (cashback desc → annual_fee asc → network_popularity asc)
108
-
-`components/marketing/card-ranking-table.tsx`— UI with spend selector
1. Before any task: check `.claude/commands/` for a relevant command file.
113
113
2. After creating a command: add it to the commands table below.
114
114
3. After non-trivial task: check if `.claude/docs/learnings/` needs a new note.
115
-
4.**Question-only mode:** If the message starts with `question:` or `answer me:`, only answer — do NOT edit any files or run any commands.
116
-
5.**Changelog:** After card data or feature changes, add entry to `content/changelog.mdx`. Use `/add-changelog`. Card/feature scope only — no UI or page structure changes. See `.claude/docs/changelog.md` for purpose, rules, tone, and format guide.
115
+
4.**Question-only mode:** If the message starts with `question:` or `answer me:`, only answer - do NOT edit any files or run any commands.
116
+
5.**Changelog:** After card data or feature changes, add entry to `content/changelog.mdx`. Use `/add-changelog`. Card/feature scope only - no UI or page structure changes. See `.claude/docs/changelog.md` for purpose, rules, tone, and format guide.
117
117
118
118
## Custom commands
119
119
@@ -128,8 +128,10 @@ See `@.claude/docs/layout.md` for container conventions and CSS/typography rules
128
128
|`/add-ow-ui`|`commands/add-ow-ui.md`| Move component to `ow-ui/`, rename to `Ow*`, create story, report usages |
129
129
|`/commit-all`|`commands/commit-all.md`| Stage + commit all changes in logical groups with conventional commit messages |
130
130
|`/sync-api-types`|`commands/sync-api-types.md`| Regenerate types from API schema, diff changes, scan codebase, suggest updates |
131
+
|`/edit-system-prompt`|`commands/edit-system-prompt.md`| Edit Owie's system prompt, enforce invariants, push to Langfuse |
-**Positive over negative** - "do X" beats "don't do Y" where possible
30
+
-**Concrete over vague** - add examples for new rules, not just descriptions
31
+
-**No contradictions** - new rules must not conflict with existing ones; later rule wins but inconsistently
32
+
-**Tool rules last** - LLMs read top-heavy; scope/persona matters most at top
33
+
34
+
### 3. Sync the fallback
35
+
`buildSystemPrompt()` in same file uses `SYSTEM_PROMPT` as base - no separate edit needed. But if `pageContext` injection logic changes, update the `if (pageContext.type === ...)` blocks too.
36
+
37
+
### 4. Check evals coverage
38
+
- Does the change affect any of the 13 eval test cases in `evals/`?
39
+
- If new behavior added: note it needs a new eval case (don't write it now unless asked).
40
+
41
+
### 5. Push to Langfuse
42
+
**STOP - do NOT run the push command automatically. Show the diff and ask for confirmation first.**
43
+
44
+
After editing, show the user what changed, then ask: "Push to Langfuse as version N?"
45
+
46
+
Only run after explicit user approval:
47
+
```bash
48
+
pnpm push:prompt
49
+
```
50
+
- Pushes `SYSTEM_PROMPT` const to Langfuse as new `production` version
51
+
- Live within 60s (cache TTL in `fetchSystemPrompt()`)
52
+
- Confirm output shows `✓ Pushed version N`
53
+
-**Note:**`STATIC_LISTS` (persona/merchant lists injected by `buildSystemPrompt()`) are NOT pushed - they are always injected at runtime from local constants. Langfuse only stores the base prompt text.
54
+
55
+
### 6. Verify
56
+
- Check Langfuse UI or wait 60s and test via `/chat`
57
+
- Hardcoded fallback in `lib/chat/system-prompt.ts` is the source of truth for the push script - they stay in sync automatically
58
+
59
+
## What NOT to change via this command
60
+
-`buildSystemPrompt()` function signature or `pageContext` types - that's a code change, not a prompt change
0 commit comments