Skip to content
← Back to portfolio

Project case study · Web system

Cyprus Sensual Festival

Solo-built Next.js festival site with a hand-rolled no-library pinch-zoom schedule viewer, responsive artist layouts, and an external ticketing handoff.

Next.jsReactTypeScriptTailwind CSS
Cyprus Sensual Festival

The challenge

Cyprus Sensual Festival needed a clear public-facing site for its 2025 event in Limassol. The page had to bring together the international artist lineup, workshops, social nights, schedule, dress codes, venue details, and several ticket options. Checkout already lived in an external registration flow, so the implementation needed to make that handoff obvious without pulling payment processing into the site.

What I built

I built and shipped the site solo end to end. It is a Next.js 14 app using React 18, TypeScript, and Tailwind CSS 3, started from Tailwind UI’s “Keynote” template and customized around the festival’s content. The landing page composes dedicated sections for the hero, artists, Jack & Jill competition, schedule, dress codes, tickets, venue, and contact. Content stays in React/TypeScript components with imported local assets; there is no database, CMS, or application backend in this project. Ticket calls to action point to the external Dizizid registration flow, so payment processing is outside the application.

Key features

Hand-rolled pinch-and-zoom schedule

The schedule has one panel for Friday, Saturday, and Sunday, each showing a local schedule image. Selecting an image opens a full-screen dialog. I wrote the mobile zoom interaction without a zoom library. Raw touch handlers use Math.hypot to calculate the distance between two fingers, clamp the scale from 1× to 4×, and track one-finger X/Y translation. Closing the viewer resets the transform state.

Responsive artist layouts

The artist lineup uses the same grouped data in two responsive modes: a horizontal snap carousel on mobile and a desktop grid at larger widths. The grid starts at two columns and grows to three at the medium breakpoint, while the carousel keeps each artist card as a fixed-width, swipeable item. The layout changes with the viewport without changing the lineup content.

Ticket handoff

The ticket section renders four options: Full Pass, Couples Pass, Party Pass, and Full Pass + Sanjay Masterclass. Each CTA uses the same external Dizizid registration endpoint; payment processing and ticket state remain outside the application.

Architecture

Frontend: Next.js 14 with React 18 and TypeScript, styled with Tailwind CSS 3. Headless UI provides the tab and dialog primitives, while next/image renders the local images.

Content: React/TypeScript component data and imported local images. The project has no application backend, database, or CMS.

Interaction: The daily schedule tabs use horizontal navigation on smaller screens and switch to vertical navigation at the large breakpoint. The schedule viewer owns its zoom and translation state in React.

Ticketing: Every ticket CTA links to the external Dizizid registration endpoint. This codebase does not implement payment processing.

Site status: The 2025 event has passed and the site is no longer hosted at its original domain.

Have a project in mind?

Tell me what you're working on and where you need help.