SKIFFLE is a framework that lets you embed a website in a Farcaster snap. A snapsite, if you will.
Navigate the snap just like you would click links on a website. Share any sub-URL back to the feed, and it still functions as an entry point to the snapsite no matter how deeply nested you are.
Webpage contents also render directly to snap images, so devs (and agents) can leverage the familiar HTML templating, CSS styling, param-based state and hierarchical data loading techniques of a modern route-based web framework.
SKIFFLE works by extending SvelteKit with:
HTML/CSS -> SVG -> PNG render pipeline (satori + resvg)The most crucial code path is in src/hooks.server.ts plus src/lib/snap-routes.ts: page URLs are overloaded and resolved through normal SvelteKit routing, while output modality is selected via HTTP Accept headers and related request context.
SKIFFLE treats SvelteKit routes as the canonical source of truth, then projects that same route into:
That keeps state, data loading, route hierarchy, and navigation semantics unified while still satisfying Farcaster frame/snap protocol requirements.
Given a single SvelteKit route URL, SKIFFLE can produce different representations:
application/farcaster-frame): for Farcaster Snap clients?image): server-rasterized page preview from the HTML/CSS resultIn practice:
GET with Snap Accept header triggers snapGetResponse(...)POST with Snap JFS payload triggers snapPostResponse(...)GET with ?image resolves the page as HTML, transforms to SVG with Satori, then to PNG with ResvgPOST) are adapted into SvelteKit action-compatible requestslink alternates and vary: Accept where relevantsrc/hooks.server.tsGlobal middleware that:
publicRequestUrl(...))link metadata to HTML responsesOPTIONS)GET / POST flows?image into HTML->PNG server rasterizationsrc/lib/snap-routes.tsSnap protocol adapters that:
fc:frame:* metadata from HTMLframePageToSnap(...)?/actionName)x-sveltekit-action: true)frame / snap / title overrides back into a final Snap responsesrc/lib/snap.tsSnap composition logic for:
src/lib/snap-components.ts: typed helpers for buttons, groups, and higher-level page buildingsrc/lib/snap-spec.ts: Snap media type/version/constantssrc/lib/snap-jfs.ts: JFS payload parsing and signature envelope handlingsrc/lib/frame-satori.ts: HTML document preparation for Satori parsingInstall and run:
pnpm install
pnpm dev
Run on a specific port:
pnpm dev --port 4000
Optional public tunnel for client integrations:
pnpm tunnel:ngrok
pnpm dev - run Vite dev serverpnpm build - production buildpnpm preview - preview production buildpnpm check - Svelte type-check pipelinepnpm lint / pnpm format - lint and formatpnpm test:unit - Vitestpnpm test:integration - Playwrightpnpm test:integration:snap - snap-focused Playwright configWhen rendering HTML/CSS through satori / resvg, some CSS features differ from browser behavior. In this codebase that often means:
flex/block flow, simple position, no grid-like assumptions)calc, z-index, and 3D transforms