Repository navigation
Releases
mason v0.8.0
Minor Changes
-
#71
509c6b0Thanks @antstanley! - the header bar has room in it again, and a settings screen behind a cog.on a phone the layout picker was three segments laid side by side, and it was
wide enough that two of its own touch targets had been shaved under 44px to fit
a fourth control beside it. it is a dropdown there now, in the same language as
the client picker, and every control on the bar is back to a 44px target. from
sm up it is the slider it always was.the bar reads left to right: layout, the wall switcher, refresh, settings. the
switcher's panel now lists the five feeds you opened most recently, as real
links, so going back to one is a tap rather than a trip through the picker.which client a post opens in has moved to settings, because it is a choice you
make once and the bar is for what changes while you read. settings is a screen
held in history state like the reader and the picker: the address bar keeps
naming the wall behind it and the back gesture closes it.two more clients to open posts in: twinkl and witchsky. twinkl spells its
profile routes differently from everyone else, so mason rewrites the path rather
than only swapping the host, which is the difference between a link that opens
and one that 404s. -
#71
509c6b0Thanks @antstanley! - a brick now opens where it lies. a plain click on a card lifts it into a reader
over the wall rather than sending you to another app: the same brick mason was
already holding, at reading width, with the trip to the source demoted to one
control inside it. the back gesture closes it, so does escape, the close button
and the scrim, and the wall behind stays dimmed, inert and exactly where you
left it. a modified click still goes straight out, because every card is still a
real link.the sensitive-media reveal now follows the brick instead of the card, so a brick
uncovered on the wall is still uncovered one click later in the reader. it is
still forgotten on reload. -
#71
509c6b0Thanks @antstanley! - a bluesky feed generator is now a wall mason can lay, and the engine treats it
as somebody else's algorithm rather than as more bricks to rank.?feed=pages
the generator itself, one appview call per page, and lays what comes back in the
order it came back: no snapshot, no cohort, no extension waves, no grout and no
mixer. the wall ends exactly when the feed does. glaze still works over it, and
asks for the generator's full page so an image wall is a wall of images rather
than four of them.a feed reference is parsed rather than forwarded, in all three spellings people
actually paste, and one that names no feed says so in its own words instead of
asking you about your handle. -
#71
509c6b0Thanks @antstanley! - a link brings its own picture to the wall.when a post links somewhere and attached no image of its own, the wall now lays
the linked page'sog:imageinstead of a line of grey text, with the host, the
headline and the description over the foot of it. an image the poster attached
still wins: what somebody chose to show beats what a page happened to advertise.no new traffic and nothing new on the wire. the AppView already resolves the
Open Graph tags when a link card is made, and mason has been receiving the
picture alongside the title and description all along without drawing it. -
#71
509c6b0Thanks @antstanley! - mason has a second front door. beside the handle box, and on the switcher of any
laid wall, there is now a feed picker: a screen for finding a bluesky feed and
laying it as a mason wall. it browses what the network ranks, remembers the last
twelve feeds you opened, and takes one box for all three ways of naming a feed.
what you type decides which question is asked: a name searches, a handle lists
the feeds that person made, and a pasted feed link or at:// uri lays it. a paste
that mason cannot lay says so at the box, and nothing navigates.it opens over whatever you were looking at rather than taking you off it, so the
back gesture, escape and the close button all put you back where you were, and
the address bar keeps showing the wall behind. feeds carrying the hidden
moderation tier are never listed, and when the appview will not answer the
picker says so quietly and keeps your recents and the paste box, which need it
for nothing. -
#76
07c423aThanks @antstanley! - the wall pulls on a desktop too. keep scrolling up when it is already at the top
and it opens the same way it does under a thumb, with the same line to cross and
the same wall staying open while it lays itself. stop scrolling and it lays: a
wheel has no letting go, so stopping is how you commit, and the pill says so.a flick that merely lands at the top does not refresh anything. the gesture has
to start from rest, which is the one thing a momentum tail cannot do, and one
stray notch of a mouse wheel moves the wall a little and costs nothing. -
#71
509c6b0Thanks @antstanley! - a feed wall now says whose feed it is: the switcher in the header carries the
generator's own avatar and name, read from the appview the way a wall owner's
face already is, and falls back to the feed's rkey rather than an empty button
when the appview has nothing to say.a feed link that names no feed also stops asking you to check your handle. it
gets its own panel, reading "no such feed", and an empty feed wall says "this
feed has no bricks yet" instead of calling it a wall. -
#71
509c6b0Thanks @antstanley! - a laid wall is no longer final. one control in the header lays it again in
place: the bricks you were reading stay on screen and reflow into the new
arrangement, rather than collapsing to skeletons or throwing away the engine,
the warm caches and any playing video the way a reload does. it does not take
you back to the top, because the reflow is the thing you asked to see.it is disabled while a wall is being laid, and that is the whole rate limit: one
refresh is one burst of upstream requests, so a double tap cannot become two.
the wall keeps its single polite announcement, which already says "laying
bricks" while it warms, and a refresh is a warm.the header bar carries four controls at 375px now, so its gaps and the layout
picker's padding are tighter below sm. it fits a 360px phone for the first time
too, which it did not before the fourth control arrived. -
#71
509c6b0Thanks @antstanley! - the reader's footer says where it is taking you, on one line."open the post" has moved up onto the line the timestamp and the counts already
had, over on the right, and it now names the client it opens: "open in Bluesky",
or whichever one is set in settings. it reads the name off the finished link
rather than off the setting, so a link that is not a bluesky post and therefore
never gets rewritten does not claim it is opening somewhere it is not.the brick counter between "previous brick" and "next brick" is gone. it read as
progress through the wall and was not: the wall keeps growing while the reader
is open, so "4 of 22" quietly became "4 of 31" without the reader having moved.
stepping still announces where it landed to a screen reader, which is a
different job and the one that number was actually doing. -
#71
509c6b0Thanks @antstanley! - a bluesky feed is a wall:/?feed=<at-uri>lays a feed generator with the same
header, the same three views and the same chrome a graph wall gets. the client's
routing surface is now both parameters, andfeedwins when a link carries both. -
#75
baaedf7Thanks @antstanley! - the wall lays itself again when you pull it. drag the top of the wall down on a
touchscreen and let go: it is the same refresh the button in the header asks for,
reached the way a thumb reaches for it. the wall follows your finger, stiffens
past the point where letting go would lay it, and says which side of that line
you are on.let go and the wall stays open a crack while it lays itself, then closes: the
gap shutting is how you know it is...
mason v0.7.0
Minor Changes
- #57
fd4700aThanks @antstanley! - the wall extends itself: when the scroll runs the pool low, mortar fans out to the next hundred authors it has never asked, in waves, until the whole follow graph is spent. endless scroll now quarries the entire graph instead of ending at the first cohort, and the wall only says it is done when there is genuinely nobody left to ask.
Patch Changes
- #55
dd676fbThanks @antstanley! - the wall now fits in a pocket: the bottom-bar controls grew visible labels and thumb-sized targets and hold a single line on any phone, and the client picker says where posts open instead of hiding behind a glyph. empty walls explain themselves ("this wall has no bricks yet") and a paused feed offers "try for more" instead of silence. bricks with zero likes and reposts stop bragging about it, card titles breathe a little more, column widths no longer animate on reflow, and the glaze caption toggle closes as readily as it opens.
mason v0.6.4
Patch Changes
-
#44
68f6fbdThanks @antstanley! - scope the WCAG 2.2 AA claim honestly (video captions excepted pending upstream data) and reserve a caption-track path: VideoBrick grows an optional captions list and the player renders track elements when it is populated -
#43
38fd727Thanks @antstanley! - a deploy no longer hard-reloads an active tab: the reload waits until the tab is hidden or the next navigation, so the wall, scroll position, and playing video survive -
#47
d5ab5a9Thanks @antstanley! - persist only the caches that changed, each under its own key, and never during preview polls -
#48
3237320Thanks @antstanley! - masonry lays one keyed list in feed order: column changes keep every brick's node, state and focus, re-lays are a single pass, and tab order follows the feed
mason v0.6.3
Patch Changes
-
#27
856271eThanks @antstanley! - the glaze alt-text overlay now works with a keyboard alone: opening it moves
focus onto the close control, escape or the close button hands focus back to
the alt trigger, the trigger reports its state with aria-expanded and
aria-controls, and the covered picture and its paging controls go inert so tab
and pointer stay on the panel. -
#27
856271eThanks @antstanley! - the glaze filmstrip is friendlier to keyboard and screen-reader users:
tabbing to the prev/next arrows reveals them instead of moving focus onto
invisible buttons, and a polite live region announces "image n of m" as the
strip pages. -
#27
856271eThanks @antstanley! - keyboard users on the glaze wall now see a brick's caption, author, and alt
button: focusing into a card reveals them the same way hovering does, and the
concealed alt button leaves the tab order until the card is revealed, so focus
no longer lands on an invisible control. -
#27
856271eThanks @antstanley! - fix: switching between bento and masonry no longer throws away your loaded wall.
Only picking (or leaving) glaze re-fetches, since glaze is a different feed; the
two grid-only layouts now just relay the same bricks instead of wiping the wall
and refetching from the top. -
#27
856271eThanks @antstanley! - darken the glaze brick's floating controls so their text clears the 4.5:1
contrast bar over any image: the paging arrows, the image counter, and the
touch reveal button sit on a heavier ink scrim, and the caption bar is now
near-opaque like the alt panel. -
#27
856271eThanks @antstanley! - fix: a valid handle no longer gets told it does not exist. mason now only shows
the handle-not-found message when the feed engine actually reports the actor is
missing, rather than on any 404. In local mode a request that slips past the
service worker onto the static host used to 404 and wrongly accuse a real
handle; that case now reads as a plain feed-unavailable hiccup. -
#27
856271eThanks @antstanley! - tidy the wall's headings for screen readers: a failed wall now shows exactly one
h1 (the failure itself, with the sr-only wall title stepping aside) instead of
two, and every brick, not just blogs, carries a consistent accessible name on
its article rather than a lone heading on some cards. -
#27
856271eThanks @antstanley! - brick links are scrubbed before they reach the wall: a blog or stream record
that smuggles ajavascript:,data:, or other non-http(s) url in its link
field now lands without a link at all instead of arming the card, and the client
picker refuses to rewrite anything but a real http(s) address. -
#27
856271eThanks @antstanley! - fix: the wall no longer hangs on an endless skeleton when the service worker
fails to register. Waiting for the worker to be ready is now bounded by the same
short timeout as everything else, so a registration that never settles falls
through to a normal request instead of leaving you staring at a loading wall
forever. -
#27
856271eThanks @antstanley! - the switch-wall button's aria-label dropped its em dash for a comma, so screen
readers announce "switch wall, currently viewing @handle" instead of reading the
dash aloud. -
#27
856271eThanks @antstanley! - the switch-wall panel is now a proper modal: it marks itself aria-modal and
closes when focus tabs out of it, so keyboard users no longer walk into the
dimmed wall behind the open switcher. -
#27
856271eThanks @antstanley! - server mode now checks where a PDS pointer actually leads before it knocks: a
DID document can no longer steer mortar at loopback, private, link-local, or
cloud-metadata addresses, and only https endpoints are followed. hostile bricks
stay outside the wall. -
#27
856271eThanks @antstanley! - fix: scrolling a playing clip off the wall before it finishes loading no longer
leaves a phantom playing in the background. If a video card is torn down while
the player library is still loading, the player now bows out instead of building
itself on a detached brick and quietly fetching segments (and audio) with nothing
left to stop it. -
#27
856271eThanks @antstanley! - the wall now narrates itself to screen readers: a single polite live region
reports laying bricks, how many fresh bricks landed, when more bricks did not
arrive, and when that is every brick, the pagination-failure tail is a status
region, and the wall is marked aria-busy while the first screen loads. -
#27
856271eThanks @antstanley! - fix: going back to a wall you already scrolled now returns it exactly as you left
it. mason keeps each wall you visit for the length of the session, so browser
back/forward rehydrates the same bricks in the same order (and your scroll lands
where it should) instead of rolling a fresh arrangement that dropped you back at
a single screen. -
#27
856271eThanks @antstanley! - fix: switching walls mid-load no longer bleeds the old wall into the new one.
When you jump to a different wall while the first one is still fetching, a late
response from the old wall could shove its bricks into the new wall, overwrite
the cursor, or wrongly mark pagination finished (a wall stuck at one screen).
Both the load-more and freeze steps now bail out when the wall has moved on, and
resetting a wall clears the loading flag so the fresh wall starts clean. -
#27
856271eThanks @antstanley! - the warming reflow now stops for everyone: navigation keys and focus landing on
the wall freeze it just like a scroll or a swipe does, and a reader who asks for
reduced motion never sees the auto-reflow at all because the wall freezes before
it starts moving.
mason v0.6.2
Patch Changes
-
#24
17284a8Thanks @antstanley! - perf: a cold wall paints sooner. Five changes to the opening of a wall, none of
which move a brick once it is laid:- one
getProfilenow resolves the handle AND reads the owner's logged-out
opt-out, folding the two sequential AppView calls that gated every cold load
into one round trip. - the first wall waits for a single follow-graph page (100 follows, already more
than the cohort samples) instead of three, so the fan-out starts two round
trips sooner. The rest of the graph is still chased in the background. - the first page's wait-for-a-better-mix deadline is now anchored to when the
snapshot was created, so the first-paint wait counts against it rather than
stacking on top of it: the opening wait is bounded, not doubled. - the landing page warms the engine while you are still at the form — a
remembered handle warms that wall's caches, and with no handle the demo wall
at least compiles the wasm off the critical path. - the roughly-first-screen bricks load their images eagerly and at high fetch
priority; the rest of the wall stays lazy.
- one
-
#23
287f40cThanks @antstanley! - feat: glaze cards get a reveal control on touch. Where there is no hover to lift
the author pill and caption, a small transparent double-chevron button now taps
them up (and back down) — it rides on the author pill's line, sitting at the
bottom-right at rest and rising with the pill when the caption lifts. On hover
devices nothing changes; the pill and caption still reveal on hover. -
#25
e9399c7Thanks @antstanley! - feat: the wall reflows as it fills, then freezes when you reach for it. Instead
of waiting for a full first page and dropping it in one block, a cold wall now
paints the moment the first bricks arrive and re-mixes the first screen as blogs,
videos and live streams land behind the posts. The instant you scroll (or the
wall settles, or a few seconds pass) the arrangement locks and normal scrolling
takes over; from there a brick never moves. The mixer is pure, so each reflow is
a real improvement rather than a reshuffle, and pages after the first are laid
once and immutable exactly as before. Server mode and the demo wall keep working
unchanged. -
#21
82ea0d0Thanks @antstanley! - fix: the menu bar stays on one line now that Glaze is a third layout, and the
layout slider's thumb hugs each option. The segments size to their own content
and the thumb measures the selected label and matches its width and position, so
a short label like Glaze no longer leaves dead space inside the white highlight.
On mobile the slider is icon-only and the client picker drops to just its icon
(sized to match the layout icons; its label and chevron return at the sm
breakpoint), keeping the bar to one row. -
#26
f1b3255Thanks @antstanley! - perf: the browser engine is 103 KB smaller. The wasm build talked to the network
through reqwest, which on wasm is only a thin wrapper over the browser's own
fetch — but it dragged theurlcrate's IDNA/ICU Unicode tables in with it, none
of which mason needs (every request URL is a plain ASCII atproto endpoint). The
browser build now uses gloo-net instead, a direct fetch wrapper with no such
tail. reqwest stays on the native server unchanged. The shared rate limiter and
429/5xx retry loop are untouched; only the one-shot GET underneath is split by
target. The shipped wasm drops from 389 KB to 286 KB gzipped (270 KB off the
raw binary), so a cold start downloads and compiles less on the very path that
gates first paint.
mason v0.6.1
Patch Changes
- #19
591ce4cThanks @antstanley! - fix: the wasm service worker survives a deploy. Each deploy deletes the previous
build's hashed assets, so a worker that installed before a deploy would 404
fetching its old wasm engine and then brick every/api/feedfor the life of
that session (the rejected init was memoised) — a 500 that only hit visitors who
had loaded the app before. The worker now precaches its own wasm and loads the
engine from that cache, so it keeps serving until it is itself replaced; a failed
init is never memoised. The client also revalidates the worker script on load
(updateViaCache: 'none'+update()) and reloads once when a new engine takes
control, so a deploy is picked up promptly instead of leaving a stale worker.
mason v0.6.0
Minor Changes
- #17
b2776d5Thanks @antstanley! - glaze: an image wall. a new menu toggle (off by default) flips the wall to
nothing but Bluesky posts that brought an image, fetched from the AppView and
ranked by the same grout the full wall uses, with moderation and!warnblur
intact. bento and masonry both lay it. glaze bricks lead with the picture and a
clear strip carrying the poster; hover one and the post's text scrolls up over
the image (a slim footer on touch, where there is no hover).
mason v0.5.0
Minor Changes
-
#15
8f22066Thanks @antstanley! - respect logged-out visibility and moderation labels. mason reads walls logged out, so it now mirrors what Bluesky itself shows a logged-out viewer.- a wall whose owner set
!no-unauthenticatedis sealed behind a "sign in to view" panel, and any followed account that opted out is dropped from the wall whole (posts, blogs, archived streams, and live), not just their skeets. - adult media (
porn,sexual,graphic-media) and moderator hard-hides (!hide) are kept off the wall, exactly as a logged-out Bluesky viewer would find them.nudity, which Bluesky shows to logged-out viewers, is shown here too. - a
!warnlabel covers a brick's image or video poster behind a "show anyway" reveal, chosen per brick and forgotten on reload. nothing hard-hidden ever reaches this tier, so a covered brick can always be uncovered.
- a wall whose owner set
mason v0.4.0
Minor Changes
- #13
96f7ebaThanks @antstanley! - lay the wall as a bento grid: feature bricks (videos, and blogs or posts with a landscape image) span two columns, and smaller bricks backfill the gaps with dense grid flow. a segmented layout picker in the header switches between the bento wall and the original masonry columns, and the choice is remembered. the client picker becomes an icon dropdown carrying each service's own mark (Bluesky, Mu Social, Blacksky), the layout picker slides between its two states, and the switch button wears the wall owner's avatar and drops an inline switcher below itself, so opening it and changing your mind never leaves the wall you are on. on a narrow screen the header sheds the wordmark and becomes a sticky bottom bar: an icon-only layout slider, the client picker, and an avatar-only switch button, evenly spread, with its menus opening upward.
mason v0.3.0
Minor Changes
-
#11
e51775cThanks @antstanley! - Streamplace video replaces Steam. The wall now carries atproto livestreams
from stream.place: archived streams from the people you follow (a 90-day
window, since an hours-long stream stays worth watching long after a skeet
about it would have expired), and anyone who is live right now.A live stream is the only brick with a deadline, so it is the only one that
jumps the queue: it opens the wall, wears a LIVE badge and a viewer count, and
never ages out while it is running. Everything else is unchanged; video is
still click-to-play, and still never autoplays.Steam is gone entirely. Its storefront API served no CORS headers, so trailers
never worked in the browser build at all; Streamplace is CORS-open, which means
the no-server build now reads exactly what the native one reads.A wall that actually arrives. Chasing the live-stream work turned up three
things that were quietly starving the first page, and they are fixed here:- The follow graph was fetched to completion before a single post was, and
follows page 100 at a time with each request blocking the next. Someone with
2000 follows waited ten seconds for a list nobody asked to see, and their
first wall came back empty. The wall is now built from a head start of
300 follows (the cohort only samples 100 authors anyway) while the rest of
the graph is fetched behind their back for next time. - standard.site documents refetched their publication record once per
document, so one blogger cost 25 sequential requests. A blogger has one blog:
it is fetched once now. The repo fan-out went from 21s to under 4s. - Posts and repo reads shared a task per author, so an author's posts waited on
plc.directory and two PDS reads before being admitted. They are fanned out
separately now, and the per-author brick cap is per KIND, so a prolific
poster's own blog is no longer turned away by a quota their skeets ate.
Infinite scroll that keeps going. The wall could stop dead with a cursor
still in its hand.IntersectionObserverfires on a change of intersection,
and a page that came back short did not grow the wall enough to push the
sentinel back out of its prefetch margin, so no second event ever arrived and
the scroll ended there. The wall now pulls rather than waits to be told: it
keeps laying while its bottom is within reach. And the AppView burst is raised
from 40 to 100 (the 10/s sustained ceiling is untouched), so a cold cohort goes
out at once instead of dripping, and a reader can no longer out-scroll their
own wall. - The follow graph was fetched to completion before a single post was, and
-
#9
05fa72eThanks @antstanley! - An atmosphere client picker, and a wall that is actually fresh.Open posts in the client you use. bsky.app, mu.social and blacksky.community share a URL structure, so the picker in the header rewrites the host and nothing else. Blog and stream links are left exactly as they are, because they are not Bluesky posts. The choice persists.
A stronger recency bias. Posts and Bluesky videos now live for 72 hours, blogs for 14 days, and nothing older is admitted to the wall at all: a hard window, not a soft preference, because decay alone leaves week-old content eligible and on a quiet follow graph it surfaces. Half-lives are steeper to match (posts 12h, blogs 3d).
A wall could belong to one person. First paint gated on the number of bricks in the pool, and a single prolific account returns thirty of them, so the wall could open before anyone else's feed arrived. It now gates on distinct authors, no author may hold more than four bricks, and when the diversity rule truly cannot be honoured the mixer falls back to the least represented author rather than re-picking the loudest.