AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Projects
  3. Tvist

Tvist

August 1, 20254 min read
View Project
Next JsTypescriptTailwind CSSPrismic
1 / 3

Overview

Tvist.is is the marketing website for Tvist, an Icelandic creative and branding agency. It is a classic agency site: a bold front page, a project portfolio, company and team pages, client lists, and open-role sections. Everything is composed from a Prismic headless CMS through a Next.js Pages Router frontend.

The site is strongly animated. Framer Motion, react-awesome-reveal, and react-fast-marquee drive the hero, text-reveal, and running-text effects, while Embla carousels and react-player handle the videotron and media slices. The visual identity leans on a pink/primary color system with a custom narrow display typeface.

Unlike Uos.is, Tvist is a single-locale (Icelandic) site. Routing is CMS-driven: page documents carry a route field, and a catch-all page resolves requests against Prismic, so editors define their own URL structure.

Tech Stack & Rationale

Layer

Technology

Why

Framework

Next.js 13.5 (Pages Router), React 18

SSG via getStaticProps/getStaticPaths; simple, mature routing for a CMS site

Language

TypeScript

Typed Prismic document/content models

Styling

Tailwind CSS 3

Utility-first styling plus custom typeface and component layers

CMS

Prismic + Slice Machine

Headless content: pages, projects, layouts, error, redirect_link types and 18 slices

Animation

Framer Motion, react-awesome-reveal, react-fast-marquee

Hero, text-reveal, and marquee animations

Media

react-player, Embla Carousel

Vimeo videotron and carousel slices

SEO

next-sitemap + @reecem/prismic-sitemap

Prismic-aware sitemap and robots.txt generation

Progress

nextjs-progressbar

Route-change progress indicator

Architecture

The site is statically generated from Prismic. A catch-all route resolves every request against the pages and redirect_link custom types, while a layout document wraps every page with the shared navbar and footer.

The flow runs: Request /route → [...customs].tsx (getStaticProps) → queryByRoute (Prismic client) → DynamicLayout (layout + slices) → queryByUID(layouts) (main-layout) → SliceZone render (18 slices).

  1. Routing — pages/[...customs].tsx is the catch-all page. Its getStaticProps calls queryByRoute(client, pathname) to find the matching pages document by its route field (or a redirect_link document to follow).
  2. Layout resolution — the page also fetches the layouts document with UID main-layout (queryByUID), which supplies the navbar, footer, and menu slices that DynamicLayout wraps around the page content.
  3. Content querying — core/prismic/client.ts re-exports typed helpers (queryByRoute, queryByUID, queryByType) built on @prismicio/client, with linkResolver and route injection handled in core/prismic/utils.
  4. Slice rendering — the page's slice zone is rendered through @prismicio/react's SliceZone with the slices/index.ts component map (FrontPageHero, Videotron, ProjectList, ClientList, EmployeeList, etc.).
  5. Build & SEO — after next build, next-sitemap (augmented by @reecem/prismic-sitemap) generates sitemap.xml and robots.txt into public/, resolving URLs from the same Prismic link resolver used at runtime.

Folder Structure

tvist/
├── pages/ # Pages Router: index, [...customs], projects/[uid], 404, api (preview)
├── components/
│ ├── _layouts/ # DynamicLayout wrapper
│ └── _shared/ # Button, Image, Link, SEOTags, Pagination, Loader, icons, animations
├── core/
│ ├── prismic/ # client + types + utils (inject, linkResolver, query)
│ ├── contexts/ # layout & project React contexts
│ ├── hooks/ # useClearance, useEmbla, useResize
│ ├── animation/ # shared motion variants/easing
│ ├── data/ # SpaceData.ts
│ ├── lib/ # generateMetaData
│ ├── styles/ # base, components, tailwind, typefaces, utilities
│ └── utils/ # animations, check, debug
├── customtypes/ # Prismic models (pages, projects, layouts, error, redirect_link)
├── slices/ # 18 reusable Prismic slices
├── prismicio.ts # Prismic client + auto previews
├── next.config.js # link resolver + Prismic sitemap wiring
└── next-sitemap.config.js # sitemap/robots.txt generation
  • pages/ — the Pages Router entry points and API routes (preview, exit-preview).
  • components/ — shared presentational components and the DynamicLayout wrapper.
  • core/ — the app's kernel: Prismic helpers, contexts, hooks, animation utilities, styles, and metadata helpers.
  • customtypes/ — the Prismic content model definitions.
  • slices/ — the slice library consumed by Slice Machine and the SliceZone.

Content Model

Tvist has no relational database; all content is editorial and lives in Prismic. A page's URL is a first-class content field, which lets editors control the site structure without code changes.

Custom type

Purpose

pages

Slice-composed pages; the route field sets the URL (/, /about, …)

projects

Portfolio projects (client name, date, category list, hero/media slices)

layouts

Shared layout documents (navbar, footer, menus) with UID main-layout

error

Custom error page content

redirect_link

CMS-managed redirects (source route → destination)

The projects type carries a client_name, a date, a categorylist group (a Select of Icelandic service categories such as STEFNUMÓTUN, VEFHÖNNUN, MÖRKUN), and a slice zone (project_hero, videotron, image, paragraph, company_role). Pages and projects both carry an SEO & Metadata tab (meta_title, meta_description, meta_image), consumed by the SEOTags component.

Impact & Results

  • In production for Tvist, an Icelandic creative and branding agency.
  • Editors define the entire URL structure through Prismic, so the site can be re-organized without code changes.

My Contributions

I contributed to this project as one of the main developers (52 commits). Key work:

  • Rebuilt the front page, navbar, and footer and fixed the mobile navbar behavior.
  • Built the project section: the project list/grid, the projects/[uid] detail page, and the "other projects" navigation with previous/next project cards.
  • Added the about page and refined the employee card and company-review slices.
  • Implemented SEO and metadata: the SEOTags component, meta tag updates, and the next-sitemap + Prismic sitemap integration.
  • Polished media and motion: the Vimeo videotron rounding, slide fixes, and font/weight adjustments across slices.

References

[1] Tvist, "Tvist — creative agency," [Online]. Available: https://tvist.is

[2] Next.js, "Next.js Pages Router documentation," nextjs.org, 2023. [Online]. Available: https://nextjs.org/docs/pages

[3] Prismic, "Prismic documentation — headless CMS," prismic.io, 2025. [Online]. Available: https://prismic.io/docs

[4] Framer Motion, "Motion for React documentation," framer.com, 2025. [Online]. Available: https://motion.dev

[5] next-sitemap, "next-sitemap — sitemap generator for Next.js," github.com, 2025. [Online]. Available: https://github.com/iamvishnusankar/next-sitemap

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!