Transforms markdown content from docs/{lang}/ into beautiful Astro pages and components. Supports multi-language builds (en, fr, sw). Creates dynamic [lang] routes, language-aware content loading, and language switcher component. Use after design-system and photo-manager have run.
Installation
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Transforms markdown content from docs/{lang}/ into beautiful Astro pages and components. Supports multi-language builds (en, fr, sw). Creates dynamic [lang] routes, language-aware content loading, and language switcher component. Use after design-system and photo-manager have run.
Page Builder Skill
Transform markdown content into stunning, production-grade Astro pages.
Universal Guidelines Reference
Before building pages, review Universal Design Guidelines for:
Visual hierarchy and cognitive load reduction
Scannable content formatting (headings, lists, short paragraphs)
Clear CTAs (calls-to-action) and value propositions
Content strategy and information architecture
Keyboard navigation and screen reader compatibility
Mobile-first responsive design approach
This skill applies these universal content and UX principles to Astro implementation.
Before Building ANY Page
Read these files first:
design-tokens.md — the design system decisions (fonts, colors, patterns)
src/assets/images/_catalog.json — available photos and their dimensions
docs/{lang}/pages.md — page structure and navigation for THIS language
The specific docs/{lang}/*.md file for the page content
Universal Design Guidelines — for content strategy and UX principles
Language Standards — tone, grammar, and style for THIS language (from language-standards skill)
Multi-Language Note: You are building pages for ONE language at a time. The website-builder will call you once per enabled language. Read content from docs/{lang}/ (e.g., docs/en/, docs/fr/, docs/sw/), not the root docs/ directory.
Build Order
First Time Only (All Languages)
src/utils/i18n.ts — language validation and utilities (shared, not language-specific)
src/components/LanguageSwitcher.astro — language switcher (shared)
src/layouts/BaseLayout.astro — language-aware HTML shell (shared, accepts lang prop)
src/components/Header.astro — language-aware navigation (shared, includes LanguageSwitcher)
Language switcher (NEW) — LanguageSwitcher component showing en/fr/sw options
CTA button if specified
Sticky/fixed positioning with backdrop blur
Clean transition on scroll (background opacity change)
---
import type { Language } from '../utils/i18n';
import LanguageSwitcher from './LanguageSwitcher.astro';
interface Props {
lang: Language; // NEW: current language
}
const { lang } = Astro.props;
const currentPath = new URL(Astro.request.url).pathname.replace(/^\/[a-z]{2}/, '') || '/';
---
<!-- Mobile menu with Alpine.js -->
<header class="sticky top-0 z-50 bg-white/95 backdrop-blur-lg">
<nav x-data="{ open: false }" class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
{/* Logo */}
<a href={`/${lang}/`}>Logo / Company Name</a>
{/* Desktop nav */}
<div class="hidden md:flex gap-8 items-center">
<a href={`/${lang}/about`}>About</a>
<a href={`/${lang}/services`}>Services</a>
{/* More links from pages.md */}
</div>
{/* Language Switcher (NEW) */}
<div class="hidden md:block">
<LanguageSwitcher currentLang={lang} currentPath={currentPath} />
</div>
{/* Mobile toggle */}
<button @click="open = !open" class="md:hidden">Menu</button>
{/* Mobile menu */}
<div x-show="open" x-transition class="absolute top-full left-0 right-0 bg-white md:hidden">
<a href={`/${lang}/about`}>About</a>
<a href={`/${lang}/services`}>Services</a>
{/* Language Switcher in mobile menu */}
<LanguageSwitcher currentLang={lang} currentPath={currentPath} />
</div>
</nav>
</header>
LanguageSwitcher (NEW): This component is automatically included. It shows language options (English, Français, Kiswahili) and navigates to the same page in the selected language. See i18n/SKILL.md for the component definition.
Section Patterns
Hero Sections
Every page gets a hero. Vary the style per page:
Homepage hero: Full-viewport, dramatic. Background image or gradient, large display font headline, subtitle, CTA button. Consider split layout (text left, image right) or full-bleed image with overlay.
Inner page hero: Shorter (40-50vh), page title prominent, optional breadcrumb, subtle background texture or color.
Screenshots and product images MUST be clickable with a fullscreen lightbox so users can view them at real size. Thumbnails alone don't communicate enough detail.
Implementation pattern:
Lightbox component (src/components/Lightbox.astro) — included once per page via BaseLayout. Uses Alpine.js x-on:open-lightbox.window to listen for custom events. Renders a fullscreen overlay with close button (X), Escape key, click-outside-to-close, caption bar, and cursor-zoom-out.
BaseLayout includes <Lightbox /> just before the Alpine.js script tag. This makes the lightbox available on every page automatically.
Screenshot thumbnails use the .screenshot-trigger CSS class and dispatch Alpine events:
CSS (in global.css) for .screenshot-trigger: cursor: zoom-in, hover scale, gradient overlay, and .expand-hint label that fades in on hover.
French label: Use "Cliquez pour agrandir" instead of "Click to enlarge". Mobile screenshots: use "Enlarge" / "Agrandir".
Rules:
NEVER show screenshots as static thumbnails — always make them clickable
Every screenshot container needs x-data and @click="$dispatch('open-lightbox', ...)"
The lightbox is zero-dependency (Alpine.js only, no external library)
Mobile screenshots also get the lightbox treatment
CTA Sections
Bold, contrasting background. Clear action. One button, one message.
Contact
Contact info (from docs/contact.md)
Simple form (Astro can handle this with form actions or static)
Embedded map (optional, use iframe)
Social links
Nested Border Radius Rule (MANDATORY)
Never round inner elements the same as their parent container. Apply the formula: outer radius = inner radius + padding. When a card uses rounded-2xl (16px) with p-4 (16px padding), inner images/buttons/elements must use a smaller radius like rounded-lg (8px) or rounded-xl (12px). Matching radii on parent and child creates bulgy, uneven corners. Always subtract the gap/padding from the parent radius.
ALWAYS use object-cover for background-style images
Check _catalog.json for available images before using ANY image
Image cards MUST NEVER have white space. Always add img { display: block; } in the base layer of global.css. Every image inside a card must use w-full h-full object-cover (or object-contain for product shots only). The image container must have overflow-hidden and a height constraint (h-full, aspect-[ratio], or explicit height). Never leave an image at its default inline display — this causes a baseline gap that produces ugly white space at the bottom of cards.
Multi-Language Text Expansion (NEW)
French and Kiswahili content will be longer than English. Design with flexibility:
Language
Expansion
Design Impact
English
1.0x (baseline)
Base design
French
1.2–1.4x
~30% longer text
Kiswahili
1.1–1.3x
~20% longer text
Flex Design Principles:
Use min-width and max-width, never fixed widths
Test all buttons, labels, and CTAs with longer text
Navigation items must wrap gracefully on smaller screens
Forms must accommodate longer labels without overlapping inputs
Avoid text in images (impossible to translate)
Testing Checklist for Multi-Language:
French button labels don't overflow
Kiswahili form labels align properly
Navigation items wrap at mobile breakpoints for all languages
Hero headlines don't become illegible in French/Kiswahili
Responsive Design Checklist
For EVERY page in EVERY language, mentally verify:
375px (mobile): Single column, readable text (min 16px), tappable buttons (min 44x44px), no horizontal scroll, text wraps properly
768px (tablet): 2-column grids where appropriate, comfortable spacing, French/Kiswahili text fits
1280px (desktop): Full layout, max-w-7xl container, generous whitespace, buttons/labels flex for longer text
Navigation: Hamburger on mobile, full nav on desktop, language switcher visible
Images: Responsive srcsets, never wider than viewport
Typography: Scales up on larger screens (text-4xl md:text-5xl lg:text-6xl), baseline text readable
Accessibility Requirements
Proper heading hierarchy (one h1 per page, sequential h2-h6)
Alt text on all images
aria-labels on icon-only buttons
Focus-visible styles on interactive elements
Sufficient color contrast (4.5:1 for body text, 3:1 for large text)
Element-vs-background contrast check (MANDATORY): Before using ANY colour class on a button, badge, text, or element, verify that the colour token actually exists in the theme (global.css@theme block) AND that it contrasts against its parent section background. For example, bg-amber does not exist if the theme only defines bg-amber-500; an undefined class renders no background, making the element invisible. Always cross-reference the exact token names in @theme. On dark backgrounds (navy, sea-800, sea-900), use bg-highlight (amber) or bg-white; on light backgrounds, use bg-primary, bg-sea-800, or bg-navy.
Skip-to-content link in BaseLayout
Keyboard navigable mobile menu
Performance Rules
NO external scripts (no Google Fonts, no analytics CDN, no external JS)
Fonts self-hosted via Fontsource
Images optimized via Astro (auto WebP/AVIF)
Critical CSS inlined by Astro
Minimal JavaScript — only Alpine.js for interactivity + scroll observer
Lazy load all below-fold images
Content Best Practices
Scannable Content Formatting
Users scan, they don't read. Format all content for quick comprehension:
Formatting Rules:
Descriptive headings (tell story in headlines)
Bullet points for features/benefits (break up paragraphs)
Short paragraphs (3-4 lines maximum)
Bold key terms and phrases
Images/visuals every 200-300 words
Adequate whitespace between sections
Content Structure:
Headline (value prop)
↓
2-3 short paragraphs (context)
↓
Bullet points (benefits/features)
↓
Visual break (image/graphic)
↓
CTA or next section
Clear Calls-to-Action
Tell users exactly what to do next.
CTA Best Practices:
Use action language ("Get Started", "Download", "Subscribe")
Make buttons visually distinct (highest contrast)
Position after value prop and benefits
Limit 1-2 primary CTAs per section
Include secondary CTA for users not ready
Content Parsing (Multi-Language)
When reading docs/{lang}/*.md files (NEW: language-specific):
YAML frontmatter (between ---) = structured data (use as props)
## Heading = section breaks
**bold text** after heading = field values (role, summary, etc.)
List items = features, values, etc.
Parse flexibly — the user's markdown won't be perfectly structured
Important for Multi-Language:
Read content from docs/{lang}/ for THIS language only
Don't mix languages or read from root docs/ directory
Each language has complete independent content
Apply language standards from language-standards skill to ensure proper tone