Akbar
Food ordering platform
Akbar's own online ordering, at akbar.co.jp. Customers around Tama Plaza and Azamino order delivery or takeout and pay online, straight from the restaurant.
Visit Live Site

Most people now order food through delivery apps, and those apps keep a big cut of every order. Calling the restaurant is slow, and someone has to stay by the phone to take it.
Top highlights

Delivery or takeout, in one tap
Customers choose delivery to their door or pickup at the shop, then order from the full menu on their phone. No waiting on the line, no misheard orders.

The whole menu, just like in the shop
Every curry, set and naan with photos and prices, sorted into tabs. Customers search, filter, pick their spice level and add-ons, and lunch sets appear only when lunch is being served.

One dashboard for the whole shop
Active orders, today's orders and today's income sit at the top, with a sales chart by day, week or month and the most popular dishes beside it. Below, every recent order shows what was ordered, how it was paid and its status, and new ones appear the moment they're placed.

A pause button for busy nights
When the kitchen is full, staff pause new orders or close specific delivery times, then reopen with one click. Customers always see what's actually available.
What it changes for the restaurant
No one stuck on the phone
Orders arrive written down and paid for, so the restaurant no longer needs a person just to answer calls and take orders.
Keep the commission
Delivery apps take a large share of every order. Orders placed on Akbar's own site skip that commission, so more of each sale stays with the restaurant.
Easier than calling
People are used to ordering food on their phones. Now they can do that with Akbar directly, any time, without waiting for someone to pick up.
At a glance
Project overview
- Client
- Akbar, an Indian restaurant serving the Tama Plaza and Azamino area of Yokohama, Japan.
- My role
- Design and full-stack development, from the customer ordering site to the staff dashboard, payments and the server it runs on. I still look after it today.
- Deliverables
- Ordering site for delivery and takeout
- Sign-up with an SMS code to confirm the phone number
- Online card payments, plus cash on delivery
- Staff dashboard with live orders, sales and popular dishes
- Menu editing with photos, add-ons and sold-out switches
- Server setup, hosting and HTTPS
- Status
- Live at akbar.co.jp and taking real orders.
Run a restaurant and want orders to come straight to you instead of through an app? Read how I approach restaurant website design.
Technical details for developers
Stack, architecture and how it is built.
Stack
Architecture
Key flows
Engineering highlights
Production cloud deployment
AWS EC2 with Nginx + Gunicorn (2–6 workers). HTTPS via Certbot. Media on Cloudflare R2. Live at akbar.co.jp serving real customers.
Zero-downtime DB migration to the edge
Migrated production DB from AWS RDS PostgreSQL to Cloudflare D1 via a custom SQLAlchemy dialect (d1+http) that proxies queries through a Cloudflare Worker, since D1 is only reachable from inside the Workers runtime. Media storage moved from S3 to R2 the same way.
Data model
| Table | What it stores |
|---|---|
| CustomerLogin | Phone number (unique), name, email, hashed password, address fields, verification status, order count |
| Admin | Restaurant admin accounts: email, PBKDF2-SHA256 hashed password (310,000 iterations), passcode |
| SuperAdmin | Top-level admin: email and 4-digit passcode. One row expected |
| DeliveryBoy | Delivery staff: name and PIN for simplified login |
| Category | Food categories with position ordering, optional time restriction, and spicy level flag |
| MenuItem | Individual items: name, description, price, image URL, availability, spice options, position, order count |
| AddonCategory | Add-on groups (e.g. "Spice Level", "Drink Choice") scoped per category or per item |
| AddonItem | Individual add-on choices (e.g. "Mild", "Medium Hot") with price. Belongs to an AddonCategory |
| Order | Placed order: links to customer, status, total, payment method, Stripe payment_intent_id, delivery method, scheduled time |
| OrderItem | Items within an order: quantity, price at time of order, spicy level, special instructions, add-ons stored as JSON |
| Settings | Restaurant settings: name, address, phone, opening hours, admin email. One row |
| TodayCurry / MonthlyCurry | CMS data: today's curry name and the monthly special (name, image URL, price) |
Deployment & security
Production stack
- AWS EC2 instance (Ubuntu)
- Nginx: reverse proxy, rate limiting, HTTPS
- Gunicorn: 2–6 workers, internal port 8000
- Cloudflare D1: all data, via a custom SQLAlchemy dialect talking HTTP to a Cloudflare Worker proxy (D1 isn't reachable outside the Workers runtime)
- Certbot: SSL certificate with auto-renewal script
- Cloudflare R2: images and PDFs, S3-compatible API
- Domain: akbar.co.jp (confirmed in nginx.conf)
Authentication
- Customers: phone + password (PBKDF2-SHA256, 310,000 iterations)
- Admins: email + password, same hash algorithm
- Super admin: 4-digit passcode
- Delivery boys: PIN number
- Sessions are signed cookies (Flask default), last 60 days
- CSRF protection via Flask-WTF on all forms
Payment security
- Card numbers never reach the Flask server
- Stripe PaymentIntent API (industry standard approach)
- Unique reference UUID per order prevents duplicate charges
- Stripe commission (3.6%) tracked separately in dashboard
- Auto-refund on cancellation via Stripe Refunds API
Environment variables
- SECRET_KEY (Flask session signing)
- STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY
- R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ACCOUNT_ID, R2_BUCKET_NAME, R2_PUBLIC_URL
- TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_VERIFY_SERVICE_ID
- MAIL_USERNAME, MAIL_PASSWORD (Zoho SMTP)
Want something like this?
I build restaurant websites with online ordering, bookings and rewards, so orders come straight to you.