|
1 | 1 | # AGENTS.md |
2 | 2 |
|
3 | | -This file provides guidance to Codex (Codex.ai/code) when working with code in this repository. |
| 3 | +## Internationalization |
4 | 4 |
|
5 | | -## Internationalization (i18n) |
| 5 | +- Translation resources live under `translations/`. Every page, module, and data change must support every locale configured in `src/i18n/config.ts`; never hardcode a locale subset. |
| 6 | +- Always use `Link` from `@/i18n/navigation`, not the Next.js default. |
| 7 | +- Localize page metadata and reuse existing translation keys and shared phrases before adding new ones. |
| 8 | +- Follow [docs/I18N-ARCHITECTURE-RULES.md](docs/I18N-ARCHITECTURE-RULES.md): keep page and component translations in their prescribed namespaces, co-locate page metadata under `meta`, and minimize cross-namespace `@:` references. |
| 9 | +- Add new keys to every locale with English placeholders first; perform proper translation as a separate batch. |
6 | 10 |
|
7 | | -**Translation Resources Location:** All translation files are located in the `translations/` directory at the project root, organized by locale code (e.g., `translations/en/`, `translations/zh-Hans/`). |
| 11 | +## Data and Schema |
8 | 12 |
|
9 | | -When creating or modifying any page, module, or data: |
10 | | -- **MUST support all configured languages (12 total):** |
11 | | - - English (en) |
12 | | - - German (de) |
13 | | - - Spanish (es) |
14 | | - - French (fr) |
15 | | - - Indonesian (id) |
16 | | - - Japanese (ja) |
17 | | - - Korean (ko) |
18 | | - - Portuguese (pt) |
19 | | - - Russian (ru) |
20 | | - - Turkish (tr) |
21 | | - - Simplified Chinese (zh-Hans) |
22 | | - - Traditional Chinese (zh-Hant) |
| 13 | +- Never store product, catalog, editorial, ranking, pricing, benchmark, configuration, or other independently adjustable data in `.ts` or `.tsx` files. |
| 14 | +- Store data in schema-validated JSON under `data/`, the appropriate manifest, or translation resources. This includes curated selections, display order, metadata, prices, scores, timelines, chart-label placement, and ranking weights. |
| 15 | +- TypeScript may contain types, loaders, validators, transformations, calculations, presentation logic, and implementation-only constants with no product or editorial meaning. When uncertain, treat a value as data. |
| 16 | +- Update the JSON schema, corresponding TypeScript type, and validation tests together whenever a data shape changes. |
| 17 | +- Keep `src/types/manifests.ts` in one-to-one correspondence with the schemas under `manifests/$schemas/`. |
23 | 18 |
|
24 | | -- **NEVER hardcode** a subset of locales like `'en' | 'zh-Hans'` |
25 | | -- **MUST use the localized Link component:** Always import and use `import { Link } from '@/i18n/navigation'` instead of Next.js default Link |
| 19 | +## Design |
26 | 20 |
|
27 | | -### Localization Best Practices |
| 21 | +- Use the existing extremely minimalist visual language: sharp corners, restrained low-saturation color, and accents only where necessary. |
| 22 | +- Prefer Lucide SVG icons; do not use emoji or text characters as icons. |
| 23 | +- Use `max-w-8xl` globally and `max-w-6xl` for content pages and the homepage. |
28 | 24 |
|
29 | | -- **Metadata localization:** All meta information (titles, descriptions, keywords, OG tags, etc.) in pages MUST be properly localized |
30 | | -- **DRY principle for translations:** Before creating new translation keys, search existing translation modules thoroughly to reuse existing terms and phrases |
31 | | -- **Consistency:** Use the same translation keys across similar contexts |
| 25 | +## Metadata and SEO |
32 | 26 |
|
33 | | -### Translation File Organization |
34 | | - |
35 | | -Follow the detailed architecture rules in [docs/I18N-ARCHITECTURE-RULES.md](docs/I18N-ARCHITECTURE-RULES.md) for organizing translation resources. |
36 | | - |
37 | | -**Core Principles:** |
38 | | -1. **Page translations**: Each page or page group should have its own JSON file (e.g., `ides.json`, `ide-detail.json`) |
39 | | -2. **Component translations**: Organize by component directory: |
40 | | - - `components/common.json` - Root-level components (Header, Footer, etc.) |
41 | | - - `components/navigation.json` - All navigation/* components |
42 | | - - `components/controls.json` - All controls/* components |
43 | | - - `components/sidebar.json` - All sidebar/* components |
44 | | - - `components/product.json` - All product/* components |
45 | | -3. **Minimize `@:` references**: Use `tPage + tShared` or `tComponent + tShared` patterns in code instead of cross-namespace references in JSON |
46 | | -4. **Metadata placement**: Co-locate page metadata (title, description, etc.) with page translations under a `meta` object |
47 | | -5. **Multi-language workflow**: New translation keys should initially use English placeholders across all locales, with proper translation in a separate batch step |
48 | | - |
49 | | -**Usage Pattern:** |
50 | | -```tsx |
51 | | -// Pages |
52 | | -const tPage = useTranslations('pages.modelDetail') |
53 | | -const tShared = useTranslations('shared') |
54 | | - |
55 | | -// Components (root-level) |
56 | | -const tComponent = useTranslations('components.common.header') |
57 | | - |
58 | | -// Components (subdirectories) |
59 | | -const tComponent = useTranslations('components.navigation.breadcrumb') |
60 | | -``` |
61 | | - |
62 | | -## Design System |
63 | | - |
64 | | -**Global Design Principles:** |
65 | | - |
66 | | -- **Minimalist approach:** Follow a unified, extremely minimalist design style throughout the entire application |
67 | | -- **No rounded corners:** All controls, components, labels, and UI elements MUST use sharp corners (border-radius: 0) |
68 | | -- **Restrained color usage:** Use colors extremely sparingly and intentionally. Prefer grayscale and limit accent colors to essential UI elements only. If colors must be used, prefer low-saturation designs. |
69 | | -- **Icon usage:** Prefer using Lucide SVG icons. Avoid using emoji or any other characters as icons. |
70 | | -- **Page width:** |
71 | | - - `max-w-8xl`: for all pages globally |
72 | | - - `max-w-6xl`: for content pages and homepage |
73 | | - |
74 | | -## Coding Principles |
75 | | - |
76 | | -### DRY - Don't Repeat Yourself |
77 | | -- Eliminate code duplication by extracting common logic |
78 | | -- Reuse existing components, functions, and translation keys |
79 | | -- Create shared utilities when patterns emerge |
80 | | - |
81 | | -### Type Safety & Schema Alignment |
82 | | -- **Manifest type definitions:** Always ensure that `src/types/manifests.ts` stays in one-to-one correspondence with the JSON schemas in `manifests/$schemas/` |
83 | | -- When modifying schema files, update the corresponding TypeScript types accordingly |
84 | | -- When adding new types, verify they match the schema structure exactly |
85 | | -- Maintain consistency between schema definitions and type definitions to prevent runtime errors |
86 | | - |
87 | | -## Metadata & SEO |
88 | | - |
89 | | -- **File-based OG images:** Use `opengraph-image.tsx` files for all routes, NOT code-based image paths |
90 | | -- **Request memoization:** Wrap all data fetchers with React `cache()` to prevent duplicate fetching in `generateMetadata()` and page components |
91 | | -- **Type-safe locales:** Always use `import type { Locale } from '@/i18n/config'` |
92 | | -- **Auto-detected OG images:** Do NOT manually specify `images` in OpenGraph metadata - Next.js auto-detects `opengraph-image.tsx` files |
93 | | - |
94 | | -**OG Image Design:** |
95 | | -- Size: 1200x630px (OpenGraph standard) |
96 | | -- Follow global design system strictly |
| 27 | +- Use route-level `opengraph-image.tsx` files; do not manually set OpenGraph image paths. OG images are 1200×630 and follow the design system. |
| 28 | +- Wrap data fetchers shared by `generateMetadata()` and page rendering with React `cache()`. |
| 29 | +- Use `Locale` from `@/i18n/config` for locale types. |
97 | 30 |
|
98 | 31 | ## Development Workflow |
99 | 32 |
|
100 | | -- **Development server:** Do not start `npm run dev` automatically. User will start it manually when needed. |
101 | | -- **Standalone preview assets:** Before starting `.next/standalone/server.js`, sync `public/` into `.next/standalone/public/` and `.next/static/` into `.next/standalone/.next/static/`. Repeat this after every production build because Next.js regenerates `.next/standalone/`. Never start the standalone server without these assets. |
102 | | -- **Standalone preview host:** The standalone server `HOSTNAME` must match the hostname used in the preview URL. For a `http://localhost:<port>` preview, start with `HOSTNAME=localhost`; do not substitute `127.0.0.1`, because locale middleware rewrites can otherwise become self-redirects. |
103 | | -- **Standalone preview verification:** After starting or restarting a standalone preview, verify that one default-locale URL without a locale prefix returns `200`, one locale-prefixed URL returns `200`, and a stylesheet referenced by the page returns `200` with a CSS content type. When using tmux, include the asset sync and matching `HOSTNAME` in the pane start command. |
104 | | -- **Git commits:** Do not create commits autonomously. Always ask the user before committing changes. |
| 33 | +- Do not start `npm run dev` automatically; the user starts it when needed. |
| 34 | +- Before every `.next/standalone/server.js` start, including after each production build, sync `public/` to `.next/standalone/public/` and `.next/static/` to `.next/standalone/.next/static/`. |
| 35 | +- Match standalone `HOSTNAME` to the preview URL hostname. For `http://localhost:<port>`, use `HOSTNAME=localhost`, never `127.0.0.1`. |
| 36 | +- After each standalone start or restart, verify a default-locale URL, a locale-prefixed URL, and a referenced stylesheet all return `200`, with the stylesheet served as CSS. A tmux start command must include asset sync and the matching `HOSTNAME`. |
| 37 | +- Never create a commit without asking the user first. |
0 commit comments