Foldkit
Prisma.Website.Foldkit deploys a Foldkit app to
Prisma Compute. It supports browser-only SPAs, server-side rendering (SSR), static site
generation (SSG), and hybrid rendering. Foldkit’s Vite plugin generates the
handler and assets; Alchemy packages them for deployment.
Install
Section titled “Install”Install the build-time integration; the resource loads /foldkit and
/foldkit/neon from your frontend project:
pnpm add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:a10573e @vercel/nftbun add -d https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:a10573e @vercel/nftnpm install -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:a10573e @vercel/nftyarn add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:a10573e @vercel/nftConfigure Vite
Section titled “Configure Vite”Keep Foldkit’s Vite setup and your existing plugins:
import { foldkit } from "@foldkit/vite-plugin";import tailwindcss from "@tailwindcss/vite";import { defineConfig } from "vite";
export default defineConfig({ plugins: [foldkit(), tailwindcss()], optimizeDeps: { entries: ["src/entry.ts"] },});Server rendering and prerendering
Section titled “Server rendering and prerendering”Configure rendering in the application’s foldkit(...) plugin. This example
uses Foldkit 0.167.0, @foldkit/vite-plugin 0.27.0 and compatible Effect
dependencies:
import { foldkit } from "@foldkit/vite-plugin";import { defineConfig } from "vite";
export default defineConfig({ plugins: [ foldkit({ ssr: { serverEntry: "/src/entry.server.ts", clientEntry: "/src/entry.ts", build: true, }, }), ],});The server entry exports renderPage and renderDocument. Import stylesheets
from the client entry and use Runtime.hydrate to start the browser application.
Remove the source index.html for this build: Foldkit generates the complete
HTML document, including the client script, stylesheets and module preload links.
import { Server } from "foldkit/experimental";
export const renderDocument = Server.renderDocument;Keep your application’s renderPage export alongside the document renderer.
Foldkit currently exposes its server rendering API through foldkit/experimental;
see its server rendering guide for
the application and hydration contract.
For static site generation (SSG), change build to { prerender: true } and
export the URLs to generate from the server entry:
export const prerenderPaths = ["/", "/about"];SSG renders those URLs during the build. SSR renders a page when its request
arrives. A hybrid application prerenders some URLs and renders others on request.
The same renderPage and renderDocument exports serve both delivery policies.
The same Website declaration deploys the client assets and generated handler.
GET and HEAD requests serve matching assets and prerendered pages first;
remaining requests go to the handler. Other methods bypass static assets.
The application owns its response status and headers through renderPage.
For an SSG-only application, return 404 for URLs outside its generated route set;
allowing those URLs to render on request makes the deployment hybrid.
Browser-only builds use SPA fallback. Server builds send unmatched requests to
the handler. Explicit assets.notFoundHandling settings override these defaults.
Vite’s resolved base also mounts the client assets. With base: "/app/",
/app/assets/main.js serves assets/main.js from the client output. SPA fallback
is limited to that prefix; server handlers receive the original URL.
Declare the Website
Section titled “Declare the Website”import * as Prisma from "@alchemy.run/prisma";
export const Website = Prisma.Website.Foldkit("Website", { rootDir: "applications/web",});Omit rootDir for an app at .. Omit project to create a
database-less Prisma project on live deploy, or pass an existing project.
Add it to the Stack
Section titled “Add it to the Stack”import * as Alchemy from "alchemy";import * as Effect from "effect/Effect";
export default Alchemy.Stack( "MyFoldkitSite", { providers: Prisma.providers(), state: Alchemy.localState() }, Effect.gen(function* () { const site = yield* Website; return { url: site.url }; }),);site.url is the Compute endpoint on deploy and Vite’s local URL in dev.
Add environment variables
Section titled “Add environment variables”export const Website = Prisma.Website.Foldkit("Website", { rootDir: "applications/web", env: { VITE_API_URL: "https://api.example.com", },});env is applied before build and dev, and passed to Compute. Server code
reads private values from process.env. Vite inlines VITE_* keys into the
browser build; keep secrets out of those keys and serialized Foldkit Flags.
Read the environment in client code
Section titled “Read the environment in client code”/// <reference types="vite/client" />
interface ImportMetaEnv { readonly VITE_API_URL: string;}This declares the client-visible key for TypeScript.
const apiUrl = import.meta.env.VITE_API_URL;Vite replaces the lookup with the build-time value.
Deep links
Section titled “Deep links”For browser-only builds, assets.notFoundHandling defaults to "single-page-application".
A path like /counter/42 returns index.html with status 200, letting
Foldkit’s client router resolve it. For real 404 responses instead:
export const Website = Prisma.Website.Foldkit("Website", { assets: { notFoundHandling: "404-page" },});Local dev
Section titled “Local dev”alchemy dev runs Vite with Foldkit live reload and devtools. The Website
creates no Prisma resources. .pipe(Alchemy.remote()) selects the live
path during dev. Pin the local address when running several apps:
export const Website = Prisma.Website.Foldkit("Website", { dev: { host: "127.0.0.1", port: 5180, strictPort: true },});Custom domain
Section titled “Custom domain”const site = yield* Prisma.Website.Foldkit("Web", { domain: "app.example.com",});This creates Prisma.CustomDomain. Configure the returned DNS records yourself
and verify status before cutover. See
Custom domains.
Where next
Section titled “Where next”- Foldkit API.
- Foldkit example.
- Vite, Websites, and Compute apps.