AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Projects
  3. Karma Yoga

Karma Yoga

December 1, 20255 min read
View Project
Next JsTypescriptTailwind CSSPrismic
1 / 3

Overview

Karma Yoga is the marketing website for Karma Yoga Studio, an Icelandic yoga studio at karmajogastudio.is. The site presents the studio's classes (námskeið), books (bækur), news (fréttir), and general pages (about, contact) in Icelandic. It was built by VISKA-IO as a client project, with content managed by non-technical editors through Prismic.

The core problem it solves is editorial independence: the studio team needs to publish and reorder course offerings, books, news posts, and page sections frequently without involving developers or redeploying the site. Prismic's Slice Machine model lets editors compose pages from reusable "slices" (hero, text-with-image, video, review, etc.), while the code stays a static Next.js app that fetches from the Prismic Delivery API and revalidates on content changes.

The primary users are prospective students and visitors in Iceland browsing the schedule and offerings, and secondarily the studio's content editors who assemble pages in the Prismic dashboard. The site also captures enquiries through a validated contact form delivered via SendGrid.

Tech Stack & Rationale

Layer

Technology

Why

Framework

Next.js 14 (App Router)

Server components, static generation, and catch-all Prismic routing

Language

TypeScript

Type safety across Prismic types and slice props

Styling

Tailwind CSS 3

Utility-first styling shared across all slices

CMS

Prismic + Slice Machine

Headless, slice-based content with editor-friendly UI

Prismic client

@prismicio/client / next / react

Delivery API queries, auto-previews, and SliceZone rendering

Forms

Formik + Yup

Validation for the contact form

Email

SendGrid (@sendgrid/mail)

Contact-form delivery via an API route

SEO

next-sitemap + schema-dts

Sitemap generation and JSON-LD structured data

Media

react-player, react-youtube, react-photo-album

Video and photo-gallery slices

Architecture

The site follows the classic Prismic + Next.js App Router integration: a single catch-all route resolves a Prismic page document by UID, then renders its slices through SliceZone. Content is fetched server-side through a cached Prismic client; the contact form is the only interactive, write path.

The flow runs: Prismic CMS (documents + webhook) → createClient (cached, tag: prismic, force-cache); [[...slug]] page.tsx (getByUID('page', uid)) → SliceZone (renders page.data.slices); Slice components (Hero, Course, News, Video…) → Contact form (Formik/Yup, server action sendEmail()) → /api/sendgrid/send (SendGrid API route).

Data flow walkthrough:

  1. A request to a URL such as /um-okkur hits the catch-all route app/(routes)/(prismic)/[[...slug]]/page.tsx, which maps the slug to a Prismic page UID (home when empty).
  2. generateMetadata() and the page body both call createClient().getByUID('page', uid). In production the client uses next: { tags: ['prismic'], cache: 'force-cache' }, so results are cached and invalidated on demand.
  3. The page renders a SliceZone with the page's data.slices, resolving each slice through slices/index.ts (which lazy-loads the slice via next/dynamic).
  4. Slices such as Course, Book, and News are themselves thin server wrappers that query related documents (courses, books, news) via core/prismic/fetcher.ts, then hand data to a client component for filtering/interaction.
  5. Detail pages (baekur/[uid], frettir/[uid], namskeid/[uid]) resolve their own documents by UID and render dedicated layouts.
  6. The contact form submits through the sendEmail server action in core/utils/sendEmail.ts, which POSTs to /api/sendgrid/send; that route forwards the message to the studio mailbox via SendGrid.
  7. The Prismic webhook calls /api/revalidate to purge the prismic cache tag when editors publish changes.

Folder Structure

karma-yoga-studio/
├── app/ # Next.js App Router (routes + API handlers)
│ ├── (routes)/(prismic)/
│ │ ├── [[...slug]]/ # Catch-all page (Prismic `page` by UID)
│ │ ├── baekur/[uid]/ # Book detail pages (bækur)
│ │ ├── frettir/[uid]/ # News detail pages (fréttir)
│ │ └── namskeid/[uid]/ # Course detail pages (námskeið)
│ ├── api/
│ │ ├── preview/route.ts # Prismic draft preview
│ │ ├── exit-preview/route.ts
│ │ ├── revalidate/route.ts # Webhook cache invalidation
│ │ └── sendgrid/send/route.ts # SendGrid contact delivery
│ ├── slice-simulator/page.tsx # Slice Machine local simulator
│ ├── layout.tsx
│ └── icon.ico
├── components/ # Shared UI
│ ├── Book/ Course/ News/ # Feature-specific components
│ └── _shared/ # Button, Icons, VimeoPopup, YoutubePopup
├── core/ # Non-route app logic
│ ├── @types/ # Prismic type aliases
│ ├── data/ # Static data (SpaceData)
│ ├── lib/ # generateMetaData, formatNumber
│ ├── prismic/ # fetcher.ts, inject.ts
│ ├── styles/ # base/components/tailwind/utilities CSS
│ └── utils/ # useResize, prismicLinkResolver, sendEmail
├── customtypes/ # Prismic custom types
│ ├── page/ book/ course/ news/ layout/
├── slices/ # Slice Machine slices (13) + index.ts
├── public/ # Static assets
├── prismicio.ts # Prismic client + preview setup
├── slicemachine.config.json
├── next.config.mjs
├── next-sitemap.config.js
├── tailwind.config.ts
├── postcss.config.mjs
└── package.json
  • app/ holds every route and API handler; the (routes)/(prismic) group isolates the Prismic-driven pages.
  • components/ contains reusable UI, split into feature folders and a _shared folder for primitives.
  • core/ is the project's own "framework" layer: Prismic fetchers, metadata generation, styles, and utilities.
  • customtypes/ defines the Prismic content models (page, book, course, news, layout) consumed by @prismicio/client.
  • slices/ holds the Slice Machine slices, each with index.tsx, model.json, and mocks.json.

Content Model

The site's "database" is Prismic. It uses five custom types and thirteen slices.

Custom types

Type

Repeatable

Key fields

page

yes

html_title, layout (link), slices (slice zone), meta_title, meta_description, meta_image

course

yes

name, image, about, more_about, date, location, price, cta (group)

book

yes

name, description, about, price, publication_year, language, cta_text/cta_link, image

news

yes

title, thumbnail, about, text, cta_link, layout (link), slices

layout

custom

slices limited to navigation_bar, children, footer

Slices — hero, text_with_image, video, review, benefit, contact, course, book, news, navigation_bar, children, footer. The page type exposes the content slices; layout is reserved for chrome (navbar/children/footer) shared across pages via the layout link field.

Impact & Results

  • In production since 2025 for Karma Yoga Studio (Iceland), letting non-technical editors publish classes, books, and news through Prismic without redeploys.
  • Client deliverable shipped by VISKA-IO as a small team.

My Contributions

My work on this project:

  • Configured the project foundation: metadata generator, next-sitemap, and ESLint/Prettier setup.
  • Established the slice workflow and built the Footer slice for desktop; created and updated the Course slice and added four slices in total.
  • Set up Tailwind theming and fonts used across the slices.
  • Built the mobile responsive layouts for the contact ("hafa samband") and classes pages.
  • Iterated on the Prismic client and content model, including image blur optimization and prismicio.ts updates.
  • Fixed the video slice layout and contributed news slice updates.

References

[1] Next.js, "App Router Documentation," nextjs.org. [Online]. Available: https://nextjs.org/docs/app [2] Prismic, "Delivery API Client (@prismicio/client)," prismic.io. [Online]. Available: https://prismic.io/docs/technical-reference/prismicio-client [3] Prismic, "Slice Machine," prismic.io. [Online]. Available: https://prismic.io/slice-machine [4] SendGrid (Twilio), "SendGrid Mail Service for Node.js," sendgrid.com. [Online]. Available: https://docs.sendgrid.com/for-developers/sending-email/mail-service [5] Tailwind CSS, "Utility-first CSS framework," tailwindcss.com. [Online]. Available: https://tailwindcss.com/

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!