A senior frontend engineering portfolio project focused on architecture, reusable UI, accessibility, testing, performance, and developer experience.
Live app: lab.joeybowser.com · Storybook: storybook.joeybowser.com
npm run devstarts the Vite app.npm run buildtypechecks and builds the production bundle.npm run lintruns ESLint.npm run testruns the Vitest suite once.npm run test:watchruns Vitest in watch mode.npm run formatchecks Prettier formatting.npm run storybookstarts Storybook.npm run build-storybookbuilds the static Storybook site.
src/
app/ App composition and provider wiring
components/ Shared component library and layout components
features/ Product feature modules
lib/ Shared framework-agnostic utilities
styles/ Global CSS, tokens, and base styles
See docs/architecture.md for architectural decisions and tradeoffs.
The app and Storybook deploy as two separate Vercel projects pointed at this same repo — see ADR 0003 for why.
- App project: import the repo into Vercel, accept the auto-detected Vite preset (build
npm run build, outputdist).vercel.jsonalready adds the SPA rewrite so/playgroundetc. don't 404 on direct navigation. - Storybook project: import the same repo as a second Vercel project. In its Project Settings, set the build command to
npm run build-storybookand the output directory tostorybook-static. - Once the Storybook project has a URL, set
VITE_STORYBOOK_URLas an environment variable on the app project (see.env.example) and redeploy — the nav's "Storybook ↗" link only renders when this is set. - Link both resulting URLs from the portfolio site whenever you're ready — this repo doesn't need to know that site exists.
MIT — see LICENSE.