Web app to run a reselling operation. It organizes everything by order and, inside each one, by the items you bought, and automatically works out what matters: real cost, margin, profit and how long it took to sell.
It started as a static page in plain JavaScript and is now built on Next.js + SQLite, with a personal login per person, data shared and synced across devices, and installable on the phone ("Add to Home Screen").
Captured from a throwaway demo instance with demo data — not real figures.
The home screen is an analytical dashboard — quick KPIs and a monthly profit chart.
| Advanced inventory table | Cash-flow forecast |
|---|---|
| Profit & categories | Partner settle-up |
|---|---|
| Order builder | Order detail |
|---|---|
| Orders list | On the phone |
|---|---|
For each item:
- Real cost — what you paid for the piece + the PayPal fee spread across the order's items + the bag
- Margin in euros and as a percentage
- Days to sell — from the goods' arrival date to the sale date
- Minimum sale price — for the minimum margin you set (e.g. 20%), it shows "don't sell below €X"
And at the business level:
- Analytical dashboard (home) — quick KPIs (total invested, net profit, average margin %, items in stock vs sold) and a monthly profit chart
- Cash-flow forecast (Sales tab) — projects money coming in (pending sales grouped by estimated receive date: ~10 days after a Vinted sale, immediate for pre-orders) against capital still tied up in transit and in stock
- Global summary: invested, unsold stock, revenue, sales profit, expenses and real profit (after everything)
- Profit per category, with bars, sell-through (% already sold) and average days per category
- Monthly chart — your profit per month, or what you received vs invested per month (toggle); on partner orders it counts your half, solo orders count in full
- Monthly report — your profit and number of sales this month vs. the previous one (click a month card to see that month's sales)
- Profit per partner — each order made with a partner splits the profit in half; solo orders are 100% yours
- Orders with purchase date, arrival date, PayPal fee and bag cost
- Partner per order — choose who it was made with (or solo); profit splits in half automatically
- Items with free-text category, size (Polo XS–XXL, football shirts S–XL), photo and notes. Photos are downscaled in the browser before upload (and iPhone HEIC is converted to JPEG, so it shows everywhere)
- Autofill from past items — type an item's name and pick a previous one to copy its photo, purchase price and category (the photo is copied, not shared)
- Order builder (tab New Order) — a draft you fill over time (each shirt with photo, name, size and quantity — they're all football shirts, so there's no category to pick); "Create order" then creates the real order (quantity N → N separate items), downloads a catalog image (grid of photos + name/size/qty) and opens the supplier's WhatsApp with the text ready
- Patches per shirt (optional) — some shirts have exclusive patches, so you can add a patch with a name and a photo (paste with ⌘/Ctrl+V too). They show small and discreet on the shirt, carry over to each created item, and appear on the catalog image and supplier text
- Pre-orders (Encomendas) — for shirts a client orders and pays upfront: you store the client, the payment date, the total cost and the final price (profit is locked in). They're auto-named
<Client> NN(a per-client counter), count as sold right away and feed every report. Tagged and filterable in the list, with their own simplified detail view. - Paste a photo (⌘/Ctrl+V) inside an order — pastes into the selected item, or creates a new item with it (and into a patch when its name field is focused); pasting over an item that already has a photo asks before replacing
- Order detail page with items as cards, large photos (click to zoom in a lightbox), mark as sold, etc.
- Bulk select — pick several items and change the category of all at once
- Advanced inventory table (Orders → Inventory) — one row per item (article, size, source order, purchase date, total cost, sale price, profit and a colour-coded status), with quick filters In transit / For sale / Sold, sortable columns and round photo thumbnails
- Search and filters — by text, partner, type (orders / pre-orders), status (in stock / sold) and category
- Recent sales — filterable by partner, showing each person's profit share
- Partners tab + settle-up per sale — each sold item of a partner order shows the profit and the amount to send = sale price ÷ 2 (the partner fronted half the cost, so half the revenue returns their cost + profit share). Mark a sale as settled and the partner's "left to send" updates live. Each partner card also shows how much they invested (half the real cost of their orders' items; pre-orders count as zero).
- Languages — the whole interface is available in Portuguese, English and Spanish; switch from the 🌐 button in the top bar or in Settings (the choice is remembered per device).
- Mark as sold in one click — small modal with price + date (suggests the minimum price and today's date)
- Stale-stock alert — items unsold for more than X days (configurable) are highlighted with a badge, and a "Not selling" list on the home page
- Expenses (chip, domain, packaging…) in their own tab, coming out of the real profit — monthly ones count for each active month, one-offs count once; each can be solo or split with a partner
- Accounts vault — stores logins/passwords per platform and per partner; passwords are encrypted (AES-256) on the server
- Automatic backups — the server saves a snapshot of the business data to
data/backups/on every change (keeps the last ~40); restore any of them from Settings. Plus manual Export as JSON or CSV (one row per item, with the calculated columns — opens straight in Excel/Sheets) and import back - Multiple users, each with their own login, sharing the same business data
- Installable on the phone — "Add to Home Screen" via the web manifest (no app store). Note: it always loads from the network — there's no offline mode
You need Node.js 24 or newer — the app uses the built-in node:sqlite module (stable without flags on 24+; on Node 22 you'd have to pass --experimental-sqlite).
npm install
npm run dev
# open http://localhost:3000The first time, create your account on the login screen. From there your partner can create their own account and you both work on the same data.
For production:
npm run build
npm startTo use the app on your phone without a domain or HTTPS, on the same Wi-Fi:
- Copy
.env.exampleto.env.localand setCOOKIE_INSEGURO=1(without this, in production the browser rejects the session cookie over HTTP and login won't work). - Start the server listening on the whole network:
npm run build npx next start -H 0.0.0.0
- Find the computer's IP (e.g.
ipconfig getifaddr en0on a Mac) and on the phone openhttp://<computer-ip>:3000.
On the phone you can also use "Add to Home Screen" to install it as an app (PWA).
When you move to a domain with HTTPS, set
COOKIE_INSEGURO=0again — it's safer.
There are two helper apps on the Desktop: ReSell and Parar ReSell.
- ReSell rebuilds the app, restarts the server (
pkillany oldnext start, thennext startagain) and openshttp://localhost:3000. Restarting every time is deliberate: it guarantees the running server is always the current build, so you never end up looking at a stale version. - Parar ReSell stops the server.
After changing the code, just click ReSell — it rebuilds and serves the new version.
There is no service worker / offline cache. An earlier version cached pages and kept showing stale versions, so it was removed — the app always loads fresh from the network. It stays installable through the web manifest ("Add to Home Screen"), it just needs a connection to the server.
Everything inside the data/ folder (created on first run, outside git):
data/resell.db— the SQLite database (orders, items, partners, expenses, accounts)data/uploads/— the item photosdata/backups/— automatic JSON snapshots of the business data (the last ~40)data/.chave— the key that encrypts the account passwords (don't lose it or share it)
Copy the data/ folder for a full backup. The Export JSON button saves the business data (orders, items, partners, expenses), but not the account passwords — those only with a copy of the DB + key.
- Next.js (App Router) — pages, API and server rendering
- SQLite via
node:sqlite— no native dependencies to compile; ships with Node - bcryptjs — login passwords hashed; AES-256-GCM (
node:crypto) for the account passwords - No UI or charting libraries: the theme (dark premium, emerald accent) is hand-written CSS and the charts are CSS bars inside the component
The app is organized by tabs at the top, each on its own page:
- Home (
/) — overview: colored summary cards, "this month" vs last month (the month cards link to that month's sales at/vendas/[mes]), monthly profit chart and a "not selling" list. - Orders (
/pedidos) — create a normal order or a pre-order (toggle), filter/search (text, partner, type, status, category) and a compact list (pre-orders are tagged). Click an order → detail (/pedidos/[id]) with items as cards, large photos (paste or upload, click to zoom), mark as sold and bulk category. Pre-orders open a simplified detail view. - New Order (
/novo-pedido) — order builder: a persistent draft of shirts (photo, name, size, quantity, and optional patches with name + photo). "Create order" makes the order (quantity → N items), downloads a catalog image and opens the supplier's WhatsApp with the text. - Profit (
/lucro) — read-only profit-per-partner summary (settle up in the Partners tab), monthly chart (profit / received vs invested, your share), profit per category, and recent sales (filterable by partner, showing each person's share). - Partners (
/socios) — manage partners and settle up per sale: each sold item of a partner order shows the profit and the amount to send (price ÷ 2); tick it as settled and the "left to send" updates. Each partner card also shows how much they invested. - Expenses (
/despesas) — recurring or one-off expenses, solo or split with a partner. - Accounts (
/contas) — logins and passwords per platform/partner (encrypted; loaded only on this page). - Settings (
/definicoes) — minimum margin, stale-stock day alert, supplier WhatsApp number, language (PT/EN/ES), automatic backups (list + restore), manual export/import and sign out.
resell-tracker/
├── app/
│ ├── layout.jsx root (html, fonts, PWA)
│ ├── login/ sign in / create account screen
│ ├── (app)/ authenticated pages (share the AppShell)
│ │ ├── layout.jsx guards the session + hands the state to AppShell
│ │ ├── page.jsx Home
│ │ ├── pedidos/ list + [id] (detail; pre-orders use a simpler view)
│ │ ├── novo-pedido/ lucro/ socios/ vendas/[mes]/ despesas/ contas/ definicoes/
│ ├── api/ endpoints (state, orders, pre-orders, items, expenses, socios, backup, export…)
│ ├── components/ AppShell (state), TopNav, pages and UI blocks
│ └── globals.css dark premium theme + emerald accent
├── lib/
│ ├── db.js SQLite connection + migrations
│ ├── repo.js reads/writes (snake_case ↔ camelCase)
│ ├── calculos.js real cost, margin, days, summaries, profit/settle-up per partner, monthly data
│ ├── backups.js on-disk snapshots: save / list / restore
│ ├── auth.js sessions and login passwords
│ ├── cripto.js encryption of account passwords (AES-256)
│ ├── fotos.js store/serve the item photos
│ └── cores.js stable color per category
├── middleware.js protects routes (no session → /login)
├── public/ manifest, service worker and icon (PWA)
└── data/ database, photos and key (generated locally)
The business state lives in a single place on the client (app/components/AppShell.jsx, provided via
context), kept alive while navigating between tabs — with optimistic editing and polling sync.
- Each expense has a date: one-off expenses count once, in their month; monthly expenses count for each month from their date up to the current month.
- A partner only bears their half of expenses marked as split with them; solo expenses are fully yours.
- Sync between devices is by polling: the app reloads the state every so often and whenever you save, so what your partner enters shows up to you shortly after.
- A hosted, multi-user version (Postgres/Supabase + cloud storage) so partners can use it from anywhere without keeping a machine on
- Sales platform per item (Vinted, OLX…) with their own fees
- Monthly goals with a progress bar
- Real-time sync (websockets) instead of polling
MIT — use, modify and share freely.