GoSmartR
GoSmartR
Studio · Errors · 5 shipped
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
gosmartr-studio
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 ↗
gosmartr-studio
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 ↗
gosmartr-studio
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 ↗
gosmartr-studio
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 ↗
gosmartr-studio
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 →