Personal site for William Lopez-Cordero — Vite, React 19, TypeScript, and plain CSS (design tokens in src/styles/). Content for metrics, disciplines, timeline, case studies, and consulting largely lives in src/data/resume.json.
bun installDependencies are locked with bun.lock. package-lock.json is ignored so npm does not introduce a second lockfile.
| Command | Purpose |
|---|---|
bun run dev |
Vite + Bun contact API together (site default http://127.0.0.1:5173, API 3001). |
bun run dev:site |
Vite only (no /api proxy target — contact form will not reach the API). |
bun run dev:api |
Bun contact API only (server/contact-api.ts). |
bun run build |
Typecheck + production bundle to dist/. |
bun run preview |
Serve the dist/ build. |
Uses concurrently so one command starts the frontend and POST /api/contact handler.
| Path | Page |
|---|---|
/ |
Home: hero (type / orbit / terminal), metrics (Selected numbers. 10+ years.), five disciplines, selected work, consulting. |
/work |
Experience timeline, discipline filters, case studies, projects. |
/about |
Full-story bio, facts, skills matrix. |
/contact |
Form (validated client + server), FAQ. |
Static files in public/ are copied to dist/ as-is, including llms.txt and humans.txt.
- Local: Vite proxies
/apitohttp://127.0.0.1:3001(vite.config.ts).bun run devstarts both. Submissions go to/api/contact(Bun + Resend). - Production: Set
VITE_CONTACT_API_BASEto the origin that serves the API (no trailing slash). The client calls${VITE_CONTACT_API_BASE}/api/contact. - From / Reply-To:
frommust be a Resend-verified sender (RESEND_FROM_EMAIL). The visitor’s email is set asreplyToand in the message body — seeserver/contact-api.ts.
Env vars for the API are in .env.example. Copy to .env for the Bun process; never commit secrets.
- Set
VITE_SITE_URLto your canonical origin (no trailing slash), e.g.https://example.com. Used for:PageHelmet/GlobalJsonLdcanonical and absolute URLs (src/lib/siteUrl.ts).sitemap.xmlandrobots.txtemitted intodist/onbun run build(plugin invite.config.ts).
If VITE_SITE_URL is unset at build time, the plugin falls back to http://127.0.0.1:5173 — set it for real deploys.
Chromewraps pages with nav, footer, cursor blob, noise, andTweaksPanel: theme, typography, density, hero variant, and home section order. Preferences persist inlocalStorageunderportfolio-tweaks.Agentation(agentation) mounts only inimport.meta.env.DEVfor in-editor annotation (App.tsx).
resume.jsonincludes awritingarray; it is not rendered on the site today. Safe to keep for later or delete if unused.- There are no resume PDFs in this repo. If you add download links, put files under
public/(e.g.public/uploads/...) and reference site-root paths in data so production URLs resolve.
- Bun — install, scripts, lockfile, and contact API (
bun run server/contact-api.ts).