1. Gambaran singkat
Econary itu monolit full-stack: frontend dan backend hidup dalam satu codebase Next.js yang sama. Tidak ada server backend terpisah (misalnya Express/FastAPI) dan tidak ada frontend yang di-build terpisah lalu dipanggil via REST ke server lain.
Autentikasi dijaga di tengah-tengah alur itu oleh NextAuth (sesi JWT), dan halaman /dashboard/* diproteksi oleh middleware.js sebelum halaman sempat dirender.
2. Tech stack lengkap
| Lapisan | Teknologi | Versi / keterangan dari package.json |
|---|---|---|
| Bahasa | JavaScript | Seluruh kode app/, components/, dan lib/ ditulis .js. Tidak ada TypeScript di codebase ini. |
| Framework | Next.js (App Router) | ^14.2.0 — routing berbasis folder di app/, Server Component + Client Component. |
| UI | React | ^18.3.0 + react-dom ^18.3.0. |
| Styling | Tailwind CSS | ^3.4.3, dengan PostCSS ^8.4.38 dan Autoprefixer ^10.4.19. Konfigurasi di tailwind.config.js: warna primer teal, font Inter, dark mode berbasis class, animasi kustom. |
| Backend | Next.js API Routes | Route handler di app/api/ (lihat bagian 4). Bukan server terpisah. |
| Database | PostgreSQL | Host yang disarankan di README: Neon. Koneksi lewat dua variabel: DATABASE_URL dan DIRECT_URL (hanya nama variabelnya, nilainya tidak ada di zip ini). |
| ORM | Prisma | @prisma/client dan prisma ^5.14.0. Skema di prisma/schema.prisma, migrasi di prisma/migrations/, seed di prisma/seed.js. |
| Autentikasi | NextAuth.js | ^4.24.0, provider Credentials (email + password) dan Google OAuth. Sesi JWT, masa berlaku 30 hari. |
| Password | bcryptjs | ^2.4.3, hash dengan 10 salt rounds di lib/auth.js. |
| Grafik | Recharts | ^2.12.0 — dipakai di dashboard, laporan, dan Alternate Universe. |
| Ikon | Lucide React | ^0.378.0 — hampir semua halaman dan komponen memakainya. |
| Tanggal | date-fns | ^3.6.0, plus utilitas sendiri lib/dateFormat.js dan lib/currency.js (format IDR). |
| Ekspor | jsPDF + autotable, html2canvas, xlsx | Ekspor PDF laporan lewat lib/exportPDF.js (jsPDF ^2.5.2 + jspdf-autotable ^3.8.2). Paket xlsx dan html2canvas terdaftar di dependensi. |
| State client | Zustand (terdaftar) | ^4.5.0 tercantum di package.json, tapi pada penelusuran file app/, components/, dan lib/ tidak ditemukan pemakaian Zustand yang menonjol — state halaman lebih banyak ditangani React state di komponen *Client.js dan Context provider. Jadi jangan mengklaim Zustand sebagai tulang punggung state-nya. |
| Deploy asal | Vercel | vercel.json: framework nextjs, region sin1 (Singapura), build prisma generate && next build. |
Catatan build: next.config.js mengaktifkan eslint.ignoreDuringBuilds dan typescript.ignoreBuildErrors. Artinya error lint tidak akan menggagalkan build — praktis untuk demo, tapi bukan standar yang bagus untuk produksi.
3. Frontend-nya gimana?
Pola utamanya: Server Component mengambil data, Client Component mengurus interaksi. Contohnya app/dashboard/page.js (async, mengambil data lewat Prisma) merender components/dashboard/DashboardClient.js yang berisi grafik, tombol, dan modal. Pola *Client.js ini dipakai konsisten di semua fitur.
Halaman yang ada
/(landing) — saat ini langsung redirect ke/loginlewatuseEffect+ router./logindan/register— form autentikasi dengan ikon Lucide, toggle lihat password./dashboard— ringkasan keuangan + grafik./dashboard/transactions,/categories,/wallets— CRUD utama./dashboard/budget(plus detail/budget/[id]),/saving-goals,/reports,/settings./dashboard/alternate-universe— fitur simulasi: proyeksi 24 bulan dari data transaksi nyata, dengan parameter gaya hidup / investasi / skenario.
Komponen
19 file di components/, dikelompokkan per fitur: dashboard/, transactions/, wallets/, categories/, budget/, saving-goals/, reports/, settings/, alternate-universe/, plus providers/ (AuthProvider untuk sesi NextAuth dan PreferencesProvider untuk preferensi). Modal-modal form (tambah transaksi, dompet, kategori, anggaran, target tabungan) masing-masing file sendiri, jadi mudah dilacak.
Styling & bahasa
- Tailwind utility-first, gaya kartu (card-based), warna hijau
#4d8061dan emas#80672ddi README, latar krem hangat#f8f5ef, tipografi Inter (sans) + Georgia serif untuk heading menurut README. - Dark mode tersedia (Tailwind
darkMode: 'class') dan tema tersimpan per user (themedi model User). - Responsif mobile–tablet–desktop; animasi landing/login di
app/landing-animations.cssdanapp/login-animations.css. - Multi-bahasa Indonesia & Inggris lewat
lib/translations.js(diganti dari Settings).
4. Backend-nya gimana?
Backend = 21 file route di app/api/, semuanya route handler Next.js. Tidak ada folder server/ terpisah. Setiap route yang menyentuh data user wajib memeriksa sesi dulu, lalu memfilter berdasarkan userId dari sesi — jadi user A tidak bisa sekadar menebak ID untuk melihat data user B lewat API normalnya.
Endpoint utama (CRUD per resource)
| Resource | Endpoint |
|---|---|
| Auth | POST /api/auth/register, NextAuth di /api/auth/[...nextauth] (signin/signout/session) |
| Transaksi | GET/POST /api/transactions, PUT/DELETE /api/transactions/[id] |
| Kategori | GET/POST /api/categories, PUT/DELETE /api/categories/[id] |
| Dompet | GET/POST /api/wallets, PUT/DELETE /api/wallets/[id] |
| Anggaran | GET/POST /api/budgets, PUT/DELETE /api/budgets/[id] |
| Target tabungan | GET/POST /api/saving-goals, PUT/DELETE /api/saving-goals/[id], GET/POST /api/saving-goals/[id]/transactions (setoran/penarikan) |
| User | GET/PUT /api/user/profile, PUT /api/user/password, DELETE /api/user/delete |
Alur satu request (contoh: ambil transaksi)
Browser (sudah login, cookie sesi JWT)
→ GET /api/transactions
→ getServerSession(authOptions) — tanpa sesi → 401 Unauthorized
→ prisma.transaction.findMany({ where: { userId: session.user.id } })
→ amount Decimal diubah ke Number, lalu dikirim sebagai JSON
Autentikasi, detailnya
- Credentials: email + password dicek ke database, password dibandingkan dengan hash bcrypt (
lib/auth.js). Password tidak pernah disimpan polos. - Google OAuth: kalau email belum ada, user baru dibuat otomatis beserta dompet default “Dompet Utama” (saldo 0, tipe cash) — sama seperti registrasi manual di
createUser(). - Sesi JWT 30 hari;
middleware.jsmemproteksi semua/dashboard/:path*vianext-auth/middleware. - Kebutuhan environment (hanya nama, tanpa nilai):
DATABASE_URL,DIRECT_URL,NEXTAUTH_URL,NEXTAUTH_SECRET, opsionalGOOGLE_CLIENT_IDdanGOOGLE_CLIENT_SECRET.
Database: 7 model Prisma
| Model | Isi penting |
|---|---|
| User | name, email (unik), password hash, phone, bio, avatarUrl, currency (default IDR), theme (default light). |
| Wallet | name, type (cash/bank/e-wallet), balance Decimal(15,2). |
| Category | name, type income/expense, icon, color, isDefault; bisa milik user tertentu atau default global (userId nullable). |
| Transaction | type, amount Decimal(15,2), note, date; terhubung ke User, Wallet, dan Category. |
| Budget | amount per kategori per bulan/tahun; unik per (user, kategori, bulan, tahun). |
| SavingGoal | targetAmount, savedAmount, targetDate, imageUrl, wallet opsional. |
| SavingTransaction | Setoran/penarikan ke target tabungan, terhubung ke SavingGoal dan Wallet. |
Relasi memakai onDelete: Cascade di sebagian besar tempat (hapus user → dompet, kategori, transaksi, anggaran, dan target ikut terhapus), kecuali wallet pada SavingGoal yang SetNull. Index sudah dipasang di kolom yang sering difilter: userId, date, type, dan month/year untuk budget.
/api/debug/env (membeberkan ada/tidaknya dan potongan kredensial Google & NextAuth), /api/debug/users (menampilkan semua user), /api/test-db (menampilkan jumlah user dan data demo, plus stack error), dan /api/setup/add-columns. Hapus keempat route itu dulu, ganti secret, dan matikan akun seed demo sebelum dipakai beneran.Menjalankan secara lokal
npm install
npx prisma generate
npx prisma migrate dev --name init
npx prisma db seed
npm run dev # http://localhost:3000
Script build produksi: prisma generate && next build, lalu next start.
5. Jadi, halaman penjelasan ini aman di Cloudflare?
- Tidak ada secret di sini: zip yang diperiksa tidak berisi file
.env(dan.gitignore-nya memang mengecualikan.env*). Halaman ini hanya menyebut nama variabel environment, bukan nilainya. - Tidak ada data keuangan asli: tidak ada data user, transaksi, saldo, atau akun demo yang bisa dipakai login yang ditampilkan di halaman ini.
- Tidak ada backend yang bisa dibobol: Cloudflare Pages untuk halaman ini hanya menyajikan file statis. Tidak ada API, tidak ada koneksi database yang bisa dieksploitasi dari halaman ini.
Yang TIDAK aman (dan tidak dilakukan di sini): men-deploy aplikasi Econary-nya sendiri ke Cloudflare Pages sebagai situs statis — itu tidak akan jalan, karena Econary butuh server Node.js untuk API Routes + NextAuth dan koneksi PostgreSQL. Jalur aslinya adalah Vercel (lihat vercel.json), atau platform lain yang mendukung Next.js server-side. Dan kalau Econary di-deploy ke mana pun, hapus dulu route debug di atas.
6. Ringkasan satu paragraf
Econary adalah aplikasi keuangan pribadi full-stack JavaScript berbasis Next.js 14 App Router + React 18, dengan UI Tailwind CSS + Lucide + Recharts, backend berupa Next.js API Routes yang diamankan NextAuth (JWT) dan password bcrypt, serta data yang disimpan di PostgreSQL (Neon) lewat Prisma dengan 7 model utama. Frontend memakai pola Server Component + *Client.js per fitur; backend memakai pola cek sesi lalu filter userId di setiap request. Cocok sebagai proyek pembelajaran/portfolio — dengan catatan route debug harus dihapus sebelum produksi.
Sumber: isi Econary-main.zip — package.json, README.md, prisma/schema.prisma, app/, components/, lib/, middleware.js, vercel.json, dan next.config.js. Versi dependensi dicantumkan sesuai package.json di zip tersebut.