Personal portfolio for Santiago Rivera — software developer, founder of Directa. Bilingual (Spanish / English), light-only neo-brutalist editorial layout with an interactive DOM hero card-stack.
Built with Next.js 15 (App Router) · TypeScript · Tailwind · next-intl · GSAP + ScrollTrigger · Lenis.
pnpm install
cp .env.example .env.local # optional — fill in if you want analytics
pnpm devOpen http://localhost:3000. The middleware redirects / to the default
locale (/es).
| Command | What it does |
|---|---|
pnpm dev |
Local dev server |
pnpm build |
Production build |
pnpm start |
Serve the production build |
pnpm lint |
Lint with Next/ESLint |
pnpm typecheck |
TypeScript no-emit |
pnpm format |
Prettier format the repo |
pnpm test:e2e |
Playwright smoke tests (boots production) |
src/
app/
[locale]/ # localized routes (next-intl, App Router)
page.tsx # home — composed of section components
about/ # /sobre-mi | /about
work/ # /trabajo | /work
directa/ # the featured case study
services/ # /servicios | /services
contact/ # /contacto | /contact
layout.tsx # root <html> + fonts
sitemap.ts # /sitemap.xml
robots.ts # /robots.txt
icon.tsx # generated favicon
opengraph-image.tsx # generated OG card
components/
layout/ # Header, Footer, CalmToggle, LocaleSwitcher
sections/ # Hero, IntroBlock, WorkPreview, ServicesGrid, etc.
motion/ # CardStack (hero), Ticker, Marker, Magnetic
ui/ # Button, Reveal, PendingBadge
providers/ # SmoothScrollProvider (Lenis + GSAP)
content/
site.ts # ⭐ single source of truth for editable content
directa.ts # Directa case-study copy
i18n/ # next-intl wiring
lib/ # fonts, cn, seo helpers
middleware.ts # locale routing
messages/
en.json # English UI strings
es.json # Spanish UI strings
public/
cv/ # drop CV PDF here
portrait/ # drop portrait here
work/directa/ # drop case-study media here
See CONTENT_GUIDE.md for how to edit content, and DESIGN_SYSTEM.md for
typography, spacing and motion rules.
The project targets Vercel out of the box.
- Create a project on Vercel and link this repository.
- Set the production env vars (mirror
.env.example):NEXT_PUBLIC_SITE_URL=https://santiagorivera.com- (optional)
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=santiagorivera.com - (optional)
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-…
- In Settings → Domains, add
santiagorivera.comandwww.santiagorivera.com. Point your registrar's A record to76.76.21.21and the CNAME forwwwtocname.vercel-dns.com. Usewwwas primary or apex — either works. - Vercel will auto-build on push to
main.
Build command: pnpm build · Output: standard Next.js.
Anything not yet verified is marked pending: true in src/content/site.ts
and src/content/directa.ts. The UI renders a small "pending" badge on every
such field so unverified claims never ship silently.
Current outstanding items:
- Portrait (
public/portrait/santiago.jpg) - Directa screenshots in
public/work/directa/ - Directa case-study copy (context, problem, strategy, etc.)
- Experience and education arrays
- Person role / positioning line and the Directa year
(WhatsApp number, calendar URL and the CV PDF are already finalized.)
When you replace a value, also flip its pending to false (or remove the
wrapper for fields whose entire wrapper is the placeholder).
Set one of:
NEXT_PUBLIC_PLAUSIBLE_DOMAIN— loads Plausible's script-only embed.NEXT_PUBLIC_GA_MEASUREMENT_ID— loads GA4 withgtag.js.
Leave both empty to ship no analytics. No third-party scripts load otherwise.
All rights reserved.