Markaz Idara Tul Islah — An ERP for an Institute That Ran on Paper
Next.js · Express · PostgreSQL · Redis · Nginx · RBAC · Bilingual Urdu/English (RTL)

This system is live in production at app.markazidaratulislah.com. Student-facing screenshots use seeded demo data.
- A Pakistani Islamic institute managed 167 students, fee collection, a matrimonial registry, and a spiritual-healing patient pipeline entirely on handwritten registers. Previous software attempts failed because nothing supported Urdu or their workflows.
- I built a full ERP from scratch: eight modules, role-based access control, and a fully bilingual Urdu/English interface with proper RTL layout, on a budget that ruled out managed cloud services.
- Live in production with 200+ active users. AI-assisted development covered roughly 80% of the CRUD surface; the schema, RBAC middleware, security hardening, and infrastructure were engineered by hand, and the case study explains exactly why that split exists.
The Challenge
They had tried software before. It failed twice, both times for the same reason: the staff primarily work in Urdu, and every off-the-shelf option was English-only with no RTL support. The deeper problem was workflow mismatch. No school product ships a spiritual-healing case pipeline or a matrimonial registry.
So the real challenge was not technical complexity, it was adoption. I was building for users ranging from young teachers comfortable with smartphones to senior staff who had never used a database-backed system. If the Urdu experience felt like a translation bolted onto an English app, it would join the previous two attempts in the drawer.
Constraints
- Budget ruled out managed cloud. The system runs on a single VPS, which shaped every infrastructure decision.
- Users span a wide digital-literacy range; the UI had to survive first-time computer users.
- Urdu is not just translation: it requires RTL layout, Nastaliq-style typography, and mixed-direction text handling (Urdu sentences containing English numbers and names).
- Spiritual-healing patient records and Rishta profiles are highly sensitive within the community. Access control was a hard requirement, not a feature.
- One developer (me), so development velocity mattered, which is where AI-assisted coding entered the picture.
Key Decisions
Backend architectureSeparate Express + Node API
Considered: Next.js full-stack (API routes / server actions) / Separate Express API behind the same Nginx
Why: RBAC lives in one Express middleware chain that every request passes through. One chokepoint to audit instead of permission checks scattered across server actions. It also keeps the door open for a future mobile app hitting the same API.
Trade-off: Two deployables instead of one, and some type duplication across the boundary that a monorepo shared-types package only partially solved.
SessionsRedis-backed sessions with HTTP-only cookies
Considered: Stateless JWT / Server-side sessions in Redis
Why: Instant revocation. When a staff member leaves, their access dies the moment an admin clicks a button. With JWTs I would have needed a denylist, which is just sessions with extra steps.
Trade-off: Redis became a hard runtime dependency on a single VPS. Mitigated with restart policies and an aggressive RDB snapshot schedule.
Permission modelDatabase-driven permission matrix, cached in Redis
Considered: Hardcoded role checks in route handlers / Role-permission matrix stored in PostgreSQL
Why: The institute kept inventing roles I had not anticipated ("finance staff who can also mark attendance for one campus"). A DB-driven matrix meant new roles without redeploys.
Trade-off: Permission checks became a lookup instead of an if-statement, so the cache layer had to be right. A stale cache here is a security bug, not a performance bug.
Urdu/RTL strategyLogical properties (margin-inline-start etc.) everywhere + per-user direction
Considered: i18n library with CSS direction flip / Designing RTL-first with logical CSS properties throughout
Why: The first prototype used a library flip and broke constantly: icons pointing the wrong way, number inputs misaligned, breadcrumbs reversing illegibly. Logical properties made direction a first-class concern instead of an override.
Trade-off: Slower initial styling, and every new component needs testing in both directions. Worth it: the Urdu UI is the product, not a translation of it.
Development approachThe split: roughly 80% AI-assisted, roughly 20% hand-engineered
Considered: Hand-write everything / AI-assisted for the CRUD surface, manual for the trust boundary
Why: Eight modules of forms, tables, and reports is an enormous CRUD surface for one developer. AI assistance made the timeline possible.
Trade-off: AI-generated code required a real review process. See What Went Wrong for the authorization bug that justified the entire 20%.
The Approach
The schema was the part I refused to rush. Eight modules share one normalized PostgreSQL database. The promotion logic, moving a cohort between academic years while preserving historical attendance and results, was the trickiest relational problem and the reason I wanted PostgreSQL over anything schemaless.
Every API request passes through one RBAC middleware chain: session check against Redis, then a permission lookup against the role-permission matrix. The healing module is the most locked-down surface in the system, because in this community, who is receiving spiritual treatment is genuinely sensitive information.
The bilingual interface is built RTL-first with CSS logical properties, per-user language preference, and Noto Nastaliq Urdu for typography. The hard part nobody warns you about is bidirectional text: an Urdu sentence containing a phone number, an English name, and a PKR amount will render in a scrambled order unless you handle Unicode bidi isolation explicitly.
Roughly 80% of this codebase was written with AI assistance. Forms, tables, report views, API endpoints that follow established patterns. The 20% I wrote by hand is the trust boundary: the schema, the RBAC middleware, session handling, the Nginx config, and every line that touches authorization. That split was not a philosophy going in. It became one after the bug described below.
System Architecture
Interactive Demo
Walk through the system design and data flow for this project step by step.
Logged in as: Teacher
Sees only their own classes. Enforced in the API middleware, not just the UI.
Live recreation of the production permission matrix. Locked modules return 403 at the API middleware — hiding the menu item is cosmetic; the middleware is the control.
Overview
Business Impact
The bilingual interface is the reason adoption succeeded where two previous attempts failed. Staff who would not touch an English-only system use the Urdu interface daily. The matrimonial registry replaced informal matchmaking with a structured, permissioned profile system. The healing practice's case files went from unsearchable handwritten records to a pipeline where treatment history is queryable in seconds.
Total infrastructure cost is a single VPS. For an institute of this size and budget, that line item is the difference between having a system and not having one.
What Went Wrong
RTL was a two-front war. The layout front I expected; the typography front I did not. Nastaliq script renders much taller than Latin text, so every line-height, input field, and table row that looked fine in English clipped Urdu descenders. The fix was a direction-aware typography scale.
Adoption nearly stalled in week two. The first version of attendance marking was a dense grid that made sense to me and to nobody else. Watching a teacher actually use it, hesitating, tapping the wrong cells, was humbling. I rebuilt it as a simple tap-per-student flow with big touch targets, and adoption recovered.
Lessons Learned
The AI-assisted velocity was real. I genuinely do not think a solo build of this scope was feasible otherwise on this timeline. But the review burden for generated code that touches authorization is so high that for the next project, the trust boundary gets written first, by hand, and generated code is forced through it with no exceptions. Velocity on the inside of the boundary, paranoia at the boundary itself.
The feature the client values most is not one I would have predicted. It is the monthly finance summary, because it replaced a multi-day manual notebook reconciliation. Build for the ledger, not the demo.
Technical Highlights
- Complete academic engine: campuses, programs, academic years, subjects, classes, timetables, admissions, and student promotions with historical record preservation
- Attendance management with daily tracking for 167 students, leave request approval chains, and monthly aggregate reporting
- Assessment system with configurable grading rubrics, results publishing, and per-student performance analytics
- Finance module with fee collection in PKR, expense tracking, and the monthly summary that replaced a multi-day manual reconciliation
- Matrimonial (Rishta) community module with structured profile registry and permissioned matching workflow
- Spiritual healing module with patient registry and case pipeline, treated with the same access restrictions as medical data
- Database-driven RBAC with role-permission matrix cached in Redis. New roles without redeploys, instant revocation on staff departure
- Bilingual Urdu and English interface built RTL-first with CSS logical properties, Noto Nastaliq Urdu typography, and Unicode bidi isolation for mixed-content strings
- Network-layer security with Nginx reverse proxy, rate limiting, proxy headers, and SSL termination
- Application-layer OWASP protections: parameterized queries, CSRF tokens, HTTP-only secure cookies, input validation, error sanitization
- Redis for server-side sessions (instant revocation over stateless JWTs), permission cache, and rate limiting counters
- AI-assisted development for roughly 80% of the CRUD surface; schema, RBAC middleware, session handling, and security hardening engineered by hand
Want results like this for your infrastructure?
I specialize in taking complex AI pipelines and cloud setups from concept to high-availability production. Let's discuss how to optimize your workloads, secure your environment, and reduce cloud costs.