Prompt file imported from FelipeKha/rockilus (
.github/prompts/plan-rockilusWebLandingPage.prompt.md). Fill in{{lang}}before use. Copyright stays with the author.
Plan: Rockilus Landing Page (rockilus-web)
Design System (agreed)
- Color: Deep Blue + White — primary
#2563eb(blue-600), dark#1e3a8a(blue-900), white bg - Typography: Inter (already installed via next/font/google)
- UI Vibe: Minimal & Flat — whitespace-driven, no shadows, thin borders only for inputs
- No existing branding/logo assets
TL;DR
Replace the default Next.js boilerplate in rockilus-web/ with a multilingual (EN/FR/ES) marketing landing page. Use app/[lang] dynamic routing with generateStaticParams for static export, JSON dictionaries for translations, and modular marketing components styled with Tailwind v4 and the deep-blue design system.
Phase 1: Design Foundation (parallel steps)
-
Update
app/globals.css— Replace neutral/black shadcn default color tokens with deep-blue Tailwind v4@theme inlinevariables using oklch values. Set primary → blue-600, accent → blue-900, muted → slate-50, border → slate-200. Zero shadow tokens. Keep existing structure, only update:rootcolor values. -
Simplify
app/layout.tsx— Strip fonts/metadata boilerplate; keep minimal<html lang="en" suppressHydrationWarning><body className="...inter...">{children}</body></html>shell. Fonts and per-locale metadata move to[lang]/layout.tsx. -
Replace
app/page.tsx— Remove Next.js boilerplate. Add'use client'redirect usinguseEffect(() => { window.location.replace('/en') }, [])with a<meta http-equiv="refresh" content="0;url=/en" />fallback in head for static crawlers. -
Create
lib/dictionaries.ts— Server-only async loader:getDictionary(lang: Locale)dynamically importsdictionaries/{lang}.jsonwith a typedDictionaryinterface. No external lib needed — justconst dict = await import(../dictionaries/{{lang}}.json). -
Create
dictionaries/en.json— All English copy (nav, hero, problem/solution, 3 features, 4 how-it-works steps, final CTA, footer links). -
Create
dictionaries/fr.json— French translations of same keys. -
Create
dictionaries/es.json— Spanish translations of same keys.
Phase 2: i18n Routing (depends on Phase 1)
-
Create
app/[lang]/layout.tsx— ExportgenerateStaticParamsreturning[{lang:'en'},{lang:'fr'},{lang:'es'}]. ExportgenerateMetadatawith locale-aware title/description. Render<HtmlLangSync lang={params.lang} />(client component defined in same directory) to updatedocument.documentElement.langon mount. Import Inter font here (removed from root layout). -
Create
app/[lang]/page.tsx— Async server component. CallsgetDictionary(params.lang). Renders all marketing sections in order: NavBar → Hero → ProblemSolution → CoreFeatures → HowItWorks → FinalCTA → Footer. Passesdictslices as props to each component.
Phase 3: Marketing Components (parallel, depends on Phase 2 types)
All components live in components/marketing/. All accept a typed dict prop slice — no client components except the language toggle in NavBar.
-
NavBar.tsx— Server component. Fixed top, white bg, 1px bottom border. Logo left (text "Rockilus" in blue). Center links: Features, Pricing (anchor scroll). Right: "Get Started for Free" blue button +<LangToggle>client component. Mobile: hamburger menu using shadcnSheet. TheLangToggleis'use client'and usesusePathname+router.pushto swap locale segment. -
HeroSection.tsx— Full-width. Left col: H1 headline (large, bold, slate-900), subheadline (slate-600), CTA button (blue). Right col: gray placeholder div for dashboard mockup image (aspect-video, border, rounded). Two-col on md+, stacked on mobile. -
ProblemSolution.tsx— Two-col (or two-card) layout. Left card: "The Problem" with bullet pain points (red/slate icons). Right card: "The Solution" with benefit bullets (blue check icons from lucide-react). Dividing line or generous gap. -
CoreFeatures.tsx— Z-pattern: Feature 1 (text left, image placeholder right), Feature 2 (image left, text right), Feature 3 (text left, image right). Each<FeatureRow>sub-component takes title, description, isReversed bool. Image placeholders are styled divs. -
HowItWorks.tsx— 4-step horizontal row (on md+) / vertical stack (mobile). Each step: circle number, lucide icon, step title, short description. Steps: Onboard → Set Constraints → Generate → Publish. -
FinalCTA.tsx— Centered section with large heading, subheadline, and a prominent blue CTA button. Light blue-tinted muted background (bg-blue-50equivalent via CSS var). -
Footer.tsx— Simple 3-col grid: brand + tagline | links (Features, Pricing, Privacy, Terms, Contact) | language selector (LangTogglereuse). Bottom bar with copyright. No heavy styling.
Relevant Files
rockilus-web/app/globals.css— Update:rootcolor tokens to deep-blue palette (oklch)rockilus-web/app/layout.tsx— Simplify to minimal shellrockilus-web/app/page.tsx— Replace with static redirect to/enrockilus-web/app/[lang]/layout.tsx— NEW: generateStaticParams + generateMetadata + HtmlLangSyncrockilus-web/app/[lang]/page.tsx— NEW: landing page compositionrockilus-web/lib/dictionaries.ts— NEW: typed dictionary loaderrockilus-web/dictionaries/en.json— NEWrockilus-web/dictionaries/fr.json— NEWrockilus-web/dictionaries/es.json— NEWrockilus-web/components/marketing/NavBar.tsx— NEWrockilus-web/components/marketing/HeroSection.tsx— NEWrockilus-web/components/marketing/ProblemSolution.tsx— NEWrockilus-web/components/marketing/CoreFeatures.tsx— NEWrockilus-web/components/marketing/HowItWorks.tsx— NEWrockilus-web/components/marketing/FinalCTA.tsx— NEWrockilus-web/components/marketing/Footer.tsx— NEWrockilus-web/components/marketing/LangToggle.tsx— NEW (client, shared by NavBar + Footer)
Verification
cd rockilus-web && npx tsc --noEmit— zero TypeScript errorscd rockilus-web && npm run build— static export succeeds, all 3 locale routes generated (out/en/index.html,out/fr/index.html,out/es/index.html)- Open
out/en/index.htmlin browser — verify Nav, Hero, all sections render correctly - Open
out/fr/index.htmlandout/es/index.html— verify French and Spanish copy - Resize to mobile width — verify responsive layout (hamburger menu, stacked sections)
Decisions
- Tailwind v4 only: No
tailwind.config.ts; all tokens live inapp/globals.cssunder@theme inline. Color tweaks go in:root. - No external i18n lib: Pure Next.js dictionary pattern with typed JSON files and
getDictionary(). Zero client JS overhead for translations. - Static redirect: Root
/usesuseEffect+<meta refresh>(not middleware), compatible withoutput: 'export'. <html lang="">trade-off: Rootapp/layout.tsxsetslang="en" suppressHydrationWarning. TheHtmlLangSyncclient component corrects it to the active locale at runtime. Static HTML files for/frand/eswill havelang="en"in the raw HTML, whichHtmlLangSynccorrects on load.generateMetadataincludesalternates.languagesfor SEO. This is acceptable for a v1 marketing page.- Scope: First draft / boilerplate — no real images (placeholders), no actual pricing page, no form backend. Just structure + copy + styling.
Further Considerations
<html lang>in static HTML: To have the correctlangattribute baked into static HTML, movehtml/bodyfrom root layout toapp/[lang]/layout.tsxand make root layout return{children}only. Next.js will warn but in v14+ it builds without error when a nested layout provides them. Worth revisiting before launch.- Logo/hero image: Plan includes placeholders. Once brand assets exist, swap the styled
<div>placeholders with<img>(notnext/imageunlessunoptimized: trueis set innext.config.ts). - Language detection UX: Currently defaults
/→/en. Could later serve a geo-detection landing by adding an API call client-side — but must stay client-only to respect static export constraint.
