Last Updated: 3/11/2026
Architecture Overview
LinkAce is built on Laravel 11 and follows modern PHP development practices. This guide covers the application architecture, technology stack, and key design decisions.
Technology Stack
Backend
- Framework: Laravel 11.48+
- Language: PHP 8.2+
- Database: MySQL 8.0+, PostgreSQL 12+, or SQLite 3.35+
- Cache: Redis, Memcached, or file-based
- Queue: Redis, database, or sync
- Session: File, database, Redis, or cookie
Frontend
- Build Tool: Laravel Mix (Webpack)
- CSS: Bootstrap-based custom theme
- JavaScript: Alpine.js for interactivity
- Icons: Custom SVG icon set
Infrastructure
- Deployment: Docker (recommended), PHP-FPM, or Kubernetes
- Web Server: Nginx (recommended) or Apache
- Storage: Local filesystem or S3-compatible object storage
- Monitoring: Sentry integration for error tracking
Application Structure
Directory Layout
linkace/
├── app/ # Application code
│ ├── Actions/ # Business logic actions
│ ├── Audits/ # Audit modifiers
│ ├── Console/ # CLI commands
│ ├── Enums/ # Enumeration classes
│ ├── Exceptions/ # Exception handlers
│ ├── Helper/ # Helper functions
│ ├── Http/ # HTTP layer
│ │ ├── Controllers/ # Controllers
│ │ ├── Middleware/ # Middleware
│ │ └── Requests/ # Form requests
│ ├── Jobs/ # Queue jobs
│ ├── Listeners/ # Event listeners
│ ├── Mail/ # Email templates
│ ├── Models/ # Eloquent models
│ ├── Notifications/ # Notifications
│ ├── Policies/ # Authorization policies
│ ├── Providers/ # Service providers
│ ├── Repositories/ # Data access layer
│ ├── Rules/ # Validation rules
│ ├── Scopes/ # Query scopes
│ ├── Settings/ # Application settings
│ └── View/ # View composers
├── bootstrap/ # Framework bootstrap
├── config/ # Configuration files
├── database/ # Database files
│ ├── factories/ # Model factories
│ ├── migrations/ # Database migrations
│ └── seeders/ # Database seeders
├── deploy/ # Deployment configurations
├── lang/ # Translations
├── public/ # Public web root
├── resources/ # Frontend resources
│ ├── assets/ # CSS, JS, images
│ └── views/ # Blade templates
├── routes/ # Route definitions
│ ├── api.php # API routes
│ ├── channels.php # Broadcast channels
│ └── web.php # Web routes
├── storage/ # Application storage
│ ├── app/ # Application files
│ ├── framework/ # Framework cache
│ └── logs/ # Log files
└── tests/ # Automated testsKey Components
Actions
Actions encapsulate complex business logic:
- Located in
app/Actions/ - Single-responsibility classes
- Reusable across controllers and jobs
- Examples:
CreateLinkAction,ImportBookmarksAction
Repositories
Repositories provide a data access layer:
- Located in
app/Repositories/ - Abstract database queries from controllers
- Enable easier testing and swapping of data sources
- Examples:
LinkRepository,SearchRepository
Jobs
Background jobs handle asynchronous tasks:
- Located in
app/Jobs/ - Queued for processing
- Examples:
CheckLinks- Verify link availabilitySaveLinkToWaybackmachine- Archive linksProcessImport- Import bookmarks
Events & Listeners
Event-driven architecture for decoupled components:
- Events:
app/Events/ - Listeners:
app/Listeners/ - Examples:
LinkCreatedevent →InitiateBackuplistener
Design Patterns
Repository Pattern
Separates data access logic from business logic:
class LinkRepository {
public function findForUser(User $user, array $filters = []) {
return Link::byUser($user->id)
->applyFilters($filters)
->paginate();
}
}Action Pattern
Encapsulates business logic in single-purpose classes:
class CreateLinkAction {
public function execute(array $data, User $user): Link {
$link = Link::create([
'user_id' => $user->id,
'url' => $data['url'],
'title' => $data['title'] ?? $this->fetchTitle($data['url']),
]);
$link->initiateInternetArchiveBackup();
return $link;
}
}Policy Pattern
Centralizes authorization logic:
class LinkPolicy {
public function update(User $user, Link $link): bool {
return $user->id === $link->user_id;
}
}Scope Pattern
Reusable query constraints:
trait ScopesForUser {
public function scopeByUser($query, $userId = null) {
return $query->where('user_id', $userId ?? auth()->id());
}
}Data Flow
Web Request Flow
- Request → Nginx/Apache →
public/index.php - Routing →
routes/web.phpmatches route - Middleware → Authentication, CSRF, etc.
- Controller → Handles request logic
- Action/Repository → Business logic and data access
- Model → Eloquent ORM interacts with database
- View → Blade template renders HTML
- Response → Sent back to client
API Request Flow
- Request → API endpoint with Bearer token
- Routing →
routes/api.phpmatches route - Middleware →
auth:sanctum, rate limiting - Controller → API controller processes request
- Action/Repository → Business logic
- Model → Data access
- Response → JSON returned to client
Background Job Flow
- Dispatch → Job queued via
dispatch()ordispatchAfterResponse() - Queue → Stored in Redis, database, or processed immediately
- Worker →
php artisan queue:workprocesses job - Job → Executes
handle()method - Completion → Job removed from queue or retried on failure
Database Design
Schema Overview
Core Tables:
users- User accountslinks- Bookmarked URLslists- Link collectionstags- Link labelsnotes- Link annotations
Pivot Tables:
link_lists- Links ↔ Lists (many-to-many)link_tags- Links ↔ Tags (many-to-many)
System Tables:
settings- Application settings (spatie/laravel-settings)audits- Change history (owen-it/laravel-auditing)personal_access_tokens- API tokens (Laravel Sanctum)password_resets- Password reset tokensuser_invitations- User invitations
Indexes
Key indexes for performance:
links.user_id- User-based querieslinks.url- Duplicate detectionlinks.created_at- Chronological sortinglink_tags.link_id,link_tags.tag_id- Relationship querieslink_lists.link_id,link_lists.list_id- Relationship queries
Soft Deletes
All content models use soft deletes:
deleted_atcolumn stores deletion timestamp- Deleted items excluded from normal queries
- Items can be restored or permanently deleted
- Trash functionality provides access to deleted items
Caching Strategy
Cache Layers
- Query Cache - Database query results
- View Cache - Compiled Blade templates
- Config Cache - Application configuration
- Route Cache - Route definitions
Cache Drivers
- Redis - Recommended for production
- Memcached - Alternative in-memory cache
- File - Default for development
- Database - Fallback option
Cache Keys
Cache keys follow a consistent pattern:
linkace:{model}:{id}:{attribute}
linkace:user:{user_id}:links
linkace:settings:systemQueue System
Queue Drivers
- Redis - Recommended for production
- Database - Fallback option
- Sync - Immediate processing (development)
Queue Workers
Background workers process queued jobs:
# Start a queue worker
php artisan queue:work --queue=default,links,backups
# Process a single job
php artisan queue:work --once
# Restart workers after deployment
php artisan queue:restartQueue Jobs
Link Processing:
CheckLinks- Verify link availability (scheduled)SaveLinkToWaybackmachine- Archive to Internet Archive
Import/Export:
ProcessImport- Import bookmarks from HTMLProcessExport- Export bookmarks to HTML
Backups:
CreateBackup- Create database/file backupsCleanupBackups- Remove old backups
Scheduled Tasks
Cron jobs are defined in app/Console/Kernel.php:
protected function schedule(Schedule $schedule) {
// Check links daily at 3 AM
$schedule->job(new CheckLinks())
->dailyAt('03:00');
// Clean up backups weekly
$schedule->command('backup:clean')
->weekly();
}Required Cron Entry:
* * * * * cd /path-to-linkace && php artisan schedule:run >> /dev/null 2>&1Security Architecture
Authentication Layers
- Session-based - Web interface (Fortify)
- Token-based - API access (Sanctum)
- SSO - OAuth/OIDC providers (Socialite)
Authorization Layers
- Middleware - Route-level protection
- Policies - Model-level authorization
- Scopes - Query-level filtering
- Visibility - Content-level access control
Input Validation
- Form Requests - Validate incoming data
- Custom Rules - Complex validation logic
- Sanitization - XSS prevention
Output Escaping
- Blade - Auto-escapes output by default
- Markdown - Sanitized with
html_input: 'escape' - JSON - Proper encoding
File Storage
Storage Drivers
- Local - Default filesystem storage
- S3 - AWS S3 or compatible services
- FTP - FTP server storage
- SFTP - SSH-based file transfer
Stored Files
- Icons - Link favicons
- Thumbnails - Link preview images
- Backups - Database and file backups
- Exports - Generated bookmark files
- Logs - Application logs
Storage Paths
storage/
├── app/
│ ├── backups/ # Automated backups
│ ├── exports/ # Generated exports
│ ├── icons/ # Link favicons
│ └── thumbnails/ # Link previews
├── framework/
│ ├── cache/ # Application cache
│ ├── sessions/ # Session files
│ └── views/ # Compiled views
└── logs/
└── laravel.log # Application logsLogging & Monitoring
Log Channels
Configured in config/logging.php:
- Stack - Multiple channels
- Single - Single file
- Daily - Rotating daily files
- Sentry - Error tracking service
Error Tracking
Sentry integration for production:
SENTRY_LARAVEL_DSN=https://your-sentry-dsnLog Viewer
Built-in log viewer for administrators:
/admin/logsPerformance Optimization
Database Optimization
- Eager loading to prevent N+1 queries
- Proper indexing on frequently queried columns
- Query result caching
- Database connection pooling
Application Optimization
- Config caching:
php artisan config:cache - Route caching:
php artisan route:cache - View caching:
php artisan view:cache - Autoloader optimization:
composer dump-autoload --optimize
Frontend Optimization
- Asset compilation and minification (Laravel Mix)
- CDN support for static assets
- Lazy loading images
- HTTP/2 server push
Testing
Test Types
- Unit Tests - Test individual classes
- Feature Tests - Test application features
- Browser Tests - End-to-end testing (Laravel Dusk)
Running Tests
# Run all tests
php artisan test
# Run with coverage
php artisan test --coverage
# Run specific test
php artisan test --filter=LinkTestDeployment
Docker Deployment (Recommended)
- Pre-built Docker images available
- Docker Compose for easy setup
- Kubernetes Helm charts (beta)
Traditional Deployment
- PHP-FPM with Nginx/Apache
- Supervisor for queue workers
- Cron for scheduled tasks
Environment Configuration
See .env.example for all available environment variables.
Related Documentation
- Setup with Docker - Docker deployment guide
- Setup without Docker - PHP deployment guide
- Advanced Settings - Environment configuration
- CLI Commands - Artisan commands
- Data Models - Database schema details