Developers

How resell.store is built

What the pieces are, where a request ends up, and where to read next if you want to run it, change it or deploy your own.

What it is

resell.store is a marketplace where every seller gets their own shop on a subdomain, like maya.resell.store, and an AI agent that researches prices, writes listings, answers buyers and haggles within limits the seller sets. Buyers pay through PayPal, the money is held until the item arrives, and then it's released to the seller.

It was built for the PayPal AI Hackathon, and it's open source under the MIT license. The code is on GitHub.

The moving parts

It's deliberately small: one app, one database, one job runner.

  • One Next.js app (apps/app) serves everything people and programs reach: the marketplace, every store subdomain, the seller app, checkout, the public API, these docs and the hosted MCP servers. proxy.ts looks at the host name and sends each request to the right part of the app.
  • Postgres with pgvector holds all of it, including uploads when there's no object storage. The schema and migrations live in packages/db (Drizzle).
  • A Render Workflow (apps/app/workflows/main.ts) runs the timed jobs: expiring offers, reminders, cancelling unshipped orders, releasing held money, digests and webhook retries. A Render Cron Job starts it every 15 minutes. Without Render, one HTTP call runs the same jobs in-process.
  • Work that shouldn't slow a page down (research, the store agent's answers, counter-offers, emails) runs in the web process after the response is sent.
  • Packages beside the app: @repo/db, @repo/ui (the design system), @repo/email (React Email templates) and @repo/mcp (the MCP servers, built on the public API).

Where a request goes

One deployment answers on the root domain and a wildcard. The host decides which part of the app handles the request; the path does the rest.

RequestHandled by
resell.store/discoverapp/(market): the public marketplace
resell.store/homeapp/(app): the seller app, behind sign-in
resell.store/list/[id]/researchapp/(workspace): the listing workspace
resell.store/checkout/[listing]app/(checkout): buying and offers
maya.resell.store/dutch-ovenapp/store/[store]/[listing], rewritten from the subdomain
api.resell.store/v1/listingsapp/api/v1/[[...path]] → lib/server/api
docs.resell.store/devapp/docs/dev (also at resell.store/docs/dev)
mcp.resell.store/u/[token]app/api/mcp/[[...path]] → @repo/mcp
resell.store/api/paypal/webhookPayPal's webhook, lib/server/paypal-webhook.ts

Outside services

Only Postgres and an auth secret are required. Every other service switches a feature on, and the app has a fallback without it, so you can run the whole thing locally with no keys at all.

ServiceWhat it does here
AI model (Anthropic by default, via the AI SDK)Identifies items, prices them, writes listings, runs the listing chat, the store agent and the negotiator's wording
Channel3Product catalog: what an item is, what it costs new, second-hand offers
KernelHeadless browsers that read public listings on eBay, Poshmark and Depop for comps and the Shopping sidekick
JinaEmbeddings for semantic search, stored in pgvector
PayPal (sandbox)Checkout, the platform fee, held money, payouts, refunds and disputes
ResendEmail: sign-in links and notifications
Cloudflare R2Photo and video uploads
RenderHosting: the web service, Postgres, the workflow and the cron job

Where to go next