import alchemy from "alchemy"; import { Queue, TanStackStart } from "alchemy/cloudflare"; import { config } from "dotenv"; config({ path: "./.env" }); config({ path: "../env/.env" }); const app = await alchemy("kk"); /** Throws at deploy time if a required variable is missing from the environment. */ function getEnvVar(name: string): string { const value = process.env[name]; if (!value) { throw new Error(`Missing required environment variable: ${name}`); } return value; } const emailQueue = await Queue("email-queue", { name: "kk-email-queue", }); export const web = await TanStackStart("web", { cwd: "../../apps/web", bindings: { // Core DATABASE_URL: getEnvVar("DATABASE_URL"), CORS_ORIGIN: getEnvVar("CORS_ORIGIN"), BETTER_AUTH_SECRET: getEnvVar("BETTER_AUTH_SECRET"), BETTER_AUTH_URL: getEnvVar("BETTER_AUTH_URL"), // Email (SMTP) SMTP_HOST: getEnvVar("SMTP_HOST"), SMTP_PORT: getEnvVar("SMTP_PORT"), SMTP_USER: getEnvVar("SMTP_USER"), SMTP_PASS: getEnvVar("SMTP_PASS"), SMTP_FROM: getEnvVar("SMTP_FROM"), // Payments (Mollie) MOLLIE_API_KEY: getEnvVar("MOLLIE_API_KEY"), // Cron secret for protected scheduled endpoints CRON_SECRET: getEnvVar("CRON_SECRET"), // Queue binding for async email sends EMAIL_QUEUE: emailQueue, }, // Queue consumer: the worker's queue() handler processes EmailMessage batches eventSources: [ { queue: emailQueue, settings: { batchSize: 10, maxRetries: 3, retryDelay: 60, // seconds before retrying a failed message maxWaitTimeMs: 1000, }, }, ], // Fire every hour so reminder checks can run at 19:00 on 2026-03-15 (24h) and 18:00 on 2026-03-16 (1h) crons: ["0 * * * *"], domains: ["kunstenkamp.be", "www.kunstenkamp.be"], }); console.log(`Web -> ${web.url}`); await app.finalize();