Violetta Studio  /  Contact sheet No. 02
Buy $59
Contact sheet05 framesNext.js 16 photography portfolioSource included

Next.js 16 Photography Portfolio Template with Lightbox — Lens

Uniform · Masonry · Editorial · and a lightbox that really zooms

The gallery and the viewer you’d spend three weeks hand‑building — already wired. Four themes, four languages, one config file.

I want this — $59

30-day money back guarantee. Email me and you get a full refund — no questions, no forms.

Open the live demo ↗
Next.js 16React 19TypeScript strictTailwind v4Framer Motion101 testsWCAG 2.1 AA

A portfolio is judged on one interaction: what happens when somebody clicks a photograph.Everything below runs on the template’s own theme tokens. Switch a chip in the bar and this sheet develops with it.

01The sheet

Five frames off the roll.

Screens from the running template — nothing mocked up, nothing composited. Click a frame to open the viewer: wheel or + to zoom, drag to pan, arrows to move along the sheet.

Frames 01–05 · Lens Template · as shipped Click any frame to enlarge
02Layouts

Three ways to hang the same work.

Frames 02 and 03 are the same body of work, hung two different ways. The toggle sits above the grid and runs client‑side, so visitors can switch as they browse.

Uniform

Even ratios, even rhythm. The safe grid for a mixed body of work — nothing draws focus away from the pictures.

Masonry

Staggered columns that keep every native aspect ratio. Portraits stay tall, panoramas stay wide.

Editorial

Large offset plates with generous air, closer to a printed feature than a gallery wall.

Each project page adds a case study with an optional EXIF strip — camera, lens, aperture, shutter, ISO, focal length — and every image in it opens in the lightbox.

03Processing

Develop it any way you like.

Four palettes, each with a light and a dark scheme. Pick one and this page recolours — it is not a preview of the template’s tokens, it is running on them.

Palette
Scheme
--bg#0b0b0b
--bg-elev#131313
--fg#ede8e0
--fg-mutedrgba(237,232,224,.62)
--linergba(237,232,224,.12)
--accent#c9a095

Values read live off the page you are looking at. In the download they sit in src/styles/themes.css on two axes — data-theme chooses the palette, data-scheme flips it light. Copy a block, change the values, and you have a fifth theme. Monolith also brings its own fullscreen‑slider home layout.

04Datasheet

The whole specification.

No locked features, no upsell tier. This is everything in the ZIP.

Build
Framework Next.js 16 · App Router · React 19 · Framer Motion
Language TypeScript, strict mode
Styling Tailwind v4 over CSS custom properties — the token blocks shown above
Requirements Node.js 20+ · npm, pnpm or bun
Tests 37 Vitest specs, passing — run npm test
Included
Gallery Three layout modes — uniform, masonry, editorial — with a client-side toggle and category filters
Lightbox Pinch zoom, wheel zoom, double-tap, drag-to-pan, fullscreen, swipe navigation and full keyboard control
Pages Home, portfolio and case studies, journal and posts, services, about, contact, plus a docs section, a changelog and a deletable component gallery
Cursor Custom mix-blend-mode cursor in four styles — blob, dot, ring, native. Respects pointer:fine, so it switches itself off on touch.
Motion Ken Burns hero animation and an optional film-grain overlay, both driven by the theme tokens
Journal Blog index and post pages with JSON-LD BlogPosting and BreadcrumbList
Services Numbered service cards with rates and an accessible FAQ accordion
Themes Editorial Dark, Sun-bleached, Salt & Smoke, Monolith — each with a light scheme; Monolith adds a fullscreen-slider home
Type pairs Bodoni Moda, DM Serif Display, Cormorant Garamond or Playfair Display, each over Inter Tight and JetBrains Mono
Variants Every home section, plus the nav and footer, ships three real layouts. Audition them from the preview panel, then set your pick in config.
Languages English, Spanish, French, Portuguese — UI strings and per-item project content
Right-to-left Logical CSS properties, mirrored icons and direction-aware animation throughout. Set dir on a locale and the layout flips.
Contact form Works out of the box; Resend, Formspree and Web3Forms adapters sit commented in src/lib
CMS None required — content lives in src/config/site.ts. Sanity, Strapi and Contentful adapters are drop-in and signature-compatible.
Accessibility WCAG 2.1 AA, visible focus, skip link, prefers-reduced-motion respected
SEO JSON-LD, generated Open Graph images, sitemap, robots, RSS
Docs README, CUSTOMIZATION, DEPLOY, PRODUCTION, plus one guide per adapter
Licence Single use — one purchase, one deployed project. Multi-use available, just ask.
Support hello@violettadev.com
05Contents

One file holds the negatives.

Your projects, your categories, your services and rates, your journal — all of it typed, all of it in src/config/site.ts. Components read through src/lib/content.ts, so moving to a CMS later is an import change, not a rewrite.

lens-template/
├- src/
│  ├- config/site.ts          projects · categories · services · journal
│  ├- styles/themes.css       the four palettes above
│  ├- app/[locale]/           home · portfolio · journal · services · about · contact · docs
│  ├- components/sections/    Lightbox · PortfolioGallery · Hero · FaqAccordion
│  ├- components/layout/      CustomCursor · Grain · Nav · ThemeToggle
│  ├- lib/content.sanity.ts    · .strapi · .contentful — commented
│  ├- lib/contact.resend.ts    · .formspree · .web3forms — commented
│  └- i18n/                   routing and request config
├- messages/                  en · es · fr · pt
├- tests/                     37 Vitest specs
├- public/                    demo imagery, swap for yours
└- README · CUSTOMIZATION · DEPLOY · PRODUCTION · SANITY · STRAPI · CONTENTFUL · LICENSE
06Questions

Before you buy.

What lands in my downloads?

A ZIP with the complete source. Unzip, run npm install, then npm run dev and the site is at localhost:3002. Nothing is minified, obfuscated or held back.

Is the lightbox actually that good?

Frame 04 is a screenshot of it. In the template it handles pinch zoom, wheel zoom, double-tap, drag-to-pan, fullscreen, swipe navigation and the full keyboard set, with focus trapped and restored. The viewer on this page is a stripped-down stand-in I wrote so you can feel the interaction before paying for it — the real one does more, on the live demo ↗.

Do the three layout modes need any setup?

No. The toggle above the portfolio grid is client-side and works on the demo content the moment you run it. Point src/config/site.ts at your own photographs and all three modes follow.

Does the custom cursor break on phones?

It never runs on them. The cursor is gated behind pointer:fine, so touch devices get the native one. Four styles ship — blob, dot, ring and native — and choosing native removes it everywhere.

Do I have to run a CMS?

No, and that is the point — content is a typed config file, so you edit, commit and deploy. If your catalogue outgrows that, the Sanity, Strapi and Contentful adapters share the same function signatures, so swapping one in is an import change rather than a rewrite.

Are the four languages real, or machine output?

Real. English, Spanish, French and Portuguese live in messages/, project titles and case-study text included, and a unit test fails if a key exists in one locale but is missing from another.

Can I build a client site with it?

Yes — the licence covers one deployed project per purchase, so a client site counts. Building several? Email hello@violettadev.com and I’ll sort out multi-use.

Something breaks. Then what?

Email hello@violettadev.com. I wrote every line of it and I answer my own support.

Who makes this?

Violetta Studio — a one-person shop building production Next.js templates. The rest of the catalogue is at violettadev.com ↗.

Print the good one.

The portfolio you keep meaning to rebuild, finished — and yours to take apart.

Buy Next.js 16 Photography Portfolio Template with Lightbox — Lens — $59

30-day money back guarantee. Email me and you get a full refund — no questions, no forms.