# BlueCap Strategies Website Static marketing site for BlueCap Strategies, built with [Astro](https://astro.build/) and deployed to a k3s homelab cluster via GitOps (ArgoCD). ## Stack - **Astro 5** — static output (`output: "static"`), no runtime JS framework. - **Content Collections (Markdown)** — page copy lives in `src/content/` (services, focus-areas, pages, insights), validated by a Zod SEO schema at build time. - **nginx** (Alpine) serves the built `dist/` from a multi-stage Docker image. - **ArgoCD + Kustomize** (`k8s/`) reconcile the deployment; images are published to GHCR by CI. ## Local development ```bash npm install npm run dev # dev server at http://localhost:4321 npm run build # astro check (typecheck) + astro build → dist/ npm run preview # serve the production build npm run seo:lint # structural SEO checks over dist/ (run after build) npm run test:e2e # Playwright end-to-end tests ``` Copy `.env.example` to `.env` and fill in values as needed (site URL, contact form endpoint, analytics keys). Never commit `.env`. ## Editing content Page copy is Markdown with typed frontmatter — no code changes needed to edit words: - `src/content/services/*.md` — service detail pages - `src/content/focus-areas/*.md` — focus-area detail pages - `src/content/pages/*.md` — standalone long-form pages (e.g. About) - `src/content/insights/*.md` — blog/insights posts Frontmatter is enforced by the Zod schema in `src/content.config.ts` (e.g. `description` must be 120–158 chars), so the build fails fast on SEO violations. The `.md` files are **build-time source**: Astro compiles them to static HTML in `dist/`. The Markdown itself is never served. ## Project layout ``` src/ Astro pages, layouts, components, content collections, styles public/ Static assets served as-is (images, robots.txt, healthz) scripts/ Build tooling (seo-lint.mjs) tests/ Playwright e2e specs deploy/ nginx.conf for the runtime image k8s/ Kustomize manifests (namespace, deployment, service, ingress, configmap) docs/ Committed engineering records — ADRs, deployment, SEO/AEO, deviations Dockerfile Multi-stage build → nginx image containing only dist/ ``` `planning/` (git-ignored) holds working docs — content inventories, parity checklists, and the original rebuild brief. See `docs/adr/` for the decision record. ## Deployment Push to `main` → GitHub Actions runs the quality gates, builds and pushes a ``-tagged image to GHCR, and updates the image tag in `k8s/`. ArgoCD reconciles the change to k3s. GitHub never receives cluster credentials. See `docs/gitops-deployment-strategy.md`.