At HelloAsso we are used to sending each other little kind words for christmas period.
This repo contains a single page to collect words and a script to send mail.
This version has been completely refactored with a clean MVC architecture using Slim Framework:
- Framework: Slim 4 with PSR-7, PSR-11 (DI Container)
- Template Engine: Twig
- Architecture: Model-View-Controller (MVC)
- Dependency Injection: PHP-DI
- Autoloading: PSR-4
βββ src/
β βββ Controllers/ # Application controllers
β βββ Models/ # Data models
β βββ Services/ # Business logic services
β βββ Middleware/ # Custom middleware
βββ templates/ # Twig templates
βββ public/ # Web root (index.php, assets)
βββ config/ # Configuration files
βββ vendor/ # Composer dependencies
- Clean separation of concerns: Models, Views, Controllers
- Dependency Injection: All dependencies properly injected
- Type safety: PHP 8+ type declarations
- Template inheritance: Twig templates with layouts
- Middleware: Authentication middleware
- PSR standards: Following PHP-FIG standards
- User Authentication: Login with unique codes sent to email (no passwords needed)
- User Management: Renamed
receivertable touserwith additional fields - Sender Tracking: Messages now track both anonymous and authenticated senders
- Admin Interface: Manage users through
/admin
receivertable renamed touserwith new fields:receiver(boolean): Whether user can receive messageslogin_code&login_code_expires: For email-based authenticationcreated_at: Timestamp
lovetable updated with:id_sender: Links to authenticated user who sent the messagecreated_at: Timestamp
composer install- Create your MySQL database
- Import the schema:
mysql -u your_user -p your_database < db.sqlIf you're upgrading from a previous version, run the admin migration:
php migrate-admin.phpThis will:
- Add the
adminfield to existing users - Make the first user an administrator
Set these environment variables in your system or web server:
export DbUrl="localhost"
export DbPort="3306"
export DbName="spreadly"
export DbUser="root"
export DbPassword=""
export DbPrefix=""
# Configuration Postal
export PostalApiUrl="https://postal.example.com"
export PostalApiKey="your_postal_server_api_key"
export MailFromEmail="your_email@domain.com"
export MailFromName="Your Name"Copy env.example to .env and fill in your values:
cp env.example .env
# Edit .env with your configurationIf you don't configure Postal, the app runs in development mode:
- β Login codes are logged to error log
- β Login codes are displayed on screen
- β No emails are actually sent
- Visit
/login- Login page - Enter any email from your user table
- In development mode: The login code will be shown on screen
- Login as admin and visit
/admin- Manage users - Create more users and assign admin rights
- Start sending love messages!
- Edit or delete your messages - See your progress in the dropdown
- β Visual indicators in dropdown - see who you've already messaged
- β Edit existing messages - select a recipient to modify your message
- β Delete messages - remove messages you've sent
- β Progress tracking - βοΈ icon shows sent messages
- β Smart interface - button changes to "Modify message" when editing
- π Create new messages for recipients without existing messages
- βοΈ Edit existing messages by selecting the recipient
- ποΈ Delete messages with confirmation dialog
- π Timestamp display shows when message was originally sent
- π Security - can only edit/delete your own messages
- Dropdown indicators: Recipients with messages show βοΈ (message envoyΓ©)
- Auto-loading: Selecting a recipient loads existing message for editing
- Dynamic buttons: Submit button changes based on action (send/modify)
- Status messages: Clear feedback on message creation date
- Confirmation dialogs: Prevent accidental deletions
- β
Only admins can access
/adminroutes - β Only admins see the "Administration" button
- β Admins can create users and assign admin rights
- β First user is automatically made admin during migration
- Create users with receiver and admin flags
- Edit users - modify name, email, receiver and admin status
- Delete users - remove users (cannot delete yourself)
- View all users with their permissions
- Admin users are marked with a warning badge
- Bulk import users from CSV file
- Format:
nom, email, receiver (true/false), admin (true/false) - Example CSV:
Jean Dupont,jean.dupont@example.com,true,false Marie Martin,marie.martin@example.com,true,false Pierre Admin,pierre.admin@example.com,false,true
- Smart handling: Skips existing emails, reports results
- Validation: Checks email format and required fields
- π§ Edit button (βοΈ) for each user
- ποΈ Delete button with confirmation dialog
- π CSV import section with file upload
- π Results reporting for batch operations
- π‘οΈ Self-protection - cannot delete your own account
GET /login- Login pagePOST /auth/request- Request login codePOST /auth/verify- Verify login code
GET /- Home page (send messages)POST /send- Send/edit love messagePOST /message/delete/{id}- Delete messagePOST /auth/logout- Logout
GET /admin- User managementPOST /admin/create- Create new userGET /admin/edit/{id}- Edit user formPOST /admin/edit/{id}- Update userPOST /admin/delete/{id}- Delete userPOST /admin/import- Import CSV users
GET /sender- Send emails to all receivers
- Models: Add to
src/Models/for data access - Controllers: Add to
src/Controllers/for request handling - Services: Add to
src/Services/for business logic - Templates: Add to
templates/for views - Routes: Register in
public/index.php
All dependencies are managed through PHP-DI container in public/index.php
All settings centralized in config/config.php
- Deploy the application
- Create users via
/admin(requires login) - Users login via
/loginusing email + unique code - Authenticated users send messages with their identity
- Give deadline to people to write words
- Close website by updating end date
- Visit
/senderto send all emails
For production:
- Configure Postal (
PostalApiUrl,PostalApiKey) - Deploy to your web server
- Ensure at least one admin user exists
If you have an existing installation:
- Run the new
db.sqlto create the updated schema - The old files (
index.php,login.php, etc.) are still compatible vialoader.php - New routes are available through the Slim application
The old files are still functional for backward compatibility:
index.php,login.php,admin.phpwork throughloader.phpsender.phpworks with the new models- Gradual migration possible