Personal project
LiveTopnotch
One platform for a UAE steel contractor: the website, the books and an AI that reads the paperwork.
- Role
- Co-owner · built the platform
- Period
- Oct 2024 – present
- Built with
- PostgreSQL (Supabase, RLS)Cloudflare WorkersOpenNextGeminiNext.js 15React 19TypeScriptnext-intlTailwind
Topnotch Steel & Contracting FZE is a UAE contractor for steel, aluminium and fit-out work. The platform combines a public website that wins customers with a private portal that runs quoting, invoicing, job costing, banking and VAT, plus an AI assistant that reads supplier bills and bank statements. I co-own the company and built the platform.
- 22
- database tables, with row-level security
- 14
- read-only tools for the AI assistant
- ~90
- service pages, each in English and Arabic
- 525
- commits over two years
A job moves through numbered documents
Each document links to the one before it, so nothing is retyped and every figure can be traced.
- 1
Quotation
Starts from a job-type preset. Saved line items fill in with one click.
- 2
Proforma
Requests the advance payment before work starts.
- 3
Tax invoice
Raised against the quote. Revisions still count toward the same job.
- 4
Receipt
Records the payment and the account it landed in.
- 5
Credit note
Corrects or reduces an invoice.
- 6
VAT return
Quarterly figures come straight from the documents above.
What the portal does
- Documents that edit like they print
- Click any field on the A4 sheet and type. Presets by kind of job, a description library, revisions saved without overwriting, and amounts in words with 5% VAT calculated for you.
- Receivables
- Who owes the company, aged into 0–30, 31–60, 61–90 and 90+ days. Statements of account, and duplicate clients merged in one safe step.
- Costs and job costing
- Every bill and expense can be charged to a project, so profit and margin per job are visible. Subcontracts handle staged bills, advances and retention.
- Bank, cash and VAT
- Ledgers for bank, card and petty cash, balance checks with an audit trail, and a quarterly VAT return. Every sidebar item shows the Tally screen it replaces.
- A website the team runs themselves
- Around 90 bilingual service pages managed from the portal as draft or published. An AI draft button writes SEO-focused English and Arabic content from a service title.
- Found by people and by AI
- Per-page metadata, sitemap and RSS, and llms.txt files so AI assistants can describe the company accurately.
The assistant reads the paperwork. A person approves the books.
Staff upload a supplier bill or a bank statement. The assistant proposes entries as cards that a person edits and confirms, one by one.
- Modelcan be wrong
- Codedeterministic
- Persondecides
- 1
Upload
A bill or statement as PDF, JPG, PNG, WebP or HEIC, up to 10 MB.
Person - 2
Read it
Finds the account by IBAN, account number or bank name, and asks if unsure.
Model - 3
Check for duplicates
Compares with entries already recorded within three days of each line.
Code - 4
Propose entries
Exactly one editable card per statement line. Nothing skipped or merged.
Model - 5
Confirm each card
Staff edit, answer the few questions it asks, and confirm.
Person - 6
Record
Written in a single all-or-nothing database step.
Code
Decisions I'd defend
- It never posts by itself
- Every entry is a proposal. Nothing is recorded until a person confirms it.
- Numbers come from code
- Totals are calculated by the system, not estimated by the model.
- A hidden menu item is also a locked door
- Roles are sets of permission keys, enforced the same way in the menu, the pages and the database through row-level security. The assistant runs as the signed-in person, so it sees only what they may.
- Owner-only area
- The partners' profit-share record is visible to the owner login alone, not even to other admins.
- All-or-nothing steps
- Recording a statement line, merging clients and paying a partner share each run as one transactional step.
- Duplicates are refused
- Document numbers are unique, and a supplier's bill number can only be entered once.
Under the hood
One Next.js 15 codebase serves both the website and the portal. It runs on Cloudflare Workers through OpenNext, stores data in Supabase (Postgres, Auth and row-level security), and calls Gemini for the assistant. English and Arabic come from next-intl, including right-to-left layouts. Every push to main deploys automatically through Bitbucket Pipelines.
Its print sheets later became the model for the Araco admin: editable A4 sheets, quote-to-invoice links and row actions.