Writing / Article

Under the Hood: My Personal Tech Stack

A technical deep dive into the architecture, content model, styling, and deployment pipeline of this site.

Contents

This post provides a high-level overview of the architecture, content model, integrations, and build processes of SalienceNotes.dev.

1. Overview

SalienceNotes.dev is a personal technical blog focusing on cybersecurity, cloud platforms, AI security, risk management, and field notes.

The site is built as a static site using the Astro (v6) framework. I previously used Quartz 5 alongside Obsidian, but transitioned to Astro to achieve a zero client-side JavaScript footprint by default. To maintain this, all Mermaid diagrams are rendered into static SVGs at build time rather than using browser-side libraries. Mapping this out is part of threat modeling personal infrastructure to protect content and credentials.

2. Design Principles

The development of SalienceNotes.dev is guided by a few core principles, aligning with our general IT solution design principles for simple and scalable systems:

  • Static by Default: The entire site is pre-rendered into static HTML/CSS files at build time, eliminating database overhead and server-side execution.
  • Minimal JavaScript: We deliver a zero client-side JavaScript experience by default, converting complex elements like Mermaid diagrams into inline SVGs during compilation.
  • Fast Page Loads: By removing runtime scripts and leveraging built-in image optimization, pages render almost instantly.
  • Simple Content Workflow: Content is authored locally in Markdown/MDX files, and commits/pushes automatically trigger global deployment.
  • Security-First Hosting: Hosting on Cloudflare Pages completely removes standard server attack surfaces, with security headers applied directly at the edge. Sane configurations for this deployment are described in our guide on hardening headers, DNS, and build pipelines.
  • Easy Long-Term Maintenance: A minimal dependency footprint and automated Playwright end-to-end tests ensure the codebase remains stable and easy to update.

3. High-Level Logical Architecture

git push

webhook

deploy

DNS query

HTTPS GET

Local Workstation

GitHub Repo

Cloudflare Pages

Edge CDN

User Browser

Cloudflare DNS


4. Data Flow

4.1 Content & Deployment Lifecycle

  1. Content Creation: The author edits MDX or Markdown files locally.
  2. Push to Repository: Changes are committed and pushed to the private GitHub repository.
  3. Build Execution: GitHub triggers a Cloudflare Pages deployment webhook. Cloudflare pulls the repository, runs npm run build, and outputs static assets to the dist directory.
  4. Edge Distribution: Static files are distributed and cached across Cloudflare’s global edge network.

4.2 User Request & Resolution

  1. DNS Lookup: The user’s browser requests saliencenotes.dev, which resolves to Cloudflare proxy IP addresses.
  2. HTTPS Request: The browser sends an HTTPS request to the nearest Cloudflare edge node.
  3. Content Delivery: Cloudflare serves the static files from the edge cache. If the asset is uncached, it is retrieved from Cloudflare Pages storage, cached, and returned to the browser.

Data Flow Diagram

Cloudflare DNSCloudflare Edge CDNCloudflare Pages BuildGitHub Private RepoCloudflare DNSCloudflare Edge CDNCloudflare Pages BuildGitHub Private RepoBuild runner executes: npm run buildLocal AuthorPublic UserGit Commit & Push (main branch)1Webhook notification2Fetch source code3Publish static assets (dist/)4Resolve saliencenotes.dev5Return Cloudflare Edge IP (Proxy)6HTTP GET / (HTTPS)7Serve static HTML, CSS & Assets8Local AuthorPublic User

5. Integrations

The architecture relies on the following integrations:

  • GitHub App Integration: Grants Cloudflare Pages read access to the private repository.
  • Cloudflare Pages to Cloudflare DNS: Automates CNAME updates and SSL/TLS certificate renewals for saliencenotes.dev.
  • Astro Integrations:
    • @astrojs/mdx to process MDX and Markdown content.
    • @astrojs/sitemap to generate XML sitemaps during the build.
    • @astrojs/rss to generate the RSS feed.
  • Third-Party Dependencies: Managed via npm, including sharp for image optimization, reading-time for post metrics, and @playwright/test for end-to-end testing.

To improve security and resilience, the following controls outline the recommended target architecture for the site.

E2E Tests

Secret Scan

Deploy

Headers: CSP, HSTS

Pull Request

Merge Approval

Cloudflare Build

Global Edge

Public Users

Specific Target Controls

  1. GitHub Branch Protection:
    • Require pull requests (PRs) before merging to the main branch.
    • Run Playwright end-to-end tests (npm run test:e2e) and Astro type checks (npm run check) via GitHub Actions before allowing merges.
  2. Identity & Access Management (IAM):
    • Enforce multi-factor authentication (MFA) for GitHub and Cloudflare accounts.
    • Apply the principle of least privilege to API tokens.
  3. Pipeline Scanning:
    • Enable GitHub Dependabot for automated dependency alerts and updates.
    • Configure GitHub Secret Scanning to detect exposed credentials.
  4. Security Headers:
    • Define HTTP response headers by placing a _headers file in the Astro public/ directory (which copies to the build root during deployment).

7. Project Retrospective

  • Design Decisions: We established a strict, minimalist design system focused on typography, responsive layouts, and subtle CSS-only animations. We also integrated a theme toggle supporting dark, light, and reading/sepia modes.
  • Why Astro: Astro generates a zero client-side JavaScript footprint by default, ensuring maximum performance. It also provides type-safe Content Collections to validate blog frontmatter at build time.
  • Why Cloudflare: Cloudflare Pages provides automated git-driven deployments, free SSL/DNS management, and serves all static assets from a fast global edge network. It allows securing headers and deploying preview builds seamlessly.
  • Lessons Learned: Designing responsive layouts with fixed sidebars requires careful viewport constraints to prevent overflow. Automated end-to-end testing with Playwright is essential to catch subtle CSS regressions.
  • Tradeoffs: Pre-rendering Mermaid diagrams to static SVGs at build time keeps client footprint low but increases compile times. Sticking to zero-JS requires creative CSS-only solutions for interactive components.
  • Problems Encountered: Migrating Obsidian notes created build-time markdown schema violations. We also had to resolve initial layout breaks and shifting sidebars on intermediate desktop viewports.