1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
# Camagru
A web application for creating and sharing photos with superposable overlays. Users can capture images via webcam (or upload), apply overlay effects, and share them in a public gallery with likes and comments.
## Features
- **User accounts** — Register, email verification, login, password reset, profile editing
- **Photo editor** — Webcam capture or image upload with selectable overlay images (PNG with alpha), server-side compositing
- **Gallery** — Public paginated feed of all creations, likes and comments for logged-in users
- **Notifications** — Email notification when someone comments on your image (configurable)
- **Responsive** — Mobile-friendly layout
## Stack
| Component | Technology |
|-----------|------------|
| Backend | PHP 8.5 (standard library only) |
| Frontend | HTML / CSS / JavaScript |
| Database | MariaDB 10.11 |
| Web server | Nginx 1.27 |
| Containers | Docker Compose |
## Getting started
```sh
# 1. Clone the repository
git clone <repo-url> && cd camagru
# 2. Create your environment file
cp .env.example .env
# Edit .env with your own values
# 3. Install dev tools
composer install
# 4. Build and run
docker-compose up --build
# 5. Open in browser
# http://localhost:8080
```
## Host setup (Manjaro)
`phpactor` (LSP) requires the `iconv` extension. Install and enable it:
```sh
pamac install php85-iconv
sudo sed -i 's/;extension=iconv/extension=iconv/' /etc/php/php.ini
```
## Note on composer.json
This project does not use Composer for runtime dependencies — only the PHP standard library is used. The `composer.json` exists to satisfy dev tooling:
- `php-cs-fixer` — code style formatting (requires `composer.json` to determine target PHP version)
- `php-parallel-lint` — syntax checking (dev dependency)
These are development tools only and are not part of the application code.
## Linting
```sh
vendor/bin/parallel-lint src/
```
## PHP architecture
This project follows standard PHP patterns commonly used in framework-less applications:
### Front controller
All HTTP requests are routed by Nginx to a single file: `src/public/index.php`. This file bootstraps the app and delegates to the router. No other PHP file is directly accessible from the web.
### Namespaces and autoloading
PHP namespaces organize classes into a hierarchy (like directories). `namespace App\Controllers;` means the class lives under `App\Controllers`. The `use` keyword imports a class so you can refer to it by its short name instead of the full path (e.g. `Database` instead of `\App\Database`).
The autoloader in `bootstrap.php` uses `spl_autoload_register` to automatically `require` class files when they're first used. It maps the `App\` namespace prefix to the `src/app/` directory, so `App\Controllers\HomeController` loads from `src/app/Controllers/HomeController.php`.
### MVC pattern
- **Models** (`src/app/Models/`) — Data access layer, each model wraps a database table and uses prepared statements via PDO
- **Views** (`src/app/Views/`) — PHP templates that output HTML. A layout file (`layouts/main.php`) wraps page-specific content via an `include`. View files have variables that appear undefined — this is because they are `include`d by controllers and inherit all variables from the calling scope (e.g. `$dbStatus` defined in `HomeController::index()` is available in the view it includes)
- **Controllers** (`src/app/Controllers/`) — Handle requests, call models, and render views
### Request lifecycle
1. Nginx receives request, forwards to `public/index.php`
2. `bootstrap.php` starts the session, loads `.env`, registers the autoloader
3. Routes are defined in `config/routes.php` (mapping URL patterns to controller methods)
4. `Router::dispatch()` matches the URL against registered patterns and calls the matching controller method
5. The controller fetches data via models and renders a view inside the layout
## Image format choices
- **Overlays** are PNG (alpha channel required for transparency)
- **User input** (webcam captures, uploads) may be JPEG or PNG — GD is compiled with JPEG support to handle both
- **Final composited images** are saved as PNG to preserve overlay transparency
## Project structure
```
camagru/
├── docker-compose.yml
├── .env.example
├── docker/
│ ├── nginx/ # Nginx Dockerfile and config
│ ├── php/ # PHP-FPM Dockerfile (GD + PDO)
│ └── mariadb/ # Database init script
└── src/
├── public/ # Document root (entry point, CSS, JS, assets)
├── app/ # Application code (Controllers, Models, Views)
├── config/ # Route definitions
└── uploads/ # User-generated images
```
|