@@ -89,24 +89,41 @@ export const { generateUploadUrl, recordAsset, gcOldAssets, listAssets } =
8989{
9090 "scripts" : {
9191 "build" : " vite build" ,
92- "deploy:static" : " npm run build && npx @get-convex/self-static-hosting upload"
92+ "deploy:static" : " npx @get-convex/self-static-hosting upload --build --prod "
9393 }
9494}
9595```
9696
97- The CLI will automatically find your ` dist/ ` directory and upload to the
98- ` staticHosting ` component.
97+ ** Important:** Use ` --build ` to ensure ` VITE_CONVEX_URL ` is set correctly for
98+ production. Don't run ` npm run build ` separately before the upload command, as
99+ that would use the dev URL from ` .env.local ` .
99100
100101** CLI Options:**
101102
102103``` bash
103104npx @get-convex/self-static-hosting upload [options]
104105
105106Options:
106- -d, --dist < path> Path to dist directory (default: ./dist)
107+ -d, --dist < path> Path to dist directory (default: ./dist)
107108 -c, --component < name> Convex component name (default: staticHosting)
108- --domain < name> Domain for Cloudflare cache purge (auto-detects zone ID)
109- -h, --help Show help
109+ --prod Deploy to production Convex deployment
110+ --dev Deploy to dev deployment (default)
111+ -b, --build Run ' npm run build' with correct VITE_CONVEX_URL
112+ --domain < name> Custom domain for URL output and Cloudflare cache purge
113+ -h, --help Show help
114+ ```
115+
116+ ** Examples:**
117+
118+ ``` bash
119+ # Deploy to production with automatic build
120+ npx @get-convex/self-static-hosting upload --build --prod
121+
122+ # Deploy to production with custom domain (also purges Cloudflare cache)
123+ npx @get-convex/self-static-hosting upload --build --prod --domain mysite.com
124+
125+ # Deploy to dev (for testing)
126+ npx @get-convex/self-static-hosting upload --build
110127```
111128
112129## Deployment
@@ -115,13 +132,28 @@ Options:
115132# Make sure you're logged in to Convex
116133npx convex login
117134
118- # Deploy to Convex
135+ # Deploy your Convex backend to production first
136+ npx convex deploy
137+
138+ # Deploy static files to production
119139npm run deploy:static
140+ ```
141+
142+ Your app is now live at ` https://your-deployment.convex.site `
120143
121- # Your app is now live at:
122- # https://your-deployment.convex.site
144+ If you have a custom domain set up via Cloudflare, add ` --domain ` :
145+
146+ ``` json
147+ {
148+ "scripts" : {
149+ "deploy:static" : " npx @get-convex/self-static-hosting upload --build --prod --domain mysite.com"
150+ }
151+ }
123152```
124153
154+ This will show your custom domain in the output and automatically purge the
155+ Cloudflare cache.
156+
125157## Security
126158
127159The upload API uses ** internal functions** that can only be called via:
@@ -147,9 +179,12 @@ This interactive wizard will:
147179
1481801 . Login to Cloudflare (via wrangler)
1491812 . Let you select or add a domain
150- 3 . Configure DNS pointing to your Convex site
151- 4 . Create an API token for cache purging
152- 5 . Save credentials to ` .env.local `
182+ 3 . Detect your production Convex deployment URL
183+ 4 . Configure DNS (CNAME pointing to your Convex site)
184+ 5 . Deploy a Cloudflare Worker to handle Host header rewriting
185+ 6 . Ensure SSL/TLS mode is set to "Full" (prevents redirect loops)
186+ 7 . Set up cache purge credentials
187+ 8 . Offer to deploy your Convex backend and static files
153188
154189Then just deploy - cache is automatically purged!
155190
@@ -198,7 +233,9 @@ This lets you configure Cloudflare Page Rules separately:
198233
199234Your app will be available at ` https://yourdomain.com/app/ `
200235
201- ### Setting Up Cloudflare
236+ ### Setting Up Cloudflare (Manual)
237+
238+ If you prefer to set up manually instead of using the wizard:
202239
2032401 . ** Add your site to Cloudflare** and update your domain's nameservers
204241
@@ -211,40 +248,70 @@ Your app will be available at `https://yourdomain.com/app/`
211248 Proxy: Enabled (orange cloud)
212249 ```
213250
214- 3 . ** Configure SSL** - Set to "Full" in Cloudflare SSL/TLS settings
251+ 3 . ** Deploy a Cloudflare Worker** to rewrite the Host header (required because
252+ Convex validates the Host header matches ` *.convex.site ` ):
253+
254+ ``` js
255+ export default {
256+ async fetch (request ) {
257+ const url = new URL (request .url );
258+ const convexUrl = new URL (
259+ url .pathname + url .search ,
260+ " https://your-deployment.convex.site" ,
261+ );
262+ const headers = new Headers (request .headers );
263+ headers .set (" Host" , " your-deployment.convex.site" );
264+ return fetch (convexUrl .toString (), {
265+ method: request .method ,
266+ headers,
267+ body: request .body ,
268+ });
269+ },
270+ };
271+ ```
272+
273+ Then add a route: ` yourdomain.com/* ` → your worker
215274
216- 4 . ** (Optional) Add Page Rules** for fine-grained cache control:
275+ 4 . ** Set SSL/TLS mode to "Full"** - This is critical! "Flexible" mode will cause
276+ redirect loops because Cloudflare sends HTTP to Convex, which redirects to
277+ HTTPS.
278+
279+ 5 . ** (Optional) Add Page Rules** for fine-grained cache control:
217280 - ` /app/assets/* ` → Cache Level: Cache Everything, Edge TTL: 1 year
218281 - ` /app/* ` → Cache Level: Cache Everything, Edge TTL: 1 day
219282
220283### Cache Purging
221284
222285The CLI can automatically purge Cloudflare cache after deploying.
223286
224- ** Option 1: Use ` --domain ` flag (easiest )**
287+ ** Option 1: Use ` --domain ` flag (recommended )**
225288
226289``` bash
227290# First, login to Cloudflare via wrangler
228291npx wrangler login
229292
230293# Then deploy with your domain
231- npx @get-convex/self-static-hosting upload --domain mysite.com
294+ npx @get-convex/self-static-hosting upload --build --prod -- domain mysite.com
232295```
233296
234297The CLI will auto-detect your zone ID and purge the cache.
235298
236299** Option 2: Environment variables (for CI/CD)**
237300
301+ If you ran ` setup-cloudflare ` , the credentials are saved in ` .env.local ` .
302+ Otherwise, set them manually:
303+
238304``` bash
239305export CLOUDFLARE_ZONE_ID=" your-zone-id"
240306export CLOUDFLARE_API_TOKEN=" your-api-token"
241- npx @get-convex/self-static-hosting upload
307+ npx @get-convex/self-static-hosting upload --build --prod
242308```
243309
244310To get these values:
245311
246312- Zone ID: Found on your domain's overview page in Cloudflare
247- - API Token: Create at Account → API Tokens with "Cache Purge" permission
313+ - API Token: Create at dash.cloudflare.com/profile/api-tokens with "Cache Purge"
314+ permission
248315
249316** Option 3: Via Convex function (for advanced CI/CD)**
250317
0 commit comments