Commit graph

36 commits

Author SHA1 Message Date
ae60a7c856 refactor(home): finalise hero subhead copy
All checks were successful
deploy / build-and-deploy (push) Successful in 11s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 16:43:15 +10:00
27e743bffd feat(visual): particle field background + section-anchored accent marks 2026-06-03 16:39:44 +10:00
f533e9933b chore(particle-field): visual tuning — tighter glow, dimmer field, cursor brightness boost 2026-06-03 16:38:38 +10:00
993cedf0ed chore(layout): remove orphaned marks slot 2026-06-03 16:00:40 +10:00
73170a29e5 chore(layout): remove unused Mark import from BaseLayout 2026-06-03 15:55:52 +10:00
d71a7a214d refactor(marks): anchor post layout marks to posthead and postnav 2026-06-03 15:51:28 +10:00
45e84c1856 refactor(marks): anchor 404 page marks to content section 2026-06-03 15:51:02 +10:00
867a8c1762 refactor(marks): anchor art page marks to caption column 2026-06-03 15:50:49 +10:00
cfc5983f41 refactor(marks): anchor code page marks to section edges 2026-06-03 15:50:36 +10:00
8bcd2486e3 refactor(marks): anchor blog index marks to section edges 2026-06-03 15:50:16 +10:00
91546ab393 refactor(marks): anchor home page marks to section edges 2026-06-03 15:49:51 +10:00
be6e9ea13d refactor(marks): switch Mark from fixed to absolute positioning 2026-06-03 15:49:20 +10:00
f112e26784 feat(layout): integrate ParticleField as sitewide background layer 2026-06-03 15:46:50 +10:00
f8113f7a94 refactor(islands): remove dead offscreen canvas pixel writes from updateField 2026-06-03 15:45:59 +10:00
24db26177e feat(islands): add ambient ParticleField canvas background
Self-contained React canvas island with Perlin/fBm noise-driven particle
field; warm ochre palette, transparent background, pointer-events none.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 15:42:11 +10:00
698ac14dd7 refactor(home): refresh hero copy to reflect considered, exploratory voice
All checks were successful
deploy / build-and-deploy (push) Successful in 12s
Replaces the generated placeholder copy with language that better reflects
the site owner's values — deliberate in practice, restless in curiosity.
Adds the 'engineer errant' nod as a quiet eyebrow descriptor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 15:37:34 +10:00
b643c0be3e fix(ci): isolate DOCKER_CONFIG so login skips the host pass credstore
All checks were successful
deploy / build-and-deploy (push) Successful in 24s
The desktop runner's ~/.docker/config.json uses credsStore: pass, which isn't
initialised, so docker login failed to store creds. Use a throwaway
DOCKER_CONFIG under RUNNER_TEMP (outside the build context) for the job.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 23:53:18 +10:00
085e0bb3b6 fix(deploy): default REGISTRY_OWNER to joshbairstow (actual Forgejo owner)
Some checks failed
deploy / build-and-deploy (push) Failing after 13s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 23:46:56 +10:00
7ecd1b32ae feat(deploy): self-hosted CI/CD + dedicated edge-proxy topology
Refactor the site container from a TLS-owning, port-binding proxy into an
internal plaintext static server that sits behind a dedicated edge reverse
proxy, and add an automated build/deploy pipeline.

- Caddyfile: single :80 listener (auto_https off), Host-matcher routing for
  apex/blog/art/code with /_astro+/assets re-root and www->apex redirect
- Dockerfile: EXPOSE 80 only (TLS now handled by the edge proxy)
- compose.yml: pull registry image, join external 'edge' network, declare
  routing via caddy-docker-proxy labels; drop build/ports/cert volumes
- compose.dev.yml: local container preview on :8080
- .forgejo/workflows/deploy.yml: push-to-main -> desktop runner builds, pushes
  to the Forgejo registry, SSH-deploys to the VPS
- docs + .dockerignore updated for the new topology

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 15:31:16 +10:00
5c9d4a99cc Merge branch 'fix/blog-search-featured-match' 2026-06-02 12:48:38 +10:00
0a5a7d5e45 fix(blog): make featured article respect search match
The featured article previously hid whenever a query was active,
regardless of whether it matched. Treat it as a normal [data-search]
row instead: visible iff it matches the query, and counted toward
visibleCount so a featured-only match no longer triggers the
"no entries match" message.

Closes the follow-up at
docs/superpowers/follow-ups/2026-06-02-blog-search-featured-match.md
and updates the design spec to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 12:48:35 +10:00
82e5ff6309 Merge branch 'feat/blog-search'
Adds light client-side keyword filter to /blog. Data-search attributes
on each post row (and the featured article) drive a small inline script
that hides non-matches as the reader types, collapses empty year heads,
and shows a no-results message. Keyboard shortcuts: / focuses, Esc
clears.

Known follow-up: featured article currently hides on any query; should
respect match state instead. See
docs/superpowers/follow-ups/2026-06-02-blog-search-featured-match.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 01:54:56 +10:00
be9b0ac994 chore(blog-search): add astro/check dep, plan, and follow-up note
- @astrojs/check + typescript bump are needed to run `npx astro check`,
  which is the type-verification command used throughout this branch.
- docs/superpowers/plans/ pairs with the existing spec under specs/.
- docs/superpowers/follow-ups/ records the featured-match behaviour
  change surfaced during manual test; addresses in a later branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 01:54:46 +10:00
d80cd255d4 fix(blog): make .is-hidden global, strip HTML tags from search text, add role=search
Final-review findings:

- .is-hidden was scoped to blog/index.astro, so it didn't match PostRow
  or YearHead roots (which carry their own component scope hashes). Net
  effect: the filter visibly only hid the featured article, while all
  archive rows + year heads stayed on screen. Wrap in :global() so the
  runtime-toggled class actually fires its display rule everywhere.
- buildSearchText regex stripped > but not <, so inline HTML open-tags
  like <span class="leadin"> leaked into data-search. Add < to the
  character class so the haystack stays plain text.
- Add role="search" landmark to the BlogSearch wrapper so screen-reader
  users can navigate to it directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 01:45:27 +10:00
75e7859146 chore(blog): guard keydown for IME composition and <select>
Code review forward-proofing:
- Early-return on event.isComposing so the / shortcut doesn't disrupt
  IME composition (multi-keystroke input methods).
- Treat <select> as editable so / doesn't steal focus while a dropdown
  is open and the user is typing to seek.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 01:35:53 +10:00
963ea56314 feat(blog): / focuses search, Esc clears and blurs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 01:32:08 +10:00
468d4e460d feat(blog): live in-page filter via data-search attributes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 01:27:02 +10:00
8423759f03 fix(blog): drop duplicated hairline and align class names
Code review nits:
- .bsearch border-bottom + .feature border-top rendered a doubled
  hairline; removed the bottom border (feature's top is sufficient).
- Renamed bsearch__input / bsearch__hint to binput / bhint to match
  the project's flat single-class convention (postrow, pdate, yr, ln).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 01:25:26 +10:00
8f12b3afe5 fix(blog): use curly quotes around empty-state query span
Spec called for U+201C / U+201D; commit d7dc22d landed ASCII quotes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 01:17:04 +10:00
d7dc22d0c8 feat(blog): render search input, empty-state, hidden utility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 01:10:27 +10:00
5ac622e576 feat(blog): build per-post searchText, wire to PostRow and featured
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 00:21:34 +10:00
44d4d327a1 feat(blog): YearHead emits data-year-head for filter targeting 2026-06-02 00:18:20 +10:00
9158207657 chore(blog): reorder PostRow props to group required before optional
Code review nit: searchText (required) was appended after the optional
deck/tag, breaking the required-then-optional convention used by the
rest of the interface.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 00:10:25 +10:00
cc04ea7753 feat(blog): PostRow accepts searchText, emits data-search 2026-06-02 00:08:25 +10:00
9e8dfaedb7 docs: spec for light blog search
Tiny client-side filter on /blog using data-search attributes on each
row. No new deps, no JSON index, no React island. Filters in place
within the year-grouped archive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 23:45:06 +10:00
3ba76b4f02 initial commit 2026-06-01 19:35:56 +10:00