feat: initial next.js boilerplate, set up .env, add outline documents

This commit is contained in:
2026-05-27 15:21:10 -07:00
parent 946cf28141
commit dd8cbe1c45
8 changed files with 810 additions and 0 deletions
View File
+1
View File
@@ -32,6 +32,7 @@ yarn-error.log*
# env files (can opt-in for committing if needed) # env files (can opt-in for committing if needed)
.env* .env*
!.env.example
# vercel # vercel
.vercel .vercel
+3
View File
@@ -0,0 +1,3 @@
{
"js/ts.tsdk.path": "node_modules/typescript/lib"
}
+94
View File
@@ -0,0 +1,94 @@
// File-based routing: this file's location IS the URL.
// /app/about/page.tsx → https://yoursite.com/about
//
// Conventions:
// page.tsx = the route's UI
// layout.tsx = a wrapper shared across this folder + any nested routes
// loading.tsx = shown while the page is loading
// not-found.tsx = shown on 404 within this segment
import type { Metadata } from "next";
import Link from "next/link";
// Route-level metadata. Next reads this at build time and emits the
// correct <title>, <meta description>, OG tags, etc. into <head>.
// The root layout (/app/layout.tsx) had its own metadata; this overrides
// the title for /about specifically.
export const metadata: Metadata = {
title: "About — Angel Mankel",
// description:
// "Frontend engineer with deep AI-tooling fluency. Currently at Village Medical.",
};
// This is a Server Component by default. It runs on the server, sends
// HTML to the browser, and ships zero JavaScript for this page itself.
// You only add "use client" at the top of a file when you need
// interactivity (useState, onClick, etc).
//
// Because it's a server component, you could `await fetch()` here, read
// a markdown file from disk, or query a DB directly — no API route needed.
export default function AboutPage() {
return (
<main className="mx-auto max-w-2xl px-6 py-24">
<h1 className="text-3xl font-semibold mb-12">About</h1>
<section className="space-y-6 text-base leading-relaxed text-neutral-200">
<p>
I came up through healthcare IT help desk, then Salesforce admin,
then software engineer at Village Medical, where I lead React and
TypeScript redesigns of patient-facing apps and the internal
component library.
</p>
<p>
In parallel I&apos;ve gone deep on AI-assisted development. Claude
Code, custom slash commands, MCP integrations the tooling layer
that&apos;s reshaping how I work across the stack.
</p>
<p>
I&apos;m looking for remote-US product-engineering roles where
shipping React is the day job and using and building AI tooling is
first-class.
</p>
</section>
<section className="mt-16">
<div className="text-xs uppercase tracking-wider text-neutral-500 mb-3">
Timeline
</div>
<ul className="font-mono text-sm space-y-1.5 text-neutral-200">
<li>
<span className="text-neutral-500 mr-3">2024 now</span>
Village Medical · Software Engineer
</li>
<li>
<span className="text-neutral-500 mr-3">2022 2024</span>
Village Medical · Salesforce Admin
</li>
<li>
<span className="text-neutral-500 mr-3">2019 2022</span>
Gila River · Help Desk / IT
</li>
</ul>
</section>
{/* next/link does client-side navigation between routes (no full
page reload) and prefetches the target route when the link
enters the viewport. Use it for any internal nav. For external
links and file downloads, plain <a> is fine. */}
<p className="mt-10 text-sm">
<a href="/cv.pdf" className="underline underline-offset-4 text-amber-400">
Download CV (PDF)
</a>
</p>
<nav className="mt-16 pt-8 border-t border-neutral-800 flex gap-6 text-sm text-neutral-400">
<Link href="/" className="hover:text-white">
Back home
</Link>
<Link href="/projects" className="hover:text-white">
See projects
</Link>
</nav>
</main>
);
}
+84
View File
@@ -0,0 +1,84 @@
// File-based routing: this file's location IS the URL.
// /app/about/page.tsx → https://yoursite.com/about
//
// Conventions:
// page.tsx = the route's UI
// layout.tsx = a wrapper shared across this folder + any nested routes
// loading.tsx = shown while the page is loading
// not-found.tsx = shown on 404 within this segment
import type { Metadata } from "next";
import Link from "next/link";
// Route-level metadata. Next reads this at build time and emits the
// correct <title>, <meta description>, OG tags, etc. into <head>.
// The root layout (/app/layout.tsx) had its own metadata; this overrides
// the title for /work specifically.
export const metadata: Metadata = {
title: "Work — Angel Mankel",
// description:
// "Frontend engineer with deep AI-tooling fluency. Currently at Village Medical.",
};
// This is a Server Component by default. It runs on the server, sends
// HTML to the browser, and ships zero JavaScript for this page itself.
// You only add "use client" at the top of a file when you need
// interactivity (useState, onClick, etc).
//
// Because it's a server component, you could `await fetch()` here, read
// a markdown file from disk, or query a DB directly — no API route needed.
export default function WorkPage() {
return (
<main className="mx-auto max-w-2xl px-6 py-24">
<h1 className="text-3xl font-semibold mb-12">Work</h1>
<section className="space-y-6 text-base leading-relaxed text-neutral-200">
<p>
I came up through healthcare IT help desk, then Salesforce admin,
then software engineer at Village Medical, where I lead React and
TypeScript redesigns of patient-facing apps and the internal
component library.
</p>
<p>
In parallel I&apos;ve gone deep on AI-assisted development. Claude
Code, custom slash commands, MCP integrations the tooling layer
that&apos;s reshaping how I work across the stack.
</p>
<p>
I&apos;m looking for remote-US product-engineering roles where
shipping React is the day job and using and building AI tooling is
first-class.
</p>
</section>
<section className="mt-16">
<div className="text-xs uppercase tracking-wider text-neutral-500 mb-3">
Timeline
</div>
<ul className="font-mono text-sm space-y-1.5 text-neutral-200">
<li>
<span className="text-neutral-500 mr-3">2024 now</span>
Village Medical · Software Engineer
</li>
<li>
<span className="text-neutral-500 mr-3">2022 2024</span>
Village Medical · Salesforce Admin
</li>
<li>
<span className="text-neutral-500 mr-3">2019 2022</span>
Gila River · Help Desk / IT
</li>
</ul>
</section>
<nav className="mt-16 pt-8 border-t border-neutral-800 flex gap-6 text-sm text-neutral-400">
<Link href="/" className="hover:text-white">
Back home
</Link>
<Link href="/about" className="hover:text-white">
See about
</Link>
</nav>
</main>
);
}
+142
View File
@@ -0,0 +1,142 @@
# Portfolio — Angel Mankel
Personal site at a reserved domain (TBD — see `config.md` once created). This is a hiring-funnel artifact, not a blog or playground.
## Who this is for
The reader is a hiring manager or recruiter at one of these companies:
- **Bullseye:** Vercel, Anthropic, Cursor, Cognition, Replit, Sourcegraph, Continue, Linear, Figma
- **Adjacent:** Stripe, Ramp, Notion, Retool, any AI-native product company shipping React-heavy surfaces
They land here from a CV, LinkedIn DM, or referral. They will spend **60-120 seconds** before deciding to reply or move on. Optimize ruthlessly for that window.
## Who Angel is (positioning)
**Headline:** Frontend engineer with deep AI-tooling fluency — ships production React and builds custom Claude Code workflows.
**The wedge:** Most React devs treat Claude Code as a toy. Most AI tinkerers can't ship a real component library. Angel does both.
**Background arc:** Healthcare IT → Salesforce admin → Software Engineer at Village Medical (current). Leads React + TypeScript redesigns of patient-facing apps and the internal component library. In parallel, heavy day-to-day Claude Code user — custom slash commands, MCP integrations, agent workflows.
**Target roles:** Frontend / Product / AI-Native engineer, remote US, mid-level (1-3 yr SWE, broader IT background). Comp target $90-130K USD, floor $100K.
Full profile lives in `~/Projects/career-ops/config/profile.yml` and `~/Projects/career-ops/cv.md`. Read those before writing any copy.
## Design direction
**Aesthetic reference:** Vercel.com, Linear.app, Anthropic.com, Rauno.me, Paco.me, Brittany Chiang's v4.
**Principles:**
- Minimalist, content-first. Typography does the heavy lifting.
- Dark only. No light theme, no theme toggle. See `palette.html` for the full spec.
- Generous whitespace. Wide line-height. Long-form readable.
- **One** signature interaction detail (subtle cursor effect, scroll-driven element, command palette) — not a museum of effects.
- No hero video, no parallax stacks, no animated SVG mascots, no "Hi I'm Angel 👋" with a waving emoji.
- Monospace accents for technical content (kbd, inline code, metadata) — sparingly.
**What we are NOT building:**
- A WebGL/Three.js showcase. Reads as "junior trying hard" to senior frontend HMs. Angel's graphics range gets one line in About, not a hero.
- A flashy gradient/blob landing page.
- A blog-first site. (Writing is welcome but not the entry point.)
- A "projects" grid of unfinished side projects. Quality over quantity — 3-4 deep case studies beats 12 thumbnails.
## Information architecture
Five routes max. Keep it skimmable.
```
/ → Landing. Name + one-line positioning + 3 case study cards + contact.
/projects → Case study index (same 3-4 cards, expandable).
/projects/[slug] → Individual case study (postmortem format).
/about → Background arc, current role, what Angel is looking for.
/uses → Optional. Tools, editor setup, Claude Code workflow. High signal for AI-native hiring.
```
Skip `/blog`, `/work` (use `/projects`), `/contact` (inline on `/`), and `/resume` (a chrono strip + Download CV link on `/about` covers it without duplicating content).
### What `/about` must include
Beyond the narrative paragraphs:
- **Chronological strip** — 3-4 rows, plain text, format: `year-range · company · role`. No bullets, no descriptions. Source from `~/Projects/career-ops/cv.md`.
- **Download CV (PDF)** — single plain-text link pointing at the PDF generated by career-ops (`generate-pdf.mjs` output). Don't style it as a button or hero CTA — one line, in flow.
## Case study format (CRITICAL)
Each case study reads like an engineering postmortem, not a marketing page. Structure:
1. **One-line summary** — what shipped, who it served, the measurable outcome.
2. **Context** — the constraint or problem. 2-3 sentences.
3. **Decisions** — 3-5 specific technical/design calls and why. Name the alternatives rejected.
4. **Outcome** — measurable result. Numbers when possible. Honest when not.
5. **What I'd do differently** — one paragraph. Signals seniority.
**Do not** include: tech stack badges, "challenges faced" sections, generic "I learned a lot" closers.
### The 3-4 case studies to write
Source material in `~/Projects/career-ops/cv.md` and `~/Projects/career-ops/modes/_profile.md` under "proof_points":
1. **Village Medical patient scheduling redesign** — React + TS rebuild of a patient-facing scheduling app. Lead with scope and UX decisions, not framework name-drops.
2. **Village Medical internal component library** — design-system ownership. This is the bullseye proof point for product/design-engineer roles. Show the API of one component, the migration story, governance model.
3. **Claude Code custom tooling** — slash commands, MCP integrations, agent workflows used day-to-day. This is the AI-native wedge. Show one concrete workflow with before/after time-on-task.
4. **(Optional) Gila River internal Electron apps** — older but quantified (100-150% productivity gains, 70% AD-script speedup). Frame as "how I got into engineering." Skip if it dilutes the frontend narrative; keep if it adds blue-collar engineering credibility.
## Tech stack recommendation
**Default:** Next.js 15 (App Router) + TypeScript + Tailwind v4 + MDX for case studies.
Why: it's the stack the bullseye companies ship. Using it is itself a signal.
**Deployment:** Self-hosted by Angel. Traefik is already configured and pointing at the domain. Do not propose Vercel, Netlify, Cloudflare Pages, or any managed host — the infra is in-house and stays that way. Build target should produce a standard Node server or static export that drops into the existing Traefik setup; ask Angel for specifics (container? bare Node? static `out/`?) before wiring CI.
**Alternatives considered:**
- Astro — better for static-heavy content sites, but Next.js signals stack alignment with target employers. Use Astro only if Angel wants to demonstrate range.
- Plain HTML/CSS — would actually be impressive ("I don't need a framework for this") but reads as contrarian unless the design carries it. Skip.
**Other choices:**
- `next/font` for self-hosted typography. Suggested pairing: Inter (UI) + JetBrains Mono / Geist Mono (code). Or splurge on a paid display face for the name only.
- `next-mdx-remote` or built-in MDX for case studies.
- `shiki` for code blocks (matches Vercel/Anthropic aesthetic better than Prism).
- View Transitions API for `/projects``/projects/[slug]` navigation. One signature detail.
- No CMS. Content lives in MDX files in-repo. Version-controlled, no DB.
## Tone and copy
Read `~/Projects/career-ops/modes/_profile.md` under "Writing Style" if it exists; otherwise extract style from `~/Projects/career-ops/writing-samples/` before drafting any user-facing copy.
Defaults if no samples found:
- First person, active voice. "I led", "I shipped", not "responsible for".
- Short sentences. Mix in a longer one for rhythm.
- Specific over abstract. "Cut p95 from 2.1s to 380ms" beats "improved performance."
- Zero corporate clichés: no "passionate", "results-oriented", "proven track record", "leveraged", "synergies", "cutting-edge."
- No emoji in copy. (Emoji on the page = wrong audience signal for these companies.)
## What "done" looks like for v1
- [ ] Site reachable at the domain through Angel's Traefik (deployment infra is his — agent does not touch it)
- [ ] `/` renders Name + positioning line + 3 case study cards + email contact
- [ ] 3 case studies fully written (not lorem ipsum)
- [ ] `/about` written, including chrono strip and Download CV link
- [ ] CV PDF generated via career-ops and served at a stable path (e.g. `/cv.pdf`)
- [ ] Open Graph image + favicon
- [ ] Lighthouse: 100/100/100/100 (this is table stakes for the audience)
- [ ] Site is responsive but designed desktop-first (hiring managers are on laptops)
- [ ] No analytics that block (Plausible or none — definitely not GA)
## What NOT to do
- Do not scaffold a Next.js project until Angel says go on the design direction.
- Do not write case study copy without first reading `~/Projects/career-ops/cv.md` and `~/Projects/career-ops/modes/_profile.md`.
- Do not invent metrics or experience. Pull only from CV + article-digest.md (if present).
- Do not add a "currently learning" or "tech stack" badge wall.
- Do not commit Angel's phone number, address, or any PII beyond name + email + LinkedIn + GitHub.
- Do not generate AI art for the OG image. A clean typographic OG card is the right move.
## Cross-references
- CV (source of truth): `~/Projects/career-ops/cv.md`
- Profile & narrative: `~/Projects/career-ops/config/profile.yml`, `~/Projects/career-ops/modes/_profile.md`
- Proof point details (if exists): `~/Projects/career-ops/article-digest.md`
- Writing samples (if exists): `~/Projects/career-ops/writing-samples/`
+191
View File
@@ -0,0 +1,191 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Portfolio Palette — Angel Mankel</title>
<style>
html, body { margin: 0; padding: 0; font-family: ui-sans-serif, system-ui, sans-serif; background: #fff; color: #000; }
body { padding: 40px 20px 120px; }
.wrap { max-width: 1100px; margin: 0 auto; }
h1 { font-size: 22px; margin: 0 0 32px; }
h2 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.08em; margin: 48px 0 12px; color: #555; }
.row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
.swatch { border: 1px solid #000; overflow: hidden; font-family: ui-monospace, monospace; font-size: 11px; }
.swatch .chip { height: 100px; border-bottom: 1px solid #000; }
.swatch .meta { padding: 8px 10px; line-height: 1.4; }
.swatch .role { display: block; font-weight: 600; margin-bottom: 2px; }
.swatch .hex { display: block; color: #555; }
.stage { background: #0a0a0a; padding: 20px; margin-top: 16px; }
.stage + .stage { margin-top: 16px; }
.preview { background: #1c1c1c; color: #ededed; border: 1px solid #2e2e2e; padding: 28px; font-family: ui-sans-serif, system-ui, sans-serif; }
.preview + .preview { margin-top: 16px; }
.preview h3 { font-size: 22px; margin: 0 0 6px; font-weight: 600; }
.preview p { margin: 0 0 10px; font-size: 13px; line-height: 1.6; }
.preview a { color: #d4a24a; text-decoration: underline; text-underline-offset: 3px; }
.preview .muted { color: #6b6b6b; }
.preview .nav { display: flex; justify-content: space-between; align-items: center; font-family: ui-monospace, monospace; font-size: 12px; }
.preview .nav .links { display: flex; gap: 18px; color: #6b6b6b; }
.preview .nav .links a { color: inherit; text-decoration: none; }
.preview hr { border: 0; border-top: 1px solid #2e2e2e; margin: 20px 0; }
.preview .chrono { font-family: ui-monospace, monospace; font-size: 13px; line-height: 1.8; color: #ededed; }
.preview .chrono .y { color: #6b6b6b; margin-right: 14px; }
.preview .code { background: #0f0f0f; border: 1px solid #2e2e2e; padding: 14px 16px; font-family: ui-monospace, monospace; font-size: 12px; line-height: 1.6; }
.preview .code .k { color: #d4a24a; }
.preview .code .c { color: #6b6b6b; }
.preview .case-meta { font-family: ui-monospace, monospace; font-size: 12px; color: #6b6b6b; margin-bottom: 18px; }
.preview .case-meta span + span::before { content: " · "; }
</style>
</head>
<body>
<div class="wrap">
<h1>Palette — Angel Mankel portfolio</h1>
<!-- ============================================================ -->
<h2>Neutrals</h2>
<div class="row">
<div class="swatch">
<div class="chip" style="background: #0a0a0a;"></div>
<div class="meta">
<span class="role">bg</span>
<span class="hex">#0a0a0a</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #1c1c1c;"></div>
<div class="meta">
<span class="role">bg-elevated</span>
<span class="hex">#1c1c1c</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #2e2e2e;"></div>
<div class="meta">
<span class="role">border</span>
<span class="hex">#2e2e2e</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #6b6b6b;"></div>
<div class="meta">
<span class="role">text-muted</span>
<span class="hex">#6b6b6b</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #ededed;"></div>
<div class="meta">
<span class="role">text</span>
<span class="hex">#ededed</span>
</div>
</div>
</div>
<!-- ============================================================ -->
<h2>Accent</h2>
<div class="row">
<div class="swatch">
<div class="chip" style="background: #d4a24a;"></div>
<div class="meta">
<span class="role">accent</span>
<span class="hex">#d4a24a</span>
</div>
</div>
</div>
<!-- ============================================================ -->
<h2>Hover states</h2>
<div class="row">
<div class="swatch">
<div class="chip" style="background: #262626;"></div>
<div class="meta">
<span class="role">bg-elevated · hover</span>
<span class="hex">#262626</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #3d3d3d;"></div>
<div class="meta">
<span class="role">border · hover</span>
<span class="hex">#3d3d3d</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #9a9a9a;"></div>
<div class="meta">
<span class="role">text-muted · hover</span>
<span class="hex">#9a9a9a</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #ffffff;"></div>
<div class="meta">
<span class="role">text · hover</span>
<span class="hex">#ffffff</span>
</div>
</div>
<div class="swatch">
<div class="chip" style="background: #e6b966;"></div>
<div class="meta">
<span class="role">accent · hover</span>
<span class="hex">#e6b966</span>
</div>
</div>
</div>
<!-- ============================================================ -->
<h2>Previews</h2>
<div class="stage"><div class="preview">
<div class="nav">
<div><strong>Angel Mankel</strong></div>
<div class="links"><a href="#">projects</a><a href="#">about</a><a href="#">uses</a><a href="#">email</a></div>
</div>
</div></div>
<div class="stage"><div class="preview">
<h3>Frontend engineer with deep AI-tooling fluency.</h3>
<p>I ship production React at Village Medical and build custom Claude Code workflows that make the day-to-day faster.</p>
<p><a href="#">See selected projects →</a></p>
</div></div>
<div class="stage"><div class="preview">
<h3>Village Medical — patient scheduling redesign</h3>
<div class="case-meta">
<span>Software Engineer</span><span>2024</span><span>React · TypeScript</span>
</div>
<p>Rebuilt the patient appointment scheduling app from a legacy Salesforce flow into a self-contained React surface used across clinics.</p>
<p><a href="#">Read the case study →</a></p>
</div></div>
<div class="stage"><div class="preview">
<div class="muted" style="font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 12px;">timeline</div>
<div class="chrono">
<div><span class="y">2024 now</span>Village Medical · Software Engineer</div>
<div><span class="y">2022 2024</span>Village Medical · Salesforce Admin</div>
<div><span class="y">2019 2022</span>Gila River · Help Desk / IT</div>
</div>
<hr>
<p><a href="#">Download CV (PDF)</a></p>
</div></div>
<div class="stage"><div class="preview">
<div class="code">
<span class="c">// custom Claude Code slash command</span>
<span class="k">export default</span> {
name: <span class="k">'review'</span>,
run: <span class="k">async</span> (ctx) =&gt; {
<span class="k">await</span> ctx.runDiffReview()
}
}
</div>
</div></div>
</div>
</body>
</html>
+295
View File
@@ -0,0 +1,295 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Portfolio Wireframe — Angel Mankel</title>
<style>
html, body { margin: 0; padding: 0; background: #fff; color: #000; font-family: ui-sans-serif, system-ui, sans-serif; }
body { padding: 40px 20px 120px; }
.page-meta { max-width: 1100px; margin: 0 auto 24px; font-size: 13px; color: #555; }
.page-meta h1 { font-size: 18px; margin: 0 0 4px; color: #000; }
.frame { max-width: 1100px; margin: 0 auto 80px; border: 2px solid #000; }
.frame-label { font-family: ui-monospace, monospace; font-size: 12px; background: #000; color: #fff; padding: 6px 10px; }
.frame-body { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.box { border: 1px dashed #333; padding: 14px; font-size: 13px; line-height: 1.4; }
.box .tag { font-family: ui-monospace, monospace; font-size: 11px; color: #555; display: block; margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.04em; }
.row { display: flex; gap: 12px; }
.row > .box { flex: 1; }
.row.three > .box { flex: 1 1 0; }
.nav { display: flex; justify-content: space-between; align-items: center; }
.nav .links { display: flex; gap: 18px; font-family: ui-monospace, monospace; font-size: 12px; }
.tall { min-height: 140px; }
.taller { min-height: 220px; }
.small { font-size: 12px; color: #555; }
hr.divider { border: 0; border-top: 1px solid #ccc; margin: 60px 0; }
.legend { max-width: 1100px; margin: 0 auto 40px; font-size: 12px; color: #555; padding: 12px; border: 1px dashed #999; }
.legend code { background: #eee; padding: 1px 4px; }
</style>
</head>
<body>
<div class="legend">
<strong>Wireframe legend.</strong> Solid black border = page viewport. Dashed border = a content region with a label.
No colors, no images, no real type. Purpose: agree on layout structure and flow before touching CSS.
Routes shown: <code>/</code>, <code>/projects</code>, <code>/projects/[slug]</code>, <code>/about</code>, <code>/uses</code>.
</div>
<!-- ============================================================ -->
<div class="page-meta">
<h1>Route: /</h1>
<div>Landing. Goal: in 60-120s, communicate who Angel is, what he ships, how to contact.</div>
</div>
<div class="frame">
<div class="frame-label">VIEWPORT — /</div>
<div class="frame-body">
<div class="box nav">
<div><span class="tag">brand</span>Angel Mankel</div>
<div class="links">
<span>projects</span><span>about</span><span>uses</span><span>email</span>
</div>
</div>
<div class="box taller">
<span class="tag">hero — text only, no image</span>
Large name or wordmark. One-line positioning underneath: "Frontend engineer with deep AI-tooling fluency — ships production React and builds custom Claude Code workflows."
Below that, a secondary line linking to most recent case study or "Currently at Village Medical." No CTA buttons.
</div>
<div class="box">
<span class="tag">section heading</span>
"Selected projects" — small caps or monospace label. Single line.
</div>
<div class="row three">
<div class="box tall">
<span class="tag">case study card 1</span>
Title · one-line summary · year · outcome metric.
Whole card is clickable → /projects/[slug].
</div>
<div class="box tall">
<span class="tag">case study card 2</span>
Same shape as card 1. Three cards total, sometimes four.
</div>
<div class="box tall">
<span class="tag">case study card 3</span>
Same shape.
</div>
</div>
<div class="box">
<span class="tag">contact strip</span>
Email · LinkedIn · GitHub. Plain text links, no icons-only treatment. Maybe a one-line "Open to remote-US roles."
</div>
<div class="box small nav">
<div><span class="tag">footer</span>© 2026 Angel Mankel</div>
<div>Self-hosted · Traefik · Next.js</div>
</div>
</div>
</div>
<!-- ============================================================ -->
<div class="page-meta">
<h1>Route: /projects</h1>
<div>Case study index. Same cards as the landing, but full list. Optional filter (year or tag).</div>
</div>
<div class="frame">
<div class="frame-label">VIEWPORT — /projects</div>
<div class="frame-body">
<div class="box nav">
<div><span class="tag">brand</span>Angel Mankel</div>
<div class="links"><span>projects</span><span>about</span><span>uses</span><span>email</span></div>
</div>
<div class="box">
<span class="tag">page heading</span>
"Projects" — single word. Optional one-line intro: "Selected projects, written as postmortems."
</div>
<div class="box">
<span class="tag">case study row 1</span>
Title · year · one-line summary · key metric. Full-width row, not a card grid (denser, more readable).
</div>
<div class="box">
<span class="tag">case study row 2</span>
Same shape.
</div>
<div class="box">
<span class="tag">case study row 3</span>
Same shape.
</div>
<div class="box">
<span class="tag">case study row 4 (optional)</span>
Same shape. Skip if it dilutes.
</div>
<div class="box small nav">
<div><span class="tag">footer</span>© 2026 Angel Mankel</div>
<div>Self-hosted · Traefik · Next.js</div>
</div>
</div>
</div>
<!-- ============================================================ -->
<div class="page-meta">
<h1>Route: /projects/[slug]</h1>
<div>Individual case study. Postmortem format: context · decisions · outcome · what I'd do differently.</div>
</div>
<div class="frame">
<div class="frame-label">VIEWPORT — /projects/[slug]</div>
<div class="frame-body">
<div class="box nav">
<div><span class="tag">brand</span>Angel Mankel</div>
<div class="links"><span>projects</span><span>about</span><span>uses</span><span>email</span></div>
</div>
<div class="box">
<span class="tag">case study header</span>
Project name (large). Below: role · year · stack · one-line outcome. No hero image.
</div>
<div class="row">
<div class="box" style="flex: 0 0 200px;">
<span class="tag">sidebar (desktop only)</span>
Sticky table of contents: Context · Decisions · Outcome · Retrospective. Collapses above the body on mobile.
</div>
<div class="box taller" style="flex: 1;">
<span class="tag">long-form body (MDX)</span>
Section: <em>Context</em> — the constraint, 2-3 sentences.<br>
Section: <em>Decisions</em> — 3-5 specific calls with rejected alternatives.<br>
Section: <em>Outcome</em> — measurable result, honest when not.<br>
Section: <em>What I'd do differently</em> — one paragraph.<br>
Inline: code blocks (shiki), occasional pull-quote, optional simple diagram. No carousels.
</div>
</div>
<div class="box">
<span class="tag">next/prev case study</span>
Two links: ← previous case study · next case study →. Keeps the reader in the work funnel.
</div>
<div class="box small nav">
<div><span class="tag">footer</span>© 2026 Angel Mankel</div>
<div>Self-hosted · Traefik · Next.js</div>
</div>
</div>
</div>
<!-- ============================================================ -->
<div class="page-meta">
<h1>Route: /about</h1>
<div>Background arc. Who Angel is, what he's looking for. Long-form, first person.</div>
</div>
<div class="frame">
<div class="frame-label">VIEWPORT — /about</div>
<div class="frame-body">
<div class="box nav">
<div><span class="tag">brand</span>Angel Mankel</div>
<div class="links"><span>projects</span><span>about</span><span>uses</span><span>email</span></div>
</div>
<div class="box">
<span class="tag">page heading</span>
"About" — single word.
</div>
<div class="box tall">
<span class="tag">narrative paragraph 1 — arc</span>
Healthcare IT → Salesforce admin → SWE at Village Medical. 3-5 sentences, first person, active voice.
</div>
<div class="box tall">
<span class="tag">narrative paragraph 2 — current work + AI wedge</span>
What Angel does day-to-day. React + TS leadership. Heavy Claude Code use. The "frontend engineer who actually uses AI to ship" framing.
</div>
<div class="box">
<span class="tag">narrative paragraph 3 — what I'm looking for</span>
One paragraph. Remote US, mid-level, AI-native or product-engineering. Names of companies he'd love to work with (optional but bold).
</div>
<div class="box">
<span class="tag">chronological strip</span>
Three or four rows, plain text. Each row: year-range · company · role. No bullets, no descriptions — the case studies and narrative carry the detail. Example:<br>
2024present · Village Medical · Software Engineer<br>
20222024 · Village Medical · Salesforce Admin<br>
20192022 · Gila River · Help Desk / IT
</div>
<div class="box">
<span class="tag">download CV</span>
Single line: "Download CV (PDF)" link. Points at the PDF generated by career-ops. No fancy treatment.
</div>
<div class="box">
<span class="tag">contact strip</span>
Email · LinkedIn · GitHub. Same as landing.
</div>
<div class="box small nav">
<div><span class="tag">footer</span>© 2026 Angel Mankel</div>
<div>Self-hosted · Traefik · Next.js</div>
</div>
</div>
</div>
<!-- ============================================================ -->
<div class="page-meta">
<h1>Route: /uses (optional)</h1>
<div>Tools, editor setup, Claude Code workflow. High-signal page for AI-native hiring managers.</div>
</div>
<div class="frame">
<div class="frame-label">VIEWPORT — /uses</div>
<div class="frame-body">
<div class="box nav">
<div><span class="tag">brand</span>Angel Mankel</div>
<div class="links"><span>projects</span><span>about</span><span>uses</span><span>email</span></div>
</div>
<div class="box">
<span class="tag">page heading</span>
"Uses" — single word. One-line intro: "What I reach for daily."
</div>
<div class="row">
<div class="box tall">
<span class="tag">section: hardware</span>
Plain list. Machine, monitors, keyboard. One line each.
</div>
<div class="box tall">
<span class="tag">section: editor &amp; shell</span>
VS Code config highlights, terminal, font, theme.
</div>
</div>
<div class="row">
<div class="box tall">
<span class="tag">section: AI workflow</span>
Claude Code setup. Custom slash commands. MCP servers. One paragraph per workflow with the time saved.
This is the signal-dense section — give it the most space.
</div>
<div class="box tall">
<span class="tag">section: self-hosting</span>
Traefik, the box, whatever else runs on it. One-liners. This is where "self-hosted" lives without becoming the lede.
</div>
</div>
<div class="box small nav">
<div><span class="tag">footer</span>© 2026 Angel Mankel</div>
<div>Self-hosted · Traefik · Next.js</div>
</div>
</div>
</div>
</body>
</html>