@appwarden/middleware
Version:
Instantly disable all user interaction with your app deployed on Cloudflare or Vercel
293 lines (217 loc) • 8.82 kB
Markdown
name: appwarden-middleware-get-started
description: >
Install and minimally configure @appwarden/middleware for a Cloudflare or Vercel project. Covers package installation, creating an API token, wiring middleware with debug: true, verifying the heartbeat endpoint, and switching debug off after confirming the setup. Load this skill when a user is adding Appwarden to a new project for the first time.
metadata:
type: lifecycle
library: "@appwarden/middleware"
library_version: "3.16.3"
requires: []
sources:
- "appwarden/middleware:README.md"
- "appwarden/middleware:src/index.ts"
- "appwarden/middleware:src/schemas/use-appwarden.ts"
# Appwarden Middleware — Get Started
Install `@appwarden/middleware` and wire it into a Cloudflare Worker or Vercel Edge Middleware. You can do this before or after completing Appwarden organization onboarding, but you must finish onboarding to create a valid API token in the dashboard and complete the installation.
## Setup
1. Install the package:
```bash
npm install @appwarden/middleware
```
2. Create an API token in the Appwarden dashboard at `https://use.appwarden.io/?to=/settings/security` (Settings > Security). Copy it immediately — it is shown only once.
3. Store the token as a secret:
- Cloudflare: `wrangler secret put APPWARDEN_API_TOKEN` (see https://developers.cloudflare.com/workers/configuration/secrets/)
- Vercel: add `APPWARDEN_API_TOKEN` to Project Settings > Environment Variables
4. Wire the middleware with `debug: true` during first setup.
## How to Choose Cloudflare vs Vercel
Before wiring examples, detect the platform from the repo. If detection is ambiguous, ask the user.
### Detect Cloudflare
Cloudflare projects usually contain one or more of these signals:
```text
package.json:
- wrangler
- @cloudflare/workers-types
- @astrojs/cloudflare
- @react-router/cloudflare
- @tanstack/react-start
- @opennextjs/cloudflare
config files:
- wrangler.json / wrangler.jsonc / wrangler.toml
- react-router.config.ts with cloudflare adapter
- astro.config.mjs with adapter: cloudflare()
- app.config.ts referencing tanstack-start
CI files:
- .github/workflows/*.yml with cloudflare/wrangler-action
```
### Detect supported Cloudflare frameworks
If the repo is on Cloudflare, check for one of these supported adapter patterns:
```text
- Astro Cloudflare adapter: @astrojs/cloudflare
- React Router Cloudflare adapter: @react-router/cloudflare + future.v8_middleware in react-router.config.ts
- TanStack Start Cloudflare adapter: @tanstack/react-start
- Next.js Cloudflare adapter: @opennextjs/cloudflare (Next.js 15 and earlier use middleware.ts; Next.js 16+ uses proxy.ts)
```
If none of these are present, the repo is on Cloudflare but on an unsupported framework. Recommend the standalone Cloudflare Worker approach (`appwarden-middleware-cloudflare-workflow`) instead of a framework adapter.
### Detect Vercel
Vercel projects usually contain:
```text
package.json:
- next
- vercel
config files:
- vercel.json
- middleware.ts or src/middleware.ts
CI files:
- .github/workflows/*.yml with vercel/action-deploy
```
### When to ask the user
Ask when:
- The repo contains both Cloudflare and Vercel signals.
- The repo contains neither Cloudflare nor Vercel signals.
- The framework adapter is ambiguous (e.g., multiple adapters present).
Example prompt:
> Are you deploying on Cloudflare or Vercel? If Cloudflare, are you using Astro, React Router, TanStack Start, Next.js, or a custom worker?
## Core Patterns
All `createAppwardenMiddleware` examples below use `getAppwardenConfiguration(generatedConfig, overrides)`. This helper merges the domain configuration generated by `appwarden-link` with runtime overrides such as the API token and `debug`. Cloudflare examples import the generated config from `.appwarden/linked/middleware.json`; Vercel does not use `appwarden-link`, so they pass an empty generated config.
### Minimal Cloudflare Worker middleware
```typescript
import {
createAppwardenMiddleware,
getAppwardenConfiguration,
} from "@appwarden/middleware/cloudflare"
import appwardenConfig from "../.appwarden/linked/middleware.json"
export default createAppwardenMiddleware((cloudflare) =>
getAppwardenConfiguration(appwardenConfig, {
appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN,
debug: true,
}),
)
```
`appwarden-link --fqdn=your.app` writes the generated configuration to `.appwarden/linked/middleware.json`. Keep this directory out of source control.
### Minimal Vercel Edge Middleware
```typescript
import {
createAppwardenMiddleware,
getAppwardenConfiguration,
} from "@appwarden/middleware/vercel"
export default createAppwardenMiddleware(
getAppwardenConfiguration(
{},
{
appwardenApiToken: process.env.APPWARDEN_API_TOKEN,
lockPageSlug: "/maintenance",
cacheUrl: process.env.KV_URL,
debug: true,
},
),
)
export const config = {
matcher: [
"/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
],
}
```
### Verify the heartbeat endpoint
After deploying, check `https://your.app/_appwarden/heartbeat`. A clean response contains no `configErrors` and the domain is marked verified in the dashboard at `https://use.appwarden.io/?to=/settings/security` under Settings > Security.
### Switch debug off after confirming the setup
```typescript
import {
createAppwardenMiddleware,
getAppwardenConfiguration,
} from "@appwarden/middleware/cloudflare"
import appwardenConfig from "../.appwarden/linked/middleware.json"
export default createAppwardenMiddleware((cloudflare) =>
getAppwardenConfiguration(appwardenConfig, {
appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN,
debug: false,
}),
)
```
## Common Mistakes
### CRITICAL Forgetting to provide APPWARDEN_API_TOKEN as a secret
Wrong:
```typescript
export default createAppwardenMiddleware({
appwardenApiToken: "sk_test_...",
lockPageSlug: "/maintenance",
})
```
Correct:
```typescript
import {
createAppwardenMiddleware,
getAppwardenConfiguration,
} from "@appwarden/middleware/cloudflare"
import appwardenConfig from "../.appwarden/linked/middleware.json"
export default createAppwardenMiddleware((cloudflare) =>
getAppwardenConfiguration(appwardenConfig, {
appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN,
debug: true,
}),
)
```
The API token is a secret. Hardcoding it exposes the credential and prevents Appwarden from validating the lock status.
### HIGH Setting APPWARDEN_API_TOKEN as a Wrangler var instead of a secret
Wrong:
```json
{
"vars": { "APPWARDEN_API_TOKEN": "sk_..." }
}
```
Correct:
```bash
wrangler secret put APPWARDEN_API_TOKEN
```
Wrangler vars are visible in plain text in the Cloudflare dashboard. The token must be uploaded as a secret so it is encrypted and only available at runtime.
### HIGH Passing appwardenApiHostname to getAppwardenConfiguration
Wrong:
```typescript
import { getAppwardenConfiguration } from "@appwarden/middleware/cloudflare"
import appwardenConfig from "../.appwarden/linked/middleware.json"
getAppwardenConfiguration(appwardenConfig, {
appwardenApiToken: env.APPWARDEN_API_TOKEN,
appwardenApiHostname: "https://api.appwarden.io",
})
```
Correct:
```typescript
import { getAppwardenConfiguration } from "@appwarden/middleware/cloudflare"
import appwardenConfig from "../.appwarden/linked/middleware.json"
getAppwardenConfiguration(appwardenConfig, {
appwardenApiToken: env.APPWARDEN_API_TOKEN,
})
```
The `appwardenApiHostname` override is reserved for internal testing. Agents wiring adapter config should never provide it.
### MEDIUM Leaving debug disabled during initial setup
Wrong:
```typescript
export default createAppwardenMiddleware({
appwardenApiToken: process.env.APPWARDEN_API_TOKEN,
lockPageSlug: "/maintenance",
})
```
Correct:
```typescript
import {
createAppwardenMiddleware,
getAppwardenConfiguration,
} from "@appwarden/middleware/vercel"
export default createAppwardenMiddleware(
getAppwardenConfiguration(
{},
{
appwardenApiToken: process.env.APPWARDEN_API_TOKEN,
lockPageSlug: "/maintenance",
cacheUrl: process.env.KV_URL,
debug: true,
},
),
)
```
Without `debug: true`, config validation failures and lock-status checks are silent, making first-time troubleshooting difficult. Disable debug only after the heartbeat is clean.
## Next Steps
- Add a lock page: see `appwarden-middleware-lock-page`.
- Harden CSP on Cloudflare: see `appwarden-middleware-csp`.
- Run pre-launch verification: see `appwarden-middleware-verify-setup`.
- If organization onboarding is not yet complete, finish it before creating the API token: see `appwarden-middleware-onboard-organization`.