20 KiB
Codebase Structure
Analysis Date: 2026-05-28
Directory Layout
src/ # Laravel application root
├── app/ # Application code
│ ├── Exports/ # Excel export classes (Maatwebsite)
│ ├── Http/ # HTTP layer
│ │ ├── Controllers/ # Web controllers
│ │ │ ├── Api/ # API controllers (JSON)
│ │ │ └── Auth/ # Auth controllers (Laravel Breeze)
│ │ ├── Middleware/ # Custom middleware
│ │ └── Requests/ # Form request validation classes
│ │ └── Auth/ # Auth-specific form requests
│ ├── Models/ # Eloquent models
│ ├── Notifications/ # Notification classes
│ ├── Providers/ # Service providers
│ ├── Services/ # Service classes
│ └── View/ # Blade component classes
│ └── Components/ # View components
├── bootstrap/ # Framework bootstrap
│ ├── app.php # App config (middleware, routing registration)
│ └── providers.php # Registered service providers
├── config/ # Configuration files
├── database/ # Database layer
│ ├── factories/ # Model factories
│ ├── migrations/ # Schema migrations (12 files)
│ └── seeders/ # Database seeders
├── lang/ # Localization files
│ ├── bm/ # Bahasa Malaysia
│ └── en/ # English
├── public/ # Public web root
│ ├── build/ # Vite build output
│ ├── css/ # Compiled CSS
│ ├── icon/ # Map icons
│ ├── img/ # Images
│ ├── js/ # Custom JS
│ └── logo/ # Logo files
├── resources/ # Frontend resources
│ ├── css/ # Source CSS (Tailwind + custom)
│ ├── js/ # Source JS
│ └── views/ # Blade templates
│ ├── auth/ # Auth screens (6 files)
│ ├── components/ # Shared Blade components (13 files)
│ ├── layout/ # Main app views
│ │ ├── admin/ # Admin panel views
│ │ ├── graph/ # Chart views
│ │ ├── notification/ # Notification views
│ │ │ └── history/ # Notification history views
│ │ └── siren/ # Siren views
│ ├── layouts/ # Base layout templates (Breeze)
│ ├── nav/ # Navigation partials (header, navbar, footer)
│ ├── pdf/ # PDF export templates
│ └── profile/ # Profile views
│ └── partials/
├── routes/ # Route definitions
├── storage/ # Framework storage
├── tests/ # Automated tests
│ ├── Feature/ # Feature tests
│ │ └── Auth/ # Auth feature tests
│ ├── Unit/ # Unit tests
│ └── storage/ # Test storage
├── vendor/ # Composer dependencies (excluded)
├── composer.json # PHP dependencies
├── package.json # Node dependencies (Vite, Tailwind)
├── vite.config.js # Vite configuration
├── tailwind.config.js # Tailwind CSS config
└── phpunit.xml # PHPUnit config
Directory Purposes
app/Http/Controllers/ — Web Controllers:
- Purpose: Handle authenticated web requests, query data, render Blade views
- Contains: 11 controllers + 9 auth controllers + 3 API controllers
- Key files:
MapController.php: Dashboard page — joins station + latest rainfall/waterlevel/siren dataRainfallController.php: Rainfall data display, 6-hour threshold, historical data, graph data, Excel exportWaterLevelController.php: Water level display, graph data, historical data, Excel exportSirenController.php: Siren status display, siren history, PDF exportNotificationController.php: Rainfall/waterlevel/siren notifications, history, PDF exportsAdminController.php: Station CRUD, user CRUD (access_level=1 only)cctvController.php: CCTV link display for stationsLocaleController.php: Language switching (en/bm)ProfileController.php: User profile edit/update/deleteController.php: Empty abstract base class
app/Http/Controllers/Api/ — API Controllers:
- Purpose: JSON endpoints for external IoT devices and mobile clients
- Contains: 3 controllers (no middleware/auth required on most endpoints)
- Key files:
StationController.php: 7 endpoints — current data, rainfall, waterlevel, notifications, history, siren, siren historyAuthController.php: Custom username/password login returning JSONAlertController.php: Relay station alerts via FCM push
app/Http/Controllers/Auth/ — Auth Controllers (Laravel Breeze):
- Purpose: Handle authentication flow (login, register, password reset, email verification)
- Contains: 9 controllers scaffolded by Laravel Breeze
- Key files:
AuthenticatedSessionController.php: Login with custom blocked-user + login-attempt trackingRegisteredUserController.php: User registrationNewPasswordController.php,PasswordController.php,PasswordResetLinkController.php: Password managementVerifyEmailController.php,EmailVerificationNotificationController.php,EmailVerificationPromptController.php: Email verificationConfirmablePasswordController.php: Password confirmation
app/Http/Middleware/ — Custom Middleware:
- Purpose: Request filtering and modification
- Contains: 2 middleware classes
- Key files:
AdminMiddleware.php: ChecksAuth::check()+Auth::user()->access_level === 1, redirects to/dashboardon failure. Registered as alias'admin'inbootstrap/app.php.LocalizationMiddleware.php: Readslocalefrom session, setsApp::setLocale(). Appended towebmiddleware group inbootstrap/app.php.
app/Http/Requests/ — Form Request Validation:
- Purpose: Encapsulate form validation and authorization logic
- Contains: 2 form request classes
- Key files:
ProfileUpdateRequest.php: Validates name + email (unique check ignoring current user)Auth/LoginRequest.php: Rate-limited login validation (5 attempts), customusername()returning'name'
app/Models/ — Eloquent Models:
- Purpose: Single model for Laravel authentication
- Contains:
User.php— only Eloquent model in the app - Key details:
- Extends
Authenticatable, usesHasFactory,Notifiable - Fillable:
name,email,password,access_level,login_attempts,is_blocked - Hidden:
password,remember_token - Casts:
email_verified_at(datetime),password(hashed),is_blocked(boolean) - Overrides
sendPasswordResetNotification()to use customResetPasswordNotification
- Extends
app/Services/ — Service Layer:
- Purpose: External API integrations
- Contains: 1 service class
- Key file:
FcmService.php: Firebase Cloud Messaging integration. Constructor readsFIREBASE_PROJECT_IDandFIREBASE_CREDENTIALS(path to JSON) from env.sendToTopic()authenticates viagoogle/authServiceAccountCredentials, sends POST to FCM v1 HTTP API.
app/Exports/ — Excel Exports:
- Purpose: Generate downloadable Excel spreadsheets
- Contains: 2 export classes using
Maatwebsite\Excel - Key files:
HourlyRainfallExport.php: Exports hourly rainfall with 24-column pivot (hour_00..hour_23) for a date range. ImplementsFromCollection,WithHeadings,ShouldAutoSize.WaterLevelExport.php: Exports water level readings with alert/warning/danger thresholds for a station+date. ImplementsFromCollection,WithHeadings,ShouldAutoSize.
app/Notifications/ — Notification Classes:
- Purpose: Email notifications sent by Laravel
- Contains: 1 notification class
- Key file:
ResetPasswordNotification.php: Queueable email notification for password reset. Sends viamailchannel with SIDES branding.
app/Providers/ — Service Providers:
- Purpose: Framework bootstrapping
- Contains: 1 service provider
- Key file:
AppServiceProvider.php: Currently emptyregister()andboot()methods (no custom services registered).
app/View/Components/ — Blade Components:
- Purpose: Render Blade component views
- Contains: 2 component classes
- Key files:
AppLayout.php: Renderslayouts.app(Breeze default authenticated layout)GuestLayout.php: Renderslayouts.guest(Breeze default guest layout)
routes/ — Route Definitions:
- Purpose: Map HTTP requests to controllers
- Contains: 4 route files
- Key files:
web.php(85 lines): All web routes — auth-protected (dashboard, rainfall, waterlevel, siren, notification, CCTV), admin-protected (station management, user management), and public (dashboard, stations, locale switch). Includesauth.phpat the end.auth.php(59 lines): Auth routes scaffolded by Breeze — guest routes (login, register, password reset), auth routes (verify email, confirm password, logout).api.php(19 lines): Public API routes — station data endpoints (7 GET), login, alert push. No middleware required on most endpoints.console.php(8 lines): SingleinspireArtisan command (default Laravel).
database/migrations/ — Schema Migrations:
- Purpose: Define and evolve database schema
- Contains: 12 migration files ordered by timestamp
- Key files:
0001_01_01_000000_create_users_table.php: Users, password_reset_tokens, sessions tables (Laravel default)2025_11_06_071853_create_station_table.php:stationtable — stationid (PK), name, district, lng, lat, mainriverbasin, subriverbasin, rainfall, waterlevel2025_11_06_072709_create_rainfall__table.php:rainfalltable — stationid, timestamp, anncum, daily, hourly, currentrf, battery2025_11_06_072738_create_waterlevel_table.php:waterleveltable — stationid, datetime, waterlevel, alert, warning, danger2025_11_07_024940_create_notification_table.php:notificationtable — stationid, timestamp, stationtype, level, active_time2025_11_07_031601_create_siren__table.php:sirentable — stationid, stationtype, active_time, level2025_11_07_063825_add_access_level_to_users_table.php: Addsaccess_level(int, default 2) to users2025_11_07_065418_add_block_fields_to_users_table.php: Addsis_blocked(boolean) andlogin_attempts(int) to users2025_11_08_004548_add_siren_to_station_table.php: Addssiren(int, nullable) to station2025_11_25_113158_add_cctvlink_to_station.php: Addscctv_link(string, nullable) to station
resources/views/ — Blade Templates:
- Purpose: Render all HTML and PDF output
- Contains: ~40+ Blade template files organized by domain
- Structure:
layout/app.blade.php— Main authenticated layout (@include nav.header+navbar,@yield content1/content2/content3)layout/homeapp.blade.php— Public layout (no auth, full-width)layout/dashboard.blade.php— Home page with Leaflet map + station data tablelayout/rainfall.blade.php— Rainfall data table with 7-day daily columns + graph modallayout/waterlevel.blade.php— Water level data tablelayout/threshold.blade.php— 6-hour early warning threshold viewlayout/historicalrainfall.blade.php— Historical rainfall with date range pickerlayout/historicalwl.blade.php— Historical water levellayout/cctv.blade.php— CCTV links for stationslayout/home.blade.php— Public landing page (extendslayout.homeapp)layout/siren/home.blade.php,layout/siren/history.blade.php— Siren status and historylayout/notification/rainfall.blade.php,layout/notification/waterlevel.blade.php,layout/notification/siren.blade.php— Current notificationslayout/notification/history/rainfall.blade.php,layout/notification/history/waterlevel.blade.php— Notification historylayout/graph/rainfall.blade.php— Rainfall graph pagelayout/admin/stationmgmt.blade.php(352 lines) — Station management CRUD interfacelayout/admin/usermgmt.blade.php— User management CRUD interfacepdf/rfhistory.blade.php,pdf/wlhistory.blade.php,pdf/sirenhistory.blade.php— PDF export templatesnav/header.blade.php— HTML head, CSS, Leaflet, Flatpickr, jQuery CDNsnav/navbar.blade.php— Full responsive navigation (desktop + mobile sidebar)nav/footer.blade.php— Footer partialauth/*.blade.php— Login, register, forgot/reset password, verify-email, confirm-password screenscomponents/*.blade.php— 13 shared Blade components (application-logo, dropdown, input-label, modal, nav-link, buttons, etc.)layouts/app.blade.php,layouts/guest.blade.php— Breeze default layouts (component-based)profile/edit.blade.php— Profile edit page
lang/ — Localization Files:
- Purpose: Internationalization strings for two locales
- Contains:
en/(English) andbm/(Bahasa Malaysia) directories - Key files:
messages.php(UI text),toast.php(flash messages),auth.php,validation.php,passwords.php,pagination.php
public/ — Public Web Root:
- Purpose: Entry point for HTTP requests (
index.php), static assets - Contains: Compiles CSS (
css/style.css), JavaScript (js/script.js,js/graph.js), Leaflet map icons (icon/), images (img/), logos (logo/), Vite build output (build/)
tests/ — Automated Tests:
- Purpose: PHPUnit test suite
- Contains: Feature tests and unit tests
- Key files:
tests/Feature/Auth/: 6 auth test files (most appear empty — e.g.,AuthenticationTest.phphas 0 lines)tests/Feature/ExampleTest.php,tests/Feature/ProfileTest.phptests/Unit/ExampleTest.php
Key File Locations
Entry Points:
public/index.php: HTTP entry point (Laravel front controller)artisan: CLI entry pointbootstrap/app.php: Application configuration (middleware aliases, routing, exceptions)bootstrap/providers.php: Registered service providers
Configuration:
config/app.php: App name, env, URL, timezone, locale, providers, aliasesconfig/database.php: DB connection (default: sqlite, but code uses PostgreSQL)config/auth.php: Auth guard (web, session), user provider, password reset configconfig/mail.php: Mail driver config (default: log)config/filesystems.php: Disk configs (local, public, s3)config/services.php: Third-party API keys (postmark, resend, ses, slack)config/queue.php: Queue driver (default: database)config/session.php: Session driver configconfig/cache.php: Cache driver config.env: Environment variables (exists but not read — contains credentials)
Core Routing:
routes/web.php: All web routes (85 lines)routes/auth.php: Auth routes (59 lines, included from web.php)routes/api.php: API routes (19 lines)routes/console.php: Console commands (8 lines)
Database Schema:
database/migrations/: 12 migration files defining 8+ tablesdatabase/seeders/DatabaseSeeder.php: Seeds admin user
Static Assets:
resources/css/app.css: Tailwind CSS sourceresources/css/style.css: Custom CSSresources/js/app.js: Alpine.js + Bootstrap app JSresources/js/bootstrap.js: Axios + Echo bootstrapresources/js/script.js: Custom app scriptsresources/js/graph.js: Chart.js graph rendering
Naming Conventions
Files:
- Controllers: PascalCase suffixed with
Controller(e.g.,RainfallController.php,AdminController.php) - Models: PascalCase singular (only
User.php) - Middleware: PascalCase suffixed with
Middleware(e.g.,AdminMiddleware.php) - Requests: PascalCase suffixed with
Request(e.g.,ProfileUpdateRequest.php) - Exports: PascalCase suffixed with
Export(e.g.,HourlyRainfallExport.php) - Services: PascalCase suffixed with
Service(e.g.,FcmService.php) - Notifications: PascalCase suffixed with
Notification(e.g.,ResetPasswordNotification.php) - Migrations:
YYYY_MM_DD_HHMMSS_create_{table}_table.phpor..._add_{column}_to_{table}_table.php - Blade views: Lowercase kebab-case (e.g.,
historicalrainfall.blade.php,stationmgmt.blade.php) - Routes file: Lowercase (
web.php,api.php,auth.php,console.php) - Config files: Lowercase (
app.php,database.php)
Directories:
- Namespace-matching PascalCase under
app/(e.g.,Http/Controllers/Api/) - Lowercase under
resources/views/(e.g.,layout/admin/,layout/notification/history/) - Lowercase under
config/,database/,routes/,lang/
Where to Add New Code
New Feature (e.g., new data type):
- Controller:
app/Http/Controllers/{Name}Controller.php— extendsController, usesDBfacade - Routes:
routes/web.php— add under appropriate middleware group (authoradmin) - Views:
resources/views/layout/{name}/— create view directory withhome.blade.php,history.blade.phpetc. - API endpoint:
routes/api.php+app/Http/Controllers/Api/{Name}Controller.php - Exports:
app/Exports/{Name}Export.php+resources/views/pdf/{name}history.blade.phpif needed
New API Endpoint:
- Add route to
routes/api.php - Add method to existing controller in
app/Http/Controllers/Api/or create new controller
New Middleware:
- Create class in
app/Http/Middleware/ - Register alias or group in
bootstrap/app.php→withMiddleware()
New Service:
- Create class in
app/Services/ - Inject via constructor or
app()helper in controllers
New Database Table:
- Create migration in
database/migrations/usingYYYY_MM_DD_HHMMSS_create_{table}_table.phpformat - Add seeder entry to
database/seeders/DatabaseSeeder.php
New Translation:
- Add key to both
lang/en/messages.phpandlang/bm/messages.php(or corresponding domain file) - Use
@lang('messages.key')in Blade or__('messages.key')in PHP
New Validation:
- Add inline
$request->validate([...])for simple cases - Create
app/Http/Requests/{Name}Request.phpfor reusable validation
Special Directories
resources/views/layout/:
- Purpose: Main application views (the primary view directory used by all web controllers)
- Contains: 14 files + 4 subdirectories (admin/, graph/, notification/, siren/)
- The
layout.appBlade layout is the base template accessed via@extends('layout.app')— this includes nav, header, footer, modals, scripts, CSS
resources/views/layouts/:
- Purpose: Laravel Breeze default layout templates (used by auth screens and view components)
- Contains:
app.blade.php(component-based slot layout),guest.blade.php,navigation.blade.php - This is a SEPARATE layout system from
resources/views/layout/— the application useslayout.appfor authenticated pages andlayouts.apponly for auth scaffolding views
public/js/ and public/css/:
- Purpose: Compiled/minified static assets (not source)
- Contains:
script.js,graph.js— JavaScript files directly placed in public (NOT compiled through Vite). These are loaded via<script src="{{ asset('js/script.js') }}">in thelayout.appBlade layout. - Source JS is in
resources/js/and compiled via Vite.
storage/:
- Purpose: Framework runtime storage (logs, cache, sessions, views)
- Generated: Yes
- Committed: No
vendor/:
- Purpose: Composer PHP dependencies
- Generated: Yes
- Committed: No
node_modules/:
- Purpose: NPM frontend dependencies
- Generated: Yes
- Committed: No
Structure analysis: 2026-05-28