Saya baru siapkan satu side project untuk urus kewangan peribadi, dan keseluruhan app ini saya build guna Cloudflare stack. Dalam post ini saya kongsi seni bina teknikal, kenapa saya pilih stack ini, dan beberapa keputusan reka bentuk yang saya rasa paling penting.


Tech Stack

KomponenTeknologi
FrontendHTML, CSS, JavaScript (Vanilla)
Backend APICloudflare Workers + Hono.js
DatabaseCloudflare D1 (SQLite)
AuthenticationJWT + bcrypt
HostingCloudflare Pages
PWAService Worker untuk offline support

Mengapa Cloudflare?

Saya pilih Cloudflare stack sebab beberapa benda ini memang kena dengan apa yang saya nak:

  1. Serverless sepenuhnya - Tiada pelayan untuk diurus
  2. Global edge network - Respons pantas dari mana-mana lokasi
  3. Kos rendah - Free tier sangat generous untuk projek peribadi
  4. D1 Database - SQLite yang di-host, mudah untuk schema migrations
  5. Integrasi Pages + Workers - Deploy frontend dan API dari satu repository

Seni Bina Sistem

┌─────────────────┐     ┌─────────────────────────────┐
│  Cloudflare     │     │  Cloudflare Workers         │
│  Pages          │────▶│  (Hono.js REST API)         │
│  (Frontend)     │     │                             │
└─────────────────┘     └─────────────┬───────────────┘


                        ┌─────────────────────────────┐
                        │  Cloudflare D1              │
                        │  (SQLite Database)          │
                        └─────────────────────────────┘

Ciri-ciri Utama

1. Multi-User Authentication

  • Pendaftaran dan log masuk dengan email/password
  • Password hashing menggunakan bcrypt
  • JWT tokens dengan 7 hari expiry
  • Session management via localStorage

2. Pengurusan Perbelanjaan & Pendapatan

Dashboard dengan ringkasan kewangan

  • Rekod transaksi dengan kategori
  • Periode kewangan bulanan (24hb - 23hb)
  • Sokongan untuk description/catatan
  • Import/export data JSON

3. Senarai Transaksi

Senarai perbelanjaan mengikut kategori

4. Laporan & Analitik

Laporan tahunan dengan trend bulanan

  • Dashboard dengan ringkasan
  • Carta pecahan mengikut kategori (Doughnut chart)
  • Trend bulanan (Bar chart)
  • Laporan tahunan dengan kadar simpanan

5. Progressive Web App (PWA)

  • Boleh di-install pada telefon
  • Responsive design untuk mobile dan desktop
  • Dark theme dengan glassmorphism UI

6. Admin Panel

  • Pengurusan pengguna
  • Statistik penggunaan
  • Padam akaun pengguna

Deployment ke Cloudflare Pages + D1

Kalau nak deploy app macam ini ke Cloudflare Pages dengan D1, ini flow yang saya guna.

1. Struktur Projek

Struktur projek lebih kurang macam ini:

expense-tracker/
├── frontend/           # Static files (HTML, CSS, JS)
├── functions/          # Cloudflare Pages Functions (API)
│   └── api/
│       └── [[route]].js
├── src/
│   └── db/
│       └── schema.sql  # Database schema
├── wrangler.toml       # Konfigurasi Wrangler
└── package.json

2. Konfigurasi wrangler.toml

Fail wrangler.toml ini yang jadi penghubung utama antara Pages dengan D1:

name = "expense-tracker"
compatibility_date = "2024-01-01"

# D1 Database binding
[[d1_databases]]
binding = "DB"
database_name = "expense-tracker-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Nota: database_id akan dapat lepas create database pada langkah seterusnya.

3. Mencipta D1 Database

Jalankan arahan berikut dalam terminal:

# Login ke Cloudflare (jika belum)
npx wrangler login

# Create database baru
npx wrangler d1 create expense-tracker-db

Lepas run command itu, output dia lebih kurang macam ini:

✅ Successfully created DB 'expense-tracker-db'

[[d1_databases]]
binding = "DB"
database_name = "expense-tracker-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

database_id itu nanti perlu letak semula dalam wrangler.toml.

4. Setup Database Schema

Jalankan migration untuk create tables:

# Local development
npx wrangler d1 execute expense-tracker-db --local --file=./src/db/schema.sql

# Production
npx wrangler d1 execute expense-tracker-db --remote --file=./src/db/schema.sql

5. Deploy ke Cloudflare Pages

Biasanya ada dua cara untuk deploy:

Cara A: Melalui Cloudflare Dashboard (Disyorkan)

  1. Pergi ke Cloudflare DashboardWorkers & Pages
  2. Klik CreatePagesConnect to Git
  3. Pilih repository GitHub/GitLab anda
  4. Konfigurasi build settings:
    • Build command: (kosongkan untuk static files)
    • Build output directory: frontend
  5. Klik Save and Deploy

Cara B: Menggunakan Wrangler CLI

npx wrangler pages deploy frontend --project-name=expense-tracker

6. Binding D1 ke Pages Project

Ini bahagian yang paling selalu orang terlepas pandang:

  1. Pergi ke Cloudflare DashboardWorkers & Pages
  2. Pilih Pages project anda
  3. Pergi ke SettingsFunctionsD1 database bindings
  4. Klik Add binding:
    • Variable name: DB
    • D1 database: Pilih expense-tracker-db
  5. Klik Save

⚠️ Penting: Tanpa langkah ini, Pages Functions tidak akan dapat akses database!

7. Environment Variables (Jika Perlu)

Untuk secrets seperti JWT_SECRET:

  1. Pergi ke SettingsEnvironment variables
  2. Tambah variables yang diperlukan:

8. Custom Domain (Optional)

  1. Pergi ke Custom domains dalam Pages project
  2. Klik Set up a custom domain
  3. Masukkan domain anda (contoh: duit.hafism.xyz)
  4. Cloudflare akan auto-configure DNS dan SSL

9. Local Development

Kalau nak buat development di local machine:

# Start local server dengan D1
npx wrangler pages dev frontend --d1=DB=expense-tracker-db

Ini akan start local server di http://localhost:8788 dengan akses kepada local D1 database.


Kemaskini: Ciri Pengurusan Hutang

Dikemaskini: 28 Disember 2025

Saya juga dah tambah ciri pengurusan hutang yang lebih lengkap dalam Expense Tracker, supaya pengguna boleh jejak hutang peribadi, ansuran kad kredit, dan balance transfer dalam tempat yang sama.

Ciri-ciri Baru

1. Penjejakan Hutang Peribadi

  • Hutang Diterima (Wang yang anda berhutang kepada orang lain)
  • Hutang Diberi (Wang yang orang lain berhutang kepada anda)
  • Rekod pembayaran separa dengan sejarah penuh
  • Notifikasi tarikh akhir (amaran 7 hari sebelum)
  • Pilihan auto-tambah pembayaran ke perbelanjaan

2. Pengurusan Kad Kredit

  • Simpan berbilang kad kredit
  • Jejaki hari penyata dan tarikh akhir pembayaran
  • Tetapkan had kredit

3. Penjejakan Ansuran (EPP & Balance Transfer)

  • Hubungkan ansuran ke kad kredit tertentu
  • Jejaki pembayaran bulanan dan kemajuan
  • Penciptaan perbelanjaan automatik semasa pembayaran

Implementasi Teknikal

Database Schema

Empat jadual baru ditambah ke D1:

-- Kad Kredit
CREATE TABLE credit_cards (
    id INTEGER PRIMARY KEY,
    user_id TEXT NOT NULL,
    name TEXT NOT NULL,
    card_type TEXT DEFAULT 'credit',
    last_four TEXT,
    statement_day INTEGER,
    payment_due_day INTEGER,
    credit_limit REAL
);

-- Hutang Peribadi
CREATE TABLE debts (
    id INTEGER PRIMARY KEY,
    user_id TEXT NOT NULL,
    type TEXT NOT NULL, -- 'receivable' or 'payable'
    person_name TEXT NOT NULL,
    original_amount REAL NOT NULL,
    current_balance REAL NOT NULL,
    interest_rate REAL,
    due_date TEXT,
    status TEXT DEFAULT 'active',
    auto_add_expense INTEGER DEFAULT 0
);

-- Pembayaran Hutang
CREATE TABLE debt_payments (
    id INTEGER PRIMARY KEY,
    debt_id INTEGER REFERENCES debts(id),
    user_id TEXT NOT NULL,
    amount REAL NOT NULL,
    payment_date TEXT NOT NULL,
    notes TEXT,
    expense_id INTEGER REFERENCES expenses(id)
);

-- Ansuran
CREATE TABLE installments (
    id INTEGER PRIMARY KEY,
    user_id TEXT NOT NULL,
    card_id INTEGER REFERENCES credit_cards(id),
    type TEXT NOT NULL, -- 'epp' or 'balance_transfer'
    name TEXT NOT NULL,
    total_amount REAL NOT NULL,
    monthly_payment REAL NOT NULL,
    interest_rate REAL,
    total_months INTEGER NOT NULL,
    months_paid INTEGER DEFAULT 0,
    payment_day INTEGER NOT NULL,
    start_date TEXT NOT NULL,
    status TEXT DEFAULT 'active',
    auto_add_expense INTEGER DEFAULT 0
);

API Endpoints

16 endpoints baru ditambah:

MethodEndpointKeterangan
GET/api/credit-cardsSenarai semua kad kredit
POST/api/credit-cardsCipta kad kredit
PUT/api/credit-cards/:idKemaskini kad kredit
DELETE/api/credit-cards/:idPadam kad kredit
GET/api/debtsSenarai semua hutang
POST/api/debtsCipta hutang
PUT/api/debts/:idKemaskini hutang
DELETE/api/debts/:idPadam hutang
GET/api/debts/:id/paymentsDapatkan sejarah pembayaran
POST/api/debts/:id/paymentsRekod pembayaran
GET/api/installmentsSenarai ansuran
POST/api/installmentsCipta ansuran
PUT/api/installments/:idKemaskini ansuran
DELETE/api/installments/:idPadam ansuran
POST/api/installments/:id/payRekod pembayaran ansuran
GET/api/summary/debtsDapatkan ringkasan hutang

Frontend Components

  • Seksyen navigasi “Hutang” baru
  • Antara muka tiga-tab (Hutang Diterima, Hutang Diberi, Ansuran)
  • Modal pengurusan kad kredit
  • Borang hutang dan ansuran dengan validasi
  • Progress bars untuk penjejakan hutang/ansuran
  • Rakaman pembayaran dengan paparan sejarah

Langkah Deployment

1. Kemaskini Wrangler

cd workers
npm install --save-dev wrangler@4

2. Apply Database Migration

npx wrangler d1 execute expense-tracker-db --file=./src/db/schema.sql --remote

3. Deploy Worker

npx wrangler deploy

Output Deployment

⛅️ wrangler 4.54.0
Total Upload: 175.85 KiB / gzip: 41.37 KiB
Worker Startup Time: 1 ms

Uploaded expense-tracker-api (10.80 sec)
Deployed expense-tracker-api triggers (4.61 sec)
  https://your-worker-name.your-subdomain.workers.dev

Fail yang Diubah

FailPerubahan
workers/src/db/schema.sql+40 baris (4 jadual baru)
workers/src/index.ts+490 baris (16 endpoints)
frontend/js/debts.jsFail baru (~700 baris)
frontend/js/api.js+190 baris (fungsi API)
frontend/js/app.js+20 baris (integrasi)
frontend/index.html+310 baris (komponen UI)
frontend/css/styles.css+660 baris (styling)

Paparan Hutang yang baru ini memaparkan:

  • Kad ringkasan menunjukkan jumlah hutang
  • Antara muka bertab untuk jenis hutang berbeza
  • Progress bars untuk penjejakan pembayaran
  • Butang tindakan untuk pembayaran dan suntingan

Demo

Kalau nak cuba sendiri:


Kesimpulan

Bagi saya, Cloudflare stack memang sangat sedap untuk aplikasi web moden macam ini:

  • Zero cold starts berbanding Lambda/Cloud Functions
  • SQLite compatibility dengan D1 memudahkan development
  • Generous free tier sesuai untuk side projects

Source code ada di GitHub. Kalau ada soalan atau nak sembang pasal implementation, boleh hubungi saya di X (@xhafism) atau Threads (@haf.ism).


Artikel ini sebahagian daripada siri “Building with Cloudflare”, tempat saya kongsi pengalaman build app atas edge stack yang ringan dan practical.