Portfolio Site — Maintenance Skill
This is Mitchell Palmer's personal portfolio: a Next.js 16 (App Router) rebuild of a
former Webflow site. Content lives as plain TypeScript/JSON/MDX files under src/content/
instead of a CMS. Read this before making changes so you match existing conventions
rather than introducing new patterns.
Mental model
src/content/ → DATA (what to say — edit this for almost everything)
src/app/ → PAGES (routing — one folder = one URL, App Router conventions)
src/components/ → UI PIECES (reusable — Header, Footer, ProjectCard, PhotoGallery, MDX embeds)
public/images/ → static assets, organized by section (site/, projects/, projects/hero/, photography/, icons/)
If the task is "add/edit content" (a project, a job, a bio line, a photo), it almost
certainly only touches src/content/. Don't touch src/app/ or src/components/
for pure content changes.
Content file reference
| File | Controls |
|---|---|
src/content/site.ts | Name, tagline, email, nav links, social links |
src/content/about.ts | Bio paragraphs, "journey" story, mission statement, status |
src/content/experience.ts | Work history (experience[]), education, skills list, services cards |
src/content/photography.json | Array of { src, season, location, type } — filter buttons on /photography are auto-generated from whatever values appear here |
src/content/projects.ts | Logic only (reads .mdx files from projects/) — don't edit unless changing how projects are loaded/sorted |
src/content/projects/*.mdx | One file per project. Frontmatter + Markdown/MDX body. Filename = URL slug. |
Project MDX frontmatter shape
---
title: "Project Title"
description: "1-2 sentences, shown on card + top of detail page."
image: "/images/projects/thumbnail.jpg"
heroImage: "/images/projects/hero/banner.jpg" # optional, falls back to `image`
featured: true # shows on homepage
link: { label: "GitHub Repository", href: "https://..." }
skills: ["Skill One", "Skill Two"]
tools: ["Python", "PostgreSQL"]
# OR, for projects with many technologies, use techGroups instead of skills/tools:
techGroups:
Languages & Libraries: ["Python", "pandas"]
Statistical Methods: ["CUSUM", "Z-Score Analysis"]
---
Note: ProjectCard.tsx displays project.tools ?? project.skills (tools takes priority
if both exist). techGroups is mutually exclusive with skills/tools in display — the
detail page's sidebar shows one or the other, not both.
Two custom MDX components are available inside any project body:
<DashboardEmbed src="https://your-app.streamlit.app/" title="My Dashboard" />
<PdfEmbed src="/path/to/summary.pdf" />
Styling conventions
- Tailwind v4, CSS variables defined in
src/app/globals.cssunder:root(e.g.--color-brand: #486161). Change the palette there, not by hardcoding hex values in components. - Two fonts:
--font-serif(Merriweather, headings) and--font-sans(Inter Tight, body) — both loaded vianext/font/googleinlayout.tsx. Requires internet access at build time — will fail in offline/sandboxed environments. .container-pageutility class handles consistent max-width + padding across pages.
Do NOT touch
node_modules/— gitignored, regenerated vianpm install. Never re-add to git.AGENTS.mdat repo root — auto-regenerated bynext dev, briefs AI agents on this Next.js version's specific conventions. Don't hand-edit; it'll be overwritten.CLAUDE.mdat repo root — currently just@AGENTS.md(an import). If adding persistent custom instructions, put them in a new file and reference it separately, don't overwrite the AGENTS.md import.next-env.d.ts— auto-generated, gitignored.
Common tasks, quick reference
New project → thumbnail in public/images/projects/ (+ optional hero banner) → new
.mdx file in src/content/projects/ → done, no routing code needed.
New photo → file in public/images/photography/ → matching entry in photography.json.
Edit bio/mission → src/content/about.ts, plain string edits.
New job entry → src/content/experience.ts, prepend to experience[] array (rendered
in array order, so newest-first).
Nav/social link change → src/content/site.ts.
Build & verify
npm install # after pulling changes touching package.json
npm run dev # local dev server, hot reload
npm run build # production build — run this before pushing structural changes
npm run lint # eslint check
npm run build will fail without internet access (Google Fonts fetch) — this is expected
in fully offline environments and not a code bug.