Skip to content

Replace Rails app with the static-site rebuild (Project Daedalus live site)#121

Open
AgentKush wants to merge 6 commits into
DonovanMods:mainfrom
AgentKush:feat/agentkush
Open

Replace Rails app with the static-site rebuild (Project Daedalus live site)#121
AgentKush wants to merge 6 commits into
DonovanMods:mainfrom
AgentKush:feat/agentkush

Conversation

@AgentKush

@AgentKush AgentKush commented May 7, 2026

Copy link
Copy Markdown
Contributor

This PR replaces the entire Rails 7.1 + Firestore application with a static-site rebuild that becomes the live projectdaedalus.app. It's been incubated at AgentKush/daedalus-static-poc and rebranded for production. What ships here is exactly what the POC site shows right now, byte-for-byte.

Single GitHub-API-signed commit (da962410). 221 files changed: 47 added, 169 removed, 2 modified. No Co-Authored-By trailers.


Updates since this PR was first opened

The PR has stayed open while I kept iterating on the POC. 39 commits land on top of the original da962410 snapshot. Highlights, grouped:

Mobile / responsive

  • f747e86 Stop horizontal overflow on mobile — w-screenw-full, body overflow-x-hidden, prose tables contained
  • 1d10603 Hamburger nav (was a row of 4 tabs that wrapped awkwardly on phones); overflow-x-hidden on <html> not just <body>
  • d02da38 Hamburger inline with the logo, plus grid-cols-1 baseline on every grid (implicit auto-tracks were sizing to max-content and overflowing)
  • 1e4e17d Mod-detail header stacks vertically on mobile so download buttons + file-type badges don't clip

Mod pack export

  • ba2f20c Fix selection: clicking a row now selects, not navigates
  • 96bec31 b6b5ce7 Actually bundle EXMODZ/PAK files into a zip; drop the manifest-only flow (no one wanted that)
  • 45a59d8 007f2ec 83b08f7 28620f1 CORS hardening: rewrite github.com/.../raw|blob/...raw.githubusercontent.com/.../..., route release-asset URLs via api.github.com (CORS-friendly redirect chain), magic-number validate before adding to zip, write SKIPPED.txt with the failure reason

Tags

  • 8ef4566 1e68b43 9fe9b00 e1ce11a Tag regex tightening: drop x\d+ from speed, drop dropship from creatures, add vehicles / performance / cosmetic, only match keywords in name + first 120 chars of description ("primary purpose" zone), handle plurals and suffix variations (spoilage, attachments, etc.). Nexus mods now appear on /tag/<name>/ pages with a NEXUS badge.
  • 4aae227 Fix tag filter: was keying off Firestore doc IDs, the tag index was keyed off slug(author)+slug(name)

Tools (new)

  • d0511ae Per-tool detail pages at /tools/<author>/<name>/ with live-fetched GitHub Releases history (lazy-loaded), release card per tag with title/date/changelog/asset list, prev/next nav
  • 5f8e9a3 Release-history filter: shared-repo tools (e.g. Mod Editor + Mod Manager both ship from Jimk72/Icarus_Software) only show releases tagged with their own keyword instead of echoing each other's

Mod detail / analytics

  • 7670170 Analytics: GitHub repo card pinned to the mod's actual files (not the repo root). Mod Status reflects current state.
  • 399a7d9 Mod Status now reads health.json (broken downloads) + validation.json (validator findings) and includes 6 in-browser checks (empty description, placeholder text, no image, short description, compat age, no tags)
  • 98997b3 Validator runner extended to lightweight checks for standalone PAK mods (filename _P.pak, file size, Unreal Pak magic number 0x5A6F12E1); EXMODZ still go through the full upstream validator
  • 9aa814e Mod detail surfaces the mod's image_url + readme_url from mods.json (was only checking mod_details.json, missing 329 mods)
  • 52f09a8 Move "You might also like" + share row to the bottom of mod-detail
  • 058ce45 Remove per-mod "Server install snippets" — server admins install many mods at once, snippets are impractical

Search

  • c773329 Harden padding so search-result text isn't flush against the card edge
  • c2bdf1d Include Nexus mods in /search/ via client-side filter

Onboarding / data sources

  • e86b55e sync-modinfos.mjs is case-insensitive on modinfo.json filename (some modders use ModInfo.json)
  • fc72f68 Onboard jgentil/IcarusMods + add modders_extras.json mechanism so locally-curated repos can be added without waiting for upstream changes
  • 6f825d6 Backfill: append bundled-only mods so locally-onboarded entries don't get overridden by the REST snapshot

Author profiles

  • 104453a (yesterday) Fix 404 when clicking the author of a Nexus mod — src/_data/authors.js now reads both mods.json and nexus_mods.json, profile pages render Nexus mods as cards that link out to nexusmods.com. 52 previously-404 author URLs now return 200, leaderboard auto-includes Nexus modders too.

Security / CodeQL

  • 495eb7e Fix CodeQL XSS alerts (js/xss + js/xss-through-dom) on share.js — rebuild QR overlay with the DOM API instead of innerHTML interpolation

QC + housekeeping

  • 5024486 Sitemap was missing 124 routable pages (/search/, /stats/, /leaderboard/, /status/, /api/... + every tag/week page); now complete
  • 9eacaac 5372e88 Health-check + Nexus catalog refreshed
  • c447ecd Hazer's PNGs flagged for baked transparency-checker (10/24 PNGs); upstream issue opened (Hazer-Bazer/Icarus-Mods#2)

Issues opened upstream as part of this work

These are friendly onboarding/cleanup issues opened on modders' own repos to nudge them toward catalog-compatible structure:


Post-merge action checklist (you, Donovan)

Without these, the site won't fully work. They're listed in roughly the order they need to happen.

  1. Enable GitHub Pages. Settings → Pages → Source = GitHub Actions. The first push to main after merge triggers .github/workflows/deploy.yml, which builds with Eleventy and publishes _site/.

  2. Set NEXUS_API_KEY repo secret (optional). Settings → Secrets and variables → Actions → New repository secret. Without it, Nexus mods are still served from the bundled JSON (133 mods, last refreshed locally). With it, .github/workflows/sync-nexus.yml runs daily and refreshes from the live Nexus API.

  3. Install Giscus app on this repo (https://github.com/apps/giscus → Only select repositories → tick project_daedalus).

  4. Enable Discussions (Settings → Features → Discussions). Create the General and Ideas categories if they don't exist.

  5. Generate Giscus IDs at https://giscus.app — pick this repo, the General category for mod-detail comments, and the Ideas category for the Mod Requests board. Copy the four IDs (repo-id once, category-id once each for General and Ideas).

  6. Replace placeholders. In src/mods/mod-detail.njk and src/requests.njk, replace each TODO_AFTER_GISCUS_INSTALL with the real IDs. There are exactly 4 of them, all marked with <!-- TODO --> HTML comments above each <script>.

  7. Custom-domain cutover for projectdaedalus.app. Do this after Pages is green on donovanmods.github.io/project_daedalus/. Steps in order:

    a. Verify the domain on the DonovanMods org (recommended — prevents takeover if the repo is ever deleted, billing changes, or Pages is disabled while DNS still points at GitHub):

    • GitHub: org Settings → Pages → Add a domain → enter projectdaedalus.app. (This is at the org level, not repo level — repo Pages settings don't have this.)
    • GitHub will display a TXT record name + value. The name will be _github-pages-challenge-DonovanMods (the value rotates per attempt — copy it from the GitHub UI).
    • In Cloudflare DNS, add a TXT record:
      • Name: _github-pages-challenge-DonovanMods
      • Value: (from GitHub)
      • Proxy: DNS only (grey cloud) — Cloudflare's proxy can mask TXT records during verification
    • Wait 1–10 min, then dig _github-pages-challenge-DonovanMods.projectdaedalus.app +short TXT to confirm propagation.
    • Back in GitHub, click Verify.
    • Leave the TXT record in Cloudflare permanently — removing it un-verifies the domain.

    b. Add the CNAME file to the repo root containing exactly projectdaedalus.app (no protocol, no trailing slash, single line). This survives across deploys; without it the custom domain gets dropped on the next Pages publish. Easiest: Settings → Pages → Custom domain → enter projectdaedalus.app → Save — that auto-creates the file on main.

    c. Flip Cloudflare DNS to GitHub Pages. Replace the existing A/CNAME records for projectdaedalus.app with:

    • A projectdaedalus.app 185.199.108.153
    • A projectdaedalus.app 185.199.109.153
    • A projectdaedalus.app 185.199.110.153
    • A projectdaedalus.app 185.199.111.153
    • CNAME www projectdaedalus.app (if you want www → apex)
    • Proxy: DNS only initially (grey cloud) — flip to proxied (orange cloud) only after HTTPS is enforced and the cert is issued. Cloudflare proxy with "Full (strict)" SSL works fine on top of Pages once both sides are happy.

    d. Wait for the certificate. GitHub auto-issues a Let's Encrypt cert for the apex domain via the Pages settings. Settings → Pages → "DNS check successful" → tick Enforce HTTPS. Usually 5–15 min, sometimes longer if DNS is still propagating.

    e. Sanity-check. curl -sI https://projectdaedalus.app/ | head -1 should return HTTP/2 200, and curl -sI http://projectdaedalus.app/ should redirect to https://.

  8. Confirm Firestore public-read rules. The site queries mods, tools, nexus_mods, info_content directly via Firestore REST. Existing rules already allow this; no change needed unless you've tightened them.


What's live the moment Pages deploys

Pages and routes

URL Source What it is
/ src/index.njk Mods listing — search, author/source/week/sort filters, 25-page pagination, status badge
/home/ src/home.njk Production-style landing (hero, 3 feature cards, Discord CTA)
/tools.html src/tools.njk Community modding tools, live from Firestore
/info.html src/info.njk Discord, Mod Requests, IMM Setup PDF, GPortal Install PDF — all editable in Firestore via info_content collection
/requests.html src/requests.njk Mod Requests board (Giscus on Ideas category, 👍 = upvote)
/guides/IMM_Setup_Guide.pdf public/assets/guides/ Bundled PDF, ~552 KB
/guides/GPortal_Mod_Install_Guide.pdf public/assets/guides/ Bundled PDF, ~996 KB
/mods/<author-slug>/<mod-slug>/ src/mods/mod-detail.njk (paginated) 491 pre-rendered mod detail pages, one per curated mod

Mods listing UI

  • Search input, 400 ms debounce, matches name/author/description/compatibility
  • Author filter with all 47 distinct authors in true alphabetical order (case-insensitive localeCompare), refreshes when the author set changes
  • Source filter (Curated / Nexus / All); curated wins on name+author duplicates
  • Week filter (Latest w220+ / Recent w200–219 / Older < w200 / Any) — backed by 100 % week coverage
  • Sort order (Name A–Z / Name Z–A / Newest first / Oldest first); newest/oldest sort by derived game week
  • All four dropdowns use appearance-none + a custom inline-SVG chevron so the rounded rounded-lg corner stays clean instead of being clipped by the browser-native arrow
  • NEXUS badge + "View on Nexus ↗" link on Nexus rows
  • 25-page pagination (20/page), « Prev | 1 | 2 | … | last | Next », "Showing X to Y of N mods" counter, deep-linkable via #page=N
  • Floating back-to-top button after 400 px of scroll
  • Theme toggle (moon/sun emoji), persisted in localStorage, defaults to OS preference
  • Real Daedalus logo, topo backgrounds, Inter font, icarus-500 gold palette
  • Status badge in the lower-right: ● LIVE Firestore (REST), ◐ LIVE + bundled (empty collection), or ○ Bundled snapshot

Mod detail page (per mod, pre-rendered for all 491)

  • File-type badges (exmodz = gold, pak = green, others = slate)
  • One DOWNLOAD <TYPE> button per file type
  • Author + version on a flex row
  • EXMODZ install note for mods that ship as EXMOD/EXMODZ
  • Compatibility pill (game week)
  • Image floats right inside the prose at md: and up
  • "Other mods by <author>" grid (up to 6 cards)
  • Prev / Back to List / Next navigation, pre-computed at build time
  • Live README rendering — JS pulls the mod's readmeURL from Firestore on page load, fetches markdown, renders via marked@13. GFM tables, code blocks, shields.io badges, links all style correctly against the dark theme.
  • Analytics for Mod Authors panel (collapsible):
    • File Types — coloured badges from the mod's files map
    • Mod Agefirst commit on the mod's file (not the Firestore document timestamp), via the GitHub Commits API
    • Freshnessmost recent commit on the same file. Coloured Fresh / Recent / Aging / Stale label
    • Your Activity — views + downloads tracked in localStorage, per browser
    • Compatibility + EXMOD-format note
    • Author Stats — total mods, file-type breakdown, most-recently-updated mod by the same author (clickable)
    • GitHub Stats card — lazy-loads on panel open: stars, forks, open issues, since last push, license. Cached per repo for 1 hour.
    • Mod Status — All Clear / errors / warnings
  • Anonymous mod ratings — 5-star widget. Stable per-browser fingerprint UUID prevents ballot-stuffing. Without Firestore the rating is localStorage-only ("visible only to you"); with Firestore configured, ratings aggregate live across all visitors via onSnapshot.
  • Comments via GitHub login (Giscus) — per-mod thread mapped via mod-{modId} term, on the General category. Preconnect + defer in the shared <head> for faster first-click latency.

Data flow

production Firestore (projectdaedalus-fb09f)
                ↓
                ├── meta/repos          → 47 modder GitHub repo URLs
                ├── mods                → ~491 mod docs
                ├── tools               → 4 tool docs
                ├── info_content        → info-page cards
                └── nexus_mods          → (currently empty on prod; populated from bundled JSON)
                ↓
   Browser fetches via Firestore REST API (public-read, no apiKey, no auth)
                ↓
       Static site renders, polls every 60 s for fresh data

Three-mode loader (public/assets/firebase-loader.js):

  1. Firebase Web SDK with onSnapshot — sub-second push updates (when FIREBASE_CONFIG is set)
  2. Firestore REST API — public-read collections, 60 s polling (default)
  3. Bundled JSON in public/data/ — offline fallback

Plus an empty-collection fallback: if a REST poll returns 0 documents on a collection that has a bundled fallback (e.g. nexus_mods before the live Firestore collection is populated), the loader uses the bundled JSON. Polling continues, so the moment the live collection fills, the listing automatically swaps over.

Bundled data shipped with this PR

File Records Purpose
public/data/mods.json 491 Every curated mod, every detail page is built from this
public/data/nexus_mods.json 133 All Icarus mods on Nexus (bootstrap-walked IDs 1–300)
public/data/tools.json 4 Community tools
public/data/modders.json 47 Registry of modder feed URLs (mirrored from production's meta/repos)
public/data/discovered-candidates.json 0 Output of the discovery workflow; refreshed weekly

Compatibility coverage: 491/491. The hourly sync derives the game week from each mod's latest GitHub commit when the modder didn't fill in compatibility in their modinfo.json. The URL parser handles /raw/, /blob/, raw.githubusercontent.com, and releases/download/ URLs, decodes percent-encoded paths, and passes &sha=<branch> for non-default branches.


Workflows

File Cadence Purpose
.github/workflows/deploy.yml on push to main Build with Eleventy and deploy to GitHub Pages
.github/workflows/sync-mods.yml hourly + manual Pull production's meta/repos, aggregate every modder's modinfo.json/toolinfo.json (across main/master/EXMODZ/Icarus branches), commit mods.json + tools.json if changed
.github/workflows/discover-modders.yml weekly + manual Search GitHub for Icarus mod repos not in production's registry, write public/data/discovered-candidates.json, open a verified-commit PR titled "Auto: new candidate Icarus mod repos discovered" if any new candidates turned up
.github/workflows/sync-nexus.yml daily + manual Refresh public/data/nexus_mods.json from the Nexus API. Skipped if NEXUS_API_KEY secret isn't set.

The discovery workflow uses peter-evans/create-pull-request@v8 with sign-commits: true, so the bot's PR commit is GitHub-API-signed and shows the green Verified badge. Auto-PRs only fire when the candidate set actually changes — the JSON file is deterministic across runs.


What's NOT in this PR (intentional gaps)

  • Real Giscus IDs — placeholdered as TODO_AFTER_GISCUS_INSTALL since the IDs are repo-specific and have to be regenerated after you install Giscus on this repo. Both occurrences are flagged with HTML <!-- TODO --> comments.
  • NEXUS_API_KEY secret — must be set if you want live Nexus refreshes. Until set, the daily workflow no-ops gracefully and the site uses the bundled snapshot.
  • CNAME file for projectdaedalus.app — adding the custom domain via Settings → Pages auto-creates it.
  • Discord webhook for new-mod alerts — was the focus of the closed PR Add JSON API endpoint for Discord mod notifications #115. Not ported in this rebuild; can be added as a follow-up notify-discord.yml workflow that diffs mods.json between commits.
  • i18n / multi-language — was the focus of the closed PR Add i18n infrastructure with English-only (ready for validated translations) #113. The new templates are English-only; an i18n pass with t() helpers across the new templates is a follow-up.

Closed obsolete PRs

All 8 of my previously open PRs against this repo are closed with a comment pointing here:

PR Title Status
#111 Add manual gem update workflow for GitHub Actions Obsolete (Rails-only)
#112 Restyle mod detail page with gold theme and navigation Already in this rebuild
#113 Add i18n infrastructure with English-only Follow-up (templates need translating)
#114 Update CLAUDE.md for current project state Obsolete (file removed)
#115 Add JSON API endpoint for Discord mod notifications Follow-up (notify-discord.yml)
#116 Fix mods page button colors and table container styling Already in this rebuild
#117 Upgrade to Rails 8.0 with Solid Cache and Solid Queue Obsolete (no Rails)
#119 Add Nexus Mods API integration Already in this rebuild (133 mods bundled)

Tech stack

  • Eleventy 3 — static site generator (per-page templates, build-time pagination of every mod detail page)
  • Tailwind CSS via the CDN script (no build step)
  • marked v13 for live README rendering
  • Firestore REST API for live data (no Firebase SDK, no apiKey)
  • Plain ES modules everywhere else
  • Giscus for comments + Mod Requests
  • GitHub Pages + Actions
  • Node 20+ required (engines field in package.json)

Verifying locally before merging

git fetch origin pull/121/head:feat/agentkush
git checkout feat/agentkush
npm install
npm run serve   # http://localhost:8080

npm run build writes _site/ — that's exactly what deploy.yml publishes to Pages.


What changed from the previous Rails version

Rails (previous) Live site (this branch)
Hosting cost Container host $0, GitHub Pages
Server maintenance Yes None
Mod data refresh Cron on Donovan's local machine GitHub Actions cron, hourly
Mod data freshness in browser up to 5 min Rails cache up to 60 s Firestore polling (or sub-second with Web SDK)
Search Server-side via Turbo Frame Client-side over fetched JSON
Pagination Server-rendered per page Client-side over the same fetched array
Anonymous mod ratings Server-handled Browser writes directly, security rules enforce
Comments None on production GitHub Discussions via Giscus
Mod Requests External Canny.io GitHub Discussions Ideas category
Mod Age / Freshness Static field Live from GitHub commit history
Auto-discovery of new modders None Weekly workflow opens a PR with candidates
Nexus integration PR #119 (this rebuild lands it) Live, 133 mods bundled

AgentKush added 6 commits May 7, 2026 21:14
… site)

Replaces the entire project_daedalus Rails 7.1 + Firestore application with the static-site rebuild that's been incubated at AgentKush/daedalus-static-poc, rebranded as the live Project Daedalus site (no longer a 'POC').

## What's in this commit

- 172 Rails files deleted: app/, config/, db/, lib/, spec/, Gemfile, Procfile, Dockerfile, the lot.
- 52 static-site files added: Eleventy 3 templates (src/), client assets (public/), GitHub Actions sync + discovery + deploy workflows (.github/workflows/), README + LICENSE + CONTRIBUTING + SECURITY + CODE_OF_CONDUCT, package.json + lockfile.

## Functional surface (parity with Rails app + extras)

- Mods listing: search, author/source/week/sort filters, 25-page pagination, custom-chevron dropdowns, theme toggle, mobile-aware layout.
- 491 curated mods + 133 Nexus mods bundled. Compatibility 100% (game-week derived from git commit history when blank).
- Per-mod detail page (pre-rendered for all 491): file-type badges, download buttons, live README rendering via marked, ratings widget, analytics panel, GitHub stats card, comments via Giscus.
- /home/ landing page, /tools.html, /info.html, /requests.html (Mod Requests via Giscus Ideas), /guides/* (PDFs).
- Hourly sync-mods workflow aggregates every modder's modinfo.json + toolinfo.json into bundled JSON.
- Weekly discover-modders workflow auto-PRs new candidate Icarus mod repos.

## Data flow

Browser → Firestore REST API (projectdaedalus-fb09f, public-read) for live data, with bundled JSON as offline fallback. No application server needed.

## Post-merge actions Donovan needs to take

1. **Enable GitHub Pages** on this repo: Settings → Pages → Source = GitHub Actions.
2. **Install Giscus** on this repo (https://github.com/apps/giscus → Only select repositories → tick project_daedalus). Enable Discussions in repo Settings → Features.
3. **Generate giscus IDs** at https://giscus.app for the General + Ideas categories, replace the two `TODO_AFTER_GISCUS_INSTALL` placeholders in `src/mods/mod-detail.njk` and `src/requests.njk`.
4. **Point projectdaedalus.app DNS** at `donovanmods.github.io` (or however the custom domain is currently routed) once the Pages deploy is green.

## Closed obsolete PRs

All 8 of my previously open Rails PRs (DonovanMods#111, DonovanMods#112, DonovanMods#113, DonovanMods#114, DonovanMods#115, DonovanMods#116, DonovanMods#117, DonovanMods#119) have been closed with a pointer to this consolidated PR. The functionality each one was adding is either already in this static rebuild or noted in the porting list inside the PR thread.
Firestore is authoritative when populated, but for fields the modder left blank (e.g. compatibility on the Coracks mods), the listing rendered '—' even though the hourly sync had derived the value into the bundled JSON. The loader was picking REST and never merging.

Fix: backfill missing/empty fields onto live data by (slug(author)+name) match against the bundled JSON. Firestore wins where it has values; bundled fills the gaps. New status-badge state '● LIVE + backfilled'.
Previous backfill commit changed the loader's status.source from 'rest'/'websdk' to 'rest+backfill'/'websdk+backfill' when it merges bundled JSON onto live data. mod-analytics-live.js and mod-readme-live.js both early-returned on anything that wasn't exactly 'rest' or 'websdk', so the analytics panel ('Mod Age', 'Freshness') and the live README fetch silently bailed out — the placeholders never got replaced.

Fix: gate on status.live === true instead of matching exact source strings. Covers rest, rest+backfill, websdk, websdk+backfill; still skips 'bundled'/'rest+bundled'/'websdk+bundled' which have no Firestore timestamps to read.
The info page subscribed to info_content + attached the status badge, but production's Firestore info_content collection is empty (the dynamic info-page work that would populate it was PR DonovanMods#104, closed). So every load showed an alarming orange '◐ LIVE + bundled (empty collection)' even though the page rendered correctly from the bundled JSON.

The cards are bundled-by-design until/unless Donovan populates info_content live; the badge added noise without information. Drop it. subscribe() stays so the page automatically goes live the moment the Firestore collection has docs. Mods listing + tools pages keep their badges — those genuinely run on live data.
Five new feature surfaces enabled by the static-site architecture:

1. /authors/<slug>/ — paginated Eleventy template, one page per distinct author, listing their mods with file-type breakdowns. 'By <author>' on the mod-detail page and the listing's author column both link here.

2. /search/ — Pagefind full-text search indexing every mod-detail page. Build script runs `pagefind --site _site --output-subdir pagefind` after 11ty so the index ships with the deploy.

3. /feed.xml + /sitemap.xml + /robots.txt — Atom feed of recent mods, complete sitemap covering 491 mod pages + ~47 author pages + top-level routes, robots.txt allowing all crawl and pointing at the sitemap.

4. /api/v1/{mods,tools,nexus_mods,info_content}.json — stable static JSON URLs for external consumers. /api/ index page documents the endpoints and freshness model.

5. .github/workflows/notify-discord.yml — diffs public/data/mods.json after every sync commit and posts a Discord embed for each new or version-bumped mod. Skipped silently if DISCORD_WEBHOOK_URL secret isn't set.
Search page: rewrote the Pagefind theming using its CSS custom properties (--pagefind-ui-primary, --pagefind-ui-text, etc.) plus targeted overrides for elements without variables. Result-titles are now icarus-500 gold and clearly clickable; descriptions use proper contrast in both light and dark modes; placeholder text is slate-400 (readable on both backgrounds); cards have rounded borders that hover to gold instead of white-line separators. Highlight marks tinted gold.

Listing: pre-warm both bundled JSONs at app init via Promise.all, so state.mods and state.nexusMods are populated before the first paint. Previously a hard refresh could land the listing with curated mods rendered but nexus_mods still empty (until the user touched the source filter to force a re-render). Subscribe callbacks still overlay live Firestore data once it arrives.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant