Skip to content
This repository was archived by the owner on Oct 28, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
661d038
chore(release): prepare 0.5.1 metadata
ael-dev3 Oct 23, 2026
11f3b72
docs: align contributing rules with sign-in and mini apps
ael-dev3 Oct 23, 2026
f69a5c2
test(perf): retain sanitized cold-load diagnostics
ael-dev3 Oct 23, 2026
bec9420
fix(post): react to mini-app visibility changes
ael-dev3 Oct 23, 2026
6220d5b
test(perf): omit quoted Server-Timing descriptions
ael-dev3 Oct 23, 2026
75249aa
fix(feed): exclude future casts before ranking every range
ael-dev3 Oct 23, 2026
3442602
test(profile): restore seen rows when checking hover leanings
ael-dev3 Oct 23, 2026
8e393a6
docs: refresh the release screenshots
ael-dev3 Oct 23, 2026
44440aa
test: wait for the latest presence cache expiry
ael-dev3 Oct 23, 2026
06e21bb
fix(feed): retain bounded source clock skew during ingest
ael-dev3 Oct 23, 2026
e2a63a0
fix: keep seen-feed cleanup after sort feedback
ael-dev3 Oct 23, 2026
32e11d4
fix: keep ordinary posts mounted when mini app settings change
ael-dev3 Oct 23, 2026
8233b78
fix(feed): sample time after source reads complete
ael-dev3 Oct 23, 2026
9d3d2ce
ci: retain cold-load diagnostics after every performance run
ael-dev3 Oct 23, 2026
e8d8480
test: keep leaning fixture timestamps in the past
ael-dev3 Oct 23, 2026
aa988a4
test(feed): keep pagination fixtures inside the past day
ael-dev3 Oct 23, 2026
09a10ad
test(dau): align feed timestamps with the pinned page clock
ael-dev3 Oct 23, 2026
cd7c4ec
docs: record realistic browser fixture clocks
ael-dev3 Oct 23, 2026
88eabe4
test(boot): distinguish the main module from idle splits
ael-dev3 Oct 23, 2026
fb817f3
test: show read posts before comparing feed rankings
ael-dev3 Oct 23, 2026
9dff65f
test(feed): wait for the latest source when checking time ranges
ael-dev3 Oct 23, 2026
a8f9fcd
docs: record browser readiness checks
ael-dev3 Oct 23, 2026
39f1599
test: assert deployment-specific write readiness
ael-dev3 Oct 23, 2026
795e88d
test: verify complete enabled-write status shape
ael-dev3 Oct 23, 2026
8fcbd4f
fix(emoji): align groups before progressive drawing completes
ael-dev3 Oct 23, 2026
3dce8d7
test(hosting): discover the deployed main module route
ael-dev3 Oct 23, 2026
291e194
test(ci): reject recovered browser flakes
ael-dev3 Oct 23, 2026
99674b6
test(feed): await live sorts and retain loaded images
ael-dev3 Oct 23, 2026
710e05d
ci: isolate smoothness from parallel functional fixtures
ael-dev3 Oct 23, 2026
938732d
test(video): verify held keyboard focus before sound activation
ael-dev3 Oct 23, 2026
c91f38e
test: wait for sampled routes before checking Back
ael-dev3 Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ jobs:
- run: npx playwright test e2e/perf.spec.ts
env:
E2E_BASE_URL: https://allthing.social
- name: Retain performance diagnostics
if: always()
uses: actions/upload-artifact@v6
with:
name: playwright-performance
path: |
playwright-report/
test-results/
if-no-files-found: ignore
retention-days: 7

speed:
# The speed report (docs/PERFORMANCE.md#speed-report): load times of the
Expand All @@ -116,7 +126,7 @@ jobs:
browser:
name: browser regressions (fixtures)
runs-on: ubuntu-24.04
# The suite takes 26 to 29 minutes; 30 cut runs off at their last specs.
# Build, functional fixtures, quiet smoothness and static checks share this cap.
timeout-minutes: 45
env:
WRANGLER_SEND_METRICS: "false"
Expand All @@ -142,11 +152,13 @@ jobs:
- run: npx playwright install --with-deps chromium
- run: bash scripts/build.sh
- name: Test the local build without live data
run: npx playwright test '\.fixture\.spec\.ts$'
run: sh scripts/test-browser-fixtures.sh
- name: Test the static copy
run: |
bash scripts/build-pages.sh
E2E_PAGES=1 npx playwright test e2e/static-body-limit.fixture.spec.ts e2e/static-metadata.fixture.spec.ts e2e/static-navigation.fixture.spec.ts e2e/static-follows.fixture.spec.ts e2e/preloaded-replies.fixture.spec.ts e2e/poll.fixture.spec.ts
E2E_PAGES=1 npx playwright test e2e/static-body-limit.fixture.spec.ts e2e/static-metadata.fixture.spec.ts e2e/static-navigation.fixture.spec.ts e2e/static-follows.fixture.spec.ts e2e/preloaded-replies.fixture.spec.ts e2e/poll.fixture.spec.ts --output=test-results/static
env:
PLAYWRIGHT_HTML_OUTPUT_DIR: playwright-report/static
- name: Upload browser failure reports
if: failure()
uses: actions/upload-artifact@v6
Expand Down
67 changes: 32 additions & 35 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,41 @@ All notable changes to Allthing are recorded here. The format follows [Keep a Ch

## [Unreleased]

### Changed

- Notifications coalesce refreshes from opening the page and regaining focus. Marking the list seen does not queue another read: only changed notification times refresh its rows, so a delayed duplicate cannot start after the tab is hidden.

- On phones, header search has a full-width second row, leaving Home, the online count, Settings and account controls in view. A wrapped reply's app link clears its collapse button's full tap area.

- Front-page feeds remember casts actually read for a second with at least half its possible viewport exposure visible in a foreground tab, including cards taller than the screen. Later feed generations leave these posts out, with Show seen posts below the list and Reset seen posts in Settings. History stays in this browser, separate for each signed-in FID and signed-out reader, bounded to 2,000 hashes for 30 days across four readers. Current cards stay put while read, and direct posts, profiles and threads remain complete.
## [0.5.1] - 2026-10-23

- Show mini app casts moved out of the feed into a Settings panel in the header (for every reader, signed in or not): the "N mini app casts hidden" line is removed, and the account menu no longer repeats the switch. A shown mini app cast quoted in another cast now carries its "Open in Farcaster" link inside the quote card; no other cast or quote shows mini app chrome. Quoted mini apps follow the switch in place; early cards end before a shown mini app so the app takes over without replacing it with different markup.

- The "Only N casts in …" note sits under a range's list, where it ends, not above it: it came once the list had ended and moved every card down (a layout shift at 1280).
- The front page has two tabs for a signed-in reader, as on X: **For you** and **Following**, links in place of the Following / Everyone menu, each 44 px tall. For you, the default, is the trending pool with the casts of the accounts you follow lifted: 20 times their points in hot and 6 in top (`FOLLOWED_HOT_WEIGHT`, `FOLLOWED_TOP_WEIGHT`), and new stays in time order. Following (`?feed=following`) is only their casts, in hot, new and top and over the time range, with no trending casts topping it up any more. Old `?feed=everyone` links open For you. For you costs no extra request while it is drawn: it ranks by the accounts kept from your last Following page, renewed by one background read at most every 10 minutes. Signed out, the front page has no tabs, as before; early paint draws a signed-in reader's For you, tabs and all.
### Changed

- Messages now only take verified Farcaster accounts: allthing.social's attestation key is set up (the `ATTEST_KEY` secret) and its public half, `5df241b6517235a521769788541a5cb6369bb3deb4536734b5db8b5cb23d87cb`, is pinned in the SpacetimeDB module (`spacetime/spacetimedb/src/attest_key.rs`), as `/api/v1/status` reports. Signed in, Messages verifies your account before you chat or send a message; no one can speak there as someone else's FID.
- **For you and Following.** Signed-in readers have two front-page tabs, each with hot, new and top and every time range. For you lifts casts from accounts you follow; Following shows their casts only. New stays chronological, including with Favorite and Show less.
- **Seen posts.** Later front-page visits leave out casts you read for a second in a visible tab, including cards taller than the screen. Show seen posts brings them back, and Reset seen posts clears the history in Settings. History stays in this browser, separate for each reader: at most 2,000 hashes for 30 days, across four readers. Cards stay put while you read; direct posts, profiles and threads stay complete.
- **Mini apps in Settings.** Show mini app casts is in the header's Settings panel for every reader, replacing the feed's hidden-cast count and switch. Only casts and quotes that contain mini apps show their Open in Farcaster links, and quoted mini apps follow the setting immediately.
- **A clearer header.** Phone search has a full-width second row, keeping Home, the online count, Settings and account controls in view. The online count reserves its space on desktop and stays beside Home on phones.
- **Verified Messages.** Messages verifies the signed-in Farcaster account before it can chat or send messages. The Worker's attestation key is pinned in the SpacetimeDB module, which rejects forged and expired attestations.

### Fixed

- Feed-ranking checks restore read posts through Show seen posts even when the filtered list is empty or a delayed navigation is still loading.

- Reply-composer geometry checks wait for its entrance animation before measuring exact thumbnail and tool sizes, while retaining first-frame focus and layout-shift checks.

- Pressed conversation rows keep their preview text and timestamps readable while the press animation dims the row, including on its selected background.
- The smoothness fixture locates the first feed card below both front-page tab rows before measuring navigation; its existing timing, frame and scroll-restoration budgets are unchanged.

- Messages connects under the site’s existing Content Security Policy. SpacetimeDB’s product and sum codecs now use cached closures instead of compiling JavaScript strings; the SDK version is guarded at build time, and a browser test exercises the actual bundled connection, row decoding, account verification and chat sending under the production policy.

- Following sort links and time-range changes prefetch their existing private feed, rather than fetching and waiting for unrelated For you home/latest payloads.
- The desktop online count reserves its width before loading, including at 921 px with Settings present, so the search box cannot overlap it. Phone layouts keep the compact dot and count at the 920 px breakpoint.

- Following stops automatic pagination once its source reaches the selected time limit, and retains that cursor so a wider range resumes correctly. A fully seen or otherwise filtered feed reads at most ten payloads before offering Load more posts; each explicit press permits ten more.

- Local macOS Worker and static Pages builds discover worker-build's cached `wasm-opt` under `Library/Caches`, so the browser modules receive the same optimization as CI. An explicit optimizer or one on PATH takes precedence, and cached binaries for other architectures are skipped.

- Both front-page tabs keep the time selector in New and apply the selected range consistently. New stays strictly chronological even for favorites and accounts shown less. Changing the signed-in account replaces its feed and ranking snapshot; background follow reads and their ten-minute retry cap are scoped to that account, and late answers from the old account cannot refill its private cache.
- The online count stays visible beside Home on phones, with its space reserved before loading. Showing oneself or signing in replaces the browser's anonymous presence instead of counting it twice; hiding or signing out removes the public name, including from later cached responses at other locations. Beat jitter only delays the advertised interval by up to 30 seconds, within the online grace, instead of beating too early or expiring a reader too soon.


- `scripts/attest-key.mjs` writes a public key that compiles: its pattern stopped at the `;` inside the placeholder `[0; 32]`, leaving `[0x…]; 32];` in `attest_key.rs`. It now replaces the whole array, also once a key is pinned over several lines.
- Every time range up to 7 days holds the casts just posted. Hypersnap's trending lists run 4 to 6 hours behind (its past hour's list was 5 to 6 hours old, so Past hour could come back empty), so a range's first page adds the newest casts the cron stores each minute, kept to the range.
- CI rejects browser tests that pass only on retry, so a flaky run cannot appear as a clean release check.
- Choosing an emoji group while the picker is still drawing reaches its heading on the first click, including a group at the temporary bottom of the list.
- Sort tabs show their selected state before the next feed hides read cards, keeping reading-history cleanup out of the tap handler.
- Future-dated casts cannot outrank the present in For you or Following, including All time and early paint. Cached newest-cast payloads and index rankings exclude future timestamps before selecting their visible rows. Source reads use the clock when they finish, so casts posted while a response arrives are retained. Ingest retains up to five seconds of source clock skew in the existing buffer; implausible dates are discarded, and retained rows appear only when their timestamp is reached.
- A directly opened mini app post follows Show mini app casts immediately in both directions, without a reload or refetch. Hiding it removes its body and embedded content while retaining its Open in Farcaster link; ordinary posts and ordinary quotes keep their content and media mounted.
- Short time ranges include newly posted casts even while Hypersnap's trending list lags behind. Every sort keeps the chosen range, and the end-of-range note appears below the list without moving cards down.
- Following prefetches its own feed when changing sort or range, stops automatic paging at the time limit, and resumes from that cursor for a wider range. A fully seen or filtered feed offers Load more posts after ten payloads rather than reading indefinitely.
- Changing accounts replaces the feed and ranking snapshot, and late answers from the previous account cannot refill its cache. Presence no longer counts an anonymous and signed-in visit twice; hiding or signing out also removes the public name from cached lists.
- Messages connects under the existing Content Security Policy without permitting JavaScript evaluation. Pressed conversation rows keep their previews and timestamps readable.
- Notifications coalesce refreshes from opening the page and regaining focus. Marking the list read no longer queues a duplicate request that could start after the tab is hidden.
- A wrapped reply's app link clears the collapse button's full tap area.

### Development

- Back-navigation checks wait for sampled Home and post frames before returning, preserving their exact retained-card, restored-height, position and request assertions.

- CI runs functional browser fixtures with two workers, followed by smoothness measurements alone with one. Both phases run and keep separate reports even after a failure, under the same checks and timing limits.
- Video keyboard checks verify a held Space press on the original pointer-focused control before release, retaining bounded input and media diagnostics on failure.
- Cold-load performance checks retain sanitized per-sample LCP, network, cache and long-task diagnostics, including on failure, in a seven-day Actions artifact. Their timing limits, cold contexts and sample count are unchanged.
- Browser regressions use past timestamps relative to the page’s own clock, wait for restored seen rows and the latest presence-cache expiry, and preserve their ordering, privacy, navigation and timing checks, including a deliberately delayed count refresh.
- Startup checks distinguish the main WebAssembly module from idle-loaded parts, and range navigation waits for the actual New feed response.
- Local macOS builds find worker-build's cached WebAssembly optimizer. SDK wire-format and strict-CSP browser checks cover Messages; feed-ranking, reply-composer and smoothness fixtures exercise the updated UI without changing their budgets.
- The attestation-key helper replaces the complete Rust key array, including multiline values, so a generated key compiles.

## [0.5.0] - 2026-10-22

Expand Down Expand Up @@ -595,7 +591,8 @@ Released before tagging began; the link points to its last commit, `e521cd1`.

- A read-only Next.js prototype with live Hypersnap data, on GitHub Pages.

[Unreleased]: https://github.com/ael-dev3/Allthing/compare/v0.5.0...HEAD
[Unreleased]: https://github.com/ael-dev3/Allthing/compare/v0.5.1...HEAD
[0.5.1]: https://github.com/ael-dev3/Allthing/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/ael-dev3/Allthing/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/ael-dev3/Allthing/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/ael-dev3/Allthing/compare/v0.2.0...v0.3.0
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Everyone taking part is expected to follow the [code of conduct](CODE_OF_CONDUCT

## Ground rules

- **Reads, and the reader's own likes, recasts, casts, follows and deletions.** Don't add other ways to sign in, wallet connections or anything else that writes to Farcaster unless that scope has been agreed in an issue first. The one sign-in is Sign In With Farcaster by QR code ([docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#sign-in)); a reader's likes, recasts, casts, follows and deletions are signed in their browser, with a key they approved in the Farcaster app ([docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#liking-and-recasting)).
- **Never hide content** because of who posted it: Allthing shows no account labels. Casts with mini apps or frames, and spam by the fixed rules in `allthing-core/src/spam.rs`, are left out server-side (`Cast::hidden`, `thread::without_hidden`, `thread::prune_hidden`), and new list endpoints must do the same.
- **Reads, and the reader's own likes, recasts, casts, follows and deletions.** Don't add other ways to sign in, wallet connections or anything else that writes to Farcaster unless that scope has been agreed in an issue first. Where the Worker endorses keys, one approval in the Farcaster app signs the reader in and permits writing, by QR code on a computer or a link on a phone; Sign In With Farcaster by QR code is the fallback where it does not ([docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#sign-in)). A reader's likes, recasts, casts, follows and deletions are signed in their browser, with a key they approved in the Farcaster app ([docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#liking-and-recasting)).
- **Never hide content** because of who posted it: Allthing shows no account labels. Spam by the fixed content rules in `allthing-core/src/spam.rs` is left out server-side (`thread::without_spam`, `thread::prune_spam`). Mini app and frame casts are marked with `Cast.mini_app` and kept in feed, profile, channel and thread payloads; the browser hides them unless Show mini app casts is enabled in Settings, and never runs them. Search, reply previews and notifications still drop both spam and mini apps (`Cast::hidden`). New list endpoints must follow one of these documented paths.
- **Stay within the Free plan.** Each page view makes one API call. The Worker has a 10 ms CPU limit and at most 45 subrequests per invocation, cache calls included. New upstream calls go through `allthing-data/src/upstream.rs` (token buckets, breaker, timeouts) and payloads through `cache::serve`. Update [docs/BUDGET.md](docs/BUDGET.md) when the costs change.
- **Put code where it belongs.** Pure logic and data types go in `allthing-core`, with unit tests. Provider quirks stay in `allthing-data/src/hypersnap.rs` and `allthing-core/src/normalize.rs`. The page builders in `allthing-data` also run in the browser for the static copy, so they reach the network only through the `Host` trait. UI goes in `allthing-web`, and its links are built with the helpers in `allthing-web/src/util.rs` (and opened from code with `use_go` there), because the static copy lives under `/Allthing`.
- **Keep it fast.** Stay within the budget in [docs/PERFORMANCE.md](docs/PERFORMANCE.md), and send prefetches through `api::prefetch`.
Expand Down
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ exclude = ["spacetime/spacetimedb"]
resolver = "3"

[workspace.package]
version = "0.5.0"
version = "0.5.1"
edition = "2024"
rust-version = "1.99"
license = "AGPL-3.0-or-later"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Allthing is an independent Farcaster client, written in Rust, that shows trendin

**Live at [allthing.social](https://allthing.social).**

![The Allthing front page: trending Farcaster casts with their likes, recasts and replies, the app each one was posted from, and Allthing's poll](docs/screenshots/home.webp)
![Allthing's Following feed with For you and Following tabs, sorting and time ranges, Settings, the online count and Allthing's poll](docs/screenshots/home.webp)

<p align="center">
<img src="docs/screenshots/profile.webp" alt="A profile: bio, website, followers and following, join date, NS vote and wallet activity by chain" width="49%">
Expand Down Expand Up @@ -114,7 +114,7 @@ bash scripts/check.sh # version, CSP hashes, changelog lin
npx playwright install chromium # once
npx playwright test '\.fixture\.spec\.ts$' # deterministic browser regressions, as CI runs them
npx playwright test # everything, including live Farcaster data
E2E_BASE_URL=https://allthing.social npx playwright test # against production
E2E_BASE_URL=https://allthing.social E2E_EXPECT_WRITES_READY=true npx playwright test # production
bash scripts/build-pages.sh && E2E_PAGES=1 npx playwright test # the static copy
```

Expand Down
Loading
Loading