Personal Blog

A small static personal blog. No build step, no backend — plain HTML, CSS, and vanilla JavaScript.

Pages

  • index.html — home page
  • reading.html — reading list page (curated links grouped by category, rendered from data/reading-list.js)
  • contact.html — contact page (opens the visitor's mail client with the form fields pre-filled via a mailto: link)
  • newsletter.html — newsletter signup page (posts the visitor's email to a configured serverless endpoint; no self-hosted backend or subscriber list management)

Newsletter signup

The signup form on newsletter.html POSTs the visitor's email to a serverless endpoint. Everything is configured in one file — js/newsletter-config.js:

  • NEWSLETTER_ENDPOINT — the serverless endpoint the form POSTs to.
  • NEWSLETTER_API_TOKEN — the API token sent in the Authorization header.

Security: a real API token must never be committed to the repository. The committed default is an empty placeholder; the deployer sets the real token in js/newsletter-config.js at deploy time, and only then. The page logic reads the token from this config module and never hardcodes one.

When the token is missing or the endpoint rejects it, the visitor sees a fixed, user-safe error message — the token or endpoint internals are never surfaced. After a successful signup a confirmation message is shown.

Reading list

The reading list is a single data file: data/reading-list.js. The page code renders whatever is in it, so it can grow to hundreds of entries without code changes.

To add a link, edit data/reading-list.js only — add an entry with a title, a url, a category, and an optional one-line note:

{
  category: "Engineering",
  title: "A new article",
  url: "https://example.com/article",
  note: "Optional one-liner shown under the title.",
},

Categories appear on the page in the order they are first used; entries keep the order they are listed in.

Development

Serve the directory with any static file server, e.g.:

python3 -m http.server 8000

Then open http://localhost:8000.

Tests

Tests use Node's built-in test runner (no dependencies to install):

npm test

Project layout

index.html        Home page
reading.html      Reading list page
contact.html      Contact page
newsletter.html   Newsletter signup page
css/style.css     Global + responsive styles
data/reading-list.js  Curated reading list data (edit to add links)
js/newsletter-config.js  Newsletter endpoint + API token (edit at deploy time)
js/newsletter.js  Newsletter signup wiring: POST + user-safe errors (tested)
js/mailto.js      Pure mailto: URL builder (unit tested)
js/contact.js     Contact form wiring (browser + tests)
js/reading-list.js    Reading list renderer: data file -> grouped HTML (tested)
tests/            Node built-in test suite
.gitea/workflows/ ci.yml runs `npm test` on PRs and pushes to main
S
Description
No description provided
Readme
857 KiB
Languages
JavaScript 89%
TypeScript 9.9%
Dockerfile 1.1%