Placeholder-heavy, slow, and off-system across ten surfaces
The rewrite is close on the surfaces it has been reviewed against, but a pass across ten routes turned up the same failure in different clothes: the page renders its frame first and its content later, so the reader watches placeholders hold space that the original Bumiscan fills on arrival. Where it is not slow, it is off-system, and where it is neither, it points at a host that does not resolve or charts a window it never names.
None of these are cosmetic. Each is a thing a visitor can see without trying, listed in the order they were found.
1. The six-month toggle on /observations shows a month
The 6 months toggle on the observations header renders the same window as
the month view: the chart reads Aug 21 → Sep 21 and the newest upload is
Sep 20. Six months of an upload history that started earlier should reach
back to March, and the axis should say so.
This was ported from the original app, so the defect came with the copy rather than being introduced here. That makes it worth checking the source's own toggle logic before fixing the port: if production has the same bug, this becomes a shared fix rather than a one-sided one.

The 6 months toggle is selected, and the chart below it covers one month.
2. The "With audio" filter is not highlighted, and returns nothing
Toggled on, With audio does not take the selected state the way All and
With photos do. This is worst in light mode, where the pressed and resting
fills are close enough that the control reads as inert, and it holds on every
page that carries the filter, not just observations.
It also yields no results, and the sentence the surface reaches for is wrong
about why. The counter settles at 0 of 0 and the region says "This
collection has no records yet", which is the empty-collection sentence. The
collection holds 34,404 records and is not empty.
What is empty is the audio. The indexer carries no occurrence with audio evidence at all, and none with a spectrogram either, against 8,192 that carry a photograph. So the filter is answering its question correctly and only the wording is wrong: it should say that no observation carries audio, and it should not borrow the words for an empty collection to say so. The surface still cannot tell a filtered-to-nothing region from an empty one, which is the defect underneath both readings.
Whether the filter belongs on a surface where it can never match is a separate question, and one for the product rather than the fix. Bioacoustic minutes is a headline reading on the homepage, so a reader has every reason to expect audio here; it lives on another lexicon, and nothing on this page says so.

With audio selected: no pressed state, and a count of zero.
3. /organizations is slow to resolve, and never fully settles
The grid paints before its data does, so the first seconds are placeholders: missing handles, missing names, and grey cells where identity should be. The avatars and the banner and cover images then take minutes to appear rather than seconds.
Clicking a card has the same problem from the other end. Some cards do open their modal, but not until well after the click, as though the press was never registered. The interaction is there; the feedback is not.

The grid after load: identity glyphs standing in for avatars, and a Certified chip on every row.
4. The /organizations modal repeats itself and holds placeholders
The drawer restates the description twice: once as body prose at the top,
and again in full in the Description field of the definition list below.
The same paragraph, set at two sizes, in one dialog.
The rest of the list is unfinished. Founded and Visibility render as
unlit placeholder blocks, and Created shows the raw timestamp
2026-09-15T06:29:14.714Z rather than a date a person reads. The type mixes
without a reason: the Organization lexicon line sits in tracked caps above
a value column set in a serif, and the two do not agree.

Description prose above, description field below. Founded and Visibility never resolved; Created is a raw ISO instant.
5. Every filter on /organizations is slow to acknowledge
Switching to map view changes nothing on screen for several seconds, then draws a map that has not finished loading. The tiles arrive in patches and leave the frame half-painted. The same silence precedes every other filter: the click lands, the reader waits, and nothing tells them the click was heard.
This is the same defect as the card modal in note 3, at the level of the whole toolbar. The control has no pending state and no immediate change, so on a slow response it reads as broken.

Map view mid-load: one tile painted, the rest of the panel empty, and no pending state on the view toggle.
6. /bumicerts renders placeholder-full cards
The Bumicerts grid holds its card shape with unlit rows: the contributor and certified-site counts both render as placeholder blocks, and the certificate image is a lone ribbon glyph in an empty frame above every title.
The original app loads the same collection quickly and completely, so the data is available. That half holds. The other half does not: this port reads it too. The list query asks for contributors and locations, the schema at the boundary keeps both, the mapper counts them, and the record schema carries the counts to the card. The indexer answers with them populated. On a healthy read these cards have their numbers.
So the likelier cause is a read that was not healthy. Hyperindex serves a partial page under HTTP 400 when a single record carries a malformed blob ref, and a bad ref has poisoned this exact stream before, discarding a thousand parsed edges. That is a failure to reproduce before anything is rewritten. The mappers are not where this goes wrong, and editing them would only put a bug into a path that reads correctly.

Placeholder blocks where both counts belong, on every card.
7. /equipment: a placeholder-heavy board, an off-system button, and pills that wrap
Three defects on one page.
The table renders placeholder blocks in the Holder and Site columns, so
the two columns a reader actually scans to find an item are the two that
arrive last.
Add equipment does not follow the design system. Every other action on the
surface is a pill; this one is not, and it sits against the View audit log
link at a different weight and radius. One control out of step is enough to
make the whole toolbar look assembled rather than designed.
The status pills wrap. In storage breaks across two lines inside a
rounded-full container, so the badge becomes a tall lozenge in a column
that is otherwise one line tall. A pill that wraps is not a pill.

Add equipment to the right of the toolbar, out of step with the pill system; In storage wrapping in the status column.

The wrap at a narrow column: In storage on two lines inside a pill.
8. /bumimic breaks the no-outline rule
The other pages carry their content in translucent fills, without borders.
/bumimic draws boxes: outline containers where the rest of the surface
would use a fill and a heading rule. Set beside any neighbouring page it
reads as a different product.
9. The pills on /devices are off-system
The device pills are drawn to their own spec: a different radius, a different fill, and a different relationship to the row than the pills anywhere else. They read as pasted in, and the inconsistency is the point of the note rather than the individual values.

The device column: the pill and row treatment the note compares against the system pills.
10. Outbound links point at hosts that do not resolve
Three links are wrong, and all three are in the surfaces a visitor is most likely to click from.
data.gainforest.appandcerts.gainforest.appboth resolve, which is why these read as live links and fail only on arrival. The surfaces they point at sit ongainforest.appnow: the globe at/globe, the feed at/feed, an account at/account/<did>. A bumicert has no page of its own there, so that link goes rather than moves.- The repository link on the footer points at the wrong project.
- The indexer link carries the
/graphqlroute. It should point at the indexer host without it.
11. The hero charts on the homepage are not on one clock
The hero stage swaps one chart between readings, so a reader compares them as
though they share an axis. They do not, and there are three clocks here
rather than two. Species observations is drawn from the newest thousand
records, which at the present volume is Sep 10, 2026 → Sep 21, 2026:
eleven days under a headline of 34,404. Bioacoustic minutes and wallets
created are swept over their whole history, so the same frame covers years.
Data collectors counts from a fixed date, May 1, 2026, and says so in its own
caption but not on the axis. The window changes under the reader and only the
shape of the line says so.
Observations is the only one of the four whose window is an accident of page size, and the only one that shrinks as the collection grows: at twice the volume the same thousand records cover half the days.
The short window also flatters the reading. A cumulative line over eleven days climbs hard and then runs flat to the right edge, which reads as growth that stopped rather than a tail that was cut off.
This arrived with the port: the source app tails the newest page of
occurrences for the same chart, and the rewrite carried the query over as it
stood. The question was whether the hero wants one fixed window for every
reading or a window stated per reading. Either answer is honest, and the
product owner has taken the first: twelve months for all four readings,
stated once above the stage. The same window settles note 1, and the two
tails have to agree afterwards, since the hero reads a thousand records and
/observations reads three thousand for the same collection.

A headline of 34,404 observations, charted across eleven days, with no statement that this is the newest slice rather than the history.
12. Every chart carries an undesigned slider
Under each chart sits a browser-default input type="range" at the full
width of the panel, with a permanent line above it reading "Inspect date: 16
Sept 2026. Use arrow keys, Home or End." It is on every chart on every
surface, at all times, whether or not anyone is inspecting anything.
The control earns its place and should not simply be removed. Exact readings
are otherwise reachable only by pointer hover, and a keyboard reader needs
something focusable that walks the days; the range input gives that, carries
aria-valuetext, and drives a live region under the chart. The defect is the
dressing, not the intent. This is the one control on the surface drawn by the
user agent rather than by us: a default track and thumb tinted with the
accent, sitting beside pills and toggles that were designed. The instruction
is permanent copy for a state that only exists once focus arrives.
What is wanted is the same keyboard behaviour in the surface's own control, on the standard row height, with the instruction bound to the control rather than standing as a sentence under every chart in the app.

The inspect control as it ships: a default range input and a standing instruction, repeated under every chart.
What is common to all twelve
Four of the twelve are one defect in different clothes. Notes 3, 4, 5 and 7 are the frame rendering before the content, with no control that admits it is waiting. Fix the pending state once, at the region that owns it, and all four fall together.
Note 6 looked like the fifth and is not. Its data arrives populated and the port reads it at every layer, so the unlit counts are a symptom of a degraded read rather than a late one. It needs reproducing, not rewriting.
Three are drift from the design system: the outline containers on
/bumimic, the pills on /devices, and the slider under every chart. The
equipment button and its wrapping status pills belong to that group too, and
they are the same size of edit.
Two came over with the port, and both are about what a chart claims rather than how it looks: the six-month toggle and the hero's eleven-day window. Those are worth settling with the source before they are patched on one side only.
The last two stand alone: the audio filter, which answers correctly and words the answer wrongly, and three links that resolve to the wrong place.