Live: hoobi.dev
A living resume. The portfolio data lives in data/ as YAML files and is the source of truth: edit the YAML and the site updates.
- Backend: none at runtime. The portfolio API is pre-rendered JSON/YAML at build time and published to Azure Blob Storage.
- Frontend: React + Vite. Fetches everything from the API; no hardcoded content.
- Schemas: a shared package validates the YAML on load and types both the generator's output and the frontend.
- SBOM: CycloneDX generated at build time and surfaced both as
sbom.jsonand as a visualisation in the UI. - Infra: Bicep deploys an Azure Static Web App (free tier) for the SPA, and adopts the existing storage account that fronts the API.
- CI/CD: GitHub Actions builds the static site, runs tests, attests the SBOM, and deploys via Bicep.
pnpm install --frozen-lockfile
pnpm devThe generator watches data/ and re-emits on change; Vite serves the SPA at http://localhost:5173, proxying /api/* and the site-root meta files to the generator's output. Swagger UI at http://localhost:5173/docs.
All content lives under data/. Each file maps to one zod-validated schema; invalid YAML fails the build (and CI).
| File | Contents |
|---|---|
profile.yaml |
name, headline, summary, contact, location |
principles.yaml |
the engineering principles I work to |
skills.yaml |
capability groups |
experience.yaml |
role history |
projects.yaml |
flagship + OSS projects |
azure-resources.yaml |
Azure services grouped by the principle they serve |
work-themes.yaml |
recurring engineering themes (with evidence) |
pnpm install --frozen-lockfile
pnpm buildpnpm build runs the schemas typecheck, the generator (emits the static API payload + site-root meta files), then the Vite build. Output: packages/web/dist/ (the deployable SPA, with the meta files merged in) and packages/generator/dist-api/ (the API payload, published to blob storage in CI).
CI publishes packages/web/dist/ to an Azure Static Web App and packages/generator/dist-api/ to the portfolio container on the storage account behind api.hoobi.dev. There is no container image and nothing runs at request time - see SETUP.md for the one-time infra setup.
MIT. See LICENSE.