Hradlestin Iceland




Overview
Hradlestin Iceland is the customer-facing ordering and marketing website for Hradlestin, an Icelandic hot-dog and grill chain. Visitors can browse the menu, order "Tuesday deals" and other promotions for scheduled lunch hours, and choose between in-house delivery and the Wolt delivery option — in Icelandic or English.
The site follows the standard VISKA customer pattern: Prismic manages all marketing content and the menu layout through a large slice library, while the product catalog, deals, cart, and checkout come from the shared Upsell platform via @upsell/kit and the public-api.upsell.is/v2 API. There is no local database; SWR handles client-side data fetching.
Tech Stack & Rationale
Layer | Technology | Why |
|---|---|---|
Framework | Next.js 14 (App Router), React 18 | Server-first rendering with locale route groups and dynamic Prismic params |
Language | TypeScript | Strict typing across slices, kit types, and API responses |
Styling | Tailwind CSS 3.4 | Brand styling with the custom OrplidPro headline font |
CMS | Prismic + Slice Machine | Content editors manage pages, layout, and 22 slices |
Client data fetching | SWR 2.2 | Revalidation for cart, deals, and delivery state |
Business logic | @upsell/kit + public-api.upsell.is/v2 (Axios) | Shared cart/checkout plus Wolt delivery validation |
Delivery | Wolt integration | Third-party delivery option with minimum-order pricing |
i18n | LinguiJS (is, en) + Crowdin | Compile-time catalogs, Icelandic-first locale redirect |
Icons | Iconify (@iconify/react) | Lightweight icon set for allergens and UI |
Animation | GSAP, Framer Motion, Swiper | Hero curve motion and product sliders |
Monitoring | Sentry | Production error tracking |
Hosting | Cloudflare Workers via OpenNext (migrated from Vercel) | Edge deployment of the Next.js build |
Architecture
A request is locale-normalized by middleware, server-rendered from Prismic content (with ISR enabled for the catch-all pages), then enriched client-side with catalog, deal, and delivery data. A feedback API route collects customer reviews via Google Sheets.
The flow runs: Browser request (/is/…) → middleware.ts (locale redirect → is) → Server Components (ISR Prismic [[...slug]]) → SWR hooks (deals · delivery state) → public-api (upsell.is/v2); Browser request (/is/…) → middleware.ts (locale redirect → is) → Prismic client (tag cache + preview) → @upsell/kit (cart · checkout) → feedback API (Google Sheets).
- Locale routing — middleware.ts redirects locale-less requests to /is/... and sets a locale header, exempting /api/ and /.well-known.
- Server rendering — (main) pages are React Server Components that fetch Prismic pages documents through a tag-cached client; the (prismic)/[[...slug]] catch-all enables ISR with dynamic params for CMS-driven pages.
- Deals & delivery — client components use SWR to load the deal of the day (Tuesday deals via useTuesdayStatus) and delivery options; the Wolt option enforces minimum-order pricing, and scheduled lunch-hour orders are validated.
- Checkout — the (clean) route group renders shipping, summary, and verification steps without site chrome, with a great-additions upselling page and discount-aware cart/order pages.
- Reviews — a /api/feedback route posts customer reviews into a Google Sheets workflow, and reviews are rendered from lib/reviews.ts.
Folder Structure
customers/hradlestin-web/
├── app/
│ ├── [locale]/
│ │ ├── (main)/
│ │ │ ├── (customization)/ # products/[productID], deals/[dealID]
│ │ │ ├── order/[orderID]/ · profile/ · store/ · login/
│ │ ├── (clean)/checkout/ # shipping · summary · verification · great-additions
│ │ └── (prismic)/[[...slug]]/ # CMS pages + slice-simulator
│ ├── api/ # preview, revalidate, feedback
│ └── sitemap.ts · robots.ts · manifest.ts
├── components/ # auth, cart, checkout, deal, menu, product, store…
├── slices/ # 22 slices (Hero, ChefList, StoreGrid, Slider, …)
├── customtypes/ # pages, layouts, top_banner
├── src/constants/ · utils/ # branch formatting, allergen icons, getTagColor
├── contexts/ · hooks/ # cart/checkout providers, useTuesdayStatus
├── lib/ # api.ts, reviews.ts, hooks/
├── locales/translations/ # en.po, is.po (Crowdin)
├── scripts/ # Google Sheets review setup
└── middleware.ts · appRouterI18n.ts · prismicio.tsContent Model
Prismic is the sole content source. Three custom types drive the site:
Custom type | Kind | Purpose |
|---|---|---|
pages | Repeatable | Marketing pages — uid, page_title, a layout link, a slice zone, and SEO metadata |
layouts | Repeatable | Site chrome composed of navbar, children, and footer slices; linked from each pages document |
top_banner | Singleton | An optional promo bar (paragraph, cta_text, cta_url, active) surfaced by useTopBanner |
The pages slice zone exposes 20 slices, including hero (with a curve variation), chef_list, store_grid, featured_cards, featured_products, slider, front_page_content, jumbotron_text, image_text, text_grid, list_item, mail_box, allergen, and a generic form.
Impact & Results
- In production for the Hradlestin hot-dog and grill chain in Iceland, including scheduled lunch-hour deals and Wolt delivery.
- One of 16+ customer sites served by the shared VISKA monorepo platform.
My Contributions
Worked on the Hradlestin site as part of the VISKA monorepo team:
- Added the Wolt delivery option on checkout, including the Wolt icon, delivery-method display, and minimum-order pricing validation.
- Implemented the Tuesday-deals feature (useTuesdayStatus) and discount UI on product cards and the customization page, fixing double-calculated discounts on large Prismic cards.
- Built the great-additions upselling page and the discount-aware cart/order pages.
- Added the Hero slice curve variation with the OrplidPro font and restored scheduled lunch-hour order-time restrictions.
- Added the customer review flow (Google Sheets setup and the /api/feedback route) and fixed product-slider reactivity to content changes.
References
[1] Hradlestin, "Hradlestin Iceland," hradlestin.is, 2025. [Online]. Available: https://hradlestin.is/is
[2] Vercel, "Next.js Documentation," nextjs.org. [Online]. Available: https://nextjs.org/docs
[3] Prismic, "Prismic Documentation," prismic.io. [Online]. Available: https://prismic.io/docs
[4] Vercel, "SWR — React Hooks for Data Fetching," swr.vercel.app. [Online]. Available: https://swr.vercel.app
[5] LinguiJS, "LinguiJS — Internationalization," lingui.dev. [Online]. Available: https://lingui.dev
Comments
Leave a Comment
You must be signed in to comment
0 Comments
No comments yet. Be the first to comment!