AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Projects
  3. Hvammsvik Booking

Hvammsvik Booking

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

Overview

Hvammsvik Booking is the online booking system for Hvammsvik Hot Springs, a geothermal bathing destination in Iceland. Visitors reserve admission packages for specific dates and time slots, add extras such as body oils, buy gift cards, and pay online — in Icelandic or English.

The site wraps the Tegra "BC Booking Service" activity-booking API: orders, reservations, and slot availability are created and queried through that external service rather than a local database. Payments are handled by Datatrans through Next.js API routes, with the gift card, refund, and manage-booking flows completing the lifecycle after purchase.

Content editors manage all page copy, packages, and email templates in Prismic, while SWR drives client-side data fetching for slot availability and activity info.

Tech Stack & Rationale

Layer

Technology

Why

Framework

Next.js 13 (Pages Router), React 18

Server-rendered booking pages plus a pages/api route layer

Language

TypeScript

Typed booking, payment, and gift-card flows

Styling

Tailwind CSS 3.3

Shared design system from a Next.js starter

CMS

Prismic + Slice Machine

Pages, packages, products, and email content

Client data fetching

SWR 2.2

Slot availability and activity info with caching

Booking engine

Tegra "BC Booking Service" REST API

Orders, reservations, and availability (external)

Payments

Datatrans

Transaction init, status checks, and refunds

State

Redux Toolkit + redux-persist, Zustand

Booking wizard state and manage-booking store

Email

React Email + Resend

Transactional emails (confirmation, refund)

PDF

@react-pdf/renderer

Gift card PDF attachments

Media

Cloudinary

Image hosting and delivery

Feature flags

Statsig

Experimentation and analytics

Testing

Vitest + Testing Library

Unit tests for pricing and reschedule utilities

i18n

Next.js built-in i18n (en-us, is)

Icelandic/English locale routing

Architecture

A booking flows from the Tegra catalog through a Next.js API proxy into Datatrans for payment, then back into Tegra for reservation creation and later manage-booking mutations. There is no local database — state lives in the external services and is re-fetched with SWR.

The flow runs: Booking page (package · extras · date) → SWR hooks (slot availability) → Secure Fields (Datatrans payment) → /api/datatrans/ (init · status · refund) → Datatrans (transactions); Booking page (package · extras · date) → SWR hooks (slot availability) → /api/tegra/ (orders · reservations) → Tegra API (BC Booking Service).

  1. Catalog & availability — core/swrs/useResourceSlotAvailabilities.ts (and the activity-info hooks) fetch Tegra availability through the /api/booking/loadResouceSlotAvailabilities route, cached and revalidated by SWR keyed by date.
  2. Order creation — core/utils/tegra/booking/api.ts POSTs createOrder and createReservation through /api/tegra/* proxy routes, which authenticate against the Tegra endpoint using the server-side token.
  3. Payment — the checkout builds Datatrans payloads (core/utils/booking/createPaymentDatatransData.ts) and initializes a transaction via /api/datatrans/initTransactions; the Secure Fields page collects card details and Datatrans verifies the transaction.
  4. Confirmation & email — on success, /api/booking/success finalizes the booking and Resend/React Email templates send the confirmation (and thank-you or refund emails), with gift-card PDFs rendered by @react-pdf/renderer.
  5. Manage booking — authenticated visitors reschedule, upgrade, or refund through /api/manage-booking/* routes, with Datatrans refunds gated by a JWT cookie verified in middleware.ts.

Folder Structure

hvammsvik-booking/
├── pages/
│ ├── booking/ # booking, securefields-payment, success, declined
│ ├── giftcard/ # purchase, payment, success, declined
│ ├── manage-booking/ # modify, reschedule, upgrade, refund
│ ├── admin/ # login, refund (staff-only)
│ └── api/ # tegra, datatrans, booking, giftcard, email, manage-booking, admin-auth
├── components/ # _layouts, _shared (EmailTemplate, Icons), components/*
├── core/
│ ├── cloud/ # datatrans.ts, hvammsvik.ts, tegra.ts (Axios wrappers)
│ ├── fetchers/ # slot availability, activity info, modify/refund/reschedule
│ ├── swrs/ # useResourceSlotAvailabilities, useServerDateTime, …
│ ├── redux/ # auth + booking slices (with redux-persist)
│ ├── stores/ # manage-booking Zustand store
│ ├── utils/ # booking, datatrans, email, giftcard, manage-booking, tegra
│ ├── prismic/ # client + query utilities
│ └── @types/ # auth, booking, datatrans, email, giftcard, payment
├── slices/ # Hero, GiftCardList, ManageBooking, Faq, …
├── customtypes/ # booking_page, package, product, giftCard, manage_booking, …
├── __tests__/ # Vitest unit tests for pricing/reschedule utils
├── middleware.ts · prismicio.ts · next.config.js · tailwind.config.js
└── api_documentation.json # Postman collection for the Tegra BC Booking Service

Content Model

Prismic holds the booking content and email copy; order and payment state stays in Tegra and Datatrans. Key custom types:

Custom type

Kind

Purpose

booking_page

Singleton

The main booking experience — steps, packages, and copy

booking_step

Repeatable

Individual steps in the booking flow

package

Repeatable

Admission packages and their contents

product

Repeatable

Extras and add-on products

section

Repeatable

Reusable page sections

giftCard

Singleton

Gift card purchase page content

manage_booking

Singleton

Manage-booking landing and instruction copy

refund_and_reschedule

Singleton

Refund/reschedule policy content

fully_booked_dates

Singleton

Closed/sold-out date overrides

book_with_transfer

Repeatable

Bookings that include a transfer option

email_content / thank_you_email / pdf_content

Singleton

Transactional email and gift-card PDF templates

The slice library includes Hero, GiftCardList, ManageBooking, ManageBookingHero, Faq, Accommodation, and TermsAndConditions slices.

Impact & Results

  • In production for Hvammsvik Hot Springs (Iceland), taking paid reservations and gift-card purchases in Icelandic and English.
  • Integrates the Tegra BC Booking Service for availability and Datatrans for payments.

My Contributions

Contributed to the Hvammsvik booking platform as part of the VISKA team:

  • I implemented multi-currency support across the booking flow — currency selector with flags, price conversion on the booking page, checkout summary, and success page.
  • I added Datatrans transaction verification and the currency field on the Prismic package/product types.
  • I rebuilt the booking calendar and time-slot availability UI (MonthCalendar, slot availabilities via SWR).
  • I implemented promo-code and gift-card validation utilities.
  • I contributed to the manage-booking flow (reschedule, upgrade, refund) and fixed timezone-related date formatting issues.
  • I added Icelandic/English translations and currency formatting across the booking pages.
  • I wrote Vitest unit tests for the pricing, reschedule, and upgrade calculation utilities.

References

[1] Hvammsvik, "Hvammsvik Hot Springs," hvammsvik.is. [Online]. Available: https://hvammsvik.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] Datatrans, "Datatrans API Documentation," docs.datatrans.ch. [Online]. Available: https://docs.datatrans.ch

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!