AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Projects
  3. Subway Iceland

Subway Iceland

February 1, 20244 min read
View Project
Next JsTypescriptTailwind CSSSWRPrismic
1 / 3

Overview

Subway Iceland is the customer-facing ordering and marketing website for the Icelandic Subway franchise. The site lets visitors browse the sandwich menu, customise each sandwich step by step, order party platters ("Veisluplattar"), check the nutrition table, schedule a pre-order for a future pickup time, and locate branches on a Mapbox map.

Like the other VISKA customer sites, this is a marketing/ordering shell: Prismic owns the marketing content and the menu, while the product catalog, pricing, cart, and checkout come from the shared Upsell platform through @upsell/kit and the public-api.upsell.is/v2 API. There is no local database — Prismic is the content source and SWR (via the kit) handles client-side data fetching. The site is Icelandic-only (single locale) and deployed to Cloudflare Workers.

Tech Stack & Rationale

Layer

Technology

Why

Framework

Next.js 14 (App Router), React 18

Server-first rendering with route groups ((main), (user), (guest), (prismic))

Language

TypeScript

Strict typing across slices, kit types, and API responses

Styling

Tailwind CSS 3.4

Rapid, consistent brand styling

CMS

Prismic + Slice Machine

Editors manage pages, layout, store data, and slices without code changes

Client data fetching

SWR 2.2 (via @upsell/kit)

Revalidation and caching for cart, checkout, and client state

Business logic

@upsell/kit + public-api.upsell.is/v2 (Axios)

Shared cart, checkout, and Apple Pay logic with a MobileApp-authenticated store ID

Maps

Mapbox GL + react-map-gl

Store locator and pickup-map checkout step

Forms & email

Formik + Yup, SendGrid

Contact and order-related email

Animation

GSAP, Slick, Framer Motion, Lottie

Hero motion, carousels, running-text marquee

Monitoring

Sentry

Error tracking in production

Hosting

Cloudflare Workers via OpenNext (migrated from Vercel)

Edge deployment of the Next.js standalone build

Architecture

A request is served at the Cloudflare edge, flows through server-rendered pages, then hands off to SWR-backed client components that talk to the Upsell API. Prismic content is fetched server-side with tag-based caching and preview support.

The flow runs: Browser request (/menu) → Cloudflare edge (OpenNext worker) → Server Components (RSC + generateMetadata) → SWR hooks (client revalidation) → public-api (upsell.is/v2) → SendGrid (order email); Browser request (/menu) → Cloudflare edge (OpenNext worker) → Prismic client (tag cache + preview) → @upsell/kit (cart · checkout).

  1. Edge serving — the standalone Next.js build runs as a Cloudflare Worker through OpenNext; the root app/layout.tsx wraps the whole site and the (prismic) group resolves CMS pages from the catch-all [[...slug]] route.
  2. Server rendering — (main) pages (menu, store, store-list, upsell) are React Server Components that fetch Prismic pages documents (with their linked layouts document) through a tag-cached client, then render the slice zone.
  3. Client interactivity — the sandwich customizer, party-platter builder, and cart hydrate into client components that read the product catalog through @upsell/kit, with SWR managing revalidation and optimistic cart state.
  4. Scheduled orders — a pre-order flow (lib/checkPreOrder.ts, scheduling contexts, and branch gating in constants/store.ts) lets customers pick a future pickup slot and restrict branches that only accept scheduled orders.
  5. Checkout — the (user) group renders the checkout funnel (pickup, pickup-map, summary, verification, success); payment goes through the Upsell API with Apple Pay via useApplePay and OTP verification via react18-input-otp.

Folder Structure

customers/subway-web/
├── app/(routes)/
│ ├── (main)/ # menu · store · store-list · upsell
│ │ ├── (customization)/ # products/[productID], deals/[dealID]
│ │ ├── (guest)/login/
│ │ └── (user)/checkout/ # pickup · pickup-map · summary · verification · success
│ │ └── profile/order/[id]
│ ├── (prismic)/[[...slug]]/ # CMS-driven pages
│ └── layout.tsx
├── components/ # auth, cart, checkout, deal, input, map, menu, product, profile…
├── contexts/ # DealContext, CustomizationStepContext, layout, meta
├── slices/ # 16 slices (Hero, MenuListMobile, NutritionTable, StoreBanner, …)
├── customtypes/ # app_pages, layouts, pages, store_data, top_banner, variation_setup
├── constants/ # checkout, customization, deals, extra, map, products, store, upsell
├── lib/ # api.ts, deals.ts, checkPreOrder.ts, locationSorting.ts, sendEmail.ts, hooks/
├── app/layout.tsx · prismicio.ts
└── next.config.js · wrangler.toml · open-next.config.ts

Content Model

Prismic is the single content source. Six 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 (meta_title, meta_description, meta_image, meta_keywords)

app_pages

Repeatable

App-specific pages with an empty slice zone and SEO metadata

layouts

Repeatable

Site chrome composed of navigation_bar, children, and footer slices; linked from each pages document

store_data

Singleton

Store locator config — initial_coordinate, zoom, and a branches Group (branch_id, coordinate, gmap)

variation_setup

Singleton

Variation attributes — an attributes Group (attribute_id, attribute_name, image, calories)

top_banner

Singleton

An optional promo bar (paragraph, button_text, href, active)

The pages slice zone exposes 13 slices, notably hero, text_with_image_hero, deal_section, featured_product, menu_list_mobile, nutrition_table, store_banner, running_text, content_with_tab, and the account slices order_history and order_status_popup.

Impact & Results

  • In production for the Subway franchise in Iceland — step-by-step sandwich customization, party platters, and scheduled pre-orders.
  • One of 16+ customer sites served by the shared VISKA monorepo platform.

My Contributions

Worked on the Subway Iceland site as part of the VISKA monorepo team:

  • Built the scheduled pre-order flow: schedule list modal, scheduling template categories, pickup-hour limits by date, pre-order tags, the Borgarnes branch's scheduled-order-only rule, empty-schedule handling, and the post-checkout redirect.
  • Built the party platter ("Veisluplattar") ordering flow with branch gating, labels, and customization.
  • Worked on the store locator and map: branch search, map markers, store-map navigation, branch cards, and the Akureyri branch.
  • Added the contact form, the ingredient page and its slice, card animations, the extra-confirmation modal, and gift-card handling.
  • Fixed navbar, cart, and UX issues (profile name, menu icon, cart z-index, hidden cart) and improved translations.

References

[1] Subway Iceland, "Subway — Iceland," subway.is, 2024. [Online]. Available: https://subway.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] OpenNext, "OpenNext for Cloudflare," opennext.js.org. [Online]. Available: https://opennext.js.org/cloudflare

[5] Vercel, "SWR — React Hooks for Data Fetching," swr.vercel.app. [Online]. Available: https://swr.vercel.app

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!