Complete the website and deploy
Complete the website pages and production configuration, deploy the PDF Worker and main site, and verify the launch.
The previous articles implemented the core features, quota limits, and payment integration. This article completes the pages and production configuration, deploys the services, and verifies the main flows on the production domain.
Complete the pages and components
The website's basic functionality is complete. Next, refine the pages and components to make the site look better and more professional.
The details depend on your preferences and requirements. Saavo already provides most of the pages and components, so adjust and refine them as needed. In many cases, AI can improve their appearance, followed by human review and verification.
The following pages and resources need updating:
- Homepage
- Pricing page
- About page
- Terms, Privacy, and Cookie pages
- Affiliate page
- Blog content
- Documentation content
- Products page in the user dashboard
- Icons, OG images, favicons, and other resources in the public directory
- Contents of llms.txt
Once these pages are ready, if you added or changed components, you should use saavo-localize-components to handle internationalization so that the components support multiple languages.
Each page also needs its SEO information completed. You can ask AI to generate it from the page content using hooks such as useSeoMeta and useSchemaOrg.
Prepare for launch
The features are implemented, but one final step remains before launch: replace development test settings with production configuration. Domain names, callback URLs, and keys are often more likely sources of problems here than code.
Stripe was configured in the previous article. The order below is recommended for the remaining services. Detailed setup instructions are in Optional services. This section only covers what WebpageToPDF needs before launch.
Choose the production domain
First, decide which domain the website will use in production. After deploying the Worker, follow Configure a domain to set up DNS and attach the domain. The address provided by workers.dev is suitable for temporary testing. Use your own domain for launch.
Choose the domain early because Turnstile and OAuth will need it later. WebpageToPDF uses webpagetopdf.dev, which also appears in the callback examples below. If your project uses a different domain, replace every occurrence with your own.
Configure Resend
Sign-up verification, password recovery, and security notifications all require email. Follow Configure Resend to verify the sending domain and create an API Key. Add RESEND_API_KEY, the sender address, and the support email address to the production configuration.
After deployment, you should test the complete sign-up and password recovery flows with a real email address. Sending successfully is only the first step. Also check the sender name, links in the message body, and whether messages are caught by spam filters.
Configure Turnstile
Turnstile blocks bulk sign-ups and automated requests. Follow Configure Turnstile to create a site for the production domain, then set CLOUDFLARE_TURNSTILE_SITE_KEY and CLOUDFLARE_TURNSTILE_SECRET_KEY in production.
The test keys used during local development only help debug the flow. They provide no real protection and must be replaced with live keys before launch.
Configure GitHub OAuth
To support GitHub sign-in, follow Configure GitHub OAuth to create an OAuth App. Set the production callback URL to https://webpagetopdf.dev/api/auth/oauth2/github, then add GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET to the production configuration.
After deployment, sign in with both a new account and an existing registered account. Confirm that this neither creates duplicate users nor fails because of matching email addresses.
Configure Google OAuth
To support Google sign-in, follow Configure Google OAuth to create a web application client. Set the authorized origin to https://webpagetopdf.dev and the callback URL to https://webpagetopdf.dev/api/auth/oauth2/google, then add GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to the production configuration.
If Google One Tap is enabled, test it separately on the production domain after deployment. Browser privacy settings, third-party cookies, and HTTPS can all affect whether it appears. Checking ordinary Google sign-in alone is not enough.
Prepare application resources and production configuration
Store all the keys and addresses above in .env.production. Do not commit them to Git or change them only in the Cloudflare dashboard. Prepare the complete configuration now so it can be synchronized to Cloudflare during deployment.
WebpageToPDF also uses a separate PDF Worker. Before deployment, establish its deployment command, Service Binding name, and environment variables. Saavo's general deployment process cannot automatically identify these application-specific dependencies, so they need separate handling during deployment.
Finally, run through the main features as an anonymous user, a registered user, and a Pro user. Confirm that the three conversion modes, free trial, quota consumption, and paid access match the earlier product design. Also verify whether failed conversions consume quota according to the established rules.
The product features and launch configuration are now ready. Next, deploy the project.
Deploy
Stripe, Resend, Turnstile, and third-party sign-in have been configured, and their production keys are in .env.production. This section handles the remaining Cloudflare deployment, without recreating products, webhooks, or OAuth applications.
Deploy the PDF Worker
WebpageToPDF uses a separate PDF Worker that Saavo's deployment script does not create automatically. If it has not been deployed, deploy it to the same Cloudflare account first, then confirm that the main project's Service Binding name matches the actual Worker. If you deployed it while migrating features, verify the configuration and skip this step.
Check the Cloudflare account
In the project directory, check which account Wrangler is signed in to:
npx wrangler whoamiIf you are not signed in, or the displayed account is not the one intended for WebpageToPDF, run:
npx wrangler loginKeeping the production domain, R2, and PDF Worker in this account will make resource creation and service bindings easier later.
Complete the initial deployment
Once you have confirmed the account, run:
npm run deploy:initThe project has only run saavo:init for local development and has no remote resources yet, so use deploy:init here. The script reads the existing .env.production, fills in missing deployment configuration, creates and binds D1, KV, R2, and Queue resources, initializes the remote databases, deploys the Worker, and finally checks that the website is accessible.
You do not need to reenter the Resend, Turnstile, and Stripe settings you already provided. Follow the terminal prompts to confirm them. Do not manually create another set of resources with the same names in the Cloudflare dashboard. See Initial deployment for the complete terminal walkthrough.
The initial deployment uses a workers.dev address. Once the terminal reports success, open that address and check that the homepage does not return a 500 error before attaching the production domain. Full business flows such as PDF conversion can be tested after the domain switch.
Switch to the production domain
WebpageToPDF's production address is https://webpagetopdf.dev. Switch to it with:
npm run domain:set -- https://webpagetopdf.devThis command updates the production site URL, adds a Custom Domain to the Worker, and reruns validation and deployment. Before running it, confirm that webpagetopdf.dev has been added to the current Cloudflare account. See the earlier domain configuration guide.
Check third-party services
Once the domain is active, check the production addresses in each platform again:
| Service | Production URL or hostname |
|---|---|
| Stripe Webhook | https://webpagetopdf.dev/api/webhooks/stripe |
| GitHub OAuth | https://webpagetopdf.dev/api/auth/oauth2/github |
| Google OAuth | https://webpagetopdf.dev/api/auth/oauth2/google |
| Turnstile | webpagetopdf.dev |
These were configured earlier. Only verify them here. Do not create duplicate Stripe webhooks or OAuth applications. If any keys in .env.production have changed, run:
npm run deploy:updateIf you only changed callback URLs in the GitHub, Google, or Stripe dashboards, with no changes to project code or environment variables, this step does not require redeployment.
Verify the launch
Finally, test the main flows on the production domain:
- Use a new email address to complete sign-up, email verification, sign-in, and password recovery.
- Test GitHub and Google sign-in separately. If Google One Tap is enabled, check that as well.
- Test the three PDF conversion modes as anonymous, registered, and Pro users. Confirm that quota consumption and permission limits match the earlier design.
- Confirm that purchases, webhook callbacks, and entitlement grants work in Stripe test mode. If live-mode verification is needed, use an approved low-value product to complete a transaction, then refund it through the proper process.
- Sign in to the admin dashboard and check users, orders, task logs, and Queue for problems.
See Launch verification for a more complete checklist. Once all these flows work, WebpageToPDF is ready to open to users.
For later code or production configuration changes, use npm run deploy:update. Do not run deploy:init again on the same project. For post-launch logs, scheduled tasks, and data backups, see Post-launch checks.
Checklist
Once launch verification is complete, you have finished the product development process covered by this tutorial. You can continue iterating on features from here.