- Add Astro native i18n routing (prefixDefaultLocale: false) - Introduce GeneratorLayout to deduplicate all generator pages - Enrich generator data with pageTitle, ruPageTitle, howTo/whenTo arrays - Make EN and RU generator pages identical using @/ path aliases - Extract analytics (Yandex Metrika + Top.Mail.Ru) into Analytics.astro - Move tracker IDs to src/data/config.ts, inject via define:vars - Migrate generator metadata to Content Collections (src/content/generators/*.json) - Add Zod schema with .strict() validation in src/lib/generator-schema.ts - Update CLAUDE.md with new conventions
4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What this is
Randify is a bilingual (EN/RU) static site (Astro 4 + Tailwind CSS 4) hosting random-value generators. All 10 generators are live. Deployed to randify.pro on reg.ru via GitHub Actions + rsync on push to main.
i18n is handled via Astro's built-in i18n routing. English pages live at src/pages/, Russian pages at src/pages/ru/. Both share identical templates because BaseLayout, GeneratorLayout, and components derive the active locale from Astro.currentLocale.
Commands
npm run dev # Dev server (localhost:4321)
npm run build # Static build → dist/
npm run preview # Serve the built dist/ locally
Docker (production): multi-stage build with Node 20, served via nginx:alpine with pretty URLs.
docker build -t randify .
docker run -p 8080:80 randify
No test runner or linter is configured.
Adding a new generator
Every new generator must be created in both English and Russian simultaneously.
-
src/content/generators/<slug>.json— create a JSON file with all fields:slug,title,description,icon,status,seoTitle,seoDescription,ruTitle,ruDescription,ruSeoTitle,ruSeoDescription,pageTitle,ruPageTitle,howTo,whenTo,ruHowTo,ruWhenTo. The schema is defined insrc/lib/generator-schema.tsand validated automatically at build time via Zod (.strict()— unknown fields will fail the build). -
src/components/generators/<Name>Generator.astro— the interactive component. Language detection pattern:- Frontmatter:
const isRu = Astro.url.pathname.startsWith('/ru'); const T = useT(isRu ? 'ru' : 'en'); - Client script:
const isRu = document.documentElement.lang === 'ru'; - Use
T.*keys for all user-visible strings in the template; useisRuternaries in the<script>block.
- Frontmatter:
-
src/pages/generators/<slug>.astro— create the page usingGeneratorLayout:--- import GeneratorLayout from '@/layouts/GeneratorLayout.astro'; import <Name>Generator from '@/components/generators/<Name>Generator.astro'; import { generators } from '@/data/generators'; const generator = generators.find((g) => g.slug === '<slug>')!; --- <GeneratorLayout generator={generator}> <<Name>Generator /> </GeneratorLayout> -
src/pages/ru/generators/<slug>.astro— copy the English file exactly. Because both files use@/path aliases andGeneratorLayoutderives the locale fromAstro.currentLocale, the file content is identical for both languages.
Critical: Never use a shared dynamic [slug].astro for Russian pages. Astro bundles scripts from all imported components — using a single file that imports all 10 generators causes every Russian page to run all 10 scripts, breaking them. Each page must be its own file importing only its generator.
i18n system
src/i18n/translations.ts— centralen/rutranslation objects. All UI strings (labels, buttons, errors, copy/copied feedback) live here.useT(lang)returns the typed translation object.src/components/LanguageSwitcher.astro— fixed top-right EN/RU toggle; persists choice inlocalStorage('lang-pref').src/layouts/BaseLayout.astro— acceptslangprop ('en' | 'ru'), sets<html lang>, injectshreflangalternates, and includes auto-redirect script (first visit, Russian browser →/ru/).- English pages:
/generators/<slug>/— Russian pages:/ru/generators/<slug>/ - Path aliases
@/*resolve tosrc/*and are used in all page files so EN and RU templates can be identical. GeneratorLayout.astrowraps every generator page: breadcrumb, header, AdBanner, SeoBlock, and slot for the interactive component.
Key conventions
- Accent color:
#534AB7(CSS var--accentin BaseLayout). - All SVG icons are inlined strings in the
iconsmap insideGeneratorCard.astro; add new ones there. GeneratorCard.astroauto-detects locale fromAstro.currentLocalewhen nolangprop is passed.SeoBlock.astroacceptslangprop for translated "How to use" / "When to use" headers.AdBanner.astrorandomises between two Yandex referral links; three size variants:leaderboard,rectangle,tile.- Yandex Metrika counter (ID
109130319) and Top.Mail.Ru counter (ID3765043) live insrc/components/Analytics.astro. IDs are configured insrc/data/config.tsand injected viadefine:vars. - No client-side router — each generator is a separate static HTML page.