Skip to main content

Give feedback

Back to all releases
Changelog

1.5.7

Released 2026-07-26

Added

  • The search box and Filters button on the phone filter bar now meet the 44px touch-target minimum. Both were 40px, four pixels under the size the platform commits to elsewhere — and because they live in the shared bar that now serves twelve pages, the one exception was spreading. They are now 44px, matching the filter chips, bottom sheets and overlay buttons alongside them; the bar grows by four pixels. The small removable filter chips under the bar deliberately stay at 28px: they wrap onto extra rows, so sizing them up would roughly double the bar's height once a few filters are applied and push results off the screen, and every filter can also be removed inside the filter sheet or cleared in one tap. At 28px they still meet the WCAG AA minimum; 44px is the stricter standard this platform holds itself to for primary controls.

  • A new automated check catches tests whose mocks silently do nothing. When a test replaces a whole group of components at once but the code under test loads one of those components by its own individual path, the replacement never takes effect — the real component runs instead, and the test either crashes for want of a provider, looks for markup only the stand-in produced, or checks an accessibility role the real component does not use. Six test suites were found broken this way, having gone unnoticed because the automated pipeline only ran about 50 of the project's 1,282 test files, and neither the type checker nor the linter inspects test files at all. npm run audit:dead-mocks now reads every test file and the modules it loads, works out which replacements are dead and which file the author should have named instead, and records the current findings as a baseline that can only shrink. Two blocking pipeline steps enforce it, along with a re-run of the six repaired suites so they cannot quietly rot. The check also fails if it stops finding what it is meant to inspect, so a directory rename cannot disarm it with a green build. Measurement and enforcement only — no test or component behaviour was changed.

Security

  • Patched two newly published dependency advisories. The postcss build tool (path traversal via source-map auto-loading) is bumped to a fixed release in the web frontend, and the brace-expansion glob helper (denial of service) is bumped to its fixed 5.0.8 release everywhere a fixed release exists. The remaining 1.x/2.x copies of brace-expansion — pinned by upstream developer tooling with no fixed release published for those lines yet — are documented and suppressed in the vulnerability-scan ignore file with a dated revisit note; they are build-time-only code that never ships to production or handles untrusted input. The blocking npm-audit step in the security workflow now runs through a small gate script (scripts/npm-audit-gate.mjs) that honours a reviewed, dated exception list (.npm-audit-exceptions.json) — the npm-audit counterpart of the existing Trivy ignore file — so an advisory whose only fix is a breaking major of the on-hold mobile app no longer leaves the pipeline permanently red; every other high/critical advisory still blocks, and exceptions are printed in the CI log for quarterly review. The documentation-hygiene check, which flags stray task output committed to the repo root, now exempts that exception file by name — its filename contains "audit", which the check otherwise reads as a scratch audit report.

Fixed

  • An events test that passed in the pipeline failed on Windows machines, and the pipeline's test-splitting script reported the wrong answer when asked about it. One structural check on the event-sessions service asserts across two lines of source, so it only matches files saved with Unix line endings — which is how the pipeline checks the code out, but not how it lands in a Windows working copy. The check now normalises line endings before comparing, so it holds the same guarantee on either platform. Separately, the script that divides the PHP test suite into six parallel groups keyed each file's group on its path including the path separator, so running it on Windows printed a completely different division than the one the pipeline executes — making a test look as though it were assigned to no group at all, which reads alarmingly like a check that never runs. Paths are now normalised before grouping, so the local answer matches the pipeline's. No change to which tests the pipeline runs: every one of the 1,548 test files was, and still is, assigned to exactly one group.

  • Search no longer runs a query you backed out of. The search box used one value for both what you were typing and what the results were actually for. If you opened the search field, typed something and then dismissed it without searching, the abandoned text stayed in the box as though it were the applied search — and if you then removed a filter chip or pressed Clear all, the page searched for that abandoned text while the address bar still showed the previous query. What you are typing and what has been searched for are now separate: the box, the result count, the "no results" message, saved searches and Try Again all reflect the search that actually ran, and reopening the search field starts from that search rather than from whatever was last abandoned.

  • Focused form fields no longer show two misaligned focus rings. Clicking or tabbing into any HeroUI-based field (search boxes, text inputs, selects) drew two nested purple outlines that didn't line up — the component's own ring on the field shell plus a second global outline forced onto the inner input, most visible in the new listings filter sheet's category search. The global keyboard-focus fallback (which guarantees a visible indicator on plain HTML elements) was written outside any CSS layer, so it overpowered both the component library's "the shell draws the ring" styling and custom Tailwind focus rings; it also force-changed the focused element's corner rounding. It now sits in the base layer where component and utility styles can override it, the radius override is gone, and decorated inputs (fields with icons, like the login form) — whose inner input is deliberately unstyled — now draw one correctly-shaped ring on the field shell itself, which previously had no indicator of its own. One aligned ring everywhere; keyboard-focus visibility (WCAG 2.4.7) is preserved for every element class.

  • The composer no longer shows a spurious "couldn't load groups" error on communities that have Groups turned off. The group-audience selector fetched the groups list without checking whether the community has the Groups feature enabled, so on communities with it off every composer open surfaced a red error toast. It now respects the feature flag (and treats a feature-disabled response quietly), matching the server.

  • Reduced non-actionable error noise in monitoring. Routine real-time websocket reconnects, expected message-send refusals (e.g. blocked or safeguarding-restricted recipients), and a benign Android in-app WebView teardown message are no longer reported as errors — so genuine failures are easier to see. No user-facing behaviour changes.

  • Platform administrators and cross-community members can donate and subscribe again. Making a donation or starting a member-premium subscription resolved the paying user with a community-scoped lookup, so anyone whose home community differed from the one they were acting in (platform admins, cross-community and federated members) hit a "user not found" error and could never reach the payment step. The acting user is now resolved by their global account id, while every donation and subscription record stays community-scoped; the saved Stripe customer is now persisted correctly for these users too.

  • Sending a newsletter from the admin panel no longer fails partway through. On production (which preloads compiled code) the newsletter sender referenced a delay setting that only existed when the file was loaded the old way, so triggering a send over the web crashed with a fatal "undefined constant" and left the batch half-sent. The delay is now a fixed value that is always available.

  • Listing and other detail pages no longer error on accessible custom domains. On a community's own accessible (GOV.UK-style) domain, opening a listing/event/exchange detail page returned a 500 because the host-derived community slug was appended after the page id and the two were read in the wrong order. The slug is now injected ahead of the id so pages load correctly; the standard /{community}/accessible/... URLs were unaffected.

  • Time-credit transfer limits are now enforced consistently. A community's configured maximum transfer amount was shown to the transfer form but never enforced on the server — which used a fixed platform ceiling — so a direct API call could exceed a community's stricter cap (and a cap set above the ceiling was advertised but silently reduced). The limit is now resolved in one place (the community setting, clamped to the platform safety ceiling) and used by both the enforcement path and the value the UI reads, so what's shown always matches what's applied.

  • Reusing a transfer's idempotency key for a different transfer no longer silently drops it. If a client reused one Idempotency-Key for two genuinely different transfers, the second returned the first transfer's result as success while moving no credits to the intended recipient. The key is now bound to the transfer's recipient and amount, so a different transfer is processed as the distinct transfer it is, while an accidental double-submit of the same transfer is still collapsed to a single debit.

  • Operational alarms no longer double-report themselves as failed scheduled commands. The four daily/weekly monitors that intentionally exit non-zero when they detect a problem — SLO breach, stuck Stripe webhook, overdue GDPR data-subject request, and missing backup — were scheduled in the foreground, so Laravel's scheduler read their deliberate "attention needed" exit as the command itself crashing and reported a second, context-free error to Sentry on top of the real alert. In production the overdue-GDPR pager fired this every day for as long as a genuine backlog existed, adding noise that trains operators to ignore error alerts. All four monitors now run in the background, so only their genuine alert is reported while their manual-run exit code is unchanged; a regression test locks the background scheduling in.

  • Toast notifications no longer crash the current page after a deploy. The toast viewport loaded through a plain lazy import with no stale-chunk recovery, so when a toast (an error or success message) first appeared on a tab that had been left open across a deploy, its re-hashed script file could 404 and replace the current view with the generic error screen. It now uses the app's shared stale-chunk recovery — a one-time reload to the fresh build — and a new catch-all handler extends the same recovery to every other lazily-loaded screen that wasn't already wrapped.

  • Story video upload and camera capture work again. Two separate faults were fixed. First, the July security-hardening pass added a Content-Security-Policy media-src rule without blob:, which blocked video previews, recorded-clip playback, and the live camera feed in the story composer (image previews were unaffected because they use data: URLs); blob: is now allowed for media in both the SPA and PHP policies, with a regression test locking it in. Second, the live feed never attached to its preview — a black screen — because the video element mounts a moment after the camera starts; the stream now attaches as soon as the preview exists, front/back camera flip works, and recording uses whichever format the device supports (iPhones record MP4, not WebM) instead of failing to start on iOS.

  • Taking a profile photo with the phone camera works again. The avatar picker's accept list had been narrowed to specific formats, hiding the camera option on phones. Restoring the image/* wildcard brings the camera back on many devices, but newer Android versions open the system photo picker, which has no camera option at all — so the profile-photo button (settings and onboarding) now opens an explicit menu: "Take photo" launches the camera directly, "Choose from library" opens the picker. Unsupported formats are still rejected by the existing client- and server-side validation.

  • Signup welcome credits no longer award exchange badges. New members were receiving "First Exchange", "First Earn", and "First Spend" (and progress towards higher earn/spend/transaction badges, plus credit-leaderboard rankings) purely from their signup credits, because the gamification engine counted the starting-balance grant — and the admin-approval welcome bonus, which was historically written as a self-transfer — as real transactions. Every transaction-based badge check, the badge-progress meter, and the credits-earned/credits-spent leaderboards now count only genuine member-to-member exchanges, excluding starting balances, admin wallet grants, legacy welcome-bonus rows, and self-transactions; the admin welcome bonus is now recorded as a proper system grant. A new gamification:revoke-grant-badges maintenance command (dry-run by default, --apply to write) revokes historic wrongly-awarded badges, removes their bonus XP and feed cards, and recalculates member levels — badges backed by at least one real exchange are kept.

Changed

  • Exchanges, the blog and the marketplace complete the phone rollout. All ten directory pages now share the pattern: no desktop hero on phones, the page name in the top app bar, and one slim pinned bar with a Filters button showing how many filters are applied. These three each have a single filter dimension, so their sheets apply a tap straight away with no confirm step, and exchanges has no search pill because the page has no search. "Browse Listings" on exchanges and "Sell Something" on the marketplace stay reachable on a phone, and the blog's post count moves under the bar. Tablet and desktop are unchanged. The marketplace's promoted-listings block is deliberately still shown on phones, since it is paid placement.

  • The resources library, volunteering and search now open straight into results on phones too. Same treatment: no desktop hero or filter card on phones, the page name in the top app bar, and one slim pinned bar with search, a Filters button showing the applied count, and a bottom sheet of tap-once chips that take effect when you confirm them. Volunteering had sixteen sections that wrapped into a wall of pills on a phone, so its section picker also becomes a sheet showing one control with the current section's name. Its plain-language explanation of how volunteered hours become time credits is kept as a collapsed line you can tap open, rather than dropped — it is the only place an anonymous visitor can find that out. Upload Resource, Log Hours, Browse Organisations, Register organisation and the organisation dashboard links all remain reachable on a phone. Volunteering's remote/in-person filter is currently phone-only, and clears itself if you widen the window to desktop so it cannot stay applied with no control to clear it. Tablet and desktop are unchanged.

  • Events, members, groups and job vacancies now open straight into results on phones. The same treatment the feed and listings pages already had reaches four more directory pages: the desktop hero and filter card are not rendered on phones, the page name moves into the top app bar, and one slim pinned bar holds search, a Filters button showing how many filters are applied, and the page's view switch where it has one — sliding away as you scroll down and returning on the first upward scroll. Tapping Filters opens a bottom sheet with every filter as tap-once chips; on pages with several filters the changes only take effect when you confirm them, so the results behind the sheet stop churning while you experiment, and applied filters sit under the bar as removable chips with a one-tap "Clear all". Events saves the most: it was spending more than a full screen — around 800-900 pixels — on a hero, a second calendar-view card and two filter cards before the first event. Groups keeps it simple, applying its single scope filter immediately with no confirm step. Features that previously lived only in the hero have been moved rather than dropped: the events calendar-subscription feed and Create Event, the Create Group button, and the job vacancies links to My Applications, Job Alerts and Post Vacancy are all still reachable on a phone. Tablet and desktop are unchanged on all four pages.

  • The phone filter bar and filter sheet are now one shared platform component. The sticky filter bar, the tap-once chip groups, the sheet shell and the draft-filter machine introduced for the feed and listings pages have been lifted into shared building blocks so the same pattern can be rolled out to the remaining directory pages (events, members, groups, jobs, resources, volunteering, search, exchanges, blog, marketplace) without ten divergent copies. The feed and listings pages now render from those shared blocks with no change to what they look like or how they behave on any screen size. The generic wording ("Filters", "Clear all", "Show N results", "Remove filter…") now lives in one place and is translated once for all eleven languages instead of being duplicated per page, and pages that have better wording of their own keep it — listings still says "Show 23 listings". One visible fix falls out of the move: a result count of one now reads "Show 1 result" rather than the ungrammatical "Show 1 results", in every language that distinguishes singular from plural.

  • Browsing listings on phones now opens straight into results with one slim filter bar. The listings page's large hero and filter card disappear on phones — "Listings" moves into the top app bar and a single pinned bar holds search, a Filters button, and the grid/list/map switch, sliding away on scroll down and returning on the first upward scroll (matching the feed). Tapping Filters opens the platform's bottom sheet with every filter as tap-once chips — offers/requests, sort with the ranking label, category (with a searchable full list for communities with many categories), duration, remote/in-person, posted date, and distance — and changes preview live in a "Show N listings" button before anything is applied, so experimenting with filters no longer churns the results behind the sheet. Applied filters appear as removable chips under the bar with a one-tap "Clear all", so it's always visible what's narrowing the results. Tablet and desktop keep the existing full filter card unchanged. Bottom sheets platform-wide gained an optional pinned action bar for this pattern, plus a visual polish that reaches every sheet (comments, share, GIF picker, feed filters and more): the title and close button now share one compact row instead of stacking centred, the header divider and footer run edge to edge, and filter chips align left instead of centring raggedly when they wrap.

  • The first tab on the phone bottom bar is now "Feed" with a newspaper icon. It was labelled "Home" with a house icon while already opening the community feed, so the label didn't describe where it went; it now matches the feed entry used everywhere else in the navigation.

  • "Feed" is no longer mistranslated as animal feed in the other ten languages. Machine translation had rendered the standalone "Feed" label in the feeding an animal sense across 115 of 140 strings — Japanese showed 飼料 ("livestock fodder") and 餌 ("bait"), Dutch "Voer", German "Futter"/"Füttern", Italian "Foraggio"/"Nutrire", Portuguese "Alimentação", Spanish "alimentar", Polish "Karmić", Arabic "يٌطعم", French "Nourrir"/"Alimentation", and Irish "Soláthar" ("supply"). This affected the Feed page's own title, the Groups feed tab, the mobile bottom bar, and seven admin breadcrumb and module labels. Each language now uses one consistent, correct term throughout — "Feed" for German, Spanish, Italian, Dutch and Portuguese (the native usage in those locales), "Fil d'actualité" (French), "Aktualności" (Polish), "Fotha" (Irish), "フィード" (Japanese) and "الخلاصة" (Arabic) — replacing the four to five competing variants some languages had accumulated. Twenty-four longer Arabic strings that used التغذية ("nutrition") for the social feed were swept to the same term, including "Feed Moderation", which had read as "temperance in nutrition"; genuine uses — feedback loops, RSS feeds, and data-pipeline feeds — were left untouched.

  • The Template button has been removed from the composer. The "Template" picker in the create window's header (both the desktop dialog and the mobile full-screen composer) is gone, so the Listing/Post/Event/Goal/Poll tabs now start from a clean form. Per-tab draft persistence is unaffected.

  • The floating composer now opens on the Listing tab with the full listing form. On both phones and desktop, the general "create" entry points on the feed — the "What's on your mind" prompt, the mobile pen button, and the primary create button (relabelled from "New post" to "Create") — open the compose window on Listing instead of Post; the photo and poll shortcuts still open their own tabs. The composer's listing form has been rebuilt as the same polished form used on the listings page: offer/request intent cards, AI "Help me write", the optional experience/equipment/accessibility details, in-person/remote delivery choice, searchable category picker, skill tags, and the larger photo dropzone — with the composer's draft persistence and template picker retained. Both surfaces now share one form component, so future improvements land in both automatically. The unused "UN Sustainable Development Goals" picker (never displayed anywhere in the platform) has been removed from the listing and event composers.

  • The feed page now opens straight into content on phones. The page's hero card disappears entirely on phones — "Community Feed" moves into the top app bar next to the community logo — and one slim bar below the app bar holds the For You/Recent toggle, the ranking label, and a Filters button. The bar stays pinned while browsing, slides away when scrolling down and returns on the first upward scroll, so reading posts uses the whole screen. Tapping Filters opens the platform's standard bottom sheet with every feed filter (and the Offers/Requests sub-filters when Listings is chosen); the button shows the active filter's name when one is applied. This replaces the interim horizontally scrolling filter rail; tablet and desktop keep the full hero card and wrapped filter pills unchanged. Pages can now publish their title into the app bar via a small shared hook, ready to reuse on other mobile screens.

  • Conversation threads are now full-screen on phones with a single slim header. Opening a message thread hides the site header (like the bottom tab bar already did), giving the conversation the whole screen behind one app bar: back, avatar with presence, and the name with a compact green verified check — the "ID Verified" chip no longer wraps mid-word, and the trust label moves to the status line ("Online · ID Verified"). Search-in-conversation, auto-translate, and view-profile fold into the ⋮ bottom sheet on phones (desktop and tablet keep the visible buttons and site header). The safeguarding review notice compacts to a one-line tappable pill on phones that opens the full wording, with its own X to dismiss; the dismissible full banner remains from tablet up. Safeguarding vetting blocks (DBS Enhanced and other police checks) are unchanged — the full-width restriction panel still replaces the composer. Opening a thread no longer scrolls the page itself (which could drag the thread header off-screen on long messages): messages scroll only inside their own container, and the page body is locked while a thread is open on phones.

  • Transaction-style tables now stack into cards on phones. Wallet regional-points and hour-transfer history, loyalty redemptions, data-export history, seller coupons, and ad/push campaign lists no longer force sideways scrolling on phones: each row becomes a rounded card whose values lead with their column label, and columns previously hidden for width (like the loyalty item column) reappear inside the card. The collapse is an opt-in mode of the shared table (mobileCards), so dense comparison grids keep the existing horizontal scroll; desktop rendering and the screen-reader table semantics are unchanged.

  • Long-press and pull-to-refresh now give haptic feedback on Android. Holding a message bubble, feed post, or bookmark button pulses when the action sheet is about to open, and releasing a pull-to-refresh past its threshold ticks — matching native app feedback. iPhones don't expose web vibration, so the feedback simply doesn't fire there; nothing else changes.

  • Bottom sheets no longer scroll the page behind them. Reaching the end of a menu, picker, dialog, or drawer sheet on a phone now stops the gesture at the sheet's edge instead of rubber-banding the page underneath (overscroll containment on every responsive sheet surface).

  • Logged-out visitors on phones now see both Log In and Sign Up in the header. The Log In button was hidden below 480px wide, leaving portrait phones with only Sign Up; both guest actions now stay visible at every width, with the brand logo collapsing first so the header never overflows — verified down to 320px.

  • Every horizontal tab strip is now touch-scrollable and shows its overflow. The shared tabs component's scroll affordance — hidden scrollbar with edge chevrons when more tabs exist, horizontal touch panning, and keeping the selected tab in view — is now the default for all ~100 tab strips across the platform instead of an opt-in used by two pages; vertical tab lists and strips that manage their own overflow are unaffected, and individual strips can still opt out.

  • Searching Listings and Members on a phone now opens a full-screen search experience. Tapping the search box slides up a native-style overlay with the keyboard open, your recent searches for that page (stored on the device, clearable), and live filtering behind it — the Instagram/Facebook search pattern; desktop keeps the inline filter field. The overlay is a reusable component ready to roll out to the other directory pages.

  • Editing your bio on a phone now opens a full-screen editor. Tapping the bio field in Settings opens an Instagram-style full-screen editor with Cancel and Save, instead of typing into a small inline box; desktop keeps the inline field. Numeric create-form fields (listing hours, event capacity and recurrence count) now request the matching numeric keypad.

  • Writing a comment on any detail page now opens a native composer sheet on phones. Tapping the "Write a comment…" pill on post, listing, event, blog, job, goal, ideation, volunteering, poll, resource, review, and group-discussion pages slides up the full comment thread as a bottom sheet with the composer pinned above the keyboard and focused — matching the feed's comment sheet — while the thread also stays visible in place on the page; desktop keeps the inline composer.

  • Tap-to-open info popovers now present as bottom sheets on phones. Every surface built on the shared popover — the feed ranking-algorithm explainer, match dismiss reasons, hybrid pricing and community-delivery explanations, goal reminder settings, and the theme picker — slides up from the bottom edge with a grabber and dimmed page instead of rendering as a small anchored bubble; tablet and desktop keep the anchored popover, and individual popovers can opt out where anchoring is essential.

  • Confirmation dialogs now present as bottom action sheets on phones. Delete/confirm prompts across the platform (every useConfirm-driven destructive action, plus group, event-staff, and admin confirmation dialogs) attach to the bottom edge with rounded top corners and safe-area padding on phones, matching the native sheet treatment ordinary dialogs already received; desktop keeps the centered dialog. The confirm/cancel flow itself is unchanged.

  • The Android keyboard no longer covers the page — content resizes instead. The viewport now declares interactive-widget=resizes-content, so when the soft keyboard (and its suggestion strip) opens on Android Chrome, the page and its fixed bottom composers shrink to the remaining space instead of being overlaid; iOS continues to use the visual-viewport compensation, which self-corrects so the two mechanisms never double-apply.

  • The AI chat composer now stays visible above the soft keyboard. The chat layout subtracts the keyboard inset on iOS (Android is handled by the viewport change), keeps the latest message in view while typing, and labels the keyboard's Enter key Send.

  • Mobile keyboards now get proper hints from text fields. Search boxes across the platform tell Android and iOS keyboards to show a Search key and suppress autocorrect, auto-capitalisation, and the prediction strip; the message and comment composers label the Enter key Send; and the wallet transfer and donation amount fields request the decimal keypad.

  • Feed comments now open as a native bottom sheet on phones. Tapping Comment (or the comment count) slides up a Facebook-style sheet with the full thread and a composer pinned to the bottom edge; the sheet has a drag handle, shows the live comment count in its title, and mention suggestions open upward so the keyboard never hides them. Post detail pages keep comments expanded in place, and desktop keeps the inline expansion.

  • The feed share menu is now a native bottom action sheet on phones. Repost, Quote Post, Copy Link, external share, and Send via Message present as comfortable touch rows with descriptions under the shared sheet chrome (drag handle, title, safe-area padding) instead of a converted dropdown; desktop keeps the anchored menu.

  • Conversation threads now behave like a native messenger on phones. The bottom tab bar steps aside inside a thread so the composer owns the bottom edge; the layout tracks the on-screen keyboard through the visual viewport so the composer stays visible above it on iOS and Android; Today/Yesterday/date separators group the message stream; and a jump-to-latest button with a new-message count appears when scrolled up into history — real-time messages no longer yank the view down while reading older messages.

  • The GIF picker opens as a full-height bottom sheet on phones. Search results are no longer crammed into a small popover above the keyboard; tablet and desktop keep the anchored popover.

  • The reaction picker is friendlier to touch. Long-press opens it faster, the emoji targets meet the 44px touch minimum on touch screens, and the pill clamps inside the screen instead of clipping at the viewport edge on narrow phones.

  • The new touch info-popovers announce an accessible name and the message action sheet's reaction buttons meet the 44px touch-target minimum. The tap-to-open explanation popovers added for touch users now carry a screen-reader heading, and the mobile message reaction buttons use the audited minimum touch size, keeping the platform's accessibility and touch-target contracts satisfied.

  • Information previously hidden in hover tooltips is now reachable on touch devices. A platform-wide audit classified every end-user tooltip; the six that were the sole carrier of real information are fixed: the ranking-algorithm chip, community-delivery explainer, hybrid time-plus-cash pricing explanations, and the AI applicant-ranking reason now open on tap as popovers, while the members CommunityRank score shows its label inline on phones and federation profiles display disabled-action reasons (opt-in or transaction restrictions) as visible helper text on phones. Redundant or decorative tooltips that duplicate visible text or accessible labels were left unchanged.

  • Page navigation now animates like a native app on phones. Moving deeper (a list to a detail page) slides the new page in from the right, while going back slides in from the left, using the Material shared-axis motion. The animation is phone-only, skips the initial page load, and is fully disabled for users who prefer reduced motion; custom swipe-back is deliberately not added because Android and iOS already provide system edge-swipe back gestures.

  • Date pickers now open as bottom-sheet calendars on phones. Event, goal, poll, and volunteering creation flows present their calendar in the same grabber-handled bottom sheet as menus and selects, centred and touch-friendly, while desktop keeps the anchored popover calendar.

  • Select pickers now open as bottom sheets on phones. Every dropdown selector built on the shared select — contact subjects, category and skill pickers, form selects across the platform — slides up from the bottom edge with a grabber, dimmed page, and comfortable touch-height options, while tablet and desktop keep the anchored picker. The bottom navigation moves out of the way while a picker is open.

  • The bottom navigation now hides while scrolling down and returns when scrolling up. The mobile tab bar shares the top header's scroll behaviour, giving content the full screen while reading and restoring navigation the moment it's needed — matching native app chrome behaviour.

  • The mobile message composer now gives the text box the full row while typing. Focusing the input folds the attachment and GIF buttons into a single chevron — matching native messaging apps — so the field no longer shrinks to a cramped box between oversized icons; the chevron restores the tools, and leaving the empty field brings them back automatically. Desktop keeps the full toolbar.

  • Message bubbles now open a native-style bottom action sheet on phones. Long-pressing a message (or tapping its single options button) presents reactions, copy, edit, and delete in one thumb-reach sheet with a drag handle, replacing the two cramped floating menus beside each bubble; desktop keeps its hover controls. Copied messages confirm with a toast, and the copy action is translated across all ten maintained locales.

  • Dropdown menus now present as bottom action sheets on phones. Every menu built on the shared dropdown — feed post options, share menus, conversation actions, the language switcher, and other "⋮" menus — slides up from the bottom edge with a grabber, full-screen dimming, and comfortable touch-height rows, while tablet and desktop keep the anchored popover presentation. The bottom navigation moves out of the way while a menu sheet is open.

  • Multiline text boxes now grow with their content, so the message composer no longer hides what you type. The shared HeroUI v3 textarea wrapper implements the auto-grow behaviour its minRows/maxRows props always promised: the field expands line by line up to its configured maximum, then scrolls internally. The mobile conversation composer starts as a single rounded line and grows to six lines like a native messaging app, with its attachment, voice, and send controls anchored to the bottom edge as it grows; the same fix applies to every compose, review, transfer, broker, and admin form that sets those props.

  • The Android native release gate now uses the Expo SDK 54 patch versions required by Expo Doctor. Expo 54.0.36 and Expo Updates 29.0.19 replace the immediately preceding patches, keeping the SDK dependency contract current while preserving the passing mobile type-check and 1,427-test suite.

  • The React frontend lockfile again installs cleanly with npm ci. A cleanup had removed the rxjs@7.8.2 entry still required by the i18n tooling's interactive CLI, which failed every CI dependency install; the entry is restored via a lockfile-only regeneration with no dependency version changes.

  • The root and mobile npm lockfiles now use patched brace-expansion releases across every installed major line. Versions 1.1.16, 2.1.2, and 5.0.7 close the newly published exponential-expansion denial-of-service advisory without changing the parent Expo, retired web-wrapper, ESLint, or build-tool packages.

  • Guzzle is updated to 7.15.1 following newly published upstream security advisories. The patched HTTP client preserves host-only cookie scope, bounds cookie processing, prevents redirect-generated referrers from disclosing URI fragments, and retains the proxy-authorization isolation introduced in 7.14.2; the accompanying promises, PSR-7, and Symfony deprecation-contract lockfile updates remain within existing dependency constraints.

  • Production now serves WebP and AVIF artwork as images instead of the React HTML shell. The single-container and blue/green nginx static-asset rules include modern image formats, restoring the three partner-page images for the Hour Timebank tenant and preventing the same zero-dimension placeholder failure elsewhere.

  • Laravel CI contract tests no longer fail from translated response fields or leaked test clocks. Pilot launch-readiness coverage now asserts the localized summary_code/summary_params contract, while the CRM timeline contract test disables its date window so unrelated frozen-clock state cannot hide the signup fixture.

  • The ordinary React website now behaves like one coherent mobile web app. Authenticated navigation remains in the safe-area-aware bottom tab bar, the More menu opens as a bottom drawer, the desktop footer is removed from phone layouts while its required attribution stays in the mobile menu, and the compact app header no longer leaves a desktop-sized gap above content. The More drawer now keeps its install-app promotion with the secondary actions at the bottom and presents Credits, Messages, and Alerts as equal-width, unclipped account cards. The quick-create control now opens an opaque, internally scrollable action sheet with full-height, readable create cards and no bottom-navigation bleed-through. The shared HeroUI v3 modal wrapper now presents ordinary dialogs as edge-attached bottom sheets on phones, while side drawers automatically become handled bottom drawers and marketplace or talent filters use scrollable mobile sheets instead of expanding into page content. Cookie consent, unsaved-preference controls, notifications, and other fixed surfaces now clear or temporarily replace the bottom navigation, all text-entry controls use the iOS no-zoom font baseline, and the tab bar moves away while the software keyboard or an overlay is active; tablet and desktop layouts retain their existing modal, drawer, filter, and footer presentation.

  • Super-admin billing pages now clearly identify their development status. The billing controls and revenue dashboard display a persistent translated warning that the React replacement and Stripe-connected workflows are still being validated and that displayed figures must not be treated as financial records.

  • Super-admin tenant hierarchy controls now have one clear, reliable workflow. The shared HeroUI v3 switch uses the documented clickable compound structure, edit-time Hub capability changes route to the authoritative Hub Settings control, disabling a Hub warns that tenant-super-admin privileges will be revoked, and Parent/maximum-depth guidance now explains the separate move workflow and absolute hierarchy-depth semantics.

  • Super-admin tenant editing no longer exposes obsolete legal overrides. The inert Privacy Override and Terms Override tab has been removed; tenant administrators continue to manage published, versioned legal documents through the authoritative Legal Documents administration surface.

  • Tenant feature and module controls now have one authoritative administration surface. The misleading Features tab has been removed from the super-admin tenant create/edit form, including its stale core-module switches and raw-default display logic; tenant capabilities remain managed through the tenant-scoped Module Configuration page, while new tenants inherit the canonical platform defaults.

  • Polls created from the Feed modal now save successfully. The feed endpoint uses the saved poll's numeric ID when building its response and recording feed activity, preventing the post-save server error that previously returned HTTP 500.

  • Terminated federation partnerships now display their real status. The shared admin status badge recognises every partnership lifecycle state instead of falling back to "Unknown", with translated labels across all maintained React locales.

  • Poll option fields now retain focus in both poll creation surfaces. Typing in either the standalone Polls page or the Feed composer no longer remounts the active option input after each character, so complete option text can be entered normally.

  • Security CI no longer treats npm Audit API availability or vendored mobile build templates as OWASP Dependency-Check failures. Blocking production-dependency audits explicitly cover the root, React, E2E, and mobile lockfiles, while Dependency-Check retains installed package/CVE analysis with its redundant network-dependent Node Audit Analyzer disabled. Mobile remains lockfile-audited instead of materializing third-party CocoaPods/Gem templates and native binaries for broad CPE matching, its transitive shell-quote dependency is updated to the patched 1.9.0 release, and the unpatched Metro-only image-size advisory is documented as a time-bounded build-tool risk pending an Expo/Metro update.

  • Frontend container builds now respect the repository boundary of the admin translation gates. The frontend prebuild continues linting both admin surfaces without reaching outside its Docker build context, while the full JSON integrity, indirect UI literal, API literal, and functional-token checks remain enforced by the root i18n pipeline.

  • The accessible frontend's 3,609 same-as-English translation findings are resolved and permanently gated. Gaelic, German, French, Italian, Portuguese, Spanish, Dutch, Polish, Japanese, and Arabic now translate genuine interface copy, narrowly allow only reviewed locale-specific cognates and invariant formats, and omit three unused backend status-code entries. Contextual review of the machine-assisted first pass corrected false friends, damaged Laravel plural branches, lost interpolation and boundary whitespace, inconsistent product terminology, invisible characters, and older encoding corruption; native-speaker editorial review remains recommended for final wording quality. The permanent GOV.UK catalog gate now rejects missing or extra keys, placeholder and boundary-format drift, per-branch plural damage, suspicious encoding or control characters, and unreviewed English fallbacks across all 4,101 maintained source entries.

  • The React administration surface is now translation-complete and guarded end to end. Hardcoded interface copy, raw backend error prose, generated help/glossary/editor labels, module and API documentation metadata, built-in AI/gamification/Caring Community definitions, audit descriptions, health checks, and other server-supplied display defaults now resolve through stable translation keys or semantic codes while preserving tenant-authored content. Coverage now follows admin and super-admin dependency imports, scans admin API controllers and display-metadata services, and blocks literal UI/server-message regressions. All ten non-English React locales were synchronized, with interpolation, markup, technical identifiers, routes, example data, email/phone placeholders, and machine-translation corruption audited and repaired. Permanent catalog gates now reject invalid or duplicate JSON, generated stubs, and damaged i18next/Laravel interpolation, route, schema, protocol, backend-format, and brand tokens across every locale.

  • Documentation health is now enforced as a release invariant across the maintained repository. Every docs/ page and scoped mobile, accessible-frontend, E2E, and test guide is indexed and review-dated; material module, security, privacy, CI, deployment, monitoring, API, and mobile drift was checked against current source and corrected, while a tracked local audit dump was removed and the oversized HeroUI Native task log was replaced with a concise maintained parity matrix. CI and the publishing workflow now use pinned Markdownlint, MkDocs Material, and Redocly versions, build the site strictly, and block on navigation, scoped-index, freshness, archive, link, OpenAPI, and generated-changelog integrity.

  • The canonical OpenAPI contract now matches the hardened message-media and CSP-reporting routes. It documents authenticated no-store attachment and voice delivery, the one-step multipart voice-send endpoint, both browser CSP report media types, and their real response contracts; the obsolete two-step voice-upload route is no longer published, and a focused Laravel-route parity gate prevents these security-sensitive operations from drifting again.


Back to all releases