Imported from yoh-space/esset2nd (
AGENTS.md). Install upstream withnpx skills add yoh-space/esset2nd. Copyright stays with the author.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.
Eset (እሴት) Website — AI Coding Agent Build Spec
This file is written as a direct instruction set for an AI coding agent (e.g. OpenCode, Claude Code, Cursor). It translates the Eset brand and content blueprint into concrete tasks, file structure, design tokens, and component specs. Feed this file to the agent as-is, or split it section-by-section into individual prompts.
0. Stack Assumptions
This guide assumes the Next.js project (App Router, TypeScript) already exists. Add/confirm these dependencies before starting:
- Styling: Tailwind CSS, CSS variables for design tokens
- Animation: Framer Motion or GSAP + ScrollTrigger for parallax
- Content: MDX or a simple JSON/CMS layer for Stories of Change (so non-technical staff can add stories later)
- i18n:
next-intlor a custom context for English / Amharic toggle (do not reflow layout — see §4) - Fonts: self-hosted via
next/font— Fraunces (display), Inter (body), Noto Sans Ethiopic (Amharic)
npm install framer-motion next-intl
1. Design Tokens
Add to tailwind.config.ts and globals.css. Use these exact values — do not substitute close approximations.
:root {
--color-forest: #1F3D2B;
--color-forest-tint: #E7EEE5;
--color-ochre: #B9863C;
--color-ochre-tint: #F4E8D4;
--color-ivory: #F7F4EC;
--color-charcoal: #2B2B2B;
--color-grey: #6E6E6E;
--color-line: #D9D2C4;
--font-display: "Fraunces", serif;
--font-body: "Inter", sans-serif;
--font-ethiopic: "Noto Sans Ethiopic", sans-serif;
}
// tailwind.config.ts colors
colors: {
forest: { DEFAULT: "#1F3D2B", tint: "#E7EEE5" },
ochre: { DEFAULT: "#B9863C", tint: "#F4E8D4" },
ivory: "#F7F4EC",
charcoal: "#2B2B2B",
grey: "#6E6E6E",
line: "#D9D2C4",
}
Rules for the agent to enforce everywhere:
- Headlines use
font-display, body copy usesfont-body, Amharic text usesfont-ethiopicregardless of which font-family class is active elsewhere on the page. - Never introduce a new color outside this token set without flagging it.
- Default section background is
ivory; only the impact-counter band and footer useforest.
2. Site Map & Routing
/ → Home
/about → About Us
/our-work → Our Work (Seven Pillars overview)
/our-work/[pillar] → Individual pillar detail page (7 static routes)
/stories → Stories of Change index
/stories/[slug] → Individual story article
/get-involved → Donate / Volunteer / Partner
/resources → Annual reports, financials, press
/contact → Contact page
Persistent layout elements (in app/layout.tsx):
- Header: transparent over hero, transitions to solid
forestbackground with drop shadow after 80px scroll. Logo left, nav center, language toggle + gold "Donate" button right. - Footer:
forestbackground, newsletter signup, sitemap, social links, bilingual legal text.
3. Page-by-Page Build Tasks
3.1 Home (app/page.tsx)
Build five stacked sections in this order. Each is its own component under components/home/.
Hero.tsx
- Full-bleed muted looping background video (with captions track for accessibility),
<video>element withposterfallback image. - Headline: "Rooted in Value. Building What Comes Next." —
font-display, large scale (clamp 2.5rem–5rem). - Sub-headline: "Eset is a multi-sectoral development organization advancing food security, youth innovation, and cultural heritage across Ethiopia — so that progress and identity grow together, not apart."
- Two CTAs:
See Our Work(links/our-work) andSupport the Mission(links/get-involved), styled primary/secondary. - Parallax: background video container translateY at 0.5x scroll speed relative to foreground text at 1.0x. Implement via
useScroll+useTransform(Framer Motion) or a ScrollTrigger tween.
Philosophy.tsx
- Ivory background. Centered large serif statement: "Real development is not delivered from the outside. It is unlocked from within. We work where tradition meets technology, making sure that as communities move forward, they carry their heritage with them rather than leaving it behind."
- Single photograph offset to one side, parallax background speed 0.3x.
ImpactCounters.tsx
forestbackground band, white numerals, gold underline accents, 4-column grid (2-column on mobile).- Data (pull from a
lib/impact-data.tsconstant so it's easy to update later):- Families reaching food independence — 10,000+
- Youth trained in digital entrepreneurship — 2,500+
- Cultural heritage projects revitalized — 50+
- Regions with active programs — 9
- Count-up animation triggered once on scroll-into-view (
react-intersection-observer+ a count-up hook). No parallax on this section — keep it flat and legible.
PillarsPreview.tsx
- Vertically stacked, full-viewport panels, one per pillar (7 total), each with its own background photo, icon, heading, one-paragraph summary, and a link into
/our-work/[pillar]. - Background image parallax at 0.4x per panel; icon + heading stay pinned at 1.0x.
- Pillar content (use for both this preview and the
/our-workdetail pages):
| # | Title | Summary |
|---|---|---|
| 1 | Food Security & Resilient Livelihoods | Technical expertise and material support that help families break the cycle of food insecurity through sustainable agro-ecology and skills-building, treating nutrition as a right rather than a privilege. |
| 2 | Cultural Heritage & National Identity | Protecting and promoting Ethiopia's tangible and intangible cultural assets, positioning heritage as a foundation for — not an obstacle to — modern growth. |
| 3 | Youth Innovation & Digital Skills | Technology-assisted learning and entrepreneurship training that turn job seekers into job creators, preparing young Ethiopians to build the country's next economy. |
| 4 | Environmental Stewardship | Biodiversity protection and ecosystem restoration grounded in the understanding that human prosperity and a healthy environment rise or fall together. |
| 5 | Rights & Social Inclusion | Advocacy for the socio-economic rights of women, children, the elderly, and persons with disabilities, so that progress reaches everyone, not just the most visible. |
| 6 | Social Infrastructure — Health & Education | Investment in robust health and education systems, on the premise that a healthy, educated population is the true engine of long-term development. |
| 7 | Ethical Character & Moral Leadership | Programs that nurture the inner development of young people — ethics, integrity, and moral clarity — as the foundation beneath every other pillar. |
FeaturedStory.tsx
- Split layout: parallaxing photo (0.6x) on one half, fixed pull-quote card + two-line summary on the other.
- Pulls from the same content source as
/stories(most recent or manually pinned entry).
3.2 About (app/about/page.tsx)
- Our Story copy block (see content below).
- Core Values table → render as a 4-card grid, not an HTML table, on the live site.
- Leadership & Governance grid: portrait, name, role, one-sentence personal mission per person — build as a reusable
LeadershipCard.tsx, data-driven fromlib/team-data.ts.
Our Story: Eset began with a simple conviction: every community already holds the value, or "eset," it needs to thrive. The organization's task is to help that value surface — through resources, partnership, and patient, locally led work. What started as a single community initiative has grown into a professional, accountable platform for change across Ethiopia.
Core Values:
| Value | What It Means in Practice |
|---|---|
| Integrity | Transparent budgets, audited accounts, and public reporting on every program |
| Pluralism | Ethiopia's cultural diversity is treated as a development asset, not a complication |
| Innovation | Modern tools applied to long-standing challenges in agriculture, education, and craft |
| Dignity | Communities lead their own projects; Eset provides resources, not directives |
3.3 Our Work (app/our-work/page.tsx + app/our-work/[pillar]/page.tsx)
- Index page: grid of all 7 pillars (cards, no parallax needed here — that's reserved for the home page panels).
- Detail page per pillar: full content from the table in §3.1, plus space for program photos, partner logos, and a related-stories module.
3.4 Stories of Change (app/stories/page.tsx + app/stories/[slug]/page.tsx)
- Index: card grid, newest first.
- Article template: full-width hero image with parallax (reuse the
FeaturedStoryparallax pattern), pull-quotes set infont-display, related-stories module at the end. - Seed with these three stories (write full copy per story as a separate task — these are working titles/summaries only):
- "The Green Revolution in Wollo" — how one family tripled its harvest yield.
- "From Tradition to Trend" — reviving ancestral weaving for a global market.
- "The Girl Who Coded" — how one rural tech hub changed a village's trajectory.
3.5 Get Involved (app/get-involved/page.tsx)
- No parallax on this page — flat, high-contrast, motion-free, to keep the donation path frictionless.
- Lead copy: "A contribution to Eset is not a donation in the conventional sense — it is an investment in a self-reliant Ethiopia, with transparent reporting that shows exactly how support translates into outcomes."
- Three equal-weight cards beneath the donation form:
| Pathway | Description |
|---|---|
| Donate | Support the general fund or direct a gift to one of the seven pillars |
| Volunteer | Contribute professional skills directly to local program teams |
| Partner | Corporate and foundation partnerships for large-scale, multi-year impact |
- Donation form: integrate whatever payment processor the org uses locally (flag to the team if none specified — for Ethiopia this is likely Telebirr or a similar mobile-money rail; do not assume Stripe-only).
3.6 Resources (app/resources/page.tsx)
- List of annual reports, audited financials, press materials, organized by year, downloadable as PDF. Build as a simple filterable list driven by a
lib/resources-data.tsarray ({ year, title, type, fileUrl }).
3.7 Contact (app/contact/page.tsx)
- Office locations, inquiry form, direct lines for press/partnership/volunteer inquiries, embedded map for the Addis Ababa HQ (use a privacy-respecting embed, e.g. static map image with a link out, or a lazy-loaded iframe behind a click-to-load gate).
4. Parallax & Motion Implementation Rules
Implement a single reusable hook/component so every section uses the same mechanism — do not hand-roll scroll math per component.
// hooks/useParallax.ts
import { useRef } from "react";
import { useScroll, useTransform, MotionValue } from "framer-motion";
export function useParallax(speed: number): { ref: React.RefObject<HTMLDivElement>; y: MotionValue<number> } {
const ref = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({ target: ref, offset: ["start end", "end start"] });
const y = useTransform(scrollYProgress, [0, 1], [0, (1 - speed) * 200]);
return { ref, y };
}
Speed ratios per section (1.0 = normal scroll speed; lower = slower/more depth):
| Section | Foreground | Background | Notes |
|---|---|---|---|
| Hero (video) | 1.0x (fixed) | 0.5x | Headline/CTA stay crisp; video drifts slower |
| Philosophy statement | 1.0x | 0.3x | Quote stationary; photo drifts upward |
| Impact counters | 1.0x | n/a | No parallax — count-up animation only |
| Seven Pillars panels | 1.0x (icon+heading pinned) | 0.4x per panel | Each panel's background parallaxes independently |
| Featured story | 1.0x | 0.6x | Subtle drift behind a fixed pull-quote card |
| Get Involved | 1.0x | n/a | Motion intentionally removed |
Mandatory guardrails — implement before shipping any parallax section:
- Wrap every parallax transform with a
prefers-reduced-motioncheck; fall back to a fully static layout (no transform applied) when the OS setting is on. - On viewports < 768px, dampen background speed differentials (e.g. 0.5x → 0.75x, 0.3x → 0.6x) to reduce jank on lower-powered devices.
- Replace the hero
<video>with a static high-resolution<img>on slow connections — checknavigator.connection.effectiveTypewhere the Network Information API is available, and always provide theposterimage as a no-JS fallback. - Each animation triggers once on first scroll-into-view; nothing should loop indefinitely.
5. i18n / Bilingual Requirements
- Persistent language toggle in the header switches the entire interface (nav, headings, body, forms) between English and Amharic — not just visible copy.
- When Amharic is active, swap
font-body/font-displaytext tofont-ethiopicfor any Ge'ez-script content; do not force Latin fonts onto Amharic text. - Write Amharic copy natively per page — do not machine-translate the English strings above. Flag each page's Amharic copy as a separate content task for a native speaker/reviewer if the agent cannot produce it directly.
- Test that switching languages does not break the parallax layout math (re-measure scroll containers on language switch if text length changes section height).
6. Acceptance Checklist
Before marking any page "done," confirm:
- Matches the design tokens in §1 exactly (no off-palette colors)
- Correct font applied per language/content type (display / body / ethiopic)
- Parallax speed ratios match the table in §4, with reduced-motion fallback verified
- Mobile breakpoint dampens parallax per §4
- All copy matches the content blocks in §3 (or has been explicitly approved as a rewrite)
- Header transitions from transparent to solid
forestat 80px scroll - Lighthouse performance score not degraded by video/parallax (test on throttled 4G)
7. Type Checking Protocol ⚠️
MANDATORY — do not skip or substitute.
For all UI/UX, component, and minor code changes, verify TypeScript correctness with:
npx tsc --noEmit
Never use pnpm run build to check for type errors during development. The full build is slow and unnecessary for type-checking. npx tsc --noEmit is the only acceptable command for verifying TypeScript on iterative changes.
Only run pnpm run build when:
- You need to verify the final production output before a deploy.
- You are asked explicitly to run a full build.
Failure to follow this protocol will be treated as a workflow violation.
