Files
Randify.pro/CLAUDE.md
T
emil f1ba82735b refactor: i18n routing, shared GeneratorLayout, analytics component, content collections
- 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
2026-05-10 20:42:05 +03:00

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.

  1. 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 in src/lib/generator-schema.ts and validated automatically at build time via Zod (.strict() — unknown fields will fail the build).

  2. 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; use isRu ternaries in the <script> block.
  3. src/pages/generators/<slug>.astro — create the page using GeneratorLayout:

    ---
    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>
    
  4. src/pages/ru/generators/<slug>.astro — copy the English file exactly. Because both files use @/ path aliases and GeneratorLayout derives the locale from Astro.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 — central en/ru translation 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 in localStorage('lang-pref').
  • src/layouts/BaseLayout.astro — accepts lang prop ('en' | 'ru'), sets <html lang>, injects hreflang alternates, and includes auto-redirect script (first visit, Russian browser → /ru/).
  • English pages: /generators/<slug>/ — Russian pages: /ru/generators/<slug>/
  • Path aliases @/* resolve to src/* and are used in all page files so EN and RU templates can be identical.
  • GeneratorLayout.astro wraps every generator page: breadcrumb, header, AdBanner, SeoBlock, and slot for the interactive component.

Key conventions

  • Accent color: #534AB7 (CSS var --accent in BaseLayout).
  • All SVG icons are inlined strings in the icons map inside GeneratorCard.astro; add new ones there.
  • GeneratorCard.astro auto-detects locale from Astro.currentLocale when no lang prop is passed.
  • SeoBlock.astro accepts lang prop for translated "How to use" / "When to use" headers.
  • AdBanner.astro randomises between two Yandex referral links; three size variants: leaderboard, rectangle, tile.
  • Yandex Metrika counter (ID 109130319) and Top.Mail.Ru counter (ID 3765043) live in src/components/Analytics.astro. IDs are configured in src/data/config.ts and injected via define:vars.
  • No client-side router — each generator is a separate static HTML page.