From dd8cbe1c45923899e19c518aa31bc5f4f6a285ce Mon Sep 17 00:00:00 2001 From: donny Date: Wed, 27 May 2026 15:21:10 -0700 Subject: [PATCH] feat: initial next.js boilerplate, set up .env, add outline documents --- .env.example | 0 .gitignore | 1 + .vscode/settings.json | 3 + app/about/page.tsx | 94 ++++++++++++++ app/projects/page.tsx | 84 ++++++++++++ docs/CLAUDE.md | 142 ++++++++++++++++++++ docs/palette.html | 191 +++++++++++++++++++++++++++ docs/wireframe.html | 295 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 810 insertions(+) create mode 100644 .env.example create mode 100644 .vscode/settings.json create mode 100644 app/about/page.tsx create mode 100644 app/projects/page.tsx create mode 100644 docs/CLAUDE.md create mode 100644 docs/palette.html create mode 100644 docs/wireframe.html diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore index 5ef6a52..7b8da95 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.example # vercel .vercel diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3c358ef --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "js/ts.tsdk.path": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/app/about/page.tsx b/app/about/page.tsx new file mode 100644 index 0000000..3f1c5d6 --- /dev/null +++ b/app/about/page.tsx @@ -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 , <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've gone deep on AI-assisted development. Claude + Code, custom slash commands, MCP integrations — the tooling layer + that's reshaping how I work across the stack. + </p> + <p> + I'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> + ); +} diff --git a/app/projects/page.tsx b/app/projects/page.tsx new file mode 100644 index 0000000..33251bb --- /dev/null +++ b/app/projects/page.tsx @@ -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've gone deep on AI-assisted development. Claude + Code, custom slash commands, MCP integrations — the tooling layer + that's reshaping how I work across the stack. + </p> + <p> + I'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> + ); +} diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md new file mode 100644 index 0000000..8c804d9 --- /dev/null +++ b/docs/CLAUDE.md @@ -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/` diff --git a/docs/palette.html b/docs/palette.html new file mode 100644 index 0000000..3cc4be6 --- /dev/null +++ b/docs/palette.html @@ -0,0 +1,191 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8" /> +<title>Portfolio Palette — Angel Mankel + + + +
+ +

Palette — Angel Mankel portfolio

+ + +

Neutrals

+ +
+
+
+
+ bg + #0a0a0a +
+
+
+
+
+ bg-elevated + #1c1c1c +
+
+
+
+
+ border + #2e2e2e +
+
+
+
+
+ text-muted + #6b6b6b +
+
+
+
+
+ text + #ededed +
+
+
+ + +

Accent

+ +
+
+
+
+ accent + #d4a24a +
+
+
+ + +

Hover states

+ +
+
+
+
+ bg-elevated · hover + #262626 +
+
+
+
+
+ border · hover + #3d3d3d +
+
+
+
+
+ text-muted · hover + #9a9a9a +
+
+
+
+
+ text · hover + #ffffff +
+
+
+
+
+ accent · hover + #e6b966 +
+
+
+ + +

Previews

+ +
+ +
+ +
+

Frontend engineer with deep AI-tooling fluency.

+

I ship production React at Village Medical and build custom Claude Code workflows that make the day-to-day faster.

+

See selected projects →

+
+ +
+

Village Medical — patient scheduling redesign

+
+ Software Engineer2024React · TypeScript +
+

Rebuilt the patient appointment scheduling app from a legacy Salesforce flow into a self-contained React surface used across clinics.

+

Read the case study →

+
+ +
+
timeline
+
+
2024 – nowVillage Medical · Software Engineer
+
2022 – 2024Village Medical · Salesforce Admin
+
2019 – 2022Gila River · Help Desk / IT
+
+
+

Download CV (PDF)

+
+ +
+
+// custom Claude Code slash command +export default { + name: 'review', + run: async (ctx) => { + await ctx.runDiffReview() + } +} +
+
+ +
+ + diff --git a/docs/wireframe.html b/docs/wireframe.html new file mode 100644 index 0000000..4bd11ae --- /dev/null +++ b/docs/wireframe.html @@ -0,0 +1,295 @@ + + + + +Portfolio Wireframe — Angel Mankel + + + + +
+ Wireframe legend. 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: /, /projects, /projects/[slug], /about, /uses. +
+ + +
+

Route: /

+
Landing. Goal: in 60-120s, communicate who Angel is, what he ships, how to contact.
+
+
+
VIEWPORT — /
+
+ + + +
+ hero — text only, no image + 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. +
+ +
+ section heading + "Selected projects" — small caps or monospace label. Single line. +
+ +
+
+ case study card 1 + Title · one-line summary · year · outcome metric. + Whole card is clickable → /projects/[slug]. +
+
+ case study card 2 + Same shape as card 1. Three cards total, sometimes four. +
+
+ case study card 3 + Same shape. +
+
+ +
+ contact strip + Email · LinkedIn · GitHub. Plain text links, no icons-only treatment. Maybe a one-line "Open to remote-US roles." +
+ + + +
+
+ + +
+

Route: /projects

+
Case study index. Same cards as the landing, but full list. Optional filter (year or tag).
+
+
+
VIEWPORT — /projects
+
+ + + +
+ page heading + "Projects" — single word. Optional one-line intro: "Selected projects, written as postmortems." +
+ +
+ case study row 1 + Title · year · one-line summary · key metric. Full-width row, not a card grid (denser, more readable). +
+
+ case study row 2 + Same shape. +
+
+ case study row 3 + Same shape. +
+
+ case study row 4 (optional) + Same shape. Skip if it dilutes. +
+ + + +
+
+ + +
+

Route: /projects/[slug]

+
Individual case study. Postmortem format: context · decisions · outcome · what I'd do differently.
+
+
+
VIEWPORT — /projects/[slug]
+
+ + + +
+ case study header + Project name (large). Below: role · year · stack · one-line outcome. No hero image. +
+ +
+
+ sidebar (desktop only) + Sticky table of contents: Context · Decisions · Outcome · Retrospective. Collapses above the body on mobile. +
+
+ long-form body (MDX) + Section: Context — the constraint, 2-3 sentences.
+ Section: Decisions — 3-5 specific calls with rejected alternatives.
+ Section: Outcome — measurable result, honest when not.
+ Section: What I'd do differently — one paragraph.
+ Inline: code blocks (shiki), occasional pull-quote, optional simple diagram. No carousels. +
+
+ +
+ next/prev case study + Two links: ← previous case study · next case study →. Keeps the reader in the work funnel. +
+ + + +
+
+ + +
+

Route: /about

+
Background arc. Who Angel is, what he's looking for. Long-form, first person.
+
+
+
VIEWPORT — /about
+
+ + + +
+ page heading + "About" — single word. +
+ +
+ narrative paragraph 1 — arc + Healthcare IT → Salesforce admin → SWE at Village Medical. 3-5 sentences, first person, active voice. +
+ +
+ narrative paragraph 2 — current work + AI wedge + What Angel does day-to-day. React + TS leadership. Heavy Claude Code use. The "frontend engineer who actually uses AI to ship" framing. +
+ +
+ narrative paragraph 3 — what I'm looking for + One paragraph. Remote US, mid-level, AI-native or product-engineering. Names of companies he'd love to work with (optional but bold). +
+ +
+ chronological strip + 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:
+ 2024–present · Village Medical · Software Engineer
+ 2022–2024 · Village Medical · Salesforce Admin
+ 2019–2022 · Gila River · Help Desk / IT +
+ +
+ download CV + Single line: "Download CV (PDF)" link. Points at the PDF generated by career-ops. No fancy treatment. +
+ +
+ contact strip + Email · LinkedIn · GitHub. Same as landing. +
+ + + +
+
+ + +
+

Route: /uses (optional)

+
Tools, editor setup, Claude Code workflow. High-signal page for AI-native hiring managers.
+
+
+
VIEWPORT — /uses
+
+ + + +
+ page heading + "Uses" — single word. One-line intro: "What I reach for daily." +
+ +
+
+ section: hardware + Plain list. Machine, monitors, keyboard. One line each. +
+
+ section: editor & shell + VS Code config highlights, terminal, font, theme. +
+
+ +
+
+ section: AI workflow + 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. +
+
+ section: self-hosting + Traefik, the box, whatever else runs on it. One-liners. This is where "self-hosted" lives without becoming the lede. +
+
+ + + +
+
+ + +