← Back to projects

Full-stack · 2026

Manyue

See where it went. Without typing it in. Photograph a receipt, or say one sentence. Manyue writes the entry, files it under the right category, and remembers the shop for next time.

Vue 3 Pinia TypeScript Fastify Drizzle MySQL Gemini OCR

The part nobody keeps doing

Bookkeeping tools mostly fail at the same point: the typing. A shoebox of receipts turns into an evening of data entry, so the ledger goes stale and the numbers stop being worth reading.

Manyue removes that step. A photograph or a spoken sentence becomes a draft entry with a payee, a category and a split, and the ledger still balances to the cent. Categories are one level deep on purpose, because two is a filing system nobody keeps up.

How a receipt becomes an entry

The upload answers immediately and the model call happens behind the response, so a slow extraction never holds the camera open.

Receipt upload, background extraction and client polling client Fastify API extractor MySQL POST /v1/receipts  (photo) 202 Accepted as soon as the photo is stored behind the response status: extracting draft + questions GET /v1/receipts/:id  (poll) draft, ready to confirm

A retry of a failed receipt is reset to extracting first, so nobody is shown the previous failure as though it were this attempt's.

Bring your own key

Users can store their own Gemini API key and pay their own way.

The rule that matters most in it: a stored key that will not open throws rather than falling back to the server's. Falling through would bill the owner for somebody who believed they were paying their own way — silently. Keys are written through a write-only API and never read back.

The interface

Screenshots go here.

Home Balances per currency, cash flow by month, where it went. assets/manyue-home.webp
Scan Camera capture and the extracted draft with its questions. assets/manyue-scan.webp
Register The full ledger, split across categories, balancing to the cent. assets/manyue-register.webp
AI assistant One sentence in, a recorded transaction out. assets/manyue-assistant.webp

Built out of

apps/web

Vue 3 with Pinia, vue-router and vue-i18n. IndexedDB via idb for local state, Zod for shared contracts.

apps/api

Fastify with helmet, cors, rate-limit and multipart. Drizzle over MySQL, Argon2 for passwords, jose for tokens.

packages/ocr

Receipt extraction, isolated from both the API and the web app so it can be tested on its own.

packages/shared

Zod schemas and uuidv7 ids, imported by every other workspace so the contract has one home.

A slice of the API surface

/v1/receiptsUpload a photograph; answers 202 while extraction runs behind the response.
/v1/assistant/interpretOne sentence in, a structured transaction out.
/v1/accounts/:id/reconciliationStatement reconciliation against the recorded ledger.
/v1/accounts/:id/balancesBalances per currency, which is why the home screen can add up.
/v1/auth/google/drive/callbackDrive connection, kept separate from sign-in.
/v1/categoriesOne level deep, by design.
Manyue — built by MilanDroid All projects