← All launch reviews

Emblem

A 30-day launch review of single-shop coffee roaster. 18 findings across 6 tiers of the studio's framework.

Vertical
Single-shop coffee roaster
Shipped
2025-06
Reviewed
July 15, 2025
Tier
Six-tier review
Author
Alfonso Barreiro
Findings
18

Tier 1 of 6

Strategic

  1. S1

    Roaster credential lives eight sections deep

    Severity: MediumEffort: SFiled for later

    The hero calls Emblem a 'single-shop coffee roaster in Portland' and hands the reader a photo of the storefront. The claim that Emblem actually roasts on premises, not resells someone else's beans, only lands inside the origin story near the bottom of the page. A first-time reader who bounces before scrolling that far leaves without the differentiator.

    Above the fold the copy could apply to any coffee shop with a nice interior. The roasting is the reason the shop exists and the reason a bag of beans costs $22 instead of $14, but the site treats it as a mid-page detail.

    Fix: Move one sentence from the origin story up to the hero subhead. Something like 'We roast Wednesdays and Fridays behind the bar. Everything we serve was in a burlap sack seven days ago.' Concrete and dated. Beats 'craft roaster' by two dimensions.

  2. S2

    First-visit questions live in the footer

    Severity: MediumEffort: SRecommend

    A customer landing on a coffee shop's site is usually answering three questions in the first ten seconds: are you open right now, where are you, and can I get a table. Emblem answers question two (address in the hero), buries question one (hours in the footer), and skips question three entirely.

    Hours in the footer means the user scrolls the entire page to find out whether the shop is open at 4pm on a Tuesday. Half will not bother.

    Fix: Put current hours in the hero next to the address. If build effort allows, compute an 'Open now' or 'Closed, back at 7am' indicator from the hours table. Seating notes ('walk-ins only', 'six tables and a bench') can sit next to it. The rest of the page can then do its editorial work.

  3. S3

    Retail bag price hides inside prose

    Severity: MediumEffort: MRecommend

    The menu board shows espresso and pour-over prices cleanly. The retail bag price, which is the highest-margin item on the site, appears only inside the origin story as a passing line: 'The Yirgacheffe washed lands at $22 a bag.' No product card, no add-to-cart, no dedicated Beans section in the nav.

    Fix: Add a Beans section between the menu-board and the origin story. Three or four active offerings with roast date, weight, and price on each card. If Emblem does not ship online, say 'available at the shop' on each card. Repeat the price on the origin story so both surfaces agree.

Tier 2 of 6

UX

  1. UX3

    No secondary action for returning customers

    Severity: HighEffort: SFiled for later

    The single CTA is 'Visit us' which anchors to the address. There is no 'Call ahead' link, no 'Reserve a bag' path, no clear next action for a returning customer who already knows where the shop is. The site is a brochure with a map.

    If Emblem does not do online ordering, that is fine, but the site should say so and offer a phone number as the alternative. Currently a returning customer's only recourse is to type the phone number from the footer into their own dialer.

    Fix: Add a tel: link next to the address in the hero, labeled 'Call ahead: (503) xxx-xxxx'. If Emblem takes pre-orders for retail beans, add a 'Reserve a bag' link that opens a short form or a mailto:. Either way, one more clear action beyond 'come see us.'

  2. UX1

    Menu section is a single scroll without anchors

    Severity: MediumEffort: SFixed at ship

    The top nav has Menu, Origin, Visit, Contact. Menu scrolls to the menu-board section, which works. But the menu-board is one long list with no internal anchors. A visitor who wants to see just the pour-over prices scrolls past espresso and drip first.

    Fix: Add a horizontal tab strip at the top of the menu-board: Espresso, Pour-over, Drip, Beans. Each anchors to its sub-section. Plain text buttons, no border chrome. Tabs stay in the DOM order so keyboard users hit them in reading order.

  3. UX2

    Pour-over reads as a peer of espresso, not the specialty

    Severity: MediumEffort: MRecommend

    Espresso and pour-over sit as two side-by-side columns on desktop. Same visual weight, same type scale, no signal that one is the shop's specialty. Emblem's origin story is a specialty pour-over story; the menu treatment does not reflect that.

    On mobile the columns stack and the pour-over ends up below espresso, which reinforces the lesser-emphasis read.

    Fix: Give pour-over the wider column on desktop (two-thirds vs one-third). On mobile, pour-over first. If pour-over is the specialty, the menu should say so with layout weight, not just with an origin-story paragraph.

  4. UX4

    Mobile menu close target competes with the wordmark

    Severity: LowEffort: SFiled for later

    The mobile hamburger opens a full-screen overlay. The close button is a small terracotta × in the top-right, weighted the same as the menu items. On first tap-open, two test users tapped the wordmark in the top-left instead of the × because the wordmark reads as the more prominent target.

    Fix: Bump the close × to a 44×44 tap target with a subtle circular border so it reads as a control. The wordmark inside the overlay can drop to a smaller size or a plain color so it stops competing.

Tier 3 of 6

Visual

  1. V2

    Two accents compete in the same fold

    Severity: MediumEffort: SFixed at ship

    The site's accent is a warm terracotta (#C25E44) used on CTAs and highlighted headings. A secondary olive-green (#7A8659) shows up on the 'Roast this week' badge and the origin-story pull quote. Two accents against a warm cream ground means the eye has to decide which color signals the primary action.

    Terracotta and olive are pleasant together, and they compete for attention in the hero-plus-first-fold zone.

    Fix: Drop the olive to a neutral: warm cream one shade darker for the badge, ink-color body for the pull quote. Keep terracotta as the sole accent. If a secondary accent is genuinely needed for the roast-date system, use it only inside the Beans section, not in the hero.

  2. V3

    Container padding drifts section to section

    Severity: MediumEffort: SFiled for later

    Section padding is inconsistent: hero uses px-8, menu-board uses px-6, origin story uses px-10, visit section uses px-8. Inner max-width is also uneven (max-w-5xl in some places, max-w-6xl in others, no max at all in the origin story).

    On desktop the effect is subtle. On mobile the varying horizontal padding creates a small side-to-side wobble as the user scrolls.

    Fix: Standardize on px-6 md:px-10 outer, max-w-6xl inner, applied via a shared <Container> component or a Tailwind class group. Retrofit the four inconsistent sections. Mechanical pass, probably an afternoon.

  3. V1

    Hero h1 clamp bottoms out too small on narrow phones

    Severity: LowEffort: SRecommend

    The hero h1 uses clamp(32px, 6vw, 72px). At 375px width the 6vw arm resolves to 22.5px which is below the clamp minimum, so the clamp holds at 32px. Body copy in the same fold is 20px. The 32:20 ratio flattens the hierarchy, and on 320px screens the h1 reads more like a caption.

    Fix: Raise the clamp minimum to 40px. On 375px the h1 lands at 40px, body stays at 18–20px, ratio around 2:1 reads as a heading. Retest on 320px (SE) so the h1 still wraps to two lines instead of three.

Tier 4 of 6

Technical

  1. T1

    Hero image ships as 1.9MB JPEG, no AVIF

    Severity: HighEffort: MFiled for later

    The hero storefront image ships as a 1.9MB JPEG at 2400px wide. next/image is not in use; the image is a plain <img> tag. On a 3G-throttled test the image blocks LCP at 3.4 seconds.

    AVIF at equivalent visual quality would land near 240KB. WebP fallback near 380KB. Even without a build-time conversion pipeline, a manual sips or squoosh pass would help.

    Fix: Convert the hero and the six sub-section images to AVIF (sips -s format avif, or squoosh at quality 60). Wrap them in <picture> with AVIF/WebP/JPEG fallbacks, or migrate the site to next/image and let the framework negotiate. Set explicit width and height so layout does not shift.

  2. T2

    Per-route metadata missing on /origin and /visit

    Severity: MediumEffort: SRecommend

    The homepage has a title tag and a meta description. The /origin and /visit routes inherit the same title tag ('Emblem: coffee roaster in Portland'). Open Graph tags are set on the homepage only. A link to /origin shared in a text message previews as unbranded.

    Fix: Add per-route <title> and <meta description> to /origin and /visit. Add per-route og:image and og:description. If the hero images from each page can be reused as OG cards, do that; otherwise commission a small OG card set (1200x630).

  3. T3

    Sitemap lastmod stamps every entry with build time

    Severity: LowEffort: SRecommend

    sitemap.xml lists three URLs (/, /origin, /visit) with today's date as lastmod on every entry. That signal has almost no crawl value since the crawler cannot tell which page actually changed. Small site, and the crawl-priority signal costs nothing to send correctly.

    Fix: Generate lastmod per route from the content file's mtime, or hardcode per-page last-edited dates. For the three-route case a manual constant on each entry is fine.

Tier 5 of 6

Accessibility

  1. A11y3

    Menu-board headings marked up as styled divs

    Severity: HighEffort: SFiled for later

    The menu-board headings ('Espresso', 'Pour-over', 'Drip', 'Beans') are marked up as <div class='menu-title'>. Same for the origin story's chapter titles. A screen reader user gets one long body paragraph with no landmarks, no jump-to-section, no way to skim.

    Fix: Change the menu-board headings to <h3> under the <h2> section header. Origin-story chapter titles to <h3> or <h4> depending on nesting. The div-based markup is invisible extra styling; the heading tags carry the same visual and win the accessibility on top.

  2. A11y1

    Body text on the coffee-beans photo drops below 4.5:1

    Severity: MediumEffort: SFixed at ship

    The 'Roast this week' section overlays cream-colored body text on a dark-roasted-beans photograph. The text hits about 3.9:1 contrast in the middle third of the image where the beans lighten. WCAG AA requires 4.5:1 for body copy.

    The paragraph is legible at a glance and starts to soften under bright ambient light on a phone.

    Fix: Add a semi-opaque dark scrim (bg-black/40) between the image and the text, or move the text into a solid cream card that sits over the image with 24px of padding. Either restores contrast to about 8:1.

  3. A11y2

    Focus states rely on browser default

    Severity: LowEffort: SRecommend

    The nav links, the CTA button, and the menu-board anchors all rely on the browser default focus ring. In Safari 17 the default ring is a low-contrast blue that reads against the warm cream ground as a browser bug. Keyboard users can navigate, and the current-focus indication is inconsistent across browsers.

    Fix: Add a global :focus-visible style: 2px terracotta outline, 2px offset, radius matching the element. One line in globals.css: *:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }. Test Safari, Chrome, Firefox before ship.

Tier 6 of 6

Performance

  1. P1

    LCP element has no preload or priority hint

    Severity: HighEffort: SFiled for later

    The hero image is the LCP element on the homepage. It renders as a plain <img> tag with no preload hint and no fetchpriority. On desktop-cable the LCP measures 1.8s. On mobile-3G it measures 3.4s and is the primary contributor to a 'Needs improvement' Core Web Vitals rating.

    Fix: Add <link rel='preload' as='image' href='/hero.avif' fetchpriority='high'> to the <head>. If migrating to next/image, use the priority prop instead. Combined with the AVIF conversion in T1, mobile LCP should drop below 2.5s.

  2. P2

    Google Fonts blocks first paint on mobile

    Severity: MediumEffort: SRecommend

    Fonts load via <link rel='stylesheet'> from fonts.googleapis.com in the head. That blocks first paint by 200 to 400ms on mobile. Two families load (a serif for headings, a sans for body) and each ships two weights.

    For a site this size, self-hosted fonts with font-display: swap eliminate the render-blocking round-trip.

    Fix: Download the .woff2 files for the four faces, host them under /public/fonts/, define @font-face in globals.css with font-display: swap, and drop the Google Fonts link entirely. Same visual result, 200 to 400ms faster first paint on mobile.