System Architecture

Deep dive into the technical architecture of Church Ledger.

System Architecture

Church Ledger is designed as a monolithic Laravel application with a tightly coupled React frontend via Inertia.js. This architecture ensures maximum developer productivity while providing a smooth, SPA-like user experience.

The Core Stack

  • Backend: Laravel 12 (PHP 8.3+)
  • Frontend: React 19, TypeScript, Tailwind CSS v4
  • Communication: Inertia.js v2 (Protocol for seamless data sharing)
  • Database: PostgreSQL (Relational integrity)
  • Auth: Laravel Breeze / Fortify with custom Role-Based Access Control (RBAC)

Database Schema Design

The system revolves around four primary domains: Members, Transactions, Groups, and Audit Logs.

Member Domain

Stores demographic and spiritual data.

  • members: Central table with personal info, baptism status, and household foreign keys.
  • households: Groups members for family-based giving and communication.

Ledger Domain (Financials)

Designed for double-entry integrity (conceptually).

  • funds: Categories for giving (e.g., General, Building, Missions).
  • contributions: Tracks individual tithes/offerings with high-precision decimals (decimal(19, 4)).
  • reconciliations: Batch records of processed giving.

Audit Domain

Every state change is tracked.

  • activities: Stores the 'who', 'what', 'when', and 'before/after' snapshots of model data.

Advanced Laravel Implementation

The Auditable Trait

Most models in Church Ledger implement an Auditable trait that hooks into Eloquent events.

trait Auditable { protected static function bootAuditable() { static::updated(function ($model) { ActivityLog::create([ 'user_id' => auth()->id(), 'subject_id' => $model->id, 'subject_type' => get_class($model), 'action' => 'update', 'payload' => [ 'before' => $model->getOriginal(), 'after' => $model->getAttributes(), ], ]); }); } }

Authorization Logic

We use Spatie Laravel Permission under the hood, but wrap it in custom Gate definitions to handle complex ministry scenarios (e.g., a Deacon can see attendance but not giving records).

Gate::define('access-giving', function (User $user) { return $user->hasRole('Admin') || $user->hasPermissionTo('view-finances'); });

Security & Privacy

Privacy is paramount given the sensitive nature of church data.

  • Data at Rest: Sensitive member fields are encrypted using Laravel's native encryption.
  • Soft Deletes: No member data is permanently deleted on the first pass; it is flagged for review to prevent accidental spiritual data loss.
  • Session Security: High-entropy session tokens with mandatory multi-factor authentication for administrative users.

Performance Optimization

  • Eager Loading: All Inertia controllers strictly use with() to prevent N+1 query issues in member lists.
  • Postgres Indexing: Composite indexes on (member_id, date) for contribution queries and (church_id, slug) for multi-tenant isolation.
  • Vite Bundling: Splitting the admin dashboard and public-facing routes into separate bundles for faster initial loads.