Built with
The stack
Every service resell.store talks to, what it does here, and what you lose without it. Only Postgres and an auth secret are truly required: the rest switch features on.
Every service
| Service | Role here | What it unlocks | Needed? |
|---|---|---|---|
| PayPal | Multiparty payments: sellers connect, orders paid to them with our fee, money held until delivery | Real checkout (PayPal or guest card), escrow, automatic payouts, refunds | Optional: a test checkout without it |
| AI model (Anthropic by default, via the AI SDK) | Identifies items, prices them, writes listings, answers buyers, words counters | Every agent | Optional: research falls back to plain numbers |
| Channel3 | Product catalog: what it is, new and resale prices, maker photos | The catalog and resale research steps | Optional |
| Kernel | Cloud browsers reading eBay, Poshmark and Depop listings | Live comps and the shopping sidekick | Optional |
| Render | Web service, Postgres, Workflows and a Cron Job | Hosting with store subdomains, retried timers that move money | Where it runs; locally, a cron route does the timers |
| Postgres + pgvector | Everything, plus listing embeddings | Search by meaning | Required |
| Jina | Embeddings for listings and searches | Semantic search | Optional: text search alone |
| Cloudflare R2 | Photo and video storage | Uploads off the database | Optional: bytes stay in Postgres |
| Resend | Sending email | Sign-in links, sale and offer emails, digests | Optional: logged instead |
| Better Auth | Sessions and email sign-in links | Accounts shared across store subdomains | Required |
| React Email | The 10 email templates | Emails that look like the app | Built in |
| MCP TypeScript SDK | The two MCP servers | Bring your own AI | Built in |
| Drizzle | Schema, queries and migrations | Type-safe data access | Built in |
Each service sits behind one file in lib/server/ with a …Configured flag (aiConfigured, channel3Configured, kernelConfigured, paypalEnabled(), r2Configured, embeddingsConfigured), so the app checks the flag instead of crashing on a missing key. The full list of variables is on Environment variables.
How they fit together
One sale, start to finish.
- Maya lists her yellow Le Creuset dutch oven. She signs in with an email link (Better Auth, sent by Resend from a React Email template) and uploads a photo, which goes to R2.
- Research. The AI model looks at the photo and names it. Channel3 finds the product and what it costs new. Kernel browsers read what the same pot is listed for on eBay, Poshmark and Depop. The model weighs it all and suggests $185.
- Published. The model writes the words. On publish, Jina embeds the listing into a pgvector column.
- Jess finds it by searching "yellow cast iron pot". Postgres full text and the vector match are merged into one ranking.
- Jess pays through PayPal. The order is made out to Maya's PayPal with resell.store's fee in it, and the money is held.
- Maya ships; Jess gets it. Jess taps "It's all good" and the money goes to Maya. If Jess never says, a Render Workflow task releases it 13 days after shipping, retrying until PayPal says yes.
Read more
PayPalSeller onboarding, held payments, the platform fee, releases, refunds and webhooks.AI modelThe models, every call site, and the guardrails around them.Channel3Catalog matches, new and used prices, maker photos.KernelCloud browsers that read live second-hand listings.RenderWeb service, Postgres, Workflows and Cron.Everything elseJina and pgvector, R2, Resend, Better Auth, React Email, MCP, Drizzle and the UI kit.