01.software Docs

Deploy

Prepare credentials, origins, redirects, and verification for the framework and host you choose.

Deploy

You host your own app. 01.software is the backend it talks to, so your framework and host own deployment while this guide defines the platform-specific handoff.

01.software does not choose or run your frontend framework, hosting provider, build, or release process. Use your framework and host documentation for those steps. This guide owns only the 01.software handoff around credentials, browser origins, customer redirects, and separate verification.

Common deployment handoff

Use this section for every path in Build Options. The deployment command, environment-variable syntax, build output, and release mechanism remain owned by the application runtime and hosting provider you choose.

Build Options pathContinue with
New opinionated Next.js appUse the scoped Next.js procedure below with any host that runs the app. It is path-specific guidance, not the common contract for every build option.
Existing supported JavaScript or TypeScript projectUse that project's framework and host documentation, then apply the common credential, origin, redirect, and verification requirements below. Use the Next.js procedure only when the project is Next.js.
Existing Astro, Remix, SvelteKit, or another meta-frameworkUse the manual init output plus that framework's environment and deployment documentation. Do not translate the Next.js variable names below into a claim that they are portable.
Runtime where the TypeScript SDK does not fitUse the runtime and host's deployment process for the direct HTTP path, and follow each OpenAPI operation's declared authentication. No framework adapter or hosted runtime is supplied by 01.software.

For every path:

  1. Keep deployed application credentials separate from local development credentials. A Publishable Key may be deployed in browser code. Issue and store a separate production Secret Key only when the workload performs privileged server-side SDK, CLI, or API operations; keep it in server-side runtime configuration or the host's secret store. Do not issue an sk01_ solely for a browser-only workload or one that calls only public operations. A Human CLI pat01_ is never an application credential.
  2. If the deployed app makes browser calls, add each deployed browser origin to the workspace allowlist. Server-only calls have no browser Origin; their success does not prove the browser allowlist is correct.
  3. If the app uses hosted customer OAuth, update its customer-oauth-clients row. Register at least one exact browser Origin in allowedOrigins, at least one exact callback URI in allowedRedirectUris, and every post-logout URI the app uses in allowedLogoutUris. The OAuth origin list is checked for browser token and refresh requests when an Origin header is present; a missing header is allowed for non-browser or server requests. These exact OAuth client registries do not replace the workspace Browser API origins allowlist from item 2, and the origin, redirect, and logout entries do not replace one another.
  4. Deploy with the framework and host's own process. Verify server credential reachability, browser-origin admission, and customer sign-in separately when each applies. One passing check does not prove the others, and none records a deployed state or proves launch readiness.

Next.js template procedure

The detailed procedure below applies only to the currently registered Next.js starters and existing Next.js projects that use the same environment-variable conventions. Vercel is one example host. For every other Build Options path, keep the common handoff above and follow that runtime's own documentation.

Issue deployment credentials separately

Do not copy your local .env.local into your host. It can contain a development sk01_ with a different rotation, audit, and compromise boundary. Only workloads that make server-side SDK or CLI calls need a production sk01_.

Initial production provisioning

For the first production deployment of such a workload, issue a production key in Console and put its one-time reveal in the host's server-only secret setting. No deployment or restart belongs in this credential-preparation step: configure the host here, then use the Deploy step below for the one initial deployment and its initial-key verification. The secret is shown only once; if you lose it, create a new key instead of trying to recover it.

Rotate an already deployed workload

For a workload that is already deployed, issue a replacement in Console, copy its one-time reveal into the host's server-only secret setting, update the host to use that replacement, then deploy or restart the workload. Verify the workload works with the replacement key before you revoke the old key in Console.

The Community Forum template uses a publishable key and customer JWTs, not a template-side server secret. Do not issue or configure a production sk01_ solely for that secret-free workload.

These names apply to the Next.js template covered by this page. Other template families use their own public publishable-key convention. Keep the production secret in the host's server-only secret setting only when the workload makes server-side SDK or CLI calls:

VariableWhere it ends up
NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEYthe client bundle — this is intended and safe
SOFTWARE_SECRET_KEYserver only
checkout secrets and mode/market valuesserver only

The rule is the prefix: in a Next.js app, NEXT_PUBLIC_ is what gets inlined into browser code. Anything without that prefix stays on the server. Never put an sk01_ or another secret in a NEXT_PUBLIC_, VITE_, or REACT_APP_ variable, a command-line argument, a URL, or source control.

Never add NEXT_PUBLIC_ to the secret key to "make it work" in a component that runs in the browser. If a component needs data the publishable key cannot read, move that call to a server component or route handler.

Allow the deployed origin

Browser calls are refused unless the calling origin is on your workspace allowlist. Add your deployed URL under Browser API origins on your workspace record in Console.

https://your-app.example.com

Exact origins and one level of wildcard subdomain are accepted:

https://example.com          exact
https://*.example.com        one level of subdomain
http://localhost:3000        local development

Preview deployments get their own generated URLs. Add the pattern that covers them, or the previews will fail while production works.

An empty allowlist blocks every browser call — the list is fail-closed, not permissive-by-default. If you forget this step the deploy looks broken in a confusing way: server-rendered pages work (server-to-server requests send no Origin), and only browser calls fail.

Symptom when the origin is missing: the API responds 403 with reason origin_not_allowed — but you cannot see that reason from the browser. The 403 carries no Access-Control-Allow-Origin, so the browser withholds the response from JavaScript and leaves a generic CORS error in the console.

The preflight will not warn you first. A CORS preflight announces header names and carries none of their values, so it arrives without your publishable key, takes the unauthenticated path, and is answered 200 with Access-Control-Allow-Origin: * — from any origin, allowed or not. The rejection lands on the real request that follows.

To see the reason, send the probe below. It is not what the browser sends: the key makes it take the tenant path, which reaches the CORS decision before any per-collection access check, so a 403 here means the allowlist and nothing else.

curl -i -X OPTIONS https://api.01.software/api/products \
  -H "X-Publishable-Key: pk01_..." \
  -H "Origin: https://your-app.example.com" \
  -H "Access-Control-Request-Method: GET"
ResponseMeaning
204 with Access-Control-Allow-OriginThe origin is allowed
403 with body "reason":"origin_not_allowed"This step is the cause
200 with Access-Control-Allow-Origin: *The key header did not arrive, so nothing was tested — check the command
503Stopped at the key/tenant lookup, before the CORS check — inconclusive

Register customer OAuth origins and redirect URIs — only if you enabled customer accounts

This step applies only to hosted customer OAuth — today, the ecommerce template with customer accounts enabled. The other templates sign customers in with local email and password and need nothing registered. Check whether your app has app/api/auth/customer/callback; if it does not, skip this step.

For hosted OAuth, one customer-oauth-clients row owns three separate lists:

  • allowedOrigins requires at least one exact normalized browser Origin, such as https://your-app.example.com. The token endpoint checks it for browser-originated authorization-code exchanges and refresh requests when an Origin header is present. A missing Origin is allowed for non-browser or server requests.
  • allowedRedirectUris requires at least one exact callback URI.
  • allowedLogoutUris contains every exact post-logout URI the app uses.

The authorize page checks redirect URI and scope, not allowedOrigins. At each field's actual runtime stage, a supplied value is matched against its own list by exact string. There is no wildcard form, so an unregistered value is rejected outright:

redirect_uri is not registered for this client

Register the deployed browser Origin, callback URI, and any post-logout URIs in their matching fields. Your template's README lists the exact paths it uses.

allowedOrigins: https://your-app.example.com
allowedRedirectUris: https://your-app.example.com/api/auth/customer/callback
allowedLogoutUris: https://your-app.example.com/account
allowedLogoutUris: https://your-app.example.com/

Preview deployments get their own generated URL. Exact matching means every preview Origin, callback URI, and post-logout URI needs its own entry. Unlike the workspace Browser API origins allowlist in step 2, no wildcard pattern covers an OAuth client entry.

These registries are separate. The workspace Browser API origins in step 2 gate API CORS. The OAuth client's allowedOrigins gates browser-originated token and refresh requests when they carry an Origin header; it does not gate the authorize page, and origin-less non-browser or server requests are allowed. Its allowedRedirectUris and allowedLogoutUris gate the callback and post-logout destinations. Satisfying one does nothing for the others — skipping an OAuth client entry fails the applicable token, sign-in, or logout stage, not the workspace API CORS check.

Deploy

At this point nothing is 01.software-specific. Follow your Next.js host's deployment documentation. For example, on Vercel, import the repository, configure only the required public and server-only values from step 1 in the host settings, and deploy. Vercel is not required or preferred. This is the one deployment action for initial production provisioning. Do not paste a local environment file. Any host that runs the Next.js app can own this step — the only 01.software-specific parts are the requirements above.

After that initial deployment, verify that the workload's server-side SDK or CLI calls work with the initial production key. This verifies credential reachability only; it does not prove deployment readiness. Existing-workload rotation follows its separate replacement, deploy/restart, verification, and revocation flow in step 1.

Verify the steps separately. The scaffolded templates call the platform from the server only — no client component in any template imports the SDK, so every call runs in a server component, route handler, or server action. A deployed page that looks healthy therefore proves step 1 and says nothing about step 2: it renders identically with an empty allowlist.

What to confirmHow
Key placement (1)The deployed page renders data
No sk01_ leaked (1)Sweep the build output — see below
Origin allowed (2)Run the curl probe above against the deployed origin and read the response table

A page that renders is not enough for step 1. If you gave a secret key a NEXT_PUBLIC_ prefix to make something work, the page renders exactly the same while the key ships to every visitor. Check the build output rather than the deployed site — a leaked key usually lands in one chunk out of many, and that chunk may not be loaded on the page you happen to be looking at:

pnpm build && grep -rl 'sk01_' .next/static .next/server/app

The && is load-bearing. A failed build still leaves .next/static and .next/server/app behind from an earlier run, so a directory check would pass while the search read stale output. Chaining on the build means the search runs only against what this build produced.

No output is the acceptable answer. A hit means the key is already public and must be rotated, not just removed from the bundle.

Build with the same values the host uses. A variable defined only in your host's dashboard is absent from a local build, so a leak that depends on it will not appear here — and some, like COMMERCE_MODE, stop the build outright when missing, which the && turns into a visible failure rather than a silent pass. This finds the sk01_ secret key; other secrets have no shared prefix to search for.

Once you add your own browser-side call, loading that page confirms step 2 too.

Next Actions

On this page