Wonders of Work Review hub

Open changes waiting for a look, and what shipped recently. Anyone can open a preview below and leave feedback on GitLab.

Open for review

MR !70 by Jurjen de Vries ·

Fix

restore Cyberdigma widget house-style override

What this changes

Restores is:inline on the Cyberdigma/MeetingSelect override <style> block in BookingForm.astro, so the Wonders of Work house-style colors apply to the booking widget again instead of the vendor default styling.

How to try

1. Open a space page with the booking form and run a search that opens the Cyberdigma booking overlay. 2. Confirm the widget shows the Wonders of Work house-style colors (primary brand color), not the default Cyberdigma blue. 3. Compare against current production / the broken build to see the regression.

What this affects
  • Only src/components/BookingForm.astro — the inline override style block.
  • Root cause: merge 84d8404 (w3c-enhancements) flipped <style is:inline> to plain <style>. Astro scopes plain style blocks with a data-astro-cid attribute on selectors + rendered elements. The Cyberdigma widget DOM (.searchWidget, .c_lab-bw-widget, …) is injected at runtime by the third-party web component and never gets the scope attribute, so the scoped overrides stopped matching. is:inline keeps the CSS global/unscoped so it matches the runtime-injected widget again.
  • No JS or markup behavior change; styling only.

Updates · newest first

  • preview ↗ fix(booking): restore is:inline on Cyberdigma style override by Jurjen de Vries ·

Recently shipped to production (main) wondersofwork.nl 🎉

  • MR !69 by Jurjen de Vries ·
    Fix
    stop list from swallowing trailing paragraphs
    What this changes, and why

    Fixes two list-rendering bugs in the Nostr markdown renderer (public/scripts/render-markdown.js) seen on event previews:

    1. Text swallowed into the list. The renderer had no blank-line terminator, so every paragraph after a bullet list got pulled into the last <li> and indented. Now a blank line followed by a non-indented line ends the list, and continuation requires indentation to the item-content column (first.indent + 2). 2. Empty bullet markers. Some editors emit a list item as a bare marker plus a blank line, with the text as a separate non-indented paragraph (-\n\ntext). That left an empty bullet with the text dropped below it. An empty marker now adopts the following paragraph as its content. Blank-line termination only kicks in once an item already has content.

    Nested lists, multi-paragraph items, and same-paragraph lazy continuation still render correctly (covered by manual tests against the real event content).

    What this affects
    • Nostr markdown rendering on the event-preview and story-preview pages only. No security-sensitive areas (profile, key export, OpenBunker) touched.
    • Bumps the render-markdown.js import version query (?v=20260514?v=20260603) in both preview pages to bust the 4h public-script CDN/browser cache.
    How to try it

    Open these previews on the MR preview link:

    • /en/event-preview/?d=event:proeverij-leadership-embodiment-hoe-je-krachtig-n-ontspannen-kunt-zijn-in-uitdagende-situaties-door-belichaamd-persoonlijk-leiderschap-mpeb9k0uc6s2r3y6y504m2s — text after the bullet list ("Voor wie?" block) is left-aligned, not indented into the list.
    • /en/event-preview/?d=event:open-workshop-claude-code-mpf30obb1t1p2otx65725j — the "Wat leer je?" bullets show their text next to each arrow (not an empty arrow with the text dropped below).
  • MR !66 by Jurjen de Vries ·
    Fix
    align list markers with item text
    What this changes, and why

    Fixes a vertical gap between the list marker (arrow bullet / number) and the item text in .prose-text lists. Loose-list items render their content inside <p>. Because .prose-text lists are CSS grid containers, each <li> establishes its own block formatting context, so the paragraph's prose margin-top no longer collapses and pushes the text below the marker.

    Fix: zero margin-top on the first <p> and margin-bottom on the last <p> inside list items (.prose-text li > p).

    Spotted on the Nostr event preview (workshop event), but it affects every .prose-text surface.

    Also documents an existing implicit convention in AGENTS.md: merge request descriptions and test plans are written in English (the MR template already is).

    What this affects

    .prose-text li > p touches every .prose-text surface that renders a loose list (blank line between items, producing <li><p>…</p></li>):

    • Nostr event preview and story preview (render-markdown.js)
    • Strapi rich text via Markdown.astro: RichText, FAQs, Features, StepsGrid,
    • CardGrid, Spotlight, People, Categories, QuoteGrid, Newsletter, AudioPlayer, VideoGrid, ContactInfo

    • Hero.astro (inline marked)
    • Both bulleted (ul) and numbered (ol) lists

    Not affected: .arrow-list standalone (RichText "chapters" nav — different class), and tight lists (no <p> inside <li>, selector does not match). No security-sensitive areas touched.

    How to try it

    On the preview link, open content that contains a bulleted or numbered list with blank lines between items, and confirm the marker now lines up with the first line of text:

    • [x] Nostr event preview (the original bug) — arrow lists line up
    • [x] Nostr story preview
    • [x] Strapi RichText block: ul and ol lists
    • [x] Numbered list (ol): number circle aligns with text
    • [x] Strapi blocks with markdown that may contain lists: FAQs, Features,
    • StepsGrid, CardGrid, Spotlight, People, Categories, QuoteGrid, Newsletter, AudioPlayer, VideoGrid, ContactInfo, Hero

    • [x] Tight lists (no blank lines between items): unchanged
    • [x] Multi-paragraph list items: spacing between paragraphs preserved
    • (only first/last margin removed)

    Before you ask for review
    • [x] Branch named feat/…, fix/…, chore/…, docs/… or hotfix/…
    • [x] Commit messages follow Conventional Commits
    • [x] pnpm format has been run and the checks are green
    • [x] Tried it on the preview link
    • [x] Rebased on the latest main
  • Other
    Feature/dynamic loader
    What this changes, and why

    Replaces all spinning SVG loaders with skeleton cards that match the shape of real story, event, and people cards. Loading.astro gains a variant prop ("story" | "event" | "people") with a count. The grids fill the right space from first paint, eliminating layout shift when content arrives.

    Also adds an empty state to the profile page ("No stories or events found") for profiles with no content.

    What this affects
    • src/components/Loading.astro — new skeleton variants with shimmer; default spinner unchanged
    • src/components/blocks/CardGrid.astro — stories/events grid uses skeleton cards; removed grid.innerHTML = "" that caused a blank flash on reload
    • src/components/blocks/People.astro — people grid uses skeleton cards
    • src/pages/[...locale]/event-preview.astro — RSVP "Going" grid pre-renders people skeletons; removed JS buildAttendeeLoader spinner
    • src/pages/[...locale]/profile-preview.astro — content area shows event skeletons while loading + empty state when nothing is found
    • public/scripts/card-generator.js, profile-card-generator.js — clearGrid now preserves .skeleton-placeholder elements until the first real card replaces them
    How to try it

    1. Open a page with stories, events, or a people section (eg: /en/stories/ , /en/calendar/ , /en/wonderful-people/). 2. Reload — you should see shimmer skeleton cards immediately instead of a spinner. 3. Watch cards fade in and replace the skeletons without any layout jump. 4. On an event page, check the "The people you'll meet" section loads skeletons first. 5. On a profile with no content, confirm the empty state appears instead of a blank area.

  • MR !67 by Jurjen de Vries ·
    Feature
    surface 👍-approved stories/events regardless of follow list
    What this changes, and why

    Expands how the stories/events overviews (and homepage blocks) are curated, in two steps.

    1. Thumbs-up curation. A 👍 (kind 7) reaction from the Wonders of Work account now surfaces an individual story (30023) or calendar event (31923) in the overviews even when its author is not on the curation list. Routed through nostr-queue (not a raw directFetch), because a raw concurrent REQ during initial load was answered CLOSED by relays that cap concurrent subscriptions, so approved content silently never rendered.

    2. Correct base curation source. The overviews were gated on the account's kind:3 follow list. The intended source is the NIP-51 kind:30000 follow set titled "Approved" (d-tag HmLpoIl0DhQjBGkAGXeTr, 22 members). Switched fetchDefaultFollowList to that set, and decoupled its cache (window.approvedFollowSetCache + localStorage key approvedFollowSetCache) from people-loader's window.defaultFollowListCache (the separate "Wonderful People" set used only by the people page), which the two overviews were sharing and could clobber.

    Net rule for an item to appear: in the Approved set OR has a 👍 from the account. Author-scoped detail/profile pages are untouched (they already show everything by that author).

    What this affects
    • public/scripts/content-loader.js — curation source, approval layer, queue routing, cache key.
    • src/components/blocks/CardGrid.astro, src/pages/[...locale]/profile-preview.astro — cache-bust version query only.
    • Surfaces: /calendar/, /stories/, homepage story/event blocks (all locales).
    • Not security-sensitive (no profile, key export, or OpenBunker code). People page ("Wonderful People") deliberately left unchanged.
    How to try it

    On the preview link, open /en/calendar/ and /en/stories/ (and the NL variants):

    • The base list reflects the Approved kind:30000 set (22 members), not the old 49-member kind:3 list.
    • An event whose author is in the Approved set shows (e.g. *recharging breathwork*, *proeverij leadership*).
    • An item with only a 👍 from the account, whose author is not in the Approved set, still shows (e.g. *rise-to-get-there*).
    • Profile pages are unchanged.

    Verified each step on the Cloudflare preview with a headless browser; no console errors.

    Before you ask for review
    • [x] Branch named feat/…
    • [x] Commit messages follow Conventional Commits
    • [x] pnpm format has been run and the checks are green
    • [x] Tried it on the preview link
    • [x] Rebased on the latest main
  • MR !65 by Jurjen de Vries ·
    CI
    make the MR description check blocking
    What this changes, and why

    Flips the mr-description CI job from a non-blocking warning to blocking (exit 0 to exit 1). The team has the workflow in place, so a missing section should now fail the pipeline instead of only warning.

    What this affects

    .gitlab-ci.yml (the mr-description job) and the matching wording in CONTRIBUTING.md. No application code. Only affects MR pipelines (the job runs on merge_request_event only).

    How to try it

    This MR description has all three required sections, so the mr-description job passes here. An MR missing any of them now fails that job (and the pipeline) until added.

  • MR !62 by Jurjen de Vries ·
    Docs
    formalise MR description expectations + CI check
    What this changes, and why

    Defines the expectation that every merge request includes a clear description, what it touches, and a test plan — and aligns the template, CONTRIBUTING and CI with that expectation, so the review hub at review.wondersofwork.nl becomes genuinely useful for non-technical and AI-assisted reviewers.

    • Adds a "What this affects" section to the merge request template, between "What this changes, and why" and "How to try it".
    • CONTRIBUTING.md gets a new "Writing a good MR description" section with the three expected fields (and a TOC entry).
    • CI gets a new mr-description job that warns when any of those sections is missing, non-blocking for now.
    What this affects
    • .gitlab/merge_request_templates/Default.md — adds one section.
    • CONTRIBUTING.md — new H2 section + TOC entry, no other changes.
    • .gitlab-ci.yml — one new job (mr-description), runs only on merge_request_event pipelines, currently exits 0 (warning mode). Flip the marked exit 0 to exit 1 when the team is ready to enforce.

    Nothing that touches application behaviour, production content or security-sensitive code.

    How to try it

    On this very MR: open the pipeline and find the mr-description job — it should print "✓ MR description has all required sections." (because this description has them). To see the warning case, open a quick test MR with a minimal description; the job should list the missing sections without failing the pipeline.

  • MR !64 by Jurjen de Vries ·
    Chore
    drop duplicate astro build job
    What this changes, and why

    Removes the build job from .gitlab-ci.yml. Cloudflare Pages already runs the full astro build on every MR (the "Cloudflare Pages" external status) and gates the merge, so running it again in GitLab CI was redundant and ~3x slower.

    What this affects

    .gitlab-ci.yml only. CI keeps format, typecheck, test, commitlint and mr-description — the checks Cloudflare does not cover. No application code touched. Production build path is unchanged (Cloudflare).

    How to try it

    On this MR: the pipeline should no longer show a build job, the "Cloudflare Pages" external status still runs, and the MR stays mergeable on green.

  • MR !63 by Jurjen de Vries ·
    Other
    Fix RSVP attendee profile rendering

    <!-- See CONTRIBUTING.md if anything here is unclear. -->

    What this changes, and why

    Fixes the event detail RSVP attendee list so profile names and photos render from fetched Nostr kind:0 profile events instead of getting stuck as placeholder attendee cards.

    The HAR for the Write Club event showed that attendee profile events could arrive while the attendee cards were still being built. The old code patched DOM nodes that did not exist yet, then the initial card render wrote Anonymous placeholders afterwards. This change renders attendee cards only for profiles that already have displayable profile data, shows the existing loader while RSVP/profile data is still actively loading, fetches missing attendee profiles, and re-renders the attendee grid as data arrives.

    The section heading is now visible as soon as the RSVP UI initializes. Counts are based on displayable attendee cards instead of raw RSVP events, so incomplete anonymous profiles do not inflate The people you will meet. The loader occupies the next card slot and is removed once the RSVP/profile fetch window is finished.

    How to try it

    Open the MR preview and visit:

    /en/event-preview/?d=event:write-club-mpmmxhfu576r1q22144q561o

    On a cold load, check the section The people you will meet. The heading should be visible before all relay data is finished. Attendee cards whose profile name is already cached can render immediately; the count should increase only for displayable attendee cards. Missing or incomplete profiles should show the loader in the next card position while loading is active, without showing temporary Anonymous cards, and the loader should disappear after the profile fetch completes or times out.

    Before you ask for review
    • [x] Branch named feat/…, fix/…, chore/…, docs/… or hotfix/…
    • [x] Commit messages follow Conventional Commits
    • [x] pnpm format has been run and the checks are green
    • [x] Tried it on the preview link
    • [x] Rebased on the latest main
  • MR !61 by Jurjen de Vries ·
    Chore
    add CODEOWNERS for review routing
    What

    Adds .gitlab/CODEOWNERS so GitLab auto-requests review from the right person for the files a merge request touches.

    Ownership is a starting point derived from git history:

    • default reviewer: @ih-abir
    • build / CI / tooling / docs: @jurjendevries
    • profile / key export / OpenBunker: @mmaaaazu
    • Nostr client scripts: @ih-abir + @mmaaaazu

    Note: this only enforces approval once branch protection on main has "Require approval from Code Owners" enabled (a separate team decision). Until then it just suggests reviewers. Adjust the mapping as the team sees fit.

  • MR !60 by Jurjen de Vries ·
    Docs
    document STRAPI_URL and default .env.example to the public CMS
    What

    Documents the value of STRAPI_URL where it was missing, so a fresh clone builds out of the box.

    • .env.example now defaults STRAPI_URL to the public CMS https://strapicms.wondersofwork.nl (the instance previews and production build against), with a comment for local Strapi.
    • CONTRIBUTING.md, AGENTS.md and README.md mention the value.

    This removes the onboarding gap where external / AI contributors could not build without knowing which Strapi to point at.

See all merged changes on GitLab →