Mini Manager is an app that tidies up messy folders for you.
You point it at a folder, it looks at every file, and it works out what each one is and where it should go. You see the full list of suggested changes before anything happens. If you like them, you apply them in one click. If you change your mind, you undo them in one click.
It never deletes anything. Files you don't want are moved to an Archive folder, so you can always get them back.
- Scans a folder and reads each file's name, size and date
- Sorts files into categories using AI — Documents, Finance, Photos, Code, and so on
- Suggests better names and the right folder for each file
- Shows a confidence score for every suggestion, so you know which ones to double-check
- Flags sensitive files (passports, bank statements, ID scans) and won't move them without asking
- Remembers your corrections — fix a suggestion once and it learns for next time
- Takes rules in plain English like "put all invoices in Finance/Invoices"
- Keeps a full history so any change can be undone later
- Finds duplicates and old files you've not touched in months
- Has a chat assistant you can ask to do things like "move all my PDFs to Documents"
| Free | Pro | Business | |
|---|---|---|---|
| Price | $0 | $19/month | $49/seat/month |
| Folder scans | 250 files/month | Unlimited | Unlimited |
| AI sorting | 100/month | Unlimited | Unlimited |
| Document explanations | 3/month | 50/month | 50/month |
| Naming rules | 1 | Unlimited | Unlimited |
| Undo and Archive | Unlimited | Unlimited | Unlimited |
Undo is free on every plan, forever. We don't put safety behind a paywall.
The project has three parts in one folder:
| Folder | What it is |
|---|---|
app/, components/, lib/ |
The app you actually use, built with Next.js |
backend/api/ |
The server, built with Python and FastAPI |
website/ |
The marketing site, built with Vite |
electron/ |
Wraps the app so it runs as a Windows program |
What each part uses:
- Frontend — Next.js 16, TypeScript, Tailwind CSS v4, shadcn/ui components
- Backend — Python 3.13, FastAPI, PostgreSQL (hosted on Neon)
- AI — Groq handles file sorting, the chat assistant, conventions and onboarding. Google Gemini handles document explanations, plain-English rule compiling, and reading proof-of-payment documents.
- Login — email and password, with Google sign-in as an option. Sessions use JWT.
- Payments — Paddle for cards, plus AI-verified bank transfer (EFT) for Namibia
- Desktop — Electron
- Hosting — backend on Render, marketing site on Netlify, database on Neon
You need Node.js 18 or newer, pnpm, and Python 3.13.
This project uses pnpm, not npm. Running npm install here will fail,
because npm doesn't understand how pnpm arranges its files.
cd mini-manager-app
pnpm install
pnpm devThen open http://localhost:3000
cd mini-manager-app/backend/api
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txtThen start it from the mini-manager-app folder (not from inside backend/api,
or Python won't find the modules):
cd mini-manager-app
.\backend\api\.venv\Scripts\python.exe -m uvicorn backend.api.main:app --reload --port 8000The server runs on http://localhost:8000. Database tables are created automatically the first time it starts.
cd mini-manager-app/website
pnpm install
pnpm devCreate a file at backend/api/.env with these:
| Name | What it's for | Required |
|---|---|---|
DATABASE_URL |
Your PostgreSQL connection string | Yes |
GROQ_API_KEY |
For sorting files | Yes |
GEMINI_API_KEY |
For explanations and chat | Yes |
JWT_SECRET |
A long random string that signs login tokens | Yes |
GROQ_MODEL |
Which Groq model to use. Defaults to openai/gpt-oss-120b |
No |
FRONTEND_URL |
Your app's address, so the browser is allowed to talk to the server | No |
PADDLE_SANDBOX_API_KEY |
Payments | Only if you're taking payments |
PADDLE_WEBHOOK_SECRET |
Confirms payment messages really came from Paddle | Only if you're taking payments |
PADDLE_PRICE_ID_PRO |
The Pro plan's ID in Paddle | Only if you're taking payments |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET |
Google sign-in | Only if you want Google login |
GEMINI_MODEL |
Which Gemini model to use. Defaults to gemini-flash-lite-latest |
No |
EXTRA_CORS_ORIGINS |
Extra sites allowed to call the API, comma-separated | No |
And these if you want bank-transfer payments. They're your real banking details, so they belong in the environment, never in the repo:
| Name | What it's for |
|---|---|
EFT_ACCOUNT_NAME |
Name on the account, shown to customers |
EFT_BANK_NAME |
Bank name, shown to customers |
EFT_ACCOUNT_NUMBER |
Account number. Without it, the payment page returns 503 |
EFT_BRANCH_CODE |
Branch code. Optional — hidden if not set |
EFT_CURRENCY |
NAD for FNB Namibia, ZAR for South Africa |
EFT_ADMIN_EMAIL |
Who can reconcile payments. Must match your login email |
EFT_PROOF_EMAIL |
Optional address for customers who'd rather email their proof |
And a file at mini-manager-app/.env.local for the frontend:
| Name | What it's for |
|---|---|
NEXT_PUBLIC_PADDLE_CLIENT_TOKEN |
Loads the payment form. Safe to be public. |
NEXT_PUBLIC_PADDLE_PRICE_ID_PRO |
The Pro plan's ID |
NEXT_PUBLIC_PADDLE_ENV |
sandbox while testing, production when live |
Never put PADDLE_SANDBOX_API_KEY in a NEXT_PUBLIC_ variable. Anything
starting with NEXT_PUBLIC_ is visible to anyone using your site.
Paddle has a sandbox mode so you can practise without real money. Real cards are rejected there; use these test cards instead:
| Card number | What happens |
|---|---|
4242 4242 4242 4242 |
Payment works |
4000 0038 0000 0446 |
Payment works, with a 3D Secure step |
4000 0000 0000 0002 |
Payment is declined |
Any future expiry date and any 3-digit code will do.
One thing that catches people out: after someone pays, Paddle sends a
message to your server to confirm it. Paddle can't reach localhost, so while
you're developing you need a tunnel:
ngrok http 8000Then paste the address it gives you into the Paddle dashboard under
Developer tools → Notifications, with /api/v1/webhooks/paddle on the end.
Without this, payments go through but nobody's plan ever gets upgraded.
Namibian customers pay by instant bank transfer, and no bank offers an API that tells a server "money arrived". So an AI agent closes the loop instead.
How it works:
- The customer picks a plan and gets a reference like
MM-0042, plus your bank details - They pay from their banking app using that reference
- They upload the bank's confirmation — a PDF or screenshot
- Gemini reads the document and extracts the amount, reference, date and bank
- Plain Python decides, not the AI — it checks the reference matches, the amount is enough, the date is sensible, and the document isn't flagged as altered
- All checks pass → the plan activates immediately, marked unreconciled
- You check your bank statement and confirm on
/payments
The AI only ever reports what it sees. It never decides to grant access — that way a forged document can't argue its own case.
Be honest about the risk: proof of payment can be faked. This works because the amounts are small, access is revocable, and you reconcile daily. Don't reuse this pattern for large invoices or anything you can't take back.
The same document can never be submitted twice, uploads are capped at five per user per hour (each one costs a Gemini call), and bank details are only shown to a signed-in customer who has started a payment.
| Page | What it's for |
|---|---|
/organize |
The main one — scan a folder and apply changes |
/overview |
Summary of what's been organised |
/insights |
Duplicates, old files, storage breakdown |
/history |
Everything that's been done, with undo |
/quarantine |
Files moved to Archive, ready to restore |
/rules |
Your plain-English rules |
/documents |
Documents the AI has explained |
/settings |
Preferences, blocked folders, naming rules |
/profile |
Your name, photo, password, account |
/upgrade |
Plans and pricing |
/checkout |
Payment page — bank transfer or card |
/payments |
Owner only — reconcile EFT payments the AI verified |
Nothing is deleted. Files go to an Archive folder instead. You can always put them back from the Quarantine page.
Confidence scores. Every AI suggestion comes with a score:
- 0.85 and above — safe to apply without checking
- 0.70 to 0.85 — worth a quick look
- Below 0.70 — decide for yourself
Sensitive files. Anything that looks like a passport, ID or bank document gets flagged and is never moved unless you say so.
Blocked folders. You can list folders the app must never touch.
Learning from you. When you correct a suggestion, that correction is saved and included next time, so the same mistake doesn't repeat.
- Use pnpm, not npm. npm crashes on this project's file layout.
- Start the backend from
mini-manager-app, not from insidebackend/api, or its imports won't resolve. - Model names live in one place —
groq_modelandgemini_modelinbackend/api/config.py. Don't hardcode them anywhere else. Both providers retire models with about a week's notice, and a pinned name buried in a router is how that becomes an outage. Prefer a-latestalias for Gemini. - Payments are only real once the webhook arrives. The browser saying "payment complete" doesn't mean the plan is active — the server has to hear from Paddle first.
- Paddle's notification ID and its signing secret look alike. Only the
pdl_ntfset_…secret verifies a signature. Using the ID gives 401 on every webhook, and Paddle's delivery log is the fastest way to spot it. - Database changes go in
backend/api/migrations/as numbered.sqlfiles. They run automatically when the server starts. - Don't edit files with PowerShell's
Set-Content. On Windows PowerShell it reads as ANSI and writes UTF-8 with a BOM, which mangles dashes and quotes and can push'use client'off the first line. - Python is pinned to 3.13 in
.python-version. On 3.14pydantic-corehas no wheel and tries to build from Rust, which fails.
The backend runs on Render. render.yaml sets the build and start commands and
lists every environment variable, so New → Blueprint creates it in one step.
Leave Root Directory blank — this repo's root already is mini-manager-app.
Once deployed, point Paddle at:
https://<your-service>.onrender.com/api/v1/webhooks/paddle
subscribed to subscription.activated, subscription.updated,
subscription.canceled and transaction.completed. That replaces the ngrok
tunnel described above, which is only needed for local development.
Then build the desktop app against the hosted backend:
$env:NEXT_PUBLIC_API_URL = "https://<your-service>.onrender.com"
$env:API_URL = "https://<your-service>.onrender.com"
pnpm electron:buildBoth variables matter. Without them the installed app calls localhost:8000 on
the user's machine and silently does nothing.
Render's free tier sleeps after about 15 minutes idle, and the next request takes 50 seconds or so while it wakes. Warm it before a demo.
- Make the chat agent reliably execute commands (it chats correctly, but a command like "organise my Documents by type" doesn't always produce a task)
- Stop the same folder being recorded as several duplicate scans
- Let document explain read images and longer PDFs — it's capped at 2000 characters of text today, though Gemini itself supports both
- Dedupe API calls on page load (preferences is fetched four times)
- Sign the Windows app so it doesn't trigger a SmartScreen warning
- Longer logins that survive more than two hours away
- Email notifications — nothing is emailed today, in or out
- Scheduled scans that run on their own
- Cloud folder support (Google Drive, OneDrive)
Not yet decided.