How this site is built
Everything below is this site's own setup, not a case study. The pipeline runs on every pull request and on every merge to main. A merge deploys only once every gate has passed: there is no skip input and no manual override.
Live Real data about this site.
This site right now
- Up since
- 3 Nov 2026
- Last deploy
- 3 Nov 2026, 10:12 UTC
- Pipeline passing
- Trivy passing
Last updated
Cloudflare settings on the free plan, about twelve resources, in the repository's infra folder. State lives on HCP Terraform with local execution from CI.
- Pages project
- Direct upload, production branch main. Created first, on its own, so the rest of the site had somewhere to deploy to.
- Domain and DNS
- The apex and www records, pointing at the Pages hostname. Staged behind a variable that stays false until launch, so a missing zone never blocks a build.
- Zone settings
- Strict SSL, always use HTTPS, a minimum TLS of 1.2, TLS 1.3 on. Rocket Loader and email obfuscation are off, because both inject scripts the content security policy would block.
- Redirect rule
- www to the apex.
Terraform does not deploy the site. CI uploads the built files directly, and apply is a manual run the owner starts, never part of a merge.
The pipeline
Jobs in the middle stage run at the same time. Deploy waits for all of them.
Every push
- Build both outputs
- Check images against their models
- Check size budgets
Gates
- Lint and types
- Unit tests
- Confidentiality scan
- Semgrep
- Trivy
- Browser tests with axe
- Lighthouse
Main only
- Write the status values
- Deploy to Cloudflare Pages
After the deploy
- Smoke test the live site
- Record this deploy on the metrics branch
When a gate fails on main
A failed run on main, or a failed smoke test, triggers a second workflow. It reads the last deployed commit, rebuilds that code with a failing status, and deploys it. The site stays up and says so. If that workflow fails too, it fails loudly and Cloudflare keeps serving the previous deploy.
The gates
Each one says what it blocks and what it only reports.
Lint and types
Blocks a deploy
- Blocks
- Any ESLint error or warning, any TypeScript error, any Astro check finding at hint level or worse.
- Only reports
- Nothing. Warnings are errors here.
Unit tests
Blocks a deploy
- Blocks
- Any failing test, including the simulators pinned to the real config they claim to model.
- Only reports
- Nothing.
Size budgets
Blocks a deploy
- Blocks
- A chunk over its budget: the inline script, the shell, the 3D stack, each demo, each scene module and the images.
- Only reports
- The measured size of each one, pass or fail.
Image check
Blocks a deploy
- Blocks
- A committed image that no longer matches the model that drew it, so the pictures cannot drift from the 3D.
- Only reports
- Nothing.
Confidentiality scan
Blocks a deploy
- Blocks
- Account numbers, ARNs, VPC, subnet, security group and instance ids, webhook URLs, phone numbers, almost any IP address, and a private list of names, across the source, the built HTML and the whole git history.
- Only reports
- A hit is reported by its position in the list, never by its text. It cannot catch a paraphrase, so a person reads the site before launch.
Semgrep
Blocks a deploy
- Blocks
- Any finding from the JavaScript, TypeScript, React and GitHub Actions rule packs.
- Only reports
- Nothing. These are community rule packs, not an audit.
Trivy
Blocks a deploy
- Blocks
- A high or critical vulnerability, secret or misconfiguration that has a fix, including in the Terraform files.
- Only reports
- Findings with no fix available yet. Its result is also what the status strip above reports.
Browser tests
Blocks a deploy
- Blocks
- Any failing test at three widths in both themes, with reduced motion, including the accessibility checks axe runs on every page.
- Only reports
- Nothing. axe catches part of accessibility, not all of it.
Lighthouse
Blocks a deploy
- Blocks
- A score under 90 in any category on this page, the metrics page or the journey, on mobile or desktop, or a largest contentful paint over 2.5 s, or layout shift over 0.02.
- Only reports
- Everything else it measures.
Smoke test
Reports only
- Blocks
- The deploy is already live when this runs, so nothing. A failure triggers the rollback above.
- Only reports
- Live status codes, the real security headers, the cache headers on fonts, that the published status matches this commit, and any console or policy error on a real load.
Metrics
Reports only
- Blocks
- Nothing, by design. A measurement that fails is left out rather than guessed.
- Only reports
- The numbers charted on the metrics page.
What this doesn't prove
- A static site on Cloudflare stays up almost by default. The uptime figure mostly proves the monitor runs, not that anything difficult is being kept alive.
- Lighthouse runs in CI against the built files on a fixed machine, not against the live host from a real connection.
- Frame rate is not measured in CI. A shared runner on software graphics would produce a number that means nothing, so no chart claims one.
- Memory is measured on software graphics in CI. It is useful as a trend between deploys and not as a figure about any real machine.
- The branch cannot be protected while the repository is private on the free plan, so nothing stops a direct push to main today. Protection goes on when the repository becomes public.
- Semgrep and Trivy find what their rules know about. Neither is a security review.
The code
The pipeline, the Terraform and every script described here are in the repository.
github.com/Anshul-exe/PortfolioWhat each deploy measures