EDARA (أدارة — "Administrasi") is a multi-tenant SaaS platform for Indonesian Islamic school foundations (yayasan) managing 2–10 educational units (MI, MTs, MA, SD, SMP, SMA, Pesantren). The system replaces Excel-based workflows with a structured, role-based platform covering student lifecycle management, teacher records, SPP (tuition) billing with flexible discount schemes, cash flow tracking, and activity calendars.
- Technology Stack
- Project Architecture
- Getting Started
- Project Structure
- Key Features
- Development Workflow
- Coding Standards
- Testing
- Contributing
- License
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | React ^19.x | UI framework |
| Routing | TanStack Router ^1.x | File-based routing, type-safe |
| State (Server) | TanStack Query ^5.x | Server state, caching, mutations |
| State (UI) | Zustand ^5.x | UI state (active unit, sidebar, theme) |
| Styling | Tailwind CSS ^4.x | Utility-first CSS, design tokens |
| Components | shadcn/ui (Radix UI) | Headless accessible components |
| Forms | React Hook Form ^7.x + Zod ^4.x | Schema-driven validation |
| Charts | Recharts ^2.x | Cashflow and SPP trend charts |
| Calendar | react-big-calendar | Calendar view for events |
| App Runtime | TanStack Start | SPA-rendered app shell plus embedded server runtime for auth and RPC |
| API | oRPC | Type-safe RPC layer |
| Auth | Better Auth | Auth with email/password, sessions |
| ORM | Drizzle ORM | Type-safe SQL query builder |
| Jobs | pg-boss | PostgreSQL-native job queue |
| Database | Neon (PostgreSQL) | Serverless PostgreSQL |
| Deployment Runtime | Nitro / Node server output | Hosts /api/auth and /api/rpc in production |
| Package Manager | pnpm | Fast, disk space efficient |
EDARA uses TanStack Start in SPA render mode. The UI is client-rendered, while the same repo also ships an embedded server runtime that hosts Better Auth and oRPC endpoints. The correct mental model is SPA-first, not backendless.
Current Phase 1 reality is mixed by domain: auth, tenant flows, academic years, dashboard, activity logs, teachers, classes, and the Student API Router are already live on the real backend. The remaining migration work is now concentrated in mock/local-state frontend surfaces, especially Student Frontend plus the SPP, cashflow, events, and users domains.
EDARA follows these key patterns:
Every database table carries school_id (tenant) and optionally unit_id (sub-tenant). PostgreSQL Row Level Security (RLS) policies enforce isolation at the database layer, independent from application code.
SPP payment status (paid/partial/unpaid) is never stored — derived via SQL aggregation from payment_transactions at query time. This ensures consistency and enables reversal mechanisms without data corruption.
payment_transactions has no updated_at column and no UPDATE/DELETE permissions at the application layer. Corrections use reversal transactions referencing the original transaction ID.
[!INFO] For full product specification details, see: Product Requirements (PRD)
- Node.js ^20.x
- pnpm ^9.x
- PostgreSQL (Neon) account
- Better Auth account (or use email/password)
# Clone the repository
git clone https://github.com/alarwasyi98/edara.git
cd edara
# Install dependencies
pnpm install
# Copy environment template
cp .env.example .envEdit .env and add your credentials:
# Database (Neon)
DATABASE_URL="postgresql://user:pass@host.neon.tech/db?sslmode=require"
# Better Auth
BETTER_AUTH_SECRET="your-secret-key-here"
BETTER_AUTH_URL="http://localhost:3000"# Development
pnpm dev
# Build for production
pnpm build
# Run type checking
pnpm typecheck
# Run linting
pnpm lint├── .agents/ # AI agent memory & rules
│ ├── memory/ # Layered memory system
│ │ ├── system.md # Tech stack, constraints, conventions
│ │ ├── project.md # Feature inventory, status, gotchas
│ │ ├── decisions.md # ADR log with rationale
│ │ ├── log.md # Session log (what happened)
│ │ └── graph.md # Dependency/relationship map
│ ├── external/ # External memory sources
│ └── rules/ # Coding standards, commit conventions
├── docs/ # Project documentation
│ ├── PRD.md # Product Requirements Document
│ ├── implementation-plan.md
│ └── naming-dictionary.json
├── src/
│ ├── components/ # Reusable UI components
│ │ ├── layout/ # App shell, sidebar, header
│ │ ├── ui/ # shadcn/ui base components
│ │ └── data-table/ # Data table components
│ ├── features/ # Feature modules
│ │ ├── auth/ # Authentication
│ │ ├── dashboard/ # Dashboard & analytics
│ │ ├── teachers/ # Teacher management
│ │ ├── students/ # Student management
│ │ ├── classes/ # Class management
│ │ ├── spp/ # SPP billing
│ │ ├── cashflow/ # Cash flow tracking
│ │ └── events/ # Calendar events
│ ├── lib/ # Shared utilities
│ │ ├── validators/ # Zod schemas
│ │ ├── constants/ # App constants
│ │ ├── utils/ # Helper functions
│ │ └── formatters/ # Formatters (currency, dates)
│ ├── routes/ # TanStack Router routes
│ ├── server/ # Backend
│ │ ├── db/ # Drizzle ORM & schema
│ │ ├── routers/ # oRPC routers
│ │ ├── middleware/# Auth, RLS, RBAC
│ │ └── jobs/ # pg-boss workers
│ └── stores/ # Zustand stores
├── .github/ # GitHub configs
├── AGENTS.md # AI agent activation contract
├── package.json
└── README.md
| Feature | Description |
|---|---|
| Multi-Tenant Management | Register and manage foundations with multiple educational units |
| Unit Switching | Role-based context switching between units |
| Academic Year | Manage academic years with exclusive activation |
| Teacher Management | Live CRUD, soft-delete, bulk import preview/partial import, and filtered Excel export |
| Student Lifecycle | Registration, enrollment, status transitions (promote, transfer, graduate) |
| Class Management | Class CRUD, capacity tracking, mass promotion |
| SPP Billing | Categories, per-class rates, discount schemes, auto-generation |
| Payment Recording | Append-only payments with reversal support |
| Payment Matrix | Dynamic payment status computed from transactions |
| Cashflow | Income/expense tracking with auto-linked SPP payments |
| Events Calendar | Table and calendar views for school activities |
| Export Reports | Excel/PDF generation via background jobs |
For feature specifications, see: PRD - Feature Specifications
The project follows a staged implementation plan from Mock/Vite SPA toward TanStack Start + oRPC + Drizzle ORM.
- Completed: Sections 1–8 plus Section 9 Steps 23–25 — through Student API Router
- In Progress: Section 9 (Class & Student Management), with Student Frontend still being migrated from mock data to live API hooks
- Next Target: Step 26 — Student Frontend (list, registration, and detail rewiring)
- Migration Reality: Teachers and classes are live end-to-end, the student backend is live, and SPP/cashflow/events/users still have mock or local-state UI surfaces
For full plan, see: Implementation Plan
main— Production-ready, receives code only via squash-merged PRsdev— Integration branch, all feature work merges here locally first- Feature branches (
feat/,fix/,chore/,docs/,refactor/) are local only — never pushed to the remote. One PR per feature:dev→main.
Important: After every squash merge from
devtomain, syncdevback immediately. See Git Workflow for the full guide.
- Type Safety: Full TypeScript with strict mode
- Validation: Zod schemas shared between client and server
- Financial Precision: decimal.js for all monetary calculations (ADR-07)
- API Contracts: oRPC for end-to-end type safety
- Styling: Tailwind CSS v4 with design tokens
- Components: shadcn/ui (Radix UI primitives)
Before submitting changes, run:
pnpm lint && pnpm format && pnpm typecheck
# Run tests
pnpm test
# Run tests in watch mode
pnpm test
# Run tests once
pnpm test:runContributions are welcome! Please read the Contributing Guide first.
- Fork the repository
- Create a feature branch (
feature/your-feature) - Make your changes
- Run lint, format, and typecheck
- Submit a pull request
This project is licensed under the ISC License.
- Product Requirements (PRD) — Feature specs, data architecture, API design
- Implementation Plan — Step-by-step implementation with progress
- Feature Stories — User stories with UX/UI considerations
- Naming Dictionary — Indonesian ↔ English identifier mapping
