Neo-brutalist portfolio kit
A full, tested portfolio template extracted from a production site. Everything is in assets/ — copy it into a fresh Vite + React project, replace the placeholder data with the owner's own, and ship. The kit was verified to vite build from scratch and render with no console errors.
What you get
- Design system — flat saturated colors, 3px borders, solid offset shadows, tilted tiles (
assets/src/brutal/brutal.css, scoped under.nb). - Sections — loader · fixed nav (scroll-spy, theme + language + sound toggles, mobile sheet) · hero with per-letter hover · about · work grid with a full-screen case-study overlay (prev/next, keyboard, focus restore) · stack · experience accordion · contact form · footer with a live local clock.
- Bilingual + RTL — English/Arabic with logical CSS properties; light/dark with no flash.
- Sound — generative 124 BPM synthwave loop and hover/click effects (each hero letter plays a pentatonic note). No audio files, no licensing.
- Assistant — floating chat backed by
api/chat.js: RAG over the owner's own data (Arabic-aware BM25 + Gemini embeddings), grounded answers, model fallback, same-origin + rate limit. The API key never reaches the browser. - Deploy config —
vercel.json(SPA rewrites),.vercelignore.
Quick start (new project)
npm create vite@latest my-portfolio -- --template reactand install the dependencies listed inassets/package.deps.json(i18next react-i18next lenis framer-motion lucide-react @emailjs/browser @google/genai).- Copy the contents of
assets/into the project root (mergesrc/, replaceindex.htmlandvite.config.js, addapi/,vercel.json,.vercelignore). Delete the defaultsrc/App.css/index.cssimports — the kit brings its own CSS viabrutal.css. - Fill in the owner's data (see What to personalize).
- Add the portrait at
src/Imgs/portrait.jpgand project screenshots underpublic/projects/(WebP, ≤1280px wide). npm run dev→ check light/dark, EN/AR, 375px and 1440px.npx vite buildmust pass.- Deploy: see
references/deploy-and-secrets.md.
What to personalize (the only files that carry content)
| File | What to put in it |
|---|---|
src/data/siteFacts.js | name (EN/AR), hero name split, nav initials, location, time zone, contact links, EmailJS public IDs, tech stack columns, tools |
src/data/projectsMeta.js | projects: title, tags, live URL (or null), order, i18nIndex |
src/data/projectImages.js | screenshots per project; first image is the card cover |
src/i18n/locales/{en,ar}.json | all copy — hero statement, about text/stats, highlights, experience, per-project subtitle/description/screen labels, project "kinds", contact text, assistant prompts |
index.html | <title>, description, favicon |
Rules while filling in: write facts only the owner can confirm; never invent clients, numbers, dates, or links; keep tech names in English in both languages; projects.items[i] in the locale files must line up with i18nIndex.
Design language (summary — exact values in references/design-system-spec.md)
- Flat color only. No gradients, glow, blur, glass, or purple "AI" look. Depth = border + hard shadow.
- Borders
3px solid var(--nb-line)· shadows solid offsets (5px/8px 8px 0,12–14pxon hover) · tilt-2°…2°, straighten on hover. - Type: Bricolage Grotesque 800 uppercase for display, Space Grotesk for body, JetBrains Mono uppercase for labels. Arabic: Cairo 700–900, no tracking, no uppercase.
- Contrast rule: text on a saturated fill is always
#111with#111borders in both themes; only neutral surfaces flip with the theme. - Section rhythm: hero yellow → about paper → work blue → stack paper → experience lilac → contact pink → footer black. Recolor by changing the
--nb-*tokens; keep the rhythm.
Engineering rules (keep these when editing)
- Reveal state in a data attribute (
data-reveal→data-in), never a class — React re-renders overwrite classes. - Case overlay needs
data-lenis-prevent, otherwise Lenis blocks the wheel inside it. Same for any scrollable overlay (assistant chat, mobile sheet). - Use logical CSS (
inline-start/end,margin-inline), flip arrows in RTL, wrap numeric counters indir="ltr", never letter-space Arabic. - Never call
localhostfrom production code — browsers ask visitors for local-network permission. Call an API only when its URL env var is set. - Performance: lazy-load below-the-fold sections; WebP images with
loading="lazy"; animatetransform/opacityonly; respectprefers-reduced-motion; no heavy 3D/UI libraries on the public path. - Secrets: API keys live only in server env vars (
GEMINI_API_KEY). Never prefix a secret withVITE_(it is bundled into the browser). Public EmailJS IDs are fine in client code. - Accessibility: visible focus ring, skip link,
aria-pressedon toggles,role="dialog"+ focus restore on overlays, reduced-motion support.
Verify before saying "done"
npx vite buildpasses.- Light + dark, EN + AR (RTL), 375px and 1440px; no horizontal overflow.
- Open a case study → Prev/Next/
Esc, scroll inside it with the mouse wheel. - Hover the hero name and controls (after one click) to confirm sounds; toggles persist.
- If the assistant is deployed: ask a contact question, a list-all-projects question, and something not in the data (it must say it doesn't know).
- The preview pane may be hidden (animations paused) — confirm motion with a second screenshot or a real browser.
Design-system artifacts
DESIGN-SYSTEM.md— overview + palette/rules table with links.design-system/tokens.cssandtokens.json— the tokens for use outside the React kit.design-system/styleguide.html— living style guide (open in a browser): palette with contrast, type scale, shadow/tilt scales, every component, motion, do/don't.
References (read when needed)
references/design-system-spec.md— the exact design system: principles, every color and where it goes, contrast numbers, type scale, spacing, shadow/border/tilt scales, motion tokens, z-index, breakpoints, component anatomy and states.references/design-system.md— class catalog, section recipes, how to recolor or add a section.references/interaction-and-sound.md— hover/press behavior, reveal system, music + SFX architecture and tuning.references/i18n-and-rtl.md— locale structure, key map, Arabic typography, RTL checklist.references/assistant-rag.md— how the chat endpoint works, knowledge chunks, tuning retrieval and the prompt.references/deploy-and-secrets.md— GitHub + Vercel steps, env vars, key rotation, troubleshooting.