Host Atelier on Render
On this page
Deploy a private staging installation with real email and Stripe test subscriptions, then prepare a separate live installation. The supplied deployment runs a web service and a background worker from the same source revision. PostgreSQL, your domain, Resend and Stripe are configured separately.
Complete the local demo first so that you can recognize the account, team and subscription workflows you will check after deployment.
1. Prepare the installation
You need:
- A PostgreSQL 18 database reachable from your workstation and Render using a direct connection with verified TLS. For a new installation, use an empty dedicated database and credentials allowed to create its schema.
- A domain or subdomain you control, with HTTPS configured by the host.
- Resend sending-domain verification, a sending API key and a webhook.
- A selected Stripe test environment, saved subscription prices, a compatible portal and a webhook endpoint.
- A Render account and a private source repository containing the revision you intend to deploy, with Render authorized to access it. Keep runtime secrets out of the repository.
Budget for both application services, PostgreSQL, email, your domain and payment services. The worker queries PostgreSQL every 30 or 60 seconds even without visitors. These queries prevent idle suspension on services such as Neon, so include database compute between visits when choosing your plan.
Use Configure a public installation to complete a private
runtime.env file. Use APP_MODE="public", APP_ENVIRONMENT="staging" and
BILLING_MODE="stripe-test". Set the final staging domain as APP_ORIGIN before
creating provider webhooks and KIT_STAGING_ACCESS.
Both services share this configuration. Keep the installation in a Render workspace whose other services you trust. The web service accepts the client IP address supplied by Render; a service that can reach it through the private network can supply a false client IP address in that header.
The supplied render.yaml creates only these two application
services. It does not create a database, DNS records, provider accounts or backups.
Choose database backup and restore arrangements before storing data you need to retain.
2. Install and check the database
From the source folder, using Node.js 24.22.1 or later within version 24 and npm 11:
npm ci
npm run with-env -- /ABS/runtime.env doctor
npm run with-env -- /ABS/runtime.env doctor -- --connection-only
The first diagnostic validates runtime formats. The second also checks connectivity, the database server's TLS certificate and PostgreSQL version. Neither verifies mail delivery or Stripe behavior. Resolve failures before applying migrations; do not disable TLS verification to make a check pass.
On the intended empty database, install the schema and then verify it:
npm run with-env -- /ABS/runtime.env db:migrate
npm run with-env -- /ABS/runtime.env doctor -- --database
npm run with-env -- /ABS/runtime.env billing:recover -- preflight
db:migrate reports the applied migration names or that no changes were needed.
The database diagnostic compares migration names and checksums with this source copy.
The Stripe preflight must print "preflight":"compatible"; it also fixes this
database's billing environment, currency and tax mode. Read its
configuration requirements before running it.
Application startup checks the installed schema; it does not apply migrations for you. Do not edit an applied migration to repair a mismatch. Use the matching sources and investigate the database history.
3. Create the Render services
Select the Render workspace dedicated to this staging installation before creating its environment group and Blueprint.
- Review
render.yaml. Both services default tofrankfurt, thestarterplan, one instance and manual deployments. Choose the region nearest your database before creation, changing both region values when needed. - In Render, create an environment group named
atelier-runtime. Add the completed runtime variables using Add from .env, preserving the JSON values. Keep the private file as the corresponding workstation configuration. - Create the Blueprint from your source repository and select its
render.yaml. Confirm the web serviceatelier-weband workeratelier-workerboth referenceatelier-runtimeand the same source revision. - Let Render build the supplied Dockerfile. The web command is
render:web; the worker command isrender:worker. Keep these role commands and the supplied 120-second shutdown allowance. - Add the custom domain matching
APP_ORIGINto the web service, publish the DNS records Render supplies, and wait for its certificate. Disable the service's Render subdomain in Settings > Custom Domains.
The Docker build uses a non-secret placeholder database URL and does not need production credentials. Runtime secrets belong in the environment group, never build files. The Docker context excludes private directories and local environment files.
The web entry point exposes port 10000 by default, or Render's PORT, and keeps
Next.js on an internal loopback port. It admits only the configured HTTPS host.
Do not replace it with npm start or expose the internal Next.js listener: the entry
point supplies staging access and trusted request-address handling.
Staging Basic Auth protects ordinary pages and requests. Only exact POST requests
to /api/billing/stripe/webhook and /api/email/resend/webhook bypass that password;
the application still verifies provider signatures. Do not append query parameters
or a trailing slash to provider webhook URLs. A normal staging page without credentials
should return 401; an alternate hostname should be rejected.
4. Verify the deployed installation
Local checks do not exercise your hosted services. Complete this workflow on the staging installation with its configured email and Stripe accounts.
Wait for both service roles to start. A running web service alone cannot deliver queued email or maintain billing state. The worker runs billing reconciliation and email payload cleanup about every minute, and email dispatch and monitoring about every 30 seconds, subject to each pass completing.
Use a staging mailbox you control and fictional account/team content:
-
Open the custom domain, enter the staging Basic Auth credentials, and create an account. Receive and follow its verification email. The public installation has no local demo mailbox.
-
Sign in and exercise the team invitation flow with a second controlled mailbox. Verify that the invitation reaches that mailbox and can be accepted.
-
As the team owner, start a subscription using Stripe's test payment flow. Verify that the application eventually shows the paid plan and allows project creation. Check that the corresponding Stripe webhook delivery succeeded.
-
Open billing management and exercise the saved portal's plan-change and period-end cancellation behavior. Check the application after synchronization.
-
Check Resend's delivery events and its webhook delivery to the installation.
-
Inspect operational status:
npm run with-env -- /ABS/runtime.env operations -- status npm run with-env -- /ABS/runtime.env email:public -- status
Operational status may initially report workers as unknown until they complete a pass. Use Operations to interpret degraded or stale results and configure external monitoring. Keep a record of the deployed revision and the outcomes you actually observed.
5. Prepare live separately
Create a new live database and a separate runtime file. In a separate Render workspace
dedicated to the live installation, create an environment group named atelier-runtime
containing only the completed live configuration. Reuse the supplied render.yaml
with its existing service names and environment-group references. The separate
workspaces keep staging and live resources apart. The live runtime values are:
APP_ENVIRONMENT="live", the liveAPP_ORIGIN, andBILLING_MODE="stripe-live".- New installation UUID, authentication secret and email encryption key.
- Live Stripe key, prices, portal and webhook endpoint/signing secret.
- The live Resend webhook destination and its signing secret.
- No
KIT_STAGING_ACCESSand noSTRIPE_TEST_CLOCK_ID.
Run migrations, database diagnostics and the live Stripe preflight against that live
database before creating the services. Do not reuse the staging database or change its
billing mode. Then create a new Blueprint in the live workspace from the intended
source revision and follow the service and custom-domain steps above for the live
origin. Verify both deployed roles' revision and their bindings to the live workspace's
atelier-runtime group. Confirm live account email delivery and
operational status; any live Checkout exercise uses real billing and should be a
deliberate transaction.
Before inviting users, finish your application-specific content, policies and support arrangements, and verify the backup/restore and monitoring arrangements you intend to rely on. See Customize the application, Operations and Handle data requests.
Deploy a later revision
Keep the web and worker on the same revision and runtime configuration. For a change
that includes database migrations or changes the runtime contract, schedule a stop of
this installation's web and worker, allow them to drain, apply pending migrations from
the new copy, run doctor -- --database, and then deploy both roles. Confirm their
revision, startup and status after the change. Back up retained data before a migration
and use a restore approach you have tested; there is no automatic down-migration flow.
Render's Blueprint disables automatic deployment. Deploy deliberately after checking the
change. A drain-unconfirmed shutdown log is not confirmation that work stopped cleanly;
inspect the service and worker state before continuing a sensitive operation.
Hand over a customized application
Give the client or incoming maintainer the deployed source revision, dependency lockfile, migration files and applied migration record. Identify the provider accounts and resources for hosting, PostgreSQL, DNS, Stripe, Resend and monitoring, and verify that the recipient has the access needed to operate them. Transfer runtime secrets and retained recovery keys through a secure channel separate from the source delivery; agree which of your accesses remain and rotate credentials where needed using Operations.
Agree who handles alerts, backups, recovery, maintenance and user support. Pass on the
backup locations, retention settings, tested restore procedure and support contacts.
Have the recipient select the correct installation, run the diagnostics in
Operations, locate web and
worker logs, and verify alert receipt and recovery readiness before taking responsibility.
For applicable delivery rights and acceptance requirements, follow
the licence, section 3 in your source copy (LICENSE.md)
and third-party notices.
Using another host
The source can be adapted, but render:web assumes Render's ingress headers and private
network trust model. A different host needs an equivalent verified HTTPS/canonical-host
boundary, trusted client-address handling, a private Next.js listener, staging access,
background scheduling and graceful shutdown. Do not assume that copying the Dockerfile
alone provides these guarantees. The supplied Render path is the concrete procedure in
this guide; another hosting integration needs its own implementation and validation.