Store Slack webhook URL as secret
Store the SLACK_WEBHOOK_URL as a secret using npx wrangler secret put SLACK_WEBHOOK_URL. When prompted, enter the webhook URL. This prevents the sensitive URL from being hardcoded in the codebase and makes it available as an environment variable in the Bindings type.
Install Hono for Workers
Install Hono framework with `npm install hono` for building Cloudflare Workers applications. Hono provides route handling and middleware support.
Hono TypeScript Bindings and Variables types
Define Hono app with typed environment and variables: `new Hono<{ Bindings: Bindings, Variables: Variables }>()`. Bindings type defines environment variables and resource bindings, Variables type defines context-scoped values set via `c.set()`.
MySQL tutorial uses TypeScript
The MySQL tutorial creates a Worker using TypeScript as the language.
Use OpenAI node library with Cloudflare Workers
The OpenAI node library can be used to interact with the OpenAI API within a Cloudflare Worker. Install it with npm: openai. Instantiate the OpenAI client by passing the API key from environment variables: const openai = new OpenAI({ apiKey: env.OPENAI_API_KEY }).
OpenAI Chat Completions API parameters
The openai.chat.completions.create() method accepts: model (string, the model to use such as gpt-4o-mini), messages (array of message objects with role and content properties), tools (array of available functions with type, function name, description, and parameters), tool_choice (string, typically 'auto' to allow the model to choose whether to call a function or respond normally).
Define OpenAI function tool structure
Each tool in the tools array has: type (always 'function'), function object containing name (function name), description (what the function does), and parameters (JSON Schema object describing the function's parameters including type, properties, and required fields).
Example: Read website content function
async function read_website_content(url) {
console.log("reading website content");
const response = await fetch(url);
const body = await response.text();
let cheerioBody = cheerio.load(body);
const resp = {
website_body: cheerioBody("p").text(),
url: url,
};
return JSON.stringify(resp);
}
This function fetches a URL, extracts text from all <p> tags using the Cheerio library, and returns the content as JSON.
Use Cheerio to parse HTML in Workers
The Cheerio library can be used within Workers to parse and extract content from HTML. Load HTML with cheerio.load(htmlString) and then use jQuery-like selectors to extract elements, for example cheerio('p').text() to extract all paragraph text.
OpenAI function calling feature overview
The function calling feature in OpenAI's Chat Completions API allows an AI model to intelligently decide when to call a function based on input and respond in JSON format to match the function's signature.
Process function call results for OpenAI
When OpenAI returns a function call, extract the function name and arguments from toolCall.function. Parse the arguments JSON, execute the function, and add the result to the messages array as an object with role 'tool', tool_call_id set to toolCall.id, name set to the function name, and content set to the function result. Then make a second API call to openai.chat.completions.create() with the updated messages array to get a response informed by the function results.
Extract function arguments from OpenAI tool call
Function arguments from OpenAI are returned as a JSON string in toolCall.function.arguments. Parse this with JSON.parse() to access individual parameters: const url = JSON.parse(toolCall.function.arguments).url.
Check for function calls in OpenAI response
After calling openai.chat.completions.create(), check if assistantMessage.tool_calls exists to determine if the model requested any function calls. The tool_calls property is an array, so loop through it to handle multiple potential function calls.
Postmark JavaScript library not supported on Workers
The Postmark JavaScript library is currently not supported on Cloudflare Workers. Use the Postmark email API instead when sending emails from Workers.
Send email with Postmark API from Worker example
To send emails from a Worker using Postmark's email API, make a POST request to https://api.postmarkapp.com/email with the X-Postmark-Server-Token header and a JSON body containing From, To, Subject, and HtmlBody fields. Example:
export default {
async fetch(request, env, ctx) {
return await fetch("https://api.postmarkapp.com/email", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Postmark-Server-Token": env.POSTMARK_API_TOKEN,
},
body: JSON.stringify({
From: "hello@example.com",
To: "someone@example.com",
Subject: "Hello World",
HtmlBody: "<p>Hello from Workers</p>",
}),
});
},
};
Resend email send example code
import { Resend } from "resend";
export default {
async fetch(request, env, ctx) {
const resend = new Resend("your_resend_api_key");
const { data, error } = await resend.emails.send({
from: "hello@example.com",
to: "someone@example.com",
subject: "Hello World",
html: "<p>Hello from Workers</p>",
});
return Response.json({ data, error });
},
};
Send emails from Workers with Resend SDK
To send emails from a Cloudflare Worker using Resend, import the Resend SDK and instantiate it with an API key. Call resend.emails.send() with from, to, subject, and html fields. The method returns an object with data and error properties.
Resend email send with environment variable for API key
import { Resend } from "resend";
export default {
async fetch(request, env, ctx) {
const resend = new Resend(env.RESEND_API_KEY);
const { data, error } = await resend.emails.send({
from: "hello@example.com",
to: "someone@example.com",
subject: "Hello World",
html: "<p>Hello from Workers</p>",
});
return Response.json({ data, error });
},
};
Install Resend SDK for Workers
To use Resend with Cloudflare Workers, install the Resend SDK using npm with the command: npm i resend
Resend domain verification prerequisites
Before sending emails with Resend from a Worker, the domain must be verified in Resend. Add the domain in Resend's dashboard, copy the DNS records (DKIM, SPF, and DMARC) to your Cloudflare DNS settings, then verify the records in Resend. The domain status should show as Verified before use.
PrismaClient instantiation with datasourceUrl in Workers
When creating a PrismaClient instance in Cloudflare Workers, pass the datasourceUrl from environment variables: new PrismaClient({ datasourceUrl: env.DATABASE_URL }).$extends(withAccelerate())
Worker fetch handler with Prisma example
Example Worker using Prisma: import { PrismaClient } from "@prisma/client/edge"; import { withAccelerate } from "@prisma/extension-accelerate"; export interface Env { DATABASE_URL: string; } export default { async fetch(request, env, ctx): Promise<Response> { const prisma = new PrismaClient({ datasourceUrl: env.DATABASE_URL, }).$extends(withAccelerate()); const user = await prisma.user.create({ data: { email: `Jon${Math.ceil(Math.random() * 1000)}@gmail.com`, name: "Jon Doe", }, }); const userCount = await prisma.user.count(); return new Response(`Created new user: ${user.name} (${user.email}). Number of users in the database: ${userCount}.`); }, } satisfies ExportedHandler<Env>;
Create Worker project with C3 for Prisma tutorial
To create a new Worker project for Prisma Postgres setup, run: npm create cloudflare@latest prisma-postgres-worker -- --type=hello-world --ts=true --git=true --deploy=false
Prisma Postgres features
Prisma Postgres is a managed, serverless PostgreSQL database that supports connection pooling, caching, real-time subscriptions, and query optimization recommendations.
Install Prisma dependencies
Three packages are required for Prisma Postgres with Cloudflare Workers: prisma (dev dependency), @prisma/extension-accelerate (required for Prisma Postgres), and dotenv-cli (dev dependency, to load environment variables from .dev.vars).
Initialize Prisma with Postgres database
Initialize Prisma in a Workers project by running: npm create cloudflare@latest prisma@latest init --db (using dlx). This command logs you into the Prisma Data Platform if needed, creates a Prisma project and Postgres database instance in Platform Console, generates a prisma folder with schema.prisma, and creates an .env file with DATABASE_URL.
Prisma schema file structure for PostgreSQL
A Prisma schema for PostgreSQL with Cloudflare Workers must specify the provider as postgresql and use env("DATABASE_URL") for the url. The generator should use prisma-client-js provider.
Helper scripts for Prisma with Cloudflare Workers
Add the following scripts to package.json for managing Prisma with .dev.vars: "migrate": "dotenv -e .dev.vars -- npx prisma migrate dev", "generate": "dotenv -e .dev.vars -- npx prisma generate --no-engine", "studio": "dotenv -e .dev.vars -- npx prisma studio"
Import Prisma Client with Accelerate for Workers
To use Prisma with Cloudflare Workers, import: import { PrismaClient } from "@prisma/client/edge" and import { withAccelerate } from "@prisma/extension-accelerate", then extend the client with .extends(withAccelerate())
Rust Workers event(fetch) macro
The #[event(fetch)] macro in workers-rs marks the function as the fetch event handler. The function receives Request, Env, and Context parameters and returns Result<Response>.
Access URL parameters in Rust Workers
Access URL path parameters in Rust Workers using ctx.param("parameter-name") inside route handlers. It returns Option<String>.
workers-rs library for Rust Workers
workers-rs is the Rust library for building Cloudflare Workers. It provides bindings and utilities for working with Workers features directly from Rust code.
Create Rust Worker project with cargo-generate
To create a new Rust Worker project, install cargo-generate by running 'cargo install cargo-generate', then run 'cargo generate cloudflare/workers-rs' and select the 'template/hello-world-http' template.
Use Serde for JSON in Rust Workers
Use Serde to handle JSON serialization and deserialization in Rust Workers. Install with 'cargo add serde' and derive Serialize and Deserialize traits on structs for JSON conversion.
Rust Workers Router for HTTP routes
Use Router::new() to create an HTTP router in Rust Workers. Chain route handlers with methods like .post_async(), .get_async() to define routes. Call .run(req, env).await to execute routing.
Vite config file for Cloudflare
The vite.config.ts file imports defineConfig from vite and cloudflare from @cloudflare/vite-plugin, then exports a config with plugins: [cloudflare()].
Vite plugin basic setup steps
To set up the Cloudflare Vite plugin: install vite, @cloudflare/vite-plugin, and wrangler; create a vite.config.ts file with cloudflare() plugin; create a wrangler.jsonc/json/toml config file; and create a Worker entry file.
Cloudflare Vite plugin provides full integration with Workers runtime
The Cloudflare Vite plugin enables a full-featured integration between Vite and the Workers runtime. Worker code runs inside workerd, matching production behavior as closely as possible.
Vite plugin builds front-end assets for deployment to Cloudflare
The Vite plugin builds front-end assets for deployment to Cloudflare, enabling you to build static sites, SPAs, and full-stack applications.
Vite plugin official support for TanStack Start and React Router v8
The Vite plugin provides official support for TanStack Start and React Router v8 with server-side rendering.
Vite plugin use cases
The Vite plugin supports the following use cases: TanStack Start, React Router v8, static sites such as single-page applications with or without an integrated backend API, standalone Workers, and multi-Worker applications.
Vite plugin uses Vite Environment API for Workers integration
The Cloudflare Vite plugin uses the Vite Environment API to integrate Vite with the Workers runtime, providing direct access to Workers runtime APIs and bindings.
Workers Vite plugin reference documentation structure
The Workers Vite plugin reference documentation is organized as a navigation page (pcx_content_type: navigation) with the title 'Reference'. It includes configuration options and API details. The page is positioned at sidebar order 5 within a hideIndex group and is associated with the workers product.
Assign Worker to ssr environment for TanStack Start and React Router v8
When using the Cloudflare Vite plugin with TanStack Start or React Router v8, assign the Worker to the ssr environment by setting viteEnvironment.name to 'ssr' in the plugin config. This merges the Worker's environment configuration with the framework's SSR configuration and ensures that the Worker is included as part of the framework's build output.
Example: Configure viteEnvironment for React Router
import { defineConfig } from 'vite';
import { cloudflare } from '@cloudflare/vite-plugin';
import { reactRouter } from '@react-router/dev/vite';
export default defineConfig({
plugins: [cloudflare({ viteEnvironment: { name: 'ssr' } }), reactRouter()],
});
Example: Configure Vite environment with define globals
import { defineConfig } from 'vite';
import { cloudflare } from '@cloudflare/vite-plugin';
export default defineConfig({
environments: {
my_worker: {
define: {
__APP_VERSION__: JSON.stringify('v1.0.0'),
},
},
},
plugins: [cloudflare()],
});
Vite Environment API enables Cloudflare Vite plugin integration
The Vite Environment API, released in Vite 6, is the key feature that enables the Cloudflare Vite plugin to integrate Vite directly with the Workers runtime.
Vite creates client and ssr environments by default
Vite creates two environments by default: client and ssr. A front-end only application uses the client environment, whereas a full-stack application created with a framework typically uses the client environment for front-end code and the ssr environment for server-side rendering.
Cloudflare Vite plugin creates additional environment for each Worker
When you add a Worker using the Cloudflare Vite plugin, an additional environment is created. Its name is derived from the Worker name, with any dashes replaced with underscores. This name can be used to reference the environment in your Vite config to apply environment specific configuration.
Default Vite environment name for Worker is top-level Worker name
The default Vite environment name for a Worker is always the top-level Worker name. This enables you to reference the Worker consistently in your Vite config when using multiple Cloudflare Environments.
Configure Vite environment for standalone Worker
For a standalone Worker, such as an API accessed from your front-end application or an auxiliary Worker accessed via service bindings, use the Worker name as the environment name. This is the default behavior and is appropriate for Workers that are not tightly integrated with full-stack frameworks.
Fetch deployed image from Cloudflare Images in Worker
Serve images stored in Cloudflare Images from a Worker using fetch to the image delivery URL: https://imagedelivery.net/${ACCOUNT_HASH}/${IMAGE_ID}/public where ACCOUNT_HASH is the Cloudflare account hash and IMAGE_ID is the image identifier.
Upload image to Cloudflare Images with API
To upload an image using the Upload via URL API, send a POST request to https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/images/v1 with headers including Authorization Bearer token, and form data including: url (path to image URL), metadata (JSON object with key-value pairs), and requireSignedURLs (boolean). ACCOUNT_ID is found in account settings, API_TOKEN must have Images permission scope, PATH_TO_IMAGE is the URL of the image to upload.
Image upload API response structure
The Upload via URL API response includes: result object containing id (image identifier), filename (uploaded filename), metadata (key-value pairs), uploaded (timestamp), requireSignedURLs (boolean), and variants array (list of URLs including public and thumbnail variants). The response also includes success boolean, errors array, and messages array.
Set content-type header for PNG response in Rust Worker
When returning PNG image data from a Rust Worker, set the response header 'content-type' to 'image/png' using Headers::new(), headers.set('content-type', 'image/png'), and Response::from_bytes(data)?.with_headers(headers).
Text-to-PNG rendering in Rust Worker
Use the text-to-png Rust crate (version 0.2.0) with TextRenderer::try_new_with_ttf_font_data() to load a custom font from bytes using include_bytes!(), then call renderer.render_text_to_png_data(text, size, color_hex) where text is the string to render, size is font size as integer (e.g., 60), and color_hex is RGB hex code without the # (e.g., '003682'). The method returns TextPng with a data field containing PNG bytes.
Query string handling in Rust Worker Router
In a Rust Worker, access query parameters using req.url()?.query() which returns Option<String>. Use get_async() for async route handlers. The query string can be checked with if let Some(text) = req.url()?.query() to determine if parameters were passed.
Image transformation fetch options structure
Image transformations in a Worker are applied by passing an options object to fetch() with structure: { cf: { image: { width: number, height: number, draw: array } } }. The draw array contains objects with url (overlay image URL) and left (left position in pixels) properties.
Dynamic query parameters in Worker image overlays
To make image overlays dynamic, iterate through url.searchParams.values() and pass each parameter to the overlay image URL as a query parameter. Use for (const title of url.searchParams.values()) to loop through parameters and fetch the modified image with the parameter appended to the overlay URL like ?${title}.
URL encoding handling in Rust Worker
Use the urlencoding crate to decode URL-encoded parameters in a Rust Worker. Call urlencoding::decode(&text) which returns a Result type. Map errors using .map_err(|_| worker::Error::BadEncoding)?. This handles text like '+' which represents spaces in URL-encoded format.