Skip to main content

Studio · Errors · 7 shipped

Errors.

Mistakes we shipped on this site or on client work. What fixed them. What we learnt. Every entry is real — no theatrical humility, no invented foibles. The bar for inclusion is “another practitioner could apply this to their own work.”

Paired with /changelog · /roadmap

  1. tarnshire

    Shipped a code deploy without the schema migration

    The mistake

    Tarnshire's first live booking 500'd. The deep-clean release added a `service_type` column in both the app code and a SQL migration — but the migration was never run against the production database, so the insert hit a column that didn't exist (PostgREST PGRST204).

    The fix

    Ran the pending migration in the production SQL editor and re-tested the whole booking path end to end before reopening checkout.

    The lesson

    A code deploy is not a schema deploy. Any release that adds a column, table, or constraint ships as two artefacts — the application and the database — and the database half has no CI to catch a miss. Treat the migration as a first-class deploy step, not a side effect of merging.

  2. tarnshire

    Quoted in pounds, charged in pence

    The mistake

    The booking summary displayed a price rounded to whole pounds while the Stripe charge was computed separately in pence. The two diverged by 10–40p on 7 of 48 size/frequency combinations — a customer could be charged a few pence more than the figure they agreed to.

    The fix

    Collapsed quote and charge onto a single source of truth and rounded once, at the boundary; proved penny-parity across all 48 combinations.

    The lesson

    Quote and charge must come from one source. The moment the number a customer sees and the number you bill are computed in two places, they drift — and on money, any drift is a trust and compliance problem, however small. Compute once, round once, show and charge the same value.

  3. gosmartr-studio

    Ambient video framed as "live preview" on case studies

    The mistake

    First version of the case-study browser-frame bezel embedded each project's atmospheric video reel inside a Chrome-style URL bar with the label "Live preview." The reels are background-decoration assets — close-up garden shots, abstract dashboard particles, gold-foil VFX — not the actual website.

    The fix

    Replaced the video with the case-study hero screenshot inside the same browser chrome. The bezel now represents what the live homepage actually looks like, captioned "Snapshot."

    The lesson

    Visual flair that contradicts the artefact undermines trust. If the chrome says "live preview," what's inside has to be the live thing — or the chrome has to change. Honesty is cheaper than authority.

    Fix landed in e5556bb

  4. gosmartr-studio

    Hero pacing dead-zone

    The mistake

    The first version of ScrollHero used a 200vh section with FADE_END at 0.6 — leaving roughly 80vh of empty scroll between the second scene fully landing and the next section starting. Visitors scrolled through nothing and assumed the page was broken.

    The fix

    Tightened the section to 140vh with FADE_END at 0.78 so the dead zone is ~22% of section height (~31vh) — a gentle pause rather than a void.

    The lesson

    Scroll budget is design budget. Every viewport-unit reserved for animation costs the visitor real seconds; it has to earn each one. Treat <vh> like timing in a film — precious, and never used as filler.

    Fix landed in b13b3b2

  5. gosmartr-studio

    AnimatedCounter shipped a "0" to crawlers on /pulse

    The mistake

    AnimatedCounter initialises display state to 0 and animates up on viewport entry. On /pulse — a page whose entire purpose is showcasing real numbers — the SSR HTML rendered '0' for every footprint stat. Crawlers, sharing previews, and JS-disabled visitors all saw zeroes.

    The fix

    Wrote a PulseCount progressive-enhancement wrapper: SSR renders the actual value as plain text; after mount, swaps to the animated counter. Server output and client output now both convey the truth.

    The lesson

    An animation that ships a 0 to crawlers is a regression. Default state for client-only effects should be the most informative server-renderable value, not the animation's first frame. Test with JS disabled before trusting any motion-driven UI.

    Fix landed in c36564a

  6. gosmartr-studio

    Newsletter shipped without double-opt-in

    The mistake

    Original newsletter signup wrote to the mailing list directly on form submission. Single-opt-in is GDPR-fragile (can't prove consent on dispute), spam-fragile (anyone can subscribe anyone), and engagement-fragile (cold subscribers tank deliverability for the rest of the list).

    The fix

    Added a confirmation email flow with a one-click verification link, plus a dedicated /newsletter/unsubscribe page. New entries stay in a pending state until the visitor clicks confirm.

    The lesson

    Marketing tooling is data-protection tooling. Any system that touches an identifier the user owns — email, phone, payment — needs the verification primitives before it ships, not after the first complaint.

    Fix landed in 8e5e65e

  7. gosmartr-studio

    Ghost text caused horizontal scroll on mobile

    The mistake

    Several decorative oversized 'ghost text' elements (huge background type behind hero copy) used vw-based clamp values without a maxWidth cap. On 360px-wide phones the text overflowed the viewport, triggering horizontal page scroll and making the whole site feel buggy.

    The fix

    Capped every ghost element with maxWidth + overflow-hidden on the parent; tightened vw multipliers so the text scales down faster on small viewports.

    The lesson

    Decorative type is content too — for the layout engine. Anything sized in viewport units needs a hard upper-bound, or the smallest screen will eventually find the value where your numbers break. Test at 360px before shipping.

We add to this list when something earns its place. Read the studio writings →