### Create Cloudwerk App with npm Source: https://cloudwerk.dev/getting-started/installation This snippet shows the commands to create a new Cloudwerk application using npm and then navigate into the project directory, install dependencies, and start the development server. ```bash npx @cloudwerk/create-app@latest my-app cd my-app npm install npm run dev ``` -------------------------------- ### Install Cloudwerk and Hono Packages Source: https://cloudwerk.dev/getting-started/installation Installs the core Cloudwerk packages, CLI, UI component, and Hono for manual project setup. ```bash pnpm add @cloudwerk/core @cloudwerk/cli @cloudwerk/ui hono ``` -------------------------------- ### Cloudwerk Configuration File Source: https://cloudwerk.dev/getting-started/installation Example of a basic `cloudwerk.config.ts` file, demonstrating how to import and use the defineConfig function for project configuration. ```typescript import { defineConfig } from '@cloudwerk/core'; export default defineConfig({ // Your configuration options }); ``` -------------------------------- ### Running Cloudwerk Development Server (Shell) Source: https://cloudwerk.dev/examples/blog This command starts the development server for a Cloudwerk project. It's typically used during development to preview changes locally. Ensure you have pnpm installed and are in the project's root directory. ```shell pnpm dev ``` -------------------------------- ### KV Namespace Usage Source: https://cloudwerk.dev/api/bindings Examples of how to perform common operations on a KV namespace, such as getting, putting, deleting, and listing keys. ```APIDOC ## KV Namespace Usage ### Description Examples demonstrating common operations for Cloudflare Workers KV, including retrieving values (with different types), storing data, setting expirations and metadata, deleting keys, and listing keys with optional prefixes. ### Method N/A (Usage examples) ### Endpoint N/A ### Parameters N/A ### Request Example ```javascript // Get value const value = await context.kv.get('key'); const jsonValue = await context.kv.get('key', 'json'); const streamValue = await context.kv.get('key', 'stream'); // Set value await context.kv.put('key', 'value'); await context.kv.put('key', JSON.stringify(data)); // With expiration await context.kv.put('key', 'value', { expirationTtl: 3600, // 1 hour in seconds }); // With metadata await context.kv.put('key', 'value', { metadata: { createdAt: Date.now() }, }); // Delete await context.kv.delete('key'); // List keys const keys = await context.kv.list(); const prefixedKeys = await context.kv.list({ prefix: 'user:' }); ``` ### Response N/A ``` -------------------------------- ### Create Cloudwerk App with pnpm Source: https://cloudwerk.dev/getting-started/installation This snippet demonstrates how to create a new Cloudwerk application using pnpm, change into the project directory, install dependencies, and run the development server. ```bash pnpm dlx @cloudwerk/create-app my-app cd my-app pnpm install pnpm dev ``` -------------------------------- ### Full Cloudwerk Project Configuration Example Source: https://cloudwerk.dev/reference/cloudwerk-config A comprehensive example of a `cloudwerk.config.ts` file, demonstrating various configuration options including app directory, public directory, build settings, database configuration, authentication providers, queues, durable objects, triggers, and rendering. ```typescript // cloudwerk.config.ts import { defineConfig } from '@cloudwerk/core'; import type { Database } from './lib/db/schema'; export default defineConfig({ appDir: 'app', publicDir: 'public', outDir: '.cloudwerk', dev: { port: 8787, open: true, }, build: { minify: process.env.NODE_ENV === 'production', sourcemap: true, treeshake: true, }, database: { binding: 'DB', migrationsDir: 'migrations', schema: {} as Database, }, auth: { session: { storage: 'kv', namespace: 'SESSIONS', maxAge: 60 * 60 * 24 * 7, cookie: { name: 'session', httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', }, }, providers: { github: { clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, scopes: ['user:email'], }, }, }, queues: { EMAIL_QUEUE: { handler: './workers/email-queue.ts', }, }, durableObjects: { RATE_LIMITER: { class: './workers/rate-limiter.ts', className: 'RateLimiter', }, }, triggers: { handler: './workers/triggers.ts', }, rendering: { streaming: true, renderer: 'hono-jsx', }, }); ``` -------------------------------- ### Install Dependencies Source: https://cloudwerk.dev/examples/linkly This command installs all the necessary project dependencies using the pnpm package manager. ```bash pnpm install ``` -------------------------------- ### Implement Passkey Signup Form with Hono JSX Source: https://cloudwerk.dev/guides/authentication/passkey-setup This client-side component handles user signup using Passkeys. It interacts with server endpoints to get registration options, calls the WebAuthn API to create a credential, and then verifies the credential with the server before redirecting the user. It manages form state, loading indicators, and error handling. ```tsx "use client" import { useState } from 'hono/jsx' export default function PasskeySignupForm() { const [name, setName] = useState('') const [email, setEmail] = useState('') const [error, setError] = useState(null) const [loading, setLoading] = useState(false) const handleSubmit = async (e: Event) => { e.preventDefault() setError(null) setLoading(true) try { // Step 1: Get registration options from server const optionsRes = await fetch('/auth/passkey/register/options', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email.trim(), name: name.trim() }), credentials: 'include', }) if (!optionsRes.ok) { const err = await optionsRes.json().catch(() => ({})) throw new Error(err.error || 'Failed to get registration options') } const options = await optionsRes.json() // Step 2: Call WebAuthn API to create credential const credential = await navigator.credentials.create({ publicKey: { ...options, challenge: base64UrlToBuffer(options.challenge), user: { ...options.user, id: base64UrlToBuffer(options.user.id), }, excludeCredentials: options.excludeCredentials?.map((c) => ({ ...c, id: base64UrlToBuffer(c.id), })), }, }) as PublicKeyCredential | null if (!credential) { throw new Error('Passkey creation was cancelled') } const response = credential.response as AuthenticatorAttestationResponse // Step 3: Verify with server const verifyRes = await fetch('/auth/passkey/register/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ credential: { id: credential.id, rawId: bufferToBase64Url(credential.rawId), response: { clientDataJSON: bufferToBase64Url(response.clientDataJSON), attestationObject: bufferToBase64Url(response.attestationObject), transports: response.getTransports?.() ?? [], }, type: credential.type, }, userId: options.user.id, }), credentials: 'include', }) if (!verifyRes.ok) { const err = await verifyRes.json().catch(() => ({})) throw new Error(err.error || 'Registration failed') } // Success - redirect to dashboard window.location.href = '/dashboard' } catch (err) { setLoading(false) if (err instanceof Error) { if (err.name === 'NotAllowedError') { setError('Passkey creation was cancelled or not allowed') } else { setError(err.message) } } else { setError('An error occurred') } } } return (
{error &&
{error}
} setName(e.target.value)} placeholder="Jane Smith" /> setEmail(e.target.value)} placeholder="[email protected]" />
) } ``` -------------------------------- ### Testing Example with Vitest Source: https://cloudwerk.dev/api/triggers An example of testing a trigger handler using Vitest, demonstrating the use of mock event and context factories to simulate a scheduled event and verify database interactions. ```typescript import { describe, it, expect, vi } from 'vitest' import { mockScheduledEvent, mockTriggerContext } from '@cloudwerk/trigger/testing' import trigger from './daily-cleanup' describe('daily-cleanup trigger', () => { it('should clean up expired records', async () => { const event = mockScheduledEvent({ cron: '0 0 * * *' }) const ctx = mockTriggerContext({ env: { DB: mockD1Database() }, }) await trigger.handle(event, ctx) expect(ctx.env.DB.prepare).toHaveBeenCalledWith( expect.stringContaining('DELETE FROM') ) }) }) ``` -------------------------------- ### Home Page Component Source: https://cloudwerk.dev/getting-started/installation Example of a simple home page component (`app/page.tsx`) for a Cloudwerk application, rendering a welcome message. ```typescript export default function HomePage() { return (

Welcome to Cloudwerk

Your full-stack framework for Cloudflare Workers.

); } ``` -------------------------------- ### Manual Project Initialization Source: https://cloudwerk.dev/getting-started/installation Commands to manually create a new project directory, navigate into it, and initialize a new project using pnpm. ```bash mkdir my-app && cd my-app pnpm init ``` -------------------------------- ### Implement Cloudwerk Security Middleware Source: https://cloudwerk.dev/guides/security Quick start example for integrating Cloudwerk's security middleware into an application. This setup enables CSRF protection, X-Requested-With validation, and security headers. ```typescript import { securityMiddleware } from '@cloudwerk/security/middleware' export const middleware = securityMiddleware({ allowedOrigins: ['https://myapp.com'], }) ``` -------------------------------- ### API Route for Posts (TypeScript) Source: https://cloudwerk.dev/getting-started/quick-start An API route handler for managing posts. It supports GET requests to retrieve all posts and POST requests to create a new post with a unique ID and timestamp. Requires `@cloudwerk/core` for `DB` binding and `json` helper. ```typescript import { DB } from '@cloudwerk/core/bindings' import { json } from '@cloudwerk/core' export async function GET() { const { results: posts } = await DB .prepare('SELECT * FROM posts ORDER BY created_at DESC') .all() return json(posts)} export async function POST(request: Request) { const body = await request.json() const id = crypto.randomUUID() await DB .prepare('INSERT INTO posts (id, title, content, created_at) VALUES (?, ?, ?, ?)') .bind(id, body.title, body.content, new Date().toISOString()) .run() return json({ id, title: body.title }, { status: 201 })} ``` -------------------------------- ### Install Cloudwerk Auth Package Source: https://cloudwerk.dev/guides/authentication Installs the necessary @cloudwerk/auth package using pnpm. This is the first step to integrating authentication into your project. ```bash pnpm add @cloudwerk/auth ``` -------------------------------- ### Full CloudWerk Application Configuration Example Source: https://cloudwerk.dev/api/configuration A comprehensive example of a CloudWerk application configuration file (`cloudwerk.config.ts`). It includes settings for app directory, public directory, output directory, development and build options, database binding, authentication, queues, durable objects, triggers, and rendering. ```typescript // cloudwerk.config.ts import { defineConfig } from '@cloudwerk/core'; export default defineConfig({ appDir: 'app', publicDir: 'public', outDir: '.cloudwerk', dev: { port: 8787, open: true, }, build: { minify: true, sourcemap: true, treeshake: true, }, database: { binding: 'DB', migrationsDir: 'migrations', }, auth: { session: { storage: 'kv', namespace: 'SESSIONS', maxAge: 60 * 60 * 24 * 7, cookie: { name: 'session', httpOnly: true, secure: true, sameSite: 'lax', }, }, }, queues: { EMAIL_QUEUE: { handler: './workers/email-queue.ts', }, }, durableObjects: { RATE_LIMITER: { class: './workers/rate-limiter.ts', className: 'RateLimiter', }, }, triggers: { handler: './workers/triggers.ts', }, rendering: { streaming: true, renderer: 'hono-jsx', }, }); ``` -------------------------------- ### R2 Bucket Configuration and Usage (TOML, JavaScript) Source: https://cloudwerk.dev/api/bindings Demonstrates how to configure Cloudflare R2 object storage in wrangler.toml and provides JavaScript examples for interacting with R2 buckets, including getting, putting, deleting, listing, and heading objects. ```toml # wrangler.toml [[r2_buckets]] binding = "R2" bucket_name = "my-bucket" ``` ```javascript // Get object const object = await context.r2.get('path/to/file.txt'); if (object) { const text = await object.text(); const arrayBuffer = await object.arrayBuffer(); const blob = await object.blob(); } // Put object await context.r2.put('path/to/file.txt', 'Hello, World!'); await context.r2.put('path/to/file.txt', fileStream, { httpMetadata: { contentType: 'text/plain', }, }); // Delete object await context.r2.delete('path/to/file.txt'); // List objects const objects = await context.r2.list(); const prefixedObjects = await context.r2.list({ prefix: 'uploads/', limit: 100, }); // Head (metadata only) const head = await context.r2.head('path/to/file.txt'); ``` ```typescript interface R2Bucket { get(key: string): Promise; put(key: string, value: ReadableStream | ArrayBuffer | string, options?: R2PutOptions): Promise; delete(key: string): Promise; list(options?: R2ListOptions): Promise; head(key: string): Promise; } ``` -------------------------------- ### Create Image Transformer Example Source: https://cloudwerk.dev/api/images An example of creating an image transformer using `createImageTransformer` from '@cloudwerk/images'. It configures allowed origins, defines named presets like 'thumbnail' and 'hero', and sets default transformation options. ```typescript import { createImageTransformer } from '@cloudwerk/images' export const GET = createImageTransformer({ allowedOrigins: ['https://images.mysite.com'], presets: { thumbnail: { width: 100, height: 100, fit: 'cover' }, hero: { width: 1920, height: 1080, fit: 'cover' }, }, defaults: { format: 'auto', quality: 85, }, }) ``` -------------------------------- ### Basic Cloudwerk Configuration Setup Source: https://cloudwerk.dev/api/configuration Initializes the Cloudwerk application configuration using the `defineConfig` function. This is the entry point for customizing application settings. ```typescript import { defineConfig } from '@cloudwerk/core'; export default defineConfig({ // Configuration options }); ``` -------------------------------- ### Install Development Dependencies Source: https://cloudwerk.dev/getting-started/installation Installs necessary development dependencies for Cloudwerk projects, including Wrangler for Cloudflare deployment and TypeScript support. ```bash pnpm add -D wrangler typescript @types/node ``` -------------------------------- ### Start Development Server with Cloudwerk CLI Source: https://cloudwerk.dev/api/cli Starts the Cloudwerk development server with hot reload capabilities. It accepts an optional path to the project and several options to customize the server's behavior, such as port, host, configuration file, and verbosity. ```bash # Start dev server cloudwerk dev # Custom port cloudwerk dev --port 3000 # All interfaces cloudwerk dev --host 0.0.0.0 # With custom config cloudwerk dev --config cloudwerk.staging.ts ``` -------------------------------- ### Cloudflare Bindings Configuration (TOML) Source: https://cloudwerk.dev/guides/authentication/passkey-setup This TOML snippet shows how to configure Cloudflare bindings in `wrangler.toml`. It defines KV namespaces for sessions and challenges, and D1 databases for user and credential storage, essential for the passkey authentication setup. ```toml # KV namespace for sessions and challenges [[kv_namespaces]] binding = "AUTH_SESSIONS" id = "your-kv-namespace-id" # D1 database for users and credentials [[d1_databases]] binding = "DB" database_name = "my-app-db" database_id = "your-database-id" ``` -------------------------------- ### D1 Database Usage Source: https://cloudwerk.dev/api/bindings Examples of how to query a D1 database using the query builder, raw queries, and batch queries. ```APIDOC ## D1 Database Usage ### Description Examples demonstrating how to interact with the D1 database, including using the query builder, executing raw SQL queries, and performing batch operations. ### Method N/A (Usage examples) ### Endpoint N/A ### Parameters N/A ### Request Example ```javascript // Query builder (recommended) const users = await context.db .selectFrom('users') .where('status', '=', 'active') .execute(); // Raw queries const result = await context.env.DB .prepare('SELECT * FROM users WHERE id = ?') .bind(userId) .first(); // Batch queries const results = await context.env.DB.batch([ context.env.DB.prepare('SELECT * FROM users'), context.env.DB.prepare('SELECT * FROM posts'), ]); ``` ### Response N/A ``` -------------------------------- ### Passkey Provider Configuration Source: https://cloudwerk.dev/guides/authentication/passkey-setup Configuration options for the Passkey authentication provider. ```APIDOC ## Passkey Provider Options The passkey provider accepts the following configuration options: ### Parameters #### `rpName` - **Type**: `string` - **Required**: Yes - **Description**: Display name shown in browser prompts. #### `rpId` - **Type**: `string` - **Required**: No - **Default**: `window.location.hostname` - **Description**: Your domain (no protocol/port). Must match exactly for existing passkeys. #### `origin` - **Type**: `string | string[]` - **Required**: No - **Default**: `window.location.origin` - **Description**: Allowed origins for authentication. #### `authenticatorAttachment` - **Type**: `'platform' | 'cross-platform'` - **Required**: No - **Description**: Preference for authenticator type. `platform` uses built-in authenticators (e.g., Touch ID, Face ID), `cross-platform` uses external authenticators (e.g., USB security keys). `undefined` allows both. #### `userVerification` - **Type**: `'required' | 'preferred' | 'discouraged'` - **Required**: No - **Default**: `'preferred'` - **Description**: Biometric requirement level for user verification. #### `residentKey` - **Type**: `'required' | 'preferred' | 'discouraged'` - **Required**: No - **Default**: `'required'` - **Description**: Requirement level for discoverable credentials. #### `timeout` - **Type**: `number` - **Required**: No - **Default**: `60000` - **Description**: Operation timeout in milliseconds. #### `kvBinding` - **Type**: `string` - **Required**: Yes - **Description**: KV binding name for challenges, as defined in `wrangler.toml`. #### `d1Binding` - **Type**: `string` - **Required**: Yes - **Description**: D1 binding name for credentials, as defined in `wrangler.toml`. ### Example Usage (Development) ```typescript import { defineProvider, passkey } from '@cloudwerk/auth/convention' export default defineProvider( passkey({ rpName: 'My App', rpId: 'localhost', origin: 'http://localhost:3000', authenticatorAttachment: 'platform', userVerification: 'preferred', kvBinding: 'AUTH_SESSIONS', d1Binding: 'DB', }) ) ``` ### Example Usage (Production) ```typescript import { defineProvider, passkey } from '@cloudwerk/auth/convention' export default defineProvider( passkey({ rpName: 'My App', rpId: 'myapp.com', // Your production domain origin: 'https://myapp.com', // HTTPS required in production authenticatorAttachment: 'platform', userVerification: 'preferred', kvBinding: 'AUTH_SESSIONS', d1Binding: 'DB', }) ) ``` ``` -------------------------------- ### Example Queue Definition with Configuration Source: https://cloudwerk.dev/api/queues An example demonstrating how to define a queue consumer for `OrderMessage` with specific configuration settings. This includes batch size, retry parameters, dead letter queue, and batch timeout, along with a `process` function to handle individual messages. ```typescript export default defineQueue({ config: { batchSize: 25, maxRetries: 5, retryDelay: '2m', deadLetterQueue: 'orders-dlq', batchTimeout: '10s', }, async process(message) { await processOrder(message.body) message.ack() }, }) ``` -------------------------------- ### R2 Bucket Helper (`r2`) Source: https://cloudwerk.dev/api/context Offers helper functions for interacting with R2 buckets, including getting, putting, and deleting objects. ```APIDOC ## R2 Bucket Helper (`r2`) ### Description R2 bucket helper for managing objects. ### Methods - **get**: Retrieve an object from the R2 bucket. - **put**: Upload an object to the R2 bucket. - **delete**: Remove an object from the R2 bucket. ### Example Usage ```typescript // Get object const object = await context.r2.get('path/to/file.txt'); if (object) { const text = await object.text(); } // Put object await context.r2.put('path/to/file.txt', content, { httpMetadata: { contentType: 'text/plain', }, }); // Delete await context.r2.delete('path/to/file.txt'); ``` ``` -------------------------------- ### Mock Trigger Context Example Source: https://cloudwerk.dev/api/triggers Creates a mock trigger context object for testing, allowing the simulation of environment variables and trace IDs. ```typescript const ctx = mockTriggerContext({ env: mockEnv, traceId: 'test-trace-123', }) ``` -------------------------------- ### Setting Up Credentials Source: https://cloudwerk.dev/guides/images Instructions on how to set up the necessary Cloudflare account and API token for using Cloudflare Images. ```APIDOC ## Setting Up Credentials To use Hosted Images, you need a Cloudflare account with Images enabled. 1. **Get Account ID**: Obtain your Account ID from the Cloudflare dashboard URL or Overview page. 2. **Create API Token**: Generate an API token with the `Cloudflare Images:Edit` permission. 3. **Add to Environment**: Configure your environment variables for development and production. **Development (.dev.vars):** ```bash CF_ACCOUNT_ID=abc123 CF_IMAGES_TOKEN=your-token ``` **Production (using wrangler):** ```bash wrangler secret put CF_ACCOUNT_ID wrangler secret put CF_IMAGES_TOKEN ``` ``` -------------------------------- ### Copy Markdown Functionality (JavaScript) Source: https://cloudwerk.dev/getting-started/quick-start This script enables a 'Copy Markdown' button. When clicked, it fetches the Markdown content of the current page, copies it to the clipboard, and provides visual feedback (copied/error). It also includes logic for a dropdown menu. ```javascript const e=document.querySelector("#copy-markdown"); let o="copied"; e?.addEventListener("click",async()=>{ try{ e.disabled=!0; const c=`${e.dataset.path}.md`, n=await(await fetch(c)).text(); await navigator.clipboard.writeText(n) }catch(t){ console.error(t), o="error" }finally{ e.classList.add(o), e.disabled=!1, setTimeout(()=>{ e.classList.remove(o) },3e3) } }); const s=document.querySelector("#dropdown-toggle"), r=document.querySelector("#dropdown-menu"); s?.addEventListener("click",t=>{ t.stopPropagation(), r.classList.toggle("show") }); document.addEventListener("click",()=>{ r?.classList.remove("show") }); r?.addEventListener("click",t=>{ t.stopPropagation() }); ``` -------------------------------- ### Initialize Theme Management - JavaScript Source: https://cloudwerk.dev/getting-started/quick-start This JavaScript code initializes theme management for the Cloudwerk application. It detects the user's preferred color scheme or uses a stored theme, and applies it to the document. It also provides a function to update theme pickers. ```javascript window.StarlightThemeProvider = (() => { const storedTheme = typeof localStorage !== 'undefined' && localStorage.getItem('starlight-theme'); const theme = storedTheme || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'); document.documentElement.dataset.theme = theme === 'light' ? 'light' : 'dark'; return { updatePickers(theme = storedTheme || 'auto') { document.querySelectorAll('starlight-theme-select').forEach((picker) => { const select = picker.querySelector('select'); if (select) select.value = theme; /** @type {HTMLTemplateElement | null} */ const tmpl = document.querySelector(`#theme-icons`); const newIcon = tmpl && tmpl.content.querySelector('.' + theme); if (newIcon) { const oldIcon = picker.querySelector('svg.label-icon'); if (oldIcon) { oldIcon.replaceChildren(...newIcon.cloneNode(true).childNodes); } } }); }, }; })(); ``` -------------------------------- ### Creating API Routes with route.ts in Cloudwerk Source: https://cloudwerk.dev/guides/routing Shows how to create API endpoints in Cloudwerk using `route.ts` files. This example defines GET and POST handlers for a `/api/users` endpoint. ```typescript // app/api/users/route.ts import { json } from '@cloudwerk/core'; export async function GET(request: Request, ctx: CloudwerkHandlerContext) { return json({ users: [] }); } export async function POST(request: Request, ctx: CloudwerkHandlerContext) { const body = await request.json(); return json({ created: body }, { status: 201 }); } ``` -------------------------------- ### Step Indicator Styling (CSS) Source: https://cloudwerk.dev/getting-started/installation Styles the .sl-steps component for creating numbered step indicators. It defines the appearance of step bullets, guide lines, and text alignment within each step. ```css @layer starlight.components{.sl-steps{--bullet-size: calc(var(--sl-line-height) * 1rem);--bullet-margin: .375rem;list-style:none;counter-reset:steps-counter var(--sl-steps-start, 0);padding-inline-start:0}.sl-steps>li{counter-increment:steps-counter;position:relative;padding-inline-start:calc(var(--bullet-size) + 1rem);padding-bottom:1px;min-height:calc(var(--bullet-size) + var(--bullet-margin))}.sl-steps>li+li{margin-top:0}.sl-steps>li:before{content:counter(steps-counter);position:absolute;top:0;inset-inline-start:0;width:var(--bullet-size);height:var(--bullet-size);line-height:var(--bullet-size);font-size:var(--sl-text-xs);font-weight:600;text-align:center;color:var(--sl-color-white);background-color:var(--sl-color-gray-6);border-radius:99rem;box-shadow:inset 0 0 0 1px var(--sl-color-gray-5)}.sl-steps>li:after{--guide-width: 1px;content:"";position:absolute;top:calc(var(--bullet-size) + var(--bullet-margin));bottom:var(--bullet-margin);inset-inline-start:calc((var(--bullet-size) - var(--guide-width)) / 2);width:var(--guide-width);background-color:var(--sl-color-hairline-light)}}@layer starlight.content{.sl-steps>li>:first-child{--lh: calc(1em * var(--sl-line-height));--shift-y: calc(.5 * (var(--bullet-size) - var(--lh)));transform:translateY(var(--shift-y));margin-bottom:var(--shift-y)}.sl-steps>li>:first-child:where(h1,h2,h3,h4,h5,h6){--lh: calc(1em * var(--sl-line-height-headings))}@supports (--prop: 1lh){.sl-steps>li>:first-child{--lh: 1lh}}} ``` -------------------------------- ### Configure Development Server (`dev`) Source: https://cloudwerk.dev/api/configuration Sets up the development server, including port, host, HTTPS, and auto-opening the browser. Defaults are provided for port and host. ```typescript export default defineConfig({ dev: { port: 8787, // default host: 'localhost', // default https: false, // Enable HTTPS locally open: true, // Open browser on start }, }); ``` -------------------------------- ### List Available Service Names using getServiceNames (TypeScript) Source: https://cloudwerk.dev/api/services Illustrates how to get a list of all available service names using the `getServiceNames` function from '@cloudwerk/core/bindings'. The example shows the expected output format. ```typescript import { getServiceNames } from '@cloudwerk/core/bindings' const available = getServiceNames() // ['email', 'payments', 'cache'] ``` -------------------------------- ### Define HTTP Fetch Handler for Durable Object Source: https://cloudwerk.dev/guides/durable-objects Shows how to define a Durable Object that can handle incoming HTTP requests using the `fetch` method. This allows Durable Objects to act as API endpoints. The example handles GET requests to the root path and POST requests to '/increment'. ```typescript export default defineDurableObject({ init: () => ({ value: 0 }), async fetch(request) { const url = new URL(request.url) if (request.method === 'GET' && url.pathname === '/') { return Response.json({ value: this.state.value, timestamp: Date.now(), }) } if (request.method === 'POST' && url.pathname === '/increment') { const body = await request.json() this.state.value += body.amount ?? 1 return Response.json({ value: this.state.value }) } return new Response('Not Found', { status: 404 }) }, methods: { // RPC methods are preferred over fetch async increment(amount = 1) { this.state.value += amount return this.state.value }, }, }) ``` -------------------------------- ### Root Layout Component (TypeScript) Source: https://cloudwerk.dev/getting-started/quick-start Defines the root layout for a Cloudwerk application, which wraps all pages and persists across navigation. It includes basic HTML structure, navigation links, and footer content. Requires `@cloudwerk/core` for `LayoutProps`. ```typescript import type { LayoutProps } from '@cloudwerk/core'; export default function RootLayout({ children }: LayoutProps) { return ( My Cloudwerk App
{children}

Built with Cloudwerk

); } ``` -------------------------------- ### Data Loading with `loader` Function (TypeScript) Source: https://cloudwerk.dev/getting-started/quick-start Demonstrates server-side data fetching using the `loader()` function in Cloudwerk. It retrieves the latest 10 posts from a database using a SQL query and makes them available to the page component. Requires `@cloudwerk/core` and access to the `db` binding. ```typescript import type { PageProps } from '@cloudwerk/core' import { db } from '@cloudwerk/core/bindings' export async function loader() { const { results: posts } = await db .prepare('SELECT id, title, excerpt FROM posts ORDER BY created_at DESC LIMIT 10') .all() return { posts }} interface Props extends PageProps { posts: Array<{ id: string; title: string; excerpt: string }>; } export default function HomePage({ posts }: Props) { return (

Latest Posts

); } ``` -------------------------------- ### Building Cloudwerk Application for Production (Shell) Source: https://cloudwerk.dev/examples/blog This command builds the Cloudwerk application for production deployment. It bundles server code, processes CSS, and pre-renders static pages. The output is placed in the `dist/` directory. This is a prerequisite before deploying. ```shell pnpm build ``` -------------------------------- ### Install Cloudwerk Queue Package Source: https://cloudwerk.dev/api/queues Installs the @cloudwerk/queue package using pnpm. This package provides a queue system for background jobs. ```bash pnpm add @cloudwerk/queue ``` -------------------------------- ### Install @cloudwerk/security Package Source: https://cloudwerk.dev/api/security Installs the @cloudwerk/security package using pnpm. This is the first step to integrating security features into your Cloudwerk application. ```bash pnpm add @cloudwerk/security ``` -------------------------------- ### Dynamic Route for Posts (TypeScript) Source: https://cloudwerk.dev/getting-started/quick-start Implements dynamic routing for individual blog posts based on their ID. It fetches a specific post from the database using a parameterized query and handles cases where the post is not found by throwing a `NotFoundError`. Requires `@cloudwerk/core` and access to `db` and `params`. ```typescript import type { PageProps } from '@cloudwerk/core' import { NotFoundError } from '@cloudwerk/core' import { params } from '@cloudwerk/core/context' import { db } from '@cloudwerk/core/bindings' export async function loader() { const post = await db .prepare('SELECT id, title, content FROM posts WHERE id = ?') .bind(params.id) .first() if (!post) { throw new NotFoundError('Post not found') } return { post }} interface Props extends PageProps { post: { id: string; title: string; content: string }; } export default function PostPage({ post }: Props) { return (

{post.title}

{post.content}
); } ``` -------------------------------- ### Create Test Context with Seeding Source: https://cloudwerk.dev/api/testing Demonstrates how to create a test context using `createTestContext`, including seeding the database with initial user data for testing purposes. ```typescript const ctx = await createTestContext({ // Seed database seed: async (db) => { await db.insertInto('users').values([ { id: '1', name: 'User 1' }, { id: '2', name: 'User 2' }, ]).execute(); }, }); ``` -------------------------------- ### Cloudflare Images Transformation Example Source: https://cloudwerk.dev/api/images Example demonstrating how to use the Cloudflare Images binding to upload, transform, and return an image within a worker. ```APIDOC ## POST /images/upload-and-transform ### Description Uploads an image, applies transformations using the Cloudflare Images binding, and returns the transformed image. ### Method POST ### Endpoint `/images/upload-and-transform` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **image** (File) - Required - The image file to upload and transform. ### Request Example (See code example below) ### Request Example (Code) ```javascript import { getBinding } from '@cloudwerk/core/bindings' import type { CloudflareImagesBinding } from '@cloudwerk/images' export async function POST(request: Request) { const IMAGES = getBinding('MY_IMAGES') const formData = await request.formData() const file = formData.get('image') as File // Transform the image const response = await IMAGES .input(await file.arrayBuffer()) .transform({ width: 800, rotate: 90 }) .output({ format: 'image/webp', quality: 85 }) .response() return response } ``` ### Response #### Success Response (200) Returns the transformed image. #### Response Example (Binary image data) ``` -------------------------------- ### Install Cloudwerk CLI Source: https://cloudwerk.dev/api/cli Installs the Cloudwerk CLI as a development dependency using pnpm. This command is typically run in a terminal window within your project directory. ```bash pnpm add -D @cloudwerk/cli ``` -------------------------------- ### Signup Page Component (TypeScript) Source: https://cloudwerk.dev/guides/authentication/passkey-setup Renders the signup page, checking for authentication and displaying the PasskeySignupForm. It redirects authenticated users to the dashboard. Dependencies include @cloudwerk/auth for authentication and redirection. ```typescript import { isAuthenticated, redirect } from '@cloudwerk/auth' import PasskeySignupForm from '../components/PasskeySignupForm' export async function loader() { if (isAuthenticated()) { throw redirect('/dashboard') } return {} } export default function SignupPage() { return (

Create account

Already have an account? Sign in

) } ``` -------------------------------- ### Example of Generated Queue Types Source: https://cloudwerk.dev/api/queues An example of how the generated TypeScript types appear in `.cloudwerk/types/queues.d.ts` after running the `generate-types` command. It demonstrates how different queues are typed with their respective message types. ```typescript declare module '@cloudwerk/core/bindings' { interface CloudwerkQueues { email: Queue notifications: Queue analytics: Queue } } ``` -------------------------------- ### Accessing Context with Importable Helpers (JavaScript) Source: https://cloudwerk.dev/api/context Demonstrates how to use importable context helpers like `params`, `request`, and `get` within a route handler. This is the recommended approach for accessing context anywhere within a request. ```javascript import { params, request, get, set, getRequestId } from '@cloudwerk/core/context' import { json } from '@cloudwerk/core' export async function GET() { const userId = params.id const authHeader = request.headers.get('Authorization') const user = get('user') // From middleware return json({ userId, requestId: getRequestId() }) } ``` -------------------------------- ### Cloudwerk Configuration File Example Source: https://cloudwerk.dev/api/cli Cloudwerk commands by default read their configuration from `cloudwerk.config.ts`. This example demonstrates how to override the default configuration file path using the `--config` option. ```bash cloudwerk dev --config cloudwerk.production.ts ``` -------------------------------- ### D1 Database Migration SQL Example Source: https://cloudwerk.dev/guides/database This SQL code defines a migration to create a 'users' table with common fields like id, email, name, and timestamps, including an index on the email column. ```sql -- migrations/0001_create_users.sql CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, email TEXT UNIQUE NOT NULL, name TEXT NOT NULL, password_hash TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX idx_users_email ON users(email); ``` -------------------------------- ### Install Vitest and Cloudflare Workers Pool (pnpm) Source: https://cloudwerk.dev/api/testing This command installs the necessary dependencies for testing Cloudflare Workers using Vitest and the Cloudflare Workers pool. It uses the pnpm package manager. ```bash pnpm add -D vitest @cloudflare/vitest-pool-workers ``` -------------------------------- ### Get a Typed Service by Name using getService (TypeScript) Source: https://cloudwerk.dev/api/services Shows how to retrieve a typed service instance using the `getService` function from '@cloudwerk/core/bindings'. It defines an `EmailService` interface and then gets an instance of it. ```typescript import { getService } from '@cloudwerk/core/bindings' interface EmailService { send(params: { to: string; subject: string; body: string }): Promise<{ success: boolean }> } const email = getService('email') const result = await email.send({ to: '...', subject: '...', body: '...' }) ``` -------------------------------- ### Client-Side Form Submission with Fetch Source: https://cloudwerk.dev/guides/forms-and-actions Demonstrates how to submit a form using JavaScript's Fetch API for a more dynamic user experience. ```APIDOC ## Client-Side Form Submission with Fetch ### Description This example shows how to handle form submissions asynchronously using the Fetch API in JavaScript. It prevents the default form submission, sends the form data, and handles success or error responses. ### Method POST (handled by the `fetch` call) ### Endpoint `/api/contact` (example endpoint) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body Form data will be sent as `FormData`. ### Request Example ```javascript async function handleSubmit(e) { e.preventDefault() const form = e.currentTarget const response = await fetch('/api/contact', { method: 'POST', body: new FormData(form), }) if (response.ok) { // Handle success form.reset() } else { // Handle error const error = await response.json() console.error(error) } } function ContactForm() { return (