Agung Stationery Store — Online Orders, QRIS & a RAG Chatbot
A web app for a stationery store. Customers order and pay by QRIS, then collect their items in store, the admin verifies payments and exports reports, and a RAG chatbot answers questions about stock, prices, and opening hours from the store's own data.
- Role
- Full-Stack Developer
- Period
- Sep 2025–Aug 2026
- Tools
-
- Next.js 15
- TypeScript
- PostgreSQL
- pgvector
- Supabase
- Groq
- Vitest
The challenge
Agung Stationery Store (Toko Alat Tulis Agung) already had a profile website and a simple cashier app from the first version I built. The next step was bigger: customers should be able to order and pay by QRIS on their own and just collect their items in store, the admin needed to verify payments and export reports, and repeated questions about stock, prices, or opening hours should get answered without replying to each one by hand.
My role
I built both versions as the full-stack developer: the database schema, the shopping and payment flow, the admin panel, the RAG chatbot, security, and testing.
Process
The first version (September 2025) had the store’s landing page, a dashboard, product management, a cashier, and reports. In July–August 2026 I grew it into a second version as a single Next.js project: pages and API run together as serverless functions, backed by PostgreSQL on Supabase, which also stores embedding vectors through pgvector. The schema lives in four SQL migration files, so the database can be rebuilt from scratch.
The most important decision was in the payment flow. Stock only drops when the admin approves a payment, not at checkout, so items aren’t held by orders that never get paid. Later I reworked the mobile layout (shopping, checkout, and the admin menu) and connected the homepage catalogue straight to the database.
Solution
- Online shopping & checkout: a catalogue from the database, a cart, and stock validation on the server. The browser only sends product IDs and quantities; prices are always re-read from the database with row locking.
- QRIS payment: the buyer scans the store’s QRIS, uploads proof (file type checked from its contents, up to 2 MB), and the admin approves or rejects it with a reason. Rejected buyers can upload again.
- RAG chatbot: it searches the store data first, by keyword and semantic search (768-dimension embeddings), then answers through an LLM. With no matching context it declines with a fixed message instead of making things up. The admin can ask about revenue and stock, while the same question from a buyer never reveals that data.
- Reports: transactions, stock, and payments by date range, exported to PDF or Excel from a single data structure.
- Admin dashboard: summaries, a sales chart, best sellers, a cashier, and a chatbot history showing the source of each answer.
- Security: scrypt password hashing, revocable httpOnly session cookies, a 15-minute lockout after 5 failed logins, and parameterised queries throughout.
Results
| Need | How the app handles it |
|---|---|
| No queueing | Order and pay by QRIS from a phone, then collect in store |
| Accurate stock | Stock drops when a payment is approved and can’t go negative |
| Repeated questions | The chatbot answers stock, price, and hours from store data |
| Bookkeeping | Transaction, stock, and payment reports to PDF or Excel |
- 97 unit tests across 7 files pass, covering login, the cart, the chatbot, reports, and upload validation.
- 25 black-box scenarios were written to test the flows from a user’s point of view.
Lessons
The rule “never trust the browser” ended up shaping almost the whole design: prices, stock, and user roles are always re-read on the server. For the chatbot, the hard part wasn’t calling an LLM but making sure it stays quiet when it doesn’t know and never leaks admin data to buyers. Combining keyword and semantic search also proved necessary. Keywords handle exact product names, while embeddings catch questions like “something for drawing” that never name a product.
Documentation
-
The homepage, with the store profile, catalogue, prices, location, and FAQ. -
The chatbot answers from stock and price data and shows its source. All screenshots use sample data. -
Checkout. Prices and stock are re-read on the server, never taken from the browser. -
Pay by QRIS, then upload proof. The QRIS here is still a sample image. -
The admin approves or rejects payments. Stock only drops on approval. -
The chatbot history records the source of every answer. -
The admin dashboard with a sales chart and best sellers. -
Three report types, each exportable to PDF or Excel.