Skip to main content

Overview

The v3 website is a full Astro application. The project uses Astro v6 for routing, layouts, content, and builds; Svelte 5 islands for interactive UI; MDX content collections for blog posts; and the @astrojs/cloudflare adapter for Cloudflare Workers deployment. Pages live under src/pages/, shared UI lives under src/layouts/ and src/components/, blog content lives under src/content/, and security headers are applied through Astro middleware in src/middleware.ts.

Tech Stack

Framework

Astro v6 with file-based routing and island architecture.

Interactive UI

Svelte v5 islands for search, cookie notice, and text-to-speech.

Content

MDX via @astrojs/mdx, backed by Astro content collections.

Deployment

Cloudflare Workers via @astrojs/cloudflare and Wrangler 4.

Assets

Workers Assets serving the generated dist/ directory.

Feeds

RSS at /rss.xml via @astrojs/rss; sitemap via @astrojs/sitemap.

Icons

Lucide icons through @lucide/astro and @lucide/svelte.

Fonts

Poppins and Fira Code from @fontsource, self-hosted with no external font requests.

Project Structure

public/                         # Static files copied as-is to dist/
scripts/
  generate-version.js           # Build-time script to stamp version info
src/
  assets/                       # Images imported and processed by Astro
  components/
    blog/                       # MDX-embeddable Astro components
      BreachTable.astro
      CalloutWarning.astro
      EvidenceBlock.astro
      PullQuote.astro
      SectionLabel.astro
      SourceChip.astro
      Timeline.astro
      TimelineItem.astro
    svelte/                     # Interactive Svelte island components
      BlogSearch.svelte
      CookieNotice.svelte
      TextToSpeech.svelte
    Footer.astro
    Head.astro                  # SEO meta tags, fonts, shared head content
    Header.astro
    Scripts.astro               # Shared script includes
  content/
    blog/                       # MDX blog post source files
      adguard-home.mdx
      age-verification.mdx
      chromeos-wifi-password-extractor.mdx
      death-of-learning.mdx
      dns.mdx
  layouts/
    BaseLayout.astro            # Shared page layout wrapper
  pages/
    blog/
      index.astro               # Blog index page
      [...slug].astro           # Dynamic blog post renderer
    services/
      dns.astro                 # DNS service page and tool
    404.astro
    about.astro
    contribute.astro
    index.astro                 # Homepage
    license.astro
    privacy.astro
    rss.xml.ts                  # RSS feed endpoint
    terms.astro
  content.config.ts             # Astro content collection schema
  middleware.ts                 # Security headers and HTTP method enforcement
astro.config.mjs                # Astro configuration
package.json
pnpm-workspace.yaml
svelte.config.js
tsconfig.json
wrangler.jsonc                  # Cloudflare Workers configuration

Routing

Astro owns routing through src/pages/. The Cloudflare Worker produced by the adapter serves the built site from dist/ through Workers Assets.

Primary Pages

RouteDescription
/Homepage
/aboutAbout page
/contributeContribute / donate page
/termsTerms of Service
/privacyPrivacy Policy
/licenseLicense information
/blogBlog index
/blog/[slug]Individual blog posts
/services/dnsDNS service page & tool
/rss.xmlRSS feed
/llms.txtLLM-readable site summary

Blog Posts

Blog posts are authored as MDX files in src/content/blog/, validated through the content collection schema in src/content.config.ts, and rendered by src/pages/blog/[...slug].astro.
RouteTitle
/blog/dnsDNS
/blog/adguard-homeAdGuard Home
/blog/age-verificationAge Verification
/blog/chromeos-wifi-password-extractorChromeOS Wi-Fi Password Extractor
/blog/death-of-learningDeath of Learning

Shortcuts & Redirects

Redirects are configured in astro.config.mjs.
RouteDestination
/bypass/services/dns
/dns/services/dns
/discordDiscord Invite
/githubGitHub Profile

Content Components

The MDX blog can embed reusable Astro components from src/components/blog/:
ComponentPurpose
BreachTableStructured breach or evidence tables
CalloutWarningProminent warnings inside long-form posts
EvidenceBlockSource-backed evidence excerpts and context
PullQuoteEditorial pull quotes
SectionLabelSmall section markers
SourceChipCompact source attribution links
TimelineTimeline wrapper for chronological sections
TimelineItemIndividual timeline entries

Interactive Islands

Astro renders the site statically by default and hydrates only the components that need client-side behavior:
  • BlogSearch.svelte powers client-side blog search on the blog index.
  • TextToSpeech.svelte adds a Web Speech API audio player to blog posts, including a seekable progress bar, voice selection modal, and floating player UI.
  • CookieNotice.svelte displays the site notice as a Svelte island.

Generated Files

  • /rss.xml is generated by @astrojs/rss.
  • The sitemap is generated by @astrojs/sitemap.
  • /llms.txt provides an LLM-readable site description.
  • Fira Code is self-hosted for code blocks through @fontsource.

Security

Security is enforced in src/middleware.ts. The middleware applies strict response headers to every response:
HeaderValue / Purpose
Content-Security-PolicyRestricts asset origins; allows DNS status checks against monitor.dns2.hapara.fail and blocklist fetch fallbacks.
Strict-Transport-SecurityHSTS with includeSubDomains; preload for one year.
X-Content-Type-Optionsnosniff
X-Frame-OptionsSAMEORIGIN
Referrer-Policystrict-origin-when-cross-origin
Permissions-PolicyDisables camera, microphone, geolocation, and payment APIs.
Only GET and HEAD HTTP methods are accepted; all others return 405 Method Not Allowed.

Development

Prerequisites

  • Node.js v18 or higher
  • pnpm v9 or higher
  • A Cloudflare account with Wrangler authenticated (wrangler login) for deployment

Local Setup

1

Clone

Clone the repository to your local machine:
git clone https://github.com/hapara-fail/website.git
cd website
2

Install

Install dependencies:
pnpm install
3

Run

Start the Astro development server:
pnpm run dev
This starts the local Astro dev server at http://localhost:4321 with hot module reloading.

Available Scripts

ScriptDescription
pnpm run devStart the Astro development server.
pnpm run buildGenerate the version stamp and build the site to dist/.
pnpm run previewBuild and run Wrangler dev against the built dist/.
pnpm run deployBuild and deploy to Cloudflare Workers.
pnpm run format / fmtFormat all files with Prettier.
pnpm run generate-versionStamp version data only; called automatically by build.

Deployment

Ensure Wrangler is installed and authenticated (wrangler login), then run:
pnpm run deploy
This generates the version stamp, runs astro build to produce dist/, then deploys via wrangler deploy to the hapara-fail Worker defined in wrangler.jsonc. Assets are served from dist/ through the Workers Assets binding.