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 !97 by Iftakhar Hasnayen Abir ·

Other

Fix/event content editing

What this changes, and why

creat/edit event markdown editor line break and event type detector fixed

What this affects
  • public/scripts/render-markdown.js & src/components/MarkdownEditor2.astro markdown editor rendering
  • src/pages/[...locale]/create-event.astro event type detector
  • src/pages/[...locale]/event-preview.astro preview menus after title
How to try it

1. create or edit an event description or event type 2. after update and redirect to preview page check the menus right after the title

Updates · newest first

  • preview ↗ fix: markdown editor css style by ih-abir ·
  • preview ↗ Merge remote-tracking branch 'origin/fix/event-content-editing' into fix/event-content-editing by ih-abir ·
  • preview ↗ fix: show preview menu after redirect from edit page by ih-abir ·
  • no preview fix: remove redundant log by ih-abir ·
  • no preview fix: event type detector by ih-abir ·

MR !98 by Iftakhar Hasnayen Abir ·

Other

Fix/status bar layout

What this changes, and why

Statusbar UI flexible for both desktop and mobile, text show without turncate, navbar overflow fixed, reduce motion, dynamic color detector error and fallback. disable notifiaction aria label is now from strapi

What this affects

src/utils/getGlobals.ts, src/layouts/Layout.astro, src/components/StatusBar.astro, src/components/NavBar.astro

How to try it

take a new window and load the page, check with both mobile and desktop version

Updates · newest first

  • preview ↗ fix: reduce motion, dynamic color fallback, center both text & cross by ih-abir ·
  • preview ↗ fix: status bar position by ih-abir ·
  • no preview fix: status bar enable button, aria label getting from strapi by ih-abir ·

Recently shipped to production (main) wondersofwork.nl 🎉

  • Feature
    add status bar
    What this changes, and why

    Status bar added

    What this affects

    dynamic component src/components/StatusBar.astro added, gets active, color and text update via strapi

    How to try it

    take a new new window and visit site

  • Fix
    wrong url after deleting event from /nl page
    What this changes, and why

    preview-menu.js hardcoded "calendar" as the post-delete redirect, so Dutch users always landed on /nl/calendar/ (404) instead of /nl/agenda/. Now uses window.eventCollectionPrefix which is baked in at build time per locale.

    What this affects
    • public/scripts/preview-menu.js — delete redirect for both events and stories
    • src/pages/[...locale]/event-preview.astro — inline onclick replaced with a wired handler; eventCollectionPrefix exposed via define:vars
    How to try it

    Sign in as the event owner on the NL preview link

    Open an event, click the kebab menu → Delete → confirm

    Should redirect to /nl/agenda/ — not /nl/calendar/

    Repeat on the EN preview link and confirm it still lands on /en/calendar/

  • Other
    Fix/openbunker login blank page
    What this changes, and why

    Fixes a white-page blocker for new OpenBunker users: the post-login redirect pointed at the removed /profile route. Also fixes the export-key page sending signed-out users to the same dead route, adds an OpenBunker welcome prompt on the edit-profile page, improves the offline-at-load relay error message, and disables the Send Code button while the OTP request is in flight to prevent double-submits.

    What this affects
    • public/scripts/login/check-user-metadata.js — redirect target for new OpenBunker users
    • src/pages/[...locale]/edit-profile.astro — reads source=openbunker-new and shows the completion prompt
    • src/pages/[...locale]/export-key.astro — dead /profile fallback replaced with /login
    • src/pages/[...locale]/login.astro — Send Code button disabled state + back-button reset
    • public/scripts/login/login-page.js — button loading state logic; offline relay error message says "Reload the page"
    How to try it

    Create a new OpenBunker account with no name set → should land on /edit-profile?source=openbunker-new with the "Please complete your profile details" prompt visible

    On the login page, enter an email and click Send Code → button should gray out immediately; click Back → button should be clickable again

    While on the export-key page, sign out → should redirect to /login, not a blank page

  • Fix
    navbar edit button redirect to correct page with functionality
    What this changes, and why

    Nav edit button dispatched a profileEditMode custom event the page never listened to — fixed to dispatch popstate instead. Edit href now includes key=npub built from userInfo at click time. Entering from another page appends returnUrl and redirects back on save/cancel. returnUrl was followed raw without origin check — added safeReturnUrl() matching the guard from the old profile.astro.

    What this affects
    • NavBar.astro — key=npub in edit href, popstate dispatch, returnUrl on cross-page nav
    • profile-preview.astro — leaveEditMode redirects to returnUrl when present
    • edit-profile.astro — safeReturnUrl() validates same-origin before navigating, falls back to /profile-preview
    How to try it

    Click edit profile from navbar on any page — profile-preview opens in edit mode, save/cancel returns to the originating page. Craft a link to /edit-profile?returnUrl=.... — save or cancel stays on-site instead of redirecting away.

  • Other
    Keep newest across relays
    What this changes, and why

    __fetchNewest helper__: Single shared helper replaces duplicated "keep newest across relays" logic in story/event-preview and adds it to profile-preview, which was missing it — causing stale profile data for returning visitors.

    __NIP-09 e-tag deletions fix__: deletion-cache.js only tracked a-tag (coordinate) deletions and completely ignored e-tag (event id) deletions. A kind:5 deletion referencing an event by ["e", "<id>"] was invisible, so deleted events kept showing. prefetchDeletionsForEvent also used a #a filter that excluded e-tag deletions from relay queries. Fixed by:

    • recordDeletion: now processes both a-tag and e-tag deletion references, with a comment that author-trust relies on callers using an authors filter
    • isEventDeleted: checks event.id against deleted IDs alongside the existing a-coordinate check
    • prefetchDeletionsForEvent: dropped the #a filter to retrieve all kind:5 from the author
    • removeDeletedCard: now looks up the bare d-tag from the matched event's own tags instead of using the coordinate key (kind:pubkey:dtag) as a DOM selector
    • — fixing the race where a card rendered before its deletion arrived was never removed

    • Dead code removed: kind:5 was bundled into fetchStories/fetchCalendarEvents REQs, but relays apply the #t filter to all kinds in a REQ and real deletions carry no #t tag, so those subs returned zero deletions. The overview already gets its deletions from prefetchDeletions(authors). The bundling is removed; each fetch is back to a single clean filter.
    What this affects
    • nostr-fetch.js — new fetchNewest export; kind:5 bundled into fetchStories / fetchCalendarEvents
    • deletion-cache.js — e-tag support, proactive card removal with correct d-tag lookup, author-check comment, #a filter removed from prefetchDeletionsForEvent
    • event-handlers.jshandleStory and handleCalendarEvent route kind:5 → recordDeletion
    • story-preview, event-preview, profile-preview — all use fetchNewest; profile now bypasses fetchProfiles cache short-circuit
    How to try it
    • __Profile freshness__: Update a profile from another client, reload the detail page — fresh data appears without waiting for cache expiry.
    • __Deleted events__: Publish an event/story, delete it via a kind:5 with an e-tag, reload the overview or detail page — the event is hidden.
  • Other
    Fix/relay connection delay
    What this changes, and why

    Detail pages were first-relay-wins: story-preview resolved on the first event received, event-preview gated re-renders with a one-shot found flag. A stale relay answering first meant the old version was shown even when a newer one arrived moments later. nostr-fetch was also writing cache entries under pubkey:kind:dtag while every reader uses generateUId (kind:pubkey:dtag) — dead writes under a key nobody looks up.

    Previously: late-connecting relays received a raw ws.send() without attachMux, so their EVENT/EOSE frames were silently dropped. handleCalendarEvent also had no created_at guard, so a stale relay answering last could overwrite a newer cached version.

    What this affects

    Detail pages were first-relay-wins: story-preview resolved on the first event received, event-preview gated re-renders with a one-shot found flag. A stale relay answering first meant the old version was shown even when a newer one arrived moments later. nostr-fetch was also writing cache entries under pubkey:kind:dtag while every reader uses generateUId (kind:pubkey:dtag) — dead writes under a key nobody looks up.

    Previously: late-connecting relays received a raw ws.send() without attachMux, so their EVENT/EOSE frames were silently dropped. handleCalendarEvent also had no created_at guard, so a stale relay answering last could overwrite a newer cached version.

    How to try it

    Load any page that fetches Nostr content. Edit a story or calendar event from a Nostr client, reload the detail page while one relay is slow — the updated version should always win. For the cache key fix: confirm stories and events still load correctly on overview pages after navigation.

  • MR !90 by Jurjen de Vries ·
    Other
    Revert MR 88: relay fetch change breaks calendar overview (only 1 event shows)
    What this changes

    Reverts MR 88 (fix/relay-connection-delay, merge commit 2e123fb) in full. That change introduced a regression: the calendar overview now shows only a single event instead of the full list. Reverting restores the previous, working version so it goes live again while the relay-update fix is reworked.

    How to try it

    Open any page with the calendar events overview after this merges and deploys. All events should render again, not just one.

    What this affects

    Nostr fetch/queue layer and the story/event detail pages: public/scripts/nostr-queue.js, public/scripts/nostr-fetch.js, public/scripts/event-handlers.js, public/scripts/send-message.js, src/pages/[...locale]/story-preview.astro, src/pages/[...locale]/event-preview.astro, plus the prettier bump and formatting changes bundled in MR 88. No content or auth changes.

    Note: this reverts a merge commit, so fix/relay-connection-delay will count as already-merged. The relay-update fix must be reworked on a fresh branch (or by reverting this revert) before it can land again.

  • Fix
    relay connection delay & fetch queue based on relays gets connected
    What this changes, and why

    Detail pages were first-relay-wins: story-preview resolved on the first event received, event-preview gated re-renders with a one-shot found flag. A stale relay answering first meant the old version was shown even when a newer one arrived moments later. nostr-fetch was also writing cache entries under pubkey:kind:dtag while every reader uses generateUId (kind:pubkey:dtag) — dead writes under a key nobody looks up.

    Previously: late-connecting relays received a raw ws.send() without attachMux, so their EVENT/EOSE frames were silently dropped. handleCalendarEvent also had no created_at guard, so a stale relay answering last could overwrite a newer cached version.

    What this affects

    Detail pages were first-relay-wins: story-preview resolved on the first event received, event-preview gated re-renders with a one-shot found flag. A stale relay answering first meant the old version was shown even when a newer one arrived moments later. nostr-fetch was also writing cache entries under pubkey:kind:dtag while every reader uses generateUId (kind:pubkey:dtag) — dead writes under a key nobody looks up.

    Previously: late-connecting relays received a raw ws.send() without attachMux, so their EVENT/EOSE frames were silently dropped. handleCalendarEvent also had no created_at guard, so a stale relay answering last could overwrite a newer cached version.

    How to try it

    Load any page that fetches Nostr content. Edit a story or calendar event from a Nostr client, reload the detail page while one relay is slow — the updated version should always win. For the cache key fix: confirm stories and events still load correctly on overview pages after navigation.

  • Fix
    center hero text content on multiple images
    What this changes, and why

    Center hero text content when pages have multiple images

    What this affects

    src/components/blocks/Hero.astro and src/utils/getHeroAlign.ts

    How to try it

    go to /nl/zomer-focusdagen-ondernemers/

  • MR !86 by Jurjen de Vries ·
    Feature
    add button directive to Strapi markdown
    What this changes

    Strapi editors can place a design-system button in any markdown field, without touching code:

    ``markdown ::button[Boek direct jouw spot](/boeken){variant=primary} ::button[Aanmelden bijdragen](/bijdragen){variant=secondary size=sm} ``

    Both options are optional; ::button[Label](/x) renders a medium primary button. The directive is inline, so it also works mid-sentence.

    variant selects the *role* of a button (primary, secondary, border-primary, border-secondary, stone-primary, stone-border-primary, white), not a colour. Colours stay in _colors.scss, so a rebrand remains one edit in git rather than a search-and-replace through the Strapi database. size accepts md, sm, xs.

    Variant and size resolve against an allowlist of the .btn* classes that already exist in _base.scss. An unknown value — a typo, or a Tailwind class like bg-red-500 — falls back to the default and logs a warning during the build, so an editor cannot inject arbitrary CSS classes. Link targets are limited to http:, https:, mailto:, tel: and site-relative paths; javascript: renders as href="#".

    The two white-on-transparent variants are deliberately not exposed: they are only legible on a dark background, and a markdown field cannot know what it sits on.

    The rendered anchor carries not-prose, otherwise @tailwindcss/typography's .prose :where(a) rule paints the button's label with a link colour and an underline.

    How to try

    On the preview deployment, put the two lines above into any markdown field in Strapi (for example a content page's rich text block) and open the page. Expect a violet pill and a smaller burgundy pill, matching the buttons used elsewhere on the site — no underline, no link colour.

    Locally:

    `` pnpm test:markdown ``

    Eight cases cover the class mapping, the defaults, the allowlist fallback, class injection, javascript: hrefs, label escaping, inline rendering, and that ordinary markdown is untouched.

    What this affects

    Every field rendered through Markdown.astro gains the directive. Existing content is unaffected: ::button did not previously mean anything, and ordinary markdown renders identically.

    Markdown.astro's renderer moves into src/utils/renderMarkdown.ts. That is not cosmetic — the old code called marked.setOptions() in Astro frontmatter, which re-runs per component render, and registering the extension there would have stacked it onto the shared marked singleton on every render. The new module builds one dedicated Marked instance at import time. Heading slugs and data-heading-depth behaviour are byte-for-byte unchanged, so the chapter sidebar in RichText.astro keeps working.

    Nostr stories and events render client-side through public/scripts/render-markdown.js and are deliberately left without this directive: that content is untrusted, and an author there should not be able to draw something that looks like an official call to action.

    Adds a test:markdown CI job alongside test:redirects. astro check reports the same 47 pre-existing errors as main.

See all merged changes on GitLab →