Imported from DarKSanjan/YFA-landing-page (
AGENTS.md). Install upstream withnpx skills add DarKSanjan/YFA-landing-page. Copyright stays with the author.
AGENTS.md — YFA Landing Page (Codex Handover)
Handover for Codex (and any coding agent). Read this first.
What This Is
Marketing landing page for The Young Filmmakers Academy (YFA) — a film school for ages 10–18. Single-page Next.js App Router site. Primary conversion = WhatsApp enquiry (no backend, no forms).
Current visual identity: editorial brutalism (Direction D) — oversized condensed display type, hard borders + solid offset shadows, sticker badges, numbered sections (01–09), cinematic black/ivory/gold palette with teal/coral accents.
Current State
- Branch:
main(the brutalist redesign is merged and live here). - Last commit:
2397741 chore: drop dead offset/sprocket CSS and redundant course-structure ternary. - Working tree clean except untracked
.claude/and.superpowers/(local tooling — do not commit). - All checks green:
npm run test12/12,npm run build✓,npm run test:e2e2/2 (Desktop Chrome + Mobile Safari).
Design docs:
- Spec:
docs/superpowers/specs/2026-06-06-yfa-brutalist-redesign-design.md - Plan:
docs/superpowers/plans/2026-06-06-yfa-brutalist-redesign.md - (Original pre-redesign spec/plan:
...-yfa-landing-page-*.md— historical.)
Tech Stack
Next.js (App Router, v16, Turbopack) · React 19 · TypeScript · Tailwind CSS v3 · Framer Motion v12 · lucide-react · next/font/google (Anton + Archivo Black) · Vitest + Testing Library (jsdom) · Playwright.
Commands
npm run dev # dev server → http://localhost:3000
npm run build # production build (also typechecks)
npm run test # Vitest unit/interaction tests
npm run test:e2e # Playwright (builds + serves prod, see note below)
Run after every change:
npm run test && npm run build
Architecture / File Map
app/layout.tsx— wiresnext/fontAnton (--font-display) + Archivo Black (--font-heavy) as CSS vars on<html>.app/page.tsx— composes all sections inside<main id="top">. Section order: SiteHeader → Hero → PromiseCards → FilmJourney → CurriculumNotebook → LearnByMaking → CourseStructure → FinalOutcome → FestivalTicket → MentorProfiles → AudienceFit → FinalCTA → Footer.app/globals.css— base styles,.film-grain,.ticket-notch,.snap-y/.snap-start,prefers-reduced-motionblock.tailwind.config.ts— colorsink #0a0a0a/ivory #fff7e6/gold #f3c64b/teal #24c6b8/coral #ff5b57;fontFamily.display+fontFamily.heavy;shadow-cinematic.components/landing/data.ts— ALL content:contacts,ageBatches,filmStages(label/description/long/doIt/learn/output),curriculumGroups(title/items/intro),outcomes,audienceItems,mentors,socials,siteLocation.types.ts— shared types.SectionEyebrow.tsx— theNN — NAMElabel + oversized title used by every numbered section.FramePlaceholder.tsx— bordered crop-mark image placeholder (role="img"). Where real photos drop in later.SiteHeader.tsx— sticky nav, single Enquire CTA, mobile hamburger menu (client).ClapperButton.tsx— the WhatsApp CTA button (reused by hero/final CTA).- Section components:
Hero,PromiseCards,FilmJourney,CurriculumNotebook,LearnByMaking,CourseStructure,FinalOutcome,FestivalTicket,MentorProfiles,AudienceFit,FinalCTA,Footer. __tests__/landing.test.tsx— page render + interaction tests.__tests__/primitives.test.tsx— SectionEyebrow + FramePlaceholder tests.
e2e/yfa.spec.ts— Playwright smoke flow.public/images/— 3 generated cinematic backgrounds:hero-film-set.png,learn-reels.png,festival-screening.png(decorative CSS backgrounds only).
Design System Rules
- Display type:
font-display(Anton) for big titles/wordmark;font-heavy(Archivo Black) for sub-display/buttons. Body = system sans. - Section pattern: every major section opens with
<SectionEyebrow index="NN" eyebrow="..." title="..." />. Indices are sequential 01–09 across the page — if you add/remove/reorder a section, renumber them. - Brutalist motifs:
border-[3px] border-ink(or accent), solid offset shadows via arbitraryshadow-[Xpx_Ypx_0_#color], rotated sticker badges, ghost numbers, numbered lists. Accents: gold/teal/coral. - Curriculum is a full-screen vertical scroll-snap of 4 chapter panels (
.snap-yproximity). Each = image placeholder + intro + numbered items. - Mobile-first. Verify no horizontal overflow at 390px; check 1440px too.
Locked Content & Hard Constraints (DO NOT VIOLATE)
- Never alter approved copy/facts. PDF course facts are fixed: Ages 10-13, Ages 14-18, 16 classes, 2 months, Saturdays and Sundays, 2.5 hours per day.
filmStageslabels+descriptions andcurriculumGroupstitles+items are fixed — only add fields, never edit existing strings. - Primary CTA = WhatsApp Archana
+91-98920-53066→https://wa.me/919892053066?.... No forms, no backend, no other CTA. - No audio. No autoplay. The mentor "Audio coming soon" button is
disabledand decorative (lucideAudioLinesicon only). Never add<audio>,new Audio,.play(), or autoplay. - No real or fake instructor photos / human likenesses. Mentor avatars are abstract monograms. Only the 3 generated backgrounds may be used as imagery, as decorative
aria-hiddenCSS backgrounds. - Accessibility: keep the single accessible Enquire link in the header (do NOT
aria-hiddenan interactive control to dedupe). Keeph1accessible name exactly "YFA" (a unit test asserts/^YFA$/iat level 1). Keep focus-visible rings,role="img"on placeholders,tel:/mailto:footer links, mentor fliparia-labels.
Conventions / Gotchas
- Relative imports only in
app/page.tsxandcomponents/landing/*(e.g.../components/landing/Hero,./data).@/*alias is NOT configured for Vitest — using it breaks tests. "use client"only on components using hooks/Framer Motion state (Hero, FilmJourney, CurriculumNotebook, PromiseCards, LearnByMaking, MentorProfiles, FestivalTicket, SiteHeader). Pure-static sections are server components.vitest.config.mts(ESM, intentional) excludese2e/**so Playwright specs aren't run by Vitest.playwright.config.tsuses a productionwebServer(npm run build && npm run start,reuseExistingServer:false) because the Turbopack dev HMR WebSocket fails under Playwright's sandboxed browsers — production hydrates fine. Free port 3000 beforenpm run test:e2e(lsof -ti :3000 | xargs kill).PromiseCards.tsxhas a module-topIntersectionObservernoop shim sowhileInViewrenders in jsdom. (Ideally belongs invitest.setup.ts— pre-existing; leave unless refactoring tests.)next-env.d.tschurn: the dev server rewrites it to point at.next/dev/types/.... Do NOT commit that. A productionnpm run buildrestores it. Onlygit addyour actual files (app components ...), never the dev churn.next/font/googlefetches Anton + Archivo Black at build time (needs network once; self-hosted after). If a build env is offline and font fetch fails, fall back to a system condensed stack via the--font-display/--font-heavyCSS vars.- Framer Motion
whileInViewentrance animations are correct but only complete in a focused browser (headless preview throttlesrequestAnimationFrame). Verify visuals in a real browser, not a headless screenshot.
Testing Expectations
- After each change:
npm run test(12 tests) +npm run buildmust pass. - After touching interactive flow:
npm run test:e2e(Desktop Chrome + Mobile Safari). - If a redesign changes an interaction model, REWRITE the affected test to assert the new real behavior — do not delete or weaken assertions to make them pass.
Open Follow-Ups (placeholders to replace)
- Social links in
socials(data.ts) → real Instagram/YouTube/LinkedIn URLs (currently#). - Privacy / Terms footer links → real pages (currently
#). siteLocation(data.ts) = "Mumbai, India" — confirm or correct (inferred from +91 numbers).- Real images to replace
FramePlaceholderslots: Film Journey stages (STAGE NN) and Curriculum chapters (CHAPTER NN). Do NOT add human-likeness photos for mentors.
Do Not
- Switch the CTA away from WhatsApp, or add a form/backend.
- Add audio/autoplay or any human photos.
- Change approved PDF course facts or locked copy.
- Introduce
@/import aliases without fixing Vitest config and verifying. - Commit
.claude/,.superpowers/,.next/,node_modules/, Playwrighttest-results/, or devnext-env.d.tschurn. - Skip build/test/e2e verification before declaring done.