Deploy the open-source stack with Alchemy and own the data end to end. This is the free, self-hosted option.
Replace the placeholders with your Cloudflare resources and domain, then run your Alchemy deploy. This example mirrors `alchemy.run.ts` with safe placeholder names.
Set your app name and Cloudflare domain.
Create your D1, KV, and Queue names.
Set the required secrets in your environment before deploy.
import type { SiteDurableObject } from "./db/durable/siteDurableObject";
import alchemy from "alchemy";
import { D1Database, KVNamespace, DurableObjectNamespace, Redwood, Queue } from "alchemy/cloudflare";
const app = await alchemy("your-app-name");
const adoptMode = true;
const siteDurableObject = DurableObjectNamespace<SiteDurableObject>("site-durable-object", {
className: "SiteDurableObject",
sqlite: true,
});
const lytxEvents = await KVNamespace("lytx-events", { adopt: adoptMode, delete: false });
const lytxConfig = await KVNamespace("lytx-config", { adopt: adoptMode, delete: false });
const lytxSessions = await KVNamespace("lytx-sessions", { adopt: adoptMode, delete: false });
const siteEventsQueue = await Queue("site-events-queue", { adopt: adoptMode, delete: false });
const lytxCoreDb = await D1Database("lytx-core-db", {
name: "lytx-core-db",
migrationsDir: "./db/d1/migrations",
adopt: adoptMode,
delete: false,
});
export const worker = await Redwood("lytx", {
adopt: true,
domains: [{ adopt: true, domainName: "analytics.your-domain.com" }],
wrangler: {
main: "src/worker.tsx",
transform: (spec) => ({
...spec,
compatibility_flags: ["nodejs_compat"],
}),
},
bindings: {
SITE_DURABLE_OBJECT: siteDurableObject,
LYTX_EVENTS: lytxEvents,
lytx_config: lytxConfig,
lytx_sessions: lytxSessions,
lytx_core_db: lytxCoreDb,
SITE_EVENTS_QUEUE: siteEventsQueue,
LYTX_DOMAIN: process.env.LYTX_DOMAIN,
BETTER_AUTH_SECRET: alchemy.secret(process.env.BETTER_AUTH_SECRET),
GITHUB_CLIENT_SECRET: alchemy.secret(process.env.GITHUB_CLIENT_SECRET),
GOOGLE_CLIENT_SECRET: alchemy.secret(process.env.GOOGLE_CLIENT_SECRET),
RESEND_API_KEY: alchemy.secret(process.env.RESEND_API_KEY),
ENCRYPTION_KEY: alchemy.secret(process.env.ENCRYPTION_KEY),
},
});We can walk you through setup and verify your Cloudflare resources before launch.