Using Vysmo with Next.js
Vysmo's libraries are framework-free vanilla TS with optional React wrappers. They drop straight into a Next.js app — no Next- specific adapter package needed at v1. This guide covers the common production patterns: image optimization, lazy loading, SSR, and priority hints.
Install
pnpm add @vysmo/slideshow-react @vysmo/transitions @vysmo/animations @vysmo/slideshow-react is the React component;
@vysmo/transitions ships the 60 transition shaders;
@vysmo/animations is a transitive peer dep. For a
page-flip experience, also add @vysmo/flipbook-react.
Minimal example
A drop-in gallery with WebGL transitions, lazy-loading, and a 1-slide preload window:
// app/gallery/page.tsx
"use client";
import { Slideshow } from "@vysmo/slideshow-react";
import { paintBleed } from "@vysmo/transitions";
const photos = [
"/photos/01.jpg",
"/photos/02.jpg",
"/photos/03.jpg",
];
export default function GalleryPage() {
return (
<Slideshow
slides={photos}
transition={paintBleed}
lazy
preloadWindow={1}
style={{ width: "100%", aspectRatio: "16 / 9" }}
/>
);
} lazy tells the slideshow to only decode the current
slide + immediate neighbours, with the runner's GPU cache
evicting URLs that scroll out of the window via LRU. preloadWindow=1 is the default; raise it to 2 or 3
for galleries where users rapid-fire navigation is common.
Image optimization via the Next image loader
Next.js's built-in image optimizer accepts any URL and returns
responsively-sized AVIF/WebP versions through /_next/image?url=…&w=…&q=…. Vysmo accepts
those URLs the same as any other string — pass them straight to
the slides array:
// app/gallery/page.tsx
"use client";
import { Slideshow } from "@vysmo/slideshow-react";
import { paintBleed } from "@vysmo/transitions";
const RAW_URLS = [
"/photos/01.jpg",
"/photos/02.jpg",
"/photos/03.jpg",
];
// Build Next.js image-optimizer URLs at the size the slideshow renders.
// Vysmo accepts these URL strings the same as any other.
function optimized(url: string, width = 1600): string {
return `/_next/image?url=${encodeURIComponent(url)}&w=${width}&q=80`;
}
export default function GalleryPage() {
const slides = RAW_URLS.map((u) => optimized(u, 1600));
return (
<Slideshow
slides={slides}
transition={paintBleed}
lazy
preloadWindow={1}
style={{ width: "100%", aspectRatio: "16 / 9" }}
/>
);
} For multiple breakpoints, generate URLs at the size your slideshow actually renders at (e.g. 1600px for a hero, 800px for a sidebar gallery). Next's optimizer caches each variant, so regenerating per-render is free after the first hit.
SSR + dynamic import
Vysmo's React components are SSR-safe at module load (no DOM
access during import), but the WebGL canvas itself is
browser-only. In a Next.js App Router page using server
components, wrap with next/dynamic and ssr: false to skip the wasted server render and
clean up the hydration payload:
// components/ClientSlideshow.tsx
"use client";
import dynamic from "next/dynamic";
// Render only on the client — WebGL is browser-only. Importing
// @vysmo/slideshow-react itself is SSR-safe (no DOM at module load),
// but mounting it during SSR has no effect anyway. `ssr: false` skips
// the wasted server render entirely.
export const ClientSlideshow = dynamic(
() => import("@vysmo/slideshow-react").then((m) => m.Slideshow),
{ ssr: false },
);
If your page is already a "use client" component,
you can import Slideshow directly — no dynamic
import needed.
CORS notes
Images loaded over HTTP fetch+createImageBitmap need correct
CORS headers (Access-Control-Allow-Origin) to
upload as WebGL textures without tainting the canvas. The
Next.js image optimizer handles this for URLs it serves
(/_next/image?…). For third-party images you fetch
directly, make sure the origin sets the right headers — or
proxy through your own Next API route.
What's not in scope at v1
- A dedicated
@vysmo/slideshow-nextpackage — not built yet. The core slideshow + URL inputs covers the common cases. We'll consider a deeper integration package (withnext/imageas a prop, server-side prefetch, blur-placeholder pipeline) if there's specific demand. Let us know what you need. - Blur placeholders during decode. Currently
slides render as soon as their texture is uploaded; for the
brief gap, the previous slide is visible. A built-in blur
placeholder pipeline would need to integrate with
next/image's blur data — that's the kind of thing a-nextpackage would do.
See also
- @vysmo/slideshow reference — all options
- @vysmo/flipbook reference — page-flip with drag-scrub
- @vysmo/transitions catalog — 60 transitions