Developers

Environment variables

Every setting the app reads, whether you need it, and what happens without it. Locally they go in apps/app/.env.local (start from .env.example); on Render, in each service's Environment.

Read at build time

Anything starting NEXT_PUBLIC_ is written into the app when Next builds it, on the server as well as in the browser. Changing one on Render means a new build and deploy, not just a restart; locally, restart pnpm dev. Everything else is read when the server starts.

Core

VariableNeededWhat it doesWithout it
DATABASE_URLYesPostgres with pgvector. Locally postgres://resell:resell@localhost:5433/resell; on Render it comes from the databaseNothing works
NEXT_PUBLIC_ROOT_DOMAINYesThe marketplace host, with port if any: localhost:5689 or resell.store. Stores, links, cookies and the api/docs/mcp hosts all hang off itDefaults to localhost:5689
NODE_VERSIONRenderSet to 24 in the blueprint so Render uses Node 24Render's default Node

Sign-in

VariableNeededWhat it doesWithout it
BETTER_AUTH_SECRETYesSigns sessions and tokens. openssl rand -hex 32. The blueprint generates one and copies it to the workflowAuth fails
BETTER_AUTH_URLYesThe app's own URL: http://localhost:5689, or https://resell.storeSign-in links point at the wrong place

Email

VariableNeededWhat it doesWithout it
RESEND_API_KEYProductionSends sign-in links and every notification through ResendEmails are printed to the server log. In development the sign-in link also shows on the page; in production nobody can sign in by email
EMAIL_FROMWith ResendThe sender, on a domain verified in Resend"resell.store <hello@resell.store>"
SUPPORT_EMAILOptionalWhere problems escalated to resell.store are sent for a decisionEscalations still happen; nobody at resell.store gets an email

AI

VariableNeededWhat it doesWithout it
ANTHROPIC_API_KEYRecommendedThe AI model (Anthropic), for identifying and pricing items, writing listings, the listing chat, the store agent, the negotiator's wording and the SidekickResearch prices from catalog and comps numbers; the chat, the words step, store agent answers and the Sidekick are off; counters use a template
AI_MODELOptionalThe main model as provider:modelThe default Anthropic main model
AI_MODEL_FASTOptionalThe quick model, for the store agent, negotiator, search queries and SidekickThe default Anthropic fast model

Anthropic is the only provider registered today, so out of the box both models start anthropic:. Any other model the AI SDK supports works too: add its provider in lib/server/ai.ts and its key here. See Changing the model.

Research

VariableNeededWhat it doesWithout it
CHANNEL3_API_KEYRecommendedThe product catalog: what an item is, new prices, used offers, maker photosResearch skips the catalog step and prices from comps and the model
KERNEL_API_KEYOptionalHeadless browsers that read public listings on eBay, Poshmark and Depop. Needs ANTHROPIC_API_KEY tooNo live comps step in research; the Shopping sidekick shows Coming soon
KERNEL_MAX_BROWSERSOptionalHow many Kernel browsers may run at once; extra searches queue5, the free plan's limit
VariableNeededWhat it doesWithout it
JINA_EMBEDDING_MODEL_KEYRecommendedJina embeddings for semantic search, written when a listing is publishedSearch is Postgres full text only
JINA_EMBEDDING_MODELOptionalThe Jina model. It must give 1024-dimension vectors to fit listing.embeddingjina-embeddings-v5-text-small

Files

VariableNeededWhat it doesWithout it
R2_URLProductionThe account's S3 endpoint, https://{account_id}.r2.cloudflarestorage.comUploads are stored in Postgres (file.data)
R2_ACCESS_KEYProductionAn R2 API token's access key, with read and write on the bucketSame
R2_SECRET_ACCESS_KEYProductionIts secretSame
R2_BUCKETOptionalThe bucket nameresell-store
R2_PUBLIC_URLOptionalA public domain for the bucket (e.g. files.resell.store). /api/files/[id] then redirects there instead of streaming the fileFiles are streamed through the app

PayPal

Checkout uses PayPal when the client id, secret and partner merchant id are all set. This project only runs against the sandbox.

VariableNeededWhat it doesWithout it
PAYPAL_ENVOptionalsandbox or livesandbox
PAYPAL_CLIENT_IDFor paymentsThe Platform app's client idTest checkout: orders are real, no money moves
PAYPAL_CLIENT_SECRETFor paymentsIts secretTest checkout
PAYPAL_PARTNER_MERCHANT_IDFor paymentsThe platform's own PayPal account id (the partner)Test checkout
NEXT_PUBLIC_PAYPAL_CLIENT_IDWith PayPalSame value as PAYPAL_CLIENT_ID. Only changes wording on seller screens ("PayPal holds the buyer's money until they have it")Seller screens say it's a test checkout
PAYPAL_BN_CODEOptionalSent as PayPal-Partner-Attribution-Id on every callCalls aren't attributed to the platform
PAYPAL_WEBHOOK_IDProductionThe webhook's id from the dashboard, used to verify every deliveryEvery webhook is rejected with 401
PAYPAL_DEMO_SELLER_IDSandbox demoThe shared demo seller's merchant id, from scripts/paypal-demo-seller.mjs. Sellers who haven't connected PayPal are paid here, and "Use demo PayPal" links to itA seller's items can't be bought until they connect their own PayPal
PAYPAL_DEMO_SELLER_EMAILSandbox demoThe demo seller's sandbox login, shown on Connections so people can watch sales landNot shown
PAYPAL_DEMO_SELLER_PASSWORDSandbox demoIts passwordNot shown
PAYPAL_DEMO_BUYER_EMAILSandbox demoA sandbox buyer login, shown at checkoutNot shown
PAYPAL_DEMO_BUYER_PASSWORDSandbox demoIts passwordNot shown

Fees and timers

VariableNeededWhat it doesWithout it
PLATFORM_FEE_BPSOptionalThe platform fee in basis points of the item price (shipping is never charged). 1000 = 10%1000. A blank value also means 1000
PAYOUT_DEMO_MINUTES_PER_DAYDemo onlyMakes every "day" in the shipping, delivery and release timers this many minutes. Set it on the workflow tooReal days
AGENT_SUMMARY_HOUROptionalThe UTC hour from which the seller's daily agent summary goes out. Not in the blueprint; add it to the workflow1 (early evening in the US)

Timed jobs

VariableNeededWhat it doesWithout it
CRON_SECRETProductionRequired as Authorization: Bearer on POST /api/cron/sweep outside development. The blueprint generates oneThe sweep route answers 401 (it runs without one in development)
RENDER_API_KEYCron jobLets scripts/start-sweeps.ts start tasks on the workflow. A Render API key from your account settingsThe cron job fails; nothing timed runs
RENDER_WORKFLOW_SLUGCron jobThe workflow's slug. The blueprint fills it in from the resell-sweeps serviceresell-sweeps

Demo accounts

VariableNeededWhat it doesWithout it
DEMODemo onlySet to true to offer "Sell as" and "Shop as" on the sign-in page: shared accounts that sign in with no email. They can't publish, edit what was there, or deal with real sellers, and what they add is reset. Set it on the workflow tooNo demo accounts
DEMO_SELLER_EMAILDemo onlyThe shared seller. Must already exist with a store (the seed makes it)dana.okafor@example.com
DEMO_BUYER_EMAILDemo onlyThe shared buyerava.lindqvist@example.com
DEMO_RESET_MINUTESDemo onlyThe least time between resets. The sweep cron and the next demo sign-in reset once it has passed10
DEMO_MAX_DRAFTSDemo onlyNew drafts the demo seller may start between resets (each runs research)5

Everything else

VariableNeededWhat it doesWithout it
TEST_DATABASE_URLTestsThe tests' own database. Its name must end in _testpostgres://resell:resell@localhost:5433/resell_test
RESELL_API_KEYstdio MCPFor running @repo/mcp's dist/stdio.js yourself: a secret key or agent link tokenThe seller server won't start; the buyer server runs with public marketplace tools only
RESELL_API_URLstdio MCPWhich API the stdio server talks to, e.g. http://localhost:5689/api/v1https://api.resell.store/v1

Which service needs what

  • Web service: everything above except RENDER_API_KEY, RENDER_WORKFLOW_SLUG and the test and stdio ones.
  • Workflow (resell-sweeps): DATABASE_URL, NEXT_PUBLIC_ROOT_DOMAIN (for links in emails), BETTER_AUTH_SECRET and BETTER_AUTH_URL (the sweeps import code that sets up auth), the Resend settings and SUPPORT_EMAIL, the PayPal keys (releases and refunds), PAYPAL_DEMO_SELLER_ID, PLATFORM_FEE_BPS and PAYOUT_DEMO_MINUTES_PER_DAY. The workflow runs from source with tsx, so its NEXT_PUBLIC_ values are read at start, not at build.
  • Cron job (resell-sweeps-cron): RENDER_API_KEY and RENDER_WORKFLOW_SLUG only.
render.yaml lists all of these with sync: false for secrets, so the Blueprint asks for them on first deploy. Step by step: Deploy to Render.