
Tech stack
Project breakdown
Shorten URL - Modular Laravel Monolith
Client workspace · Group-based RBAC · Redirect expiry and click tracking
Role: Solo developer. I designed the modular architecture, validation rules, and deployment flow.
Laravel 10 · PHP 8.1 · MySQL 8 · Blade · AdminLTE 3 · Docker Compose · Nginx · spatie/laravel-permission · nwidart/laravel-modules
This project separates one Laravel application into three clear surfaces: public redirects, admin back office, and a client-facing workspace. The goal was not CRUD alone, but putting business rules such as RBAC, per-user uniqueness, and redirect expiry into the correct layers.
System Architecture
I chose a modular monolith because the domains are tightly coupled. Shared auth context, one runtime, and one database made more sense than splitting the application into multiple services at this scale.
End-to-end Link Workspace
Problem: A useful URL shortener needs more than a create form. Users want filtering, custom aliases, tags, archived states, detail views, and batch-like management without bouncing through multiple screens.
Solution: Build a dedicated client workspace while reusing the same domain logic as the admin surface.
Implementation highlights:
- Client routes live under a dedicated namespace to keep boundaries clear
- Create, update, archive, delete, and tag management delegate to the same controllers and repositories used elsewhere
- Validation rules encode global and per-user uniqueness constraints
- Repository methods hydrate tag relationships so edit forms can be prefixed correctly
Result: Users get a focused workspace while the business rules remain centralized instead of drifting between admin and client implementations.
RBAC by Group and Permission Matrix
Problem: The admin surface spans many resources and actions, and hard-coded roles on the user record are too rigid once groups and permission editing enter the picture.
Solution: Map business groups to roles, seed permission matrices by module/action, and let the admin surface edit those permissions safely.
Implementation highlights:
- Seeder-driven permission generation by module and action
- Each business group owns a role mapping
- User updates sync group membership and the assigned role together
- Route middleware blocks regular users from the admin namespace before controller logic runs
- Permission forms load and sync the full matrix through Spatie permissions
Result: The authorization model scales with the product instead of remaining a fragile collection of if-statements.
Public Redirect with Expiry and Click Tracking
Problem: A redirect endpoint that only looks up a record and forwards the request misses business meaning. Expired links, missing links, and click tracking all need explicit behavior.
Solution: Treat public redirect as a first-class access flow with HTTP semantics and state mutation.
Implementation highlights:
- Catch-all route reserved for short codes only
- Access controller performs the lookup and decides between
404and410 - Successful access increments clicks and extends expiry where the product requires it
- Redirect logic stays small, but the surrounding validation and state rules remain explicit
Result: Redirects become observable business behavior rather than anonymous helper logic.
CI/CD & Deploy
- Docker Compose for both local and production variants
- Separate deployment files for production and CI-driven delivery
- HTTPS-aware configuration and explicit routing boundaries so catch-all redirects stay safe
Key screens
Client Link Workspace
Client-facing workspace for creating links, editing aliases, managing tags, and reviewing link state.
Admin Dashboard
Admin surface for system overview, user/group administration, and permission-driven management tasks.