Aplikasi keuangan pribadi & keluarga — dibangun dengan SvelteKit, Tailwind CSS, dan Supabase.
| Layer | Teknologi |
|---|---|
| Frontend | SvelteKit (SSG/SPA) |
| Styling | Tailwind CSS + Custom CSS Vars |
| Backend | Supabase (PostgreSQL + Auth + RLS) |
| Hosting | Cloudflare Pages |
dompet-app/
├── src/
│ ├── app.html # HTML template
│ ├── app.css # Global styles & design tokens
│ ├── lib/
│ │ ├── supabase.js # Supabase client & auth helpers
│ │ ├── stores.js # Svelte writable stores
│ │ ├── services/
│ │ │ ├── wallet.service.js
│ │ │ ├── transaction.service.js
│ │ │ ├── budget.service.js
│ │ │ ├── category.service.js
│ │ │ └── workspace.service.js
│ │ └── utils/
│ │ └── format.js # Currency, date formatters (IDR)
│ ├── components/
│ │ ├── ui/
│ │ │ ├── Modal.svelte
│ │ │ └── Toast.svelte
│ │ ├── layout/
│ │ │ ├── Sidebar.svelte
│ │ │ └── Topbar.svelte
│ │ └── forms/
│ │ ├── TransactionForm.svelte
│ │ └── CopyBudgetForm.svelte
│ └── routes/
│ ├── +layout.svelte # Root layout with auth guard
│ ├── auth/
│ │ ├── login/+page.svelte
│ │ └── onboarding/+page.svelte
│ ├── dashboard/+page.svelte
│ ├── transactions/+page.svelte
│ ├── budgets/+page.svelte
│ ├── wallets/+page.svelte
│ └── settings/+page.svelte
├── supabase/
│ └── schema.sql # Full DB schema + RLS + Views + Functions
├── docs/
│ └── app-demo.html # Static interactive prototype
├── svelte.config.js
├── vite.config.js
├── tailwind.config.js
└── package.json
git clone https://github.com/codengab/expense-tracker
cd expense-tracker
npm install- Buat project baru di supabase.com
- Buka SQL Editor, jalankan
supabase/schema.sql - Aktifkan Email Auth di Authentication → Providers
cp .env.example .env
# Edit .env dengan URL dan anon key dari Supabase dashboardnpm run dev| Table | Deskripsi |
|---|---|
workspaces |
Workspace keluarga/personal |
workspace_members |
Anggota + role (admin/member/viewer) |
wallets |
Dompet (tunai, bank, e-wallet, dll) |
categories |
Kategori transaksi (default + kustom) |
transactions |
Semua transaksi income/expense/transfer |
budgets |
Anggaran per kategori per bulan |
| View | Deskripsi |
|---|---|
wallet_balances |
Saldo dompet terkini (real-time) |
monthly_summary |
Ringkasan income/expense per bulan |
budget_usage |
Penggunaan anggaran + persentase |
| Function | Deskripsi |
|---|---|
copy_budget |
Salin anggaran bulan ke bulan (replace/merge) |
Setiap tabel dilindungi RLS. User hanya bisa akses data workspace yang mereka ikuti:
- Admin → akses penuh (CRUD semua)
- Member → bisa buat/edit transaksi
- Viewer → hanya baca
:root {
--bg: #F1F5F9; /* Background halaman */
--card: #FFFFFF; /* Background card */
--border: #E2E8F0; /* Border */
--primary: #0EA5E9; /* Biru utama */
--income: #16A34A; /* Hijau pemasukan */
--expense: #DC2626; /* Merah pengeluaran */
--warning: #F59E0B; /* Amber peringatan */
}- Auth (login, register, logout)
- Onboarding (buat workspace pertama)
- Manajemen dompet (CRUD, toggle aktif, saldo real-time)
- Kategori (default sistem + kustom per workspace)
- Transaksi (income, expense, transfer + filter)
- Anggaran per kategori per bulan
- Copy budget (replace / merge)
- Dashboard dengan statistik
- Laporan pengeluaran per kategori
- Multi-user workspace
- Role management (admin/member/viewer)
- Undang anggota via email
- Toast notifications
- Mobile-responsive sidebar
- Format IDR (Rp 1,5jt / Rp 24,5rb)
npm run build
# Atau connect GitHub repo ke Cloudflare Pages:
# Build command: npm run build
# Build output: .svelte-kit/cloudflare
# Environment: NODE_VERSION=18Tambahkan environment variables di Cloudflare Pages dashboard.
src/routes/nama-halaman/+page.svelte
// src/lib/services/nama.service.js
import { supabase } from '$lib/supabase';
export const namaService = {
async getAll(workspaceId) {
const { data, error } = await supabase
.from('nama_table')
.select('*')
.eq('workspace_id', workspaceId);
if (error) throw error;
return data;
}
};import { formatCurrency, formatCurrencyShort } from '$lib/utils/format';
formatCurrency(1500000) // → "Rp 1.500.000"
formatCurrencyShort(1500000) // → "Rp 1,5jt"
formatCurrencyShort(75000) // → "Rp 75rb"Apache2