AW
Kembali ke Portofolio
Pre-production · Preparing for Google Play ReleaseRetail & Sembako
Independent Product Owner & Engineer

Trasaqu

Retail-first Business Management & Point-of-Sale Platform

An end-to-end retail management and point-of-sale platform where I personally directed product scope and technical delivery: identifying retail operational pain points, defining PRDs, prioritizing functionality, and building across an offline-first Flutter mobile app, a Cloudflare Workers backend with D1 and R2, and a React/TypeScript administrative dashboard. AI-assisted development was utilized as an accelerator with human-owned engineering decisions.

Role

Independent Product Owner & Engineer

Domain

Retail & Sembako

Web

React 18 · Vite

Mobile

Flutter (Dart)

Backend

Cloudflare Workers · TypeScript

Database

Cloudflare D1 · R2

Persistence

Drift (Local SQLite)

Status

Pre-production

Distribution

Preparing Play Store

Architecture

Offline-aware · RBAC

Future Technology Collaboration: Kōhī Labs(Planned Partner)
Lifecycle Pipeline
100% Solo Ownership Initial Scope

FROM IDEA TO PRODUCTION

Setiap tahap dari riset masalah bisnis hingga persiapan rilis produksi dieksekusi secara mandiri.

01→
IDEA
Vision & Problem
02→
BUSINESS RESEARCH
Retail Workflows
03→
PRD & SCOPE
MVP Definition
04→
UX / UI
Design & Flows
05→
SYSTEM DESIGN
Architecture & DB
06→
REACT WEB
Admin Dashboard
07→
FLUTTER MOBILE
Operational App
08→
WORKERS API
Serverless Backend
09→
CLOUDFLARE D1
Relational Data
10→
INFRASTRUCTURE
Cloudflare & GitHub Actions
11→
PRE-PRODUCTION
Deploy & Tests
12
GOOGLE PLAY
Release Prep
Flutter = Mobile Operational AppReact.js = Web Admin Dashboard
🔍 Klik gambar untuk memperbesar
Trasaqu Product Showcase
Klik untuk Zoom In / Full View
01—PRODUCT & BUSINESS CONTEXT

From Retail Problems to a Production Product

Trasaqu was created around the operational problems of small and medium retail businesses that still rely on fragmented or manual workflows for sales, purchasing, stock management, receivables, and reporting.

Instead of treating the product as an isolated cashier application, the system was designed around the wider retail operational cycle:

Purchase
Incoming goods & supplier cost
Inventory
SKU tracking & movements
Sales
Cart, discounts & checkout
Payment
Cash, QRIS & receivables
Reporting
Revenue & profit ledger
Fokus awal produksi sengaja dibatasi pada Retail, Sembako, dan Grocery Stores sebelum memperluas domain ke sektor bisnis lainnya.
02—PRODUCT STRATEGY

Why Retail First?

Instead of trying to support every business type from the beginning, I chose Retail and Sembako as the initial production domain. This provided a concrete business environment for validating transactions, purchasing, inventory, multi-store operations, permissions, reporting, offline behavior, and cloud capabilities before introducing other industries with different operational models.

“Build the concrete domain first. Generalize after recurring patterns become clear.”

Generalize from proven patterns, not assumptions.

01. Focused Scope

Domain rules yang jelas mempercepat validasi ke pengguna nyata.

02. Less Premature Abstraction

Menghindari abstraksi generic yang rapuh di fase awal.

03. Solid Domain Modeling

Struktur data retail menjadi pondasi kuat untuk shared capabilities.

04. Real Production Feedback

Feedback langsung dari operasional toko nyata sebelum ekspansi vertikal.

03—END-TO-END OWNERSHIP

Built Across the Entire Product Lifecycle

Kepemilikan penuh dari perumusan visi bisnis hingga implementasi kode di semua lapisan sistem:

PRODUCT DIRECTION & PRD
  • •Business research & competitor analysis
  • •Requirement gathering & PRD
  • •MVP definition & feature prioritization
  • •Business rules & user journey flows
UI / UX DESIGN
  • •Information architecture & app flows
  • •Mobile & Web responsive interfaces
  • •Role-specific navigation structures
  • •Loading, empty, error, and offline states
WEB — REACT.JS
  • •Administrative browser dashboard
  • •Store, product, & inventory management
  • •Role & membership management
  • •REST API integration & auth state
MOBILE — FLUTTER
  • •Simplified Clean-inspired Layering
  • •Cubit → Repository → Drift & API
  • •Drift SQLite pending mutation queues
  • •Offline holder & transaction resilience
BACKEND — CLOUDFLARE WORKERS
  • •Stateless serverless REST handlers
  • •JWT & refresh token authentication
  • •Store-scoped RBAC & permission guards
  • •Request validation & error handling
DATA — D1 & R2
  • •Relational schema & store isolation
  • •Normalized movement ledger tables
  • •Constraints, foreign keys, & indices
  • •R2 image and file storage
PRODUCTION & RELEASE
  • •Cloudflare routes, secrets & configuration
  • •GitHub Actions build & deployment automation
  • •Android keystore release signing
  • •Google Play Store release preparation
04—PRODUCT CAPABILITIES

Retail Operations Covered End to End

Point of Sale (POS)

Fast cashier workflow, barcode scanning, discounts, multiple payment methods, receipt printing, and void handling.

Inventory & Stock Movements

Traceable ledger movements (in, out, adjustment, opname) instead of static overwrite numbers.

Product Master & Units

SKU management, packaging unit conversion (e.g., box to pcs), base pricing, and store-level configs.

Purchasing & Suppliers

Purchase orders, incoming stock verification, supplier debt tracking, and historical cost recording.

Multi-Store Context

Manage multiple branches with dedicated active store context, isolated data, and role assignments.

Store-Scoped RBAC

Granular permissions for Owner, Cashier, Warehouse, and Finance evaluated at the API layer.

Reporting & Financial Ledger

Revenue trends, gross profit margins, inventory valuation, top products, and exportable audit logs.

Receivables (Piutang)

Customer credit records, repayment history, due date tracking, and balance settlements.

Offline-Aware Operations

Local persistence via Drift SQLite in Flutter for resilient operation during internet instability.

05—SYSTEM ARCHITECTURE

Multi-Client Product Architecture

Pemisahan tanggung jawab klien web dan mobile yang mengonsumsi backend kontrak REST API yang sama:

React.js Web Client

Administrative Dashboard, Store Configurations, Master Data, Reporting

Flutter Mobile App

BLoC / Cubit · Repository · Dio · Drift Local DB (Offline Cache)

Cloudflare Workers API
Auth & JWTStore RBACProductsInventorySales POSPurchasingReportsSwagger API

Serverless handlers · Validation · RBAC

Cloudflare D1 Database

Relational SQLite · Store Isolation · D1 Migrations

Cloudflare R2 Storage

Images, files, and cloud backup objects

Drift Local Database

Mobile Relational SQLite Persistence for Offline Resilience

06—MOBILE ENGINEERING

Simplified Layered Clean-Inspired Flutter Architecture

The Flutter application uses a Simplified / Layered Clean-inspired Architecture rather than full Clean Architecture, as there is no explicit domain use-case layer. The architecture is pragmatic rather than dogmatic: Cubit manages presentation state and application workflow orchestration, while repositories coordinate access to remote and local data sources. For the current product complexity, Cubit coordinates feature workflows and state transitions. If domain rules grow significantly, they can be extracted into dedicated domain services or use cases when the complexity justifies the additional abstraction.

1. UI / Screen

Reactive widgets, barcode camera scanners & thermal print dialogs

2. Cubit

Presentation state, loading/success/error transitions & workflow orchestration

3. Repository

Coordinates access between remote API and local Drift SQLite data sources

4. Data Sources

RemoteDataSource & LocalDataSource abstraction boundaries

5. API / Drift

Dio REST HTTP client & Drift SQLite relational persistence

Verified Real-World Offline Implementation

The current offline-first strategy focuses on preserving local operations and queuing pending mutations for synchronization after connectivity returns. Distributed conflict resolution across multiple offline terminals is outside the current implementation and remains a future design consideration:

Drift Local Persistence

Stores products, categories, customers, and active store configurations locally in a type-safe relational SQLite schema.

Pending Mutation Queues

Captures sales transactions offline into a dedicated pending_sales_transaction table with status flags for automatic sync when connectivity returns.

Offline Holder Mechanism

Preserves in-flight cart operations and temporary cashier hold tickets across network drops and device sleep without state loss.

Dio Interceptors

Automatic JWT token attachment and transparent refresh token rotation on mobile.

Thermal Bluetooth Printing

ESC/POS byte stream formatting for 58mm & 80mm wireless receipt printers.

GetIt Service Locator

Dependency injection decoupling repositories, data sources, and cubit lifecycles.

07—WEB ENGINEERING

React 18 Admin Architecture & TanStack Query

The Trasaqu Admin Web platform is engineered with React 18 + TypeScript (Vite) as a dedicated administrative dashboard. Rather than copying Flutter architecture directly into React, I adapted the same engineering principles to the conventions of the web ecosystem(separation of concerns, centralized networking, clear data flow, feature modularity, reusable components, and predictable responsibility boundaries). For the current admin application's complexity, feature API modules combined with TanStack Query already provide clear separation between UI, server-state management, and network access. Adding an additional repository abstraction would currently duplicate responsibilities without providing enough additional value:

1. Page / UI

Tailwind CSS views, modal forms & responsive tables

2. Feature Hooks

Custom TanStack Query hooks managing server state, caching & mutations

3. Feature APIs

Modular endpoint API modules (customers, stores, products)

4. Central Axios

Centralized Axios client with base URL & active store interceptors

5. Refresh Mutex

Client-side single-flight refresh mutex with queued request replay

Verified Architecture Highlight: Client-Side Single-Flight Refresh Mutex
Source Verified in apiClient.js

The centralized Axios client uses a single-flight refresh mechanism so concurrent 401 responses do not trigger multiple refresh-token requests. Failed requests are queued and replayed after the access token is successfully rotated:

isRefreshing Flag

The first 401 sets an active mutex lock flag, ensuring only one refresh API call is in-flight to the backend at a time.

failedQueue Array

All subsequent concurrent requests that fail with 401 while refreshing are pushed into an in-memory queue of pending promises.

processQueue() Replay

When token rotation succeeds, processQueue() updates the authorization header and transparently replays all queued requests.

Subscription, Governance & Feature Status
Static Plan CatalogImplemented

Tiered plans (FREE, PRO_SOLO, PRO_STARTER, PRO_BUSINESS, ENTERPRISE) with store limits and duration validation.

Audit Log PreviewIn Development

Administrative UI preview initialized in AuditLogsPage.jsx; backend endpoint integration in progress.

Custom Plan BuilderPlanned / Future Exploration

Dynamic custom tier and feature flag builder planned for future enterprise partner deployments.

08—BACKEND ENGINEERING

Cloudflare Workers Backend

The current TypeScript backend runs on Cloudflare Workers as a stateless, request-driven API, with Cloudflare D1 for relational data and Cloudflare R2 for images and files. I migrated the original NestJS service from a self-managed Cloud VPS, adapting routing, authentication, store-scoped authorization, validation, business logic, data access, and error handling to the Workers runtime. Cloudflare now manages runtime configuration, routes, secrets, and deployment settings.

Backend migration

NestJS → Cloudflare Workers: routes, authentication, validation, business services, and store-scoped access control.

Infrastructure migration

Self-managed Cloud VPS → Cloudflare-managed serverless runtime, routes, secrets, and deployment configuration.

Release automation

GitHub Actions runs Flutter dependencies, code generation, tests, environment builds, Android signing, and Firebase App Distribution for development and staging. Google Play release is in preparation.

HTTP Request Lifecycle
1HTTP Request
2Validation
3Authentication
4Store RBAC
5Worker Handler
6Business Service
7Repository
8Cloudflare D1
09 & 10—SECURITY, RBAC & MULTI-STORE

Store-Scoped Authorization Architecture

Permission Resolution Chain

Izin pengguna tidak statis pada user, melainkan ditentukan berdasarkan membership pada toko yang sedang aktif:

USER
↓
STORE MEMBERSHIP (Active Store)
↓
ROLE (Owner / Cashier / Warehouse / Finance)
↓
PERMISSIONS (create:sale, edit:price, etc.)
“UI permission checks improve user experience. API authorization enforces security.”

Why Store Membership Model?

Model sederhana seperti user.store_id menjadi pembatas ketika satu pemilik mengelola multi-cabang atau karyawan memiliki peran berbeda di cabang berbeda:

Contextual Membership
Toko ARole: Owner
Toko BRole: Kasir

Arsitektur data ini memungkinkan isolasi multi-tenant yang aman dan skalabilitas multi-cabang sejak awal.

11—INVENTORY CONSISTENCY

Stock Is a History of Movements, Not Just a Number

Menyimpan stok hanya sebagai angka tunggal yang di-overwrite rawan kehilangan jejak audit. Trasaqu mencatat stok sebagai buku besar mutasi (stock movements) yang dapat direkonstruksi secara historis.

Purchase (Barang Masuk)+100
Sale (Penjualan Kasir)-3
Adjustment (Penyesuaian Rusak)-2
Current Stock95
Traceability
Auditability
Loss Prevention
Historical Rebuild
12—BUSINESS FLOW

A Sale Touches Multiple Domains

Satu transaksi kasir melibatkan rangkaian orkestrasi lintas domain bisnis, bukan sekadar perintah tunggal INSERT INTO sales:

1. Cashier Creates Sale
2. Authenticate User
3. Check Permission
4. Resolve Active Store
5. Validate Product SKU
6. Validate Stock Balance
7. Calculate Pricing
8. Apply Discount Rules
9. Calculate Order Total
10. Create Sale Record
11. Create Sale Items
12. Deduct Inventory
13. Create Stock Movement
14. Record Payment Method
15. Commit ACID Transaction
16. Update Ledger & Reports
13—ENGINEERING CHALLENGES

Problems Beyond Basic CRUD

Concurrent Inventory
PROBLEM:

Multiple transactions affecting the same stock concurrently.

DECISION:

Transactional database operations and atomic deductions.

WHY:

Stock state must remain reliable without race conditions.

Token Expiration
PROBLEM:

Access tokens expiring during active cashier workflows.

DECISION:

Centralized Dio refresh token interceptor with request queueing.

WHY:

Auth handling shouldn't be duplicated across individual screens.

Unstable Network
PROBLEM:

Retail shops often experience erratic internet connectivity.

DECISION:

Persist product catalog in Drift SQLite local database.

WHY:

Temporary network loss shouldn't paralyze cashier operations.

Multi-Store Auth
PROBLEM:

User having different roles across different store locations.

DECISION:

Membership-based role and permission hierarchy.

WHY:

Authorization must be strictly contextual to active store.

Subscription Expiration
PROBLEM:

Subscription expiration shouldn't destroy store historical data.

DECISION:

Separate cloud entitlement from ownership of local business records.

WHY:

Data ownership and service access are different concerns.

State Persistence
PROBLEM:

App state surviving navigation, restart, and device sleep.

DECISION:

Explicit separation between memory state, cache, and relational DB.

WHY:

Predictable lifecycle across complex multi-step workflows.

14—ENGINEERING DECISIONS

Technology Choices With Product Context

Flutter
WHY:

Mobile-first operational UI, reactive state, strong local persistence ecosystem.

TRADE-OFF:

Platform-specific channels required for hardware integration.

React.js
WHY:

Desktop-oriented admin frontend evolving independently from mobile flows.

TRADE-OFF:

Dual-client codebase to maintain across shared API contracts.

Cloudflare Workers
WHY:

Stateless TypeScript API execution with Cloudflare-managed deployment and configuration.

TRADE-OFF:

The former NestJS modules required adaptation to a request-driven runtime.

Cloudflare D1 + R2
WHY:

D1 stores relational retail data; R2 stores images and files within the Cloudflare ecosystem.

TRADE-OFF:

Database migrations and object lifecycle require careful coordination.

15—PRODUCTION THINKING

Designed Beyond the Happy Path

Access token expires during sessionHANDLED

Dio interceptor triggers refresh token queueing automatically.

Temporary network loss at cashierHANDLED

Drift local database maintains cached product catalog.

Active store switched by userHANDLED

State reset and store context header propagated across requests.

Concurrent stock deduction conflictDESIGNED FOR

Transactional database verification before sale commit.

Subscription entitlement expirationDESIGNED FOR

Local business data preserved with graceful cloud feature limits.

Cross-device multi-terminal sync conflictPLANNED / FUTURE

Distributed conflict resolution across multiple offline terminals is outside the current implementation and remains a future design consideration.

16—PRODUCTION

Production Was Part of the Engineering Scope

Tanggung jawab rekayasa tidak berhenti di localhost. Pengelolaan rahasia lingkungan, deployment backend, migrasi database, signing kunci rilis Android, hingga persiapan rilis Google Play Store dieksekusi secara terstruktur.

Android Release

Keystore signing & AAB build

Google Play Store

Store listing & release preparation

Database Migration

Cloudflare D1 schema migrations

Cloudflare Delivery

Workers, D1, R2 & configuration

17—PRODUCT EVOLUTION

Retail First. Platform Next.

Trasaqu intentionally starts with a concrete retail domain rather than attempting to model every business category from day one. Once recurring platform concerns are validated through the Retail and Sembako product, shared capabilities can gradually be extracted while new business verticals retain their own domain-specific workflows.

TRASAQU SHARED PLATFORM
Authentication · Store Isolation · Multi-Store RBAC · Subscription Entitlement · Common Infra · Offline Engine
↓ Modular Domain Specialization ↓
RETAILCURRENT
  • • Products & SKU
  • • Packaging Units
  • • Barcode Scan
  • • Stock Movements
F&BFUTURE
  • • Raw Ingredients
  • • Recipe / HPP
  • • Menu Engineering
  • • Table / Kitchen
LAUNDRYFUTURE
  • • Weight / Kiloan
  • • Service Stages
  • • Ready & Pickup
  • • Order Tracking
BENGKELFUTURE
  • • Vehicle Records
  • • Service Jobs
  • • Mechanic Assign
  • • Spare Parts

Different Businesses Share Transactions — Not Workflows

Forcing all verticals into a single generic POS introduces conditional spaghetti code and weak domain abstractions. Trasaqu aims to reuse shared platform infrastructure while allowing each business vertical to maintain its native operational workflow.

18—FUTURE COLLABORATION

From Solo Product Engineering to Collaborative Development

The initial Trasaqu Retail platform was independently designed and engineered by me from product definition through pre-production release preparation. As Trasaqu moves beyond its initial Retail and Sembako scope, future development is planned together with Kōhī Labs as a technology partner.

PHASE 01: PRE-PRODUCTIONPreparing Release
Agung Wibowo (Solo Ownership)
  • • Research, PRD, UX/UI
  • • React.js Web + Flutter Mobile
  • • Cloudflare Workers + D1 + R2
  • • Retail & Sembako Pre-production
PHASE 02: PLANNED / FUTURE EXPLORATIONPlatform Expansion
Trasaqu × Kōhī Labs
  • • Technology & IT Partner
  • • Shared Platform Scaling
  • • Deeper Domain Research
  • • Vertical Expansion (F&B, Laundry, Bengkel)
19—PRODUCT ROADMAP

Expand by Domain, Not by Feature Accumulation

Menambahkan kategori bisnis baru bukanlah sekadar “menambah menu di UI”, melainkan membutuhkan riset mendalam mengenai model bisnis, aturan domain, rancangan UX, perubahan API, pemodelan tabel data, dan pengujian validasi di lapangan.
20—TECHNOLOGY & TOOLS

Technology Stack

MOBILE APPLICATION
FlutterDartBLoC / CubitDioDrift (SQLite)GoRouterGetIt
WEB FRONTEND
React 18TanStack QueryAxiosTailwind CSS
BACKEND SERVICE
Cloudflare WorkersTypeScriptREST APIJWTStore-scoped RBACD1R2
DATABASE & INFRA
Cloudflare D1Cloudflare R2GitHub ActionsFirebase App DistributionAndroid Signing
21—ENGINEERING TAKEAWAYS

What Building the Entire Product Changed

Product Decisions Drive Architecture

Kebutuhan bisnis multi-cabang langsung membentuk relasi StoreMember di database.

Authorization Belongs on Server

UI checks hanya untuk visual affordance; API guards yang menjamin keamanan data.

Inventory Demands Traceability

Buku besar pergerakan stok mutlak diperlukan untuk audit dan mencegah selisih misterius.

Offline Changes Data Architecture

Kebutuhan offline menuntut pemisahan tegas antara remote persistence dan local cache.

22 — SUMMARY

End-to-End Product Engineering Summary

Trasaqu represents my end-to-end product engineering work: taking a retail business problem from research and PRD through UX, React.js web development, Flutter mobile engineering, Cloudflare Workers backend migration, D1 relational data, R2 object storage, Cloudflare infrastructure, GitHub Actions automation, and Google Play release preparation. The initial pre-production version focuses on Retail and Sembako. Future development is planned to expand the platform into additional business verticals together with Kōhī Labs as a technology partner.

PRODUCT & UXIndependent Product Owner & Engineer
WEB & MOBILEReact.js & Flutter
BACKEND & DATAWorkers · D1 · R2
PARTNERSHIPKōhī Labs (Planned)