feat: initial project with Phase 1 complete
This commit is contained in:
544
documentation/DEPLOYMENT-STRATEGY.md
Normal file
544
documentation/DEPLOYMENT-STRATEGY.md
Normal file
@@ -0,0 +1,544 @@
|
||||
# PreRegister — Development & Deployment Strategy
|
||||
|
||||
## Overview
|
||||
|
||||
```
|
||||
┌──────────────┐ git push ┌──────────────┐ deploy.sh ┌──────────────────┐
|
||||
│ Local Mac │ ──────────────► │ Gitea │ ─────────────► │ VPS DirectAdmin │
|
||||
│ (Cursor) │ │ (Git remote) │ │ (Production) │
|
||||
│ │ │ │ │ │
|
||||
│ Docker: │ │ Tags: │ │ Apache/PHP-FPM │
|
||||
│ - MySQL │ │ v1.0.0 │ │ MySQL/MariaDB │
|
||||
│ - phpMyAdmin│ │ v1.0.1 │ │ Node (fnm) │
|
||||
│ - Mailpit │ │ v1.1.0 │ │ │
|
||||
└──────────────┘ └──────────────┘ └──────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Local Development (Mac + Cursor)
|
||||
|
||||
### Directory structure
|
||||
|
||||
```
|
||||
~/Projects/preregister/ ← Laravel project root
|
||||
├── .cursorrules
|
||||
├── .env ← local dev config (NOT committed)
|
||||
├── .env.example ← template (committed)
|
||||
├── .gitignore
|
||||
├── docker-compose.yml ← local dev services
|
||||
├── Makefile
|
||||
├── deploy.sh ← deployment script (committed)
|
||||
├── PreRegister-Development-Prompt.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
### Daily workflow
|
||||
|
||||
```bash
|
||||
# Start of day
|
||||
cd ~/Projects/preregister
|
||||
docker compose up -d # Start MySQL, phpMyAdmin, Mailpit
|
||||
make dev # Start Laravel + Vite dev servers
|
||||
|
||||
# Open Cursor, code away...
|
||||
|
||||
# End of day
|
||||
git add -A
|
||||
git commit -m "feat: description of what you built"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Git Setup with Gitea
|
||||
|
||||
### Initial setup (once)
|
||||
|
||||
```bash
|
||||
cd ~/Projects/preregister
|
||||
|
||||
# Initialize git
|
||||
git init
|
||||
git branch -M main
|
||||
|
||||
# Add your Gitea remote
|
||||
git remote add origin https://your-gitea-server.nl/bert/preregister.git
|
||||
|
||||
# First push
|
||||
git add -A
|
||||
git commit -m "feat: initial project setup"
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### .gitignore additions
|
||||
|
||||
Make sure these are in `.gitignore` (Laravel ships most of these, but verify):
|
||||
|
||||
```gitignore
|
||||
# Laravel defaults
|
||||
/vendor/
|
||||
/node_modules/
|
||||
/public/build/
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Docker
|
||||
mysql_data/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Compiled assets are built on the server
|
||||
/public/build/
|
||||
```
|
||||
|
||||
### .env.example (committed, safe)
|
||||
|
||||
```env
|
||||
APP_NAME=PreRegister
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost:8000
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3307
|
||||
DB_DATABASE=preregister
|
||||
DB_USERNAME=preregister
|
||||
DB_PASSWORD=preregister
|
||||
|
||||
QUEUE_CONNECTION=database
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=127.0.0.1
|
||||
MAIL_PORT=1026
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Versioning Strategy
|
||||
|
||||
Use **Semantic Versioning** (SemVer): `vMAJOR.MINOR.PATCH`
|
||||
|
||||
| Version part | When to bump | Example |
|
||||
|---|---|---|
|
||||
| PATCH | Bug fixes, small tweaks | v1.0.0 → v1.0.1 |
|
||||
| MINOR | New feature, backward compatible | v1.0.1 → v1.1.0 |
|
||||
| MAJOR | Breaking changes, major rewrite | v1.1.0 → v2.0.0 |
|
||||
|
||||
### Creating a release
|
||||
|
||||
When a version is ready to deploy:
|
||||
|
||||
```bash
|
||||
# 1. Make sure everything is committed and pushed
|
||||
git add -A
|
||||
git commit -m "fix: final changes for v1.0.0"
|
||||
git push origin main
|
||||
|
||||
# 2. Tag the release
|
||||
git tag -a v1.0.0 -m "v1.0.0 - Initial release with pre-registration pages and Mailwizz sync"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
In Gitea you can also create releases via the web UI (Releases → New Release) which lets you add release notes.
|
||||
|
||||
### Branch strategy (keep it simple)
|
||||
|
||||
```
|
||||
main ← production-ready code, always deployable
|
||||
```
|
||||
|
||||
You're the sole developer — one branch is fine. If you ever want to experiment without risk:
|
||||
|
||||
```bash
|
||||
git checkout -b feature/some-experiment
|
||||
# ... work ...
|
||||
git checkout main
|
||||
git merge feature/some-experiment
|
||||
git branch -d feature/some-experiment
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. VPS Server Setup (one-time)
|
||||
|
||||
### 4.1 SSH access
|
||||
|
||||
```bash
|
||||
# From your Mac, set up SSH key access (if not already)
|
||||
ssh-copy-id user@your-vps.nl
|
||||
|
||||
# Test
|
||||
ssh user@your-vps.nl
|
||||
```
|
||||
|
||||
### 4.2 Install Node.js via fnm
|
||||
|
||||
```bash
|
||||
ssh user@your-vps.nl
|
||||
|
||||
# Install fnm
|
||||
curl -fsSL https://fnm.vercel.app/install | bash
|
||||
|
||||
# Add to shell profile (add to ~/.bashrc or ~/.bash_profile)
|
||||
echo 'eval "$(fnm env)"' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
|
||||
# Install Node 20 LTS
|
||||
fnm install 20
|
||||
fnm default 20
|
||||
|
||||
# Verify
|
||||
node -v # v20.x.x
|
||||
npm -v # 10.x.x
|
||||
```
|
||||
|
||||
### 4.3 Install Composer (if not present)
|
||||
|
||||
```bash
|
||||
cd ~
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
sudo mv composer.phar /usr/local/bin/composer
|
||||
composer --version
|
||||
```
|
||||
|
||||
### 4.4 Create the application directory
|
||||
|
||||
```bash
|
||||
# Project lives OUTSIDE public_html
|
||||
mkdir -p /home/username/preregister
|
||||
|
||||
# Symlink public/ to the domain's document root
|
||||
# Adjust the path to match your DirectAdmin domain structure
|
||||
ln -sfn /home/username/preregister/public /home/username/domains/preregister.yourdomain.nl/public_html
|
||||
```
|
||||
|
||||
### 4.5 Clone the repository
|
||||
|
||||
```bash
|
||||
cd /home/username
|
||||
git clone https://your-gitea-server.nl/bert/preregister.git
|
||||
cd preregister
|
||||
|
||||
# Install dependencies
|
||||
composer install --no-dev --optimize-autoloader
|
||||
npm ci
|
||||
|
||||
# Build frontend assets
|
||||
npm run build
|
||||
|
||||
# Create .env for production
|
||||
cp .env.example .env
|
||||
nano .env # Edit with production values (see section 5)
|
||||
|
||||
# Generate app key
|
||||
php artisan key:generate
|
||||
|
||||
# Run migrations
|
||||
php artisan migrate --force
|
||||
|
||||
# Storage link
|
||||
php artisan storage:link
|
||||
|
||||
# Cache everything
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
```
|
||||
|
||||
### 4.6 Apache .htaccess
|
||||
|
||||
Laravel ships with a `public/.htaccess` that works with Apache. Verify `mod_rewrite` is enabled (it usually is on DirectAdmin).
|
||||
|
||||
### 4.7 Set up cron for queue worker + scheduler
|
||||
|
||||
In DirectAdmin → Cron Jobs, add:
|
||||
|
||||
```
|
||||
# Laravel scheduler (every minute)
|
||||
* * * * * cd /home/username/preregister && php artisan schedule:run >> /dev/null 2>&1
|
||||
|
||||
# Queue worker - process one job per run (every minute)
|
||||
* * * * * cd /home/username/preregister && php artisan queue:work --once --queue=mailwizz >> /dev/null 2>&1
|
||||
```
|
||||
|
||||
### 4.8 Directory permissions
|
||||
|
||||
```bash
|
||||
cd /home/username/preregister
|
||||
|
||||
# Storage and cache must be writable by the web server
|
||||
chmod -R 775 storage bootstrap/cache
|
||||
chown -R username:username .
|
||||
|
||||
# If Apache runs as a different user (e.g., apache, www-data, nobody):
|
||||
# Check with: ps aux | grep apache
|
||||
# Then set group accordingly:
|
||||
# chgrp -R apache storage bootstrap/cache
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Production .env
|
||||
|
||||
```env
|
||||
APP_NAME=PreRegister
|
||||
APP_ENV=production
|
||||
APP_KEY= # generated with php artisan key:generate
|
||||
APP_DEBUG=false # NEVER true in production
|
||||
APP_URL=https://preregister.yourdomain.nl
|
||||
|
||||
LOG_CHANNEL=daily
|
||||
LOG_LEVEL=warning
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=preregister_prod
|
||||
DB_USERNAME=preregister_prod
|
||||
DB_PASSWORD=STRONG_PASSWORD_HERE
|
||||
|
||||
QUEUE_CONNECTION=database
|
||||
|
||||
SESSION_DRIVER=database
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=your-smtp-server
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=your-smtp-user
|
||||
MAIL_PASSWORD=your-smtp-password
|
||||
MAIL_ENCRYPTION=tls
|
||||
MAIL_FROM_ADDRESS="noreply@yourdomain.nl"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
```
|
||||
|
||||
Create the production database via DirectAdmin → MySQL Management:
|
||||
- Database: `preregister_prod`
|
||||
- User: `preregister_prod`
|
||||
- Strong password
|
||||
|
||||
---
|
||||
|
||||
## 6. Deployment Script
|
||||
|
||||
This is the script you run on the VPS to deploy a new version.
|
||||
|
||||
Save this as `deploy.sh` in the project root (committed to git):
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# ──────────────────────────────────────────
|
||||
# PreRegister Deploy Script
|
||||
# Run on VPS: ./deploy.sh [tag]
|
||||
# Examples:
|
||||
# ./deploy.sh → deploys latest main
|
||||
# ./deploy.sh v1.2.0 → deploys specific tag
|
||||
# ──────────────────────────────────────────
|
||||
|
||||
APP_DIR="/home/username/preregister"
|
||||
TAG="${1:-}"
|
||||
|
||||
echo "══════════════════════════════════════"
|
||||
echo " PreRegister — Deploy"
|
||||
echo "══════════════════════════════════════"
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# 1. Maintenance mode
|
||||
echo "→ Enabling maintenance mode..."
|
||||
php artisan down --retry=30 || true
|
||||
|
||||
# 2. Pull latest code
|
||||
echo "→ Pulling from Gitea..."
|
||||
git fetch --all --tags
|
||||
|
||||
if [ -n "$TAG" ]; then
|
||||
echo "→ Checking out tag: $TAG"
|
||||
git checkout "$TAG"
|
||||
else
|
||||
echo "→ Checking out latest main"
|
||||
git checkout main
|
||||
git pull origin main
|
||||
fi
|
||||
|
||||
# 3. Install PHP dependencies
|
||||
echo "→ Installing Composer dependencies..."
|
||||
composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# 4. Install Node dependencies and build
|
||||
echo "→ Installing npm packages..."
|
||||
npm ci --production=false
|
||||
|
||||
echo "→ Building frontend assets..."
|
||||
npm run build
|
||||
|
||||
# 5. Run migrations
|
||||
echo "→ Running migrations..."
|
||||
php artisan migrate --force
|
||||
|
||||
# 6. Clear and rebuild caches
|
||||
echo "→ Clearing caches..."
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
php artisan event:cache
|
||||
|
||||
# 7. Restart queue (process any pending jobs with new code)
|
||||
echo "→ Restarting queue workers..."
|
||||
php artisan queue:restart
|
||||
|
||||
# 8. Storage link (idempotent)
|
||||
php artisan storage:link 2>/dev/null || true
|
||||
|
||||
# 9. Disable maintenance mode
|
||||
echo "→ Going live!"
|
||||
php artisan up
|
||||
|
||||
echo ""
|
||||
echo "══════════════════════════════════════"
|
||||
if [ -n "$TAG" ]; then
|
||||
echo " Deployed: $TAG"
|
||||
else
|
||||
echo " Deployed: main (latest)"
|
||||
fi
|
||||
echo "══════════════════════════════════════"
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x deploy.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Deployment Workflow (day-to-day)
|
||||
|
||||
### When a release is ready:
|
||||
|
||||
**On your Mac:**
|
||||
|
||||
```bash
|
||||
# 1. Commit and push all changes
|
||||
git add -A
|
||||
git commit -m "feat: add subscriber export"
|
||||
git push origin main
|
||||
|
||||
# 2. Tag the release
|
||||
git tag -a v1.0.0 -m "Initial release"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
**On the VPS (via SSH):**
|
||||
|
||||
```bash
|
||||
ssh user@your-vps.nl
|
||||
cd /home/username/preregister
|
||||
|
||||
# Deploy a specific version
|
||||
./deploy.sh v1.0.0
|
||||
|
||||
# Or deploy latest main (for quick fixes)
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
That's it. One command deploys everything: pulls code, installs dependencies, builds assets, runs migrations, clears caches, and brings the site back up.
|
||||
|
||||
### Quick reference
|
||||
|
||||
```
|
||||
Local Gitea VPS
|
||||
───── ───── ───
|
||||
code in Cursor
|
||||
↓
|
||||
git commit + push ───► main branch
|
||||
↓
|
||||
git tag v1.x.x ───► tag stored
|
||||
ssh into VPS
|
||||
↓
|
||||
./deploy.sh v1.x.x
|
||||
↓
|
||||
git pull + composer + npm + build + migrate
|
||||
↓
|
||||
live! ✓
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Rollback Strategy
|
||||
|
||||
If a deploy goes wrong:
|
||||
|
||||
```bash
|
||||
# Deploy the previous known-good tag
|
||||
./deploy.sh v1.0.0
|
||||
|
||||
# If migrations need to be rolled back (careful!)
|
||||
php artisan migrate:rollback --step=1
|
||||
```
|
||||
|
||||
To see available tags:
|
||||
|
||||
```bash
|
||||
git tag -l --sort=-version:refname
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. File Overview
|
||||
|
||||
| File | Committed | Location | Purpose |
|
||||
|---|---|---|---|
|
||||
| `.env` | NO | local + VPS | Environment-specific config |
|
||||
| `.env.example` | YES | repo | Template for .env |
|
||||
| `.cursorrules` | YES | repo | Cursor AI coding rules |
|
||||
| `.gitignore` | YES | repo | Files excluded from git |
|
||||
| `docker-compose.yml` | YES | repo | Local dev services |
|
||||
| `Makefile` | YES | repo | Local dev shortcuts |
|
||||
| `deploy.sh` | YES | repo | VPS deployment script |
|
||||
| `PreRegister-Development-Prompt.md` | YES | repo | Full app specification |
|
||||
| `public/build/` | NO | built on VPS | Compiled CSS/JS |
|
||||
| `vendor/` | NO | installed on VPS | PHP dependencies |
|
||||
| `node_modules/` | NO | installed on VPS | Node dependencies |
|
||||
|
||||
---
|
||||
|
||||
## 10. Checklist: First Production Deploy
|
||||
|
||||
- [ ] VPS: SSH key access configured
|
||||
- [ ] VPS: PHP 8.2+ selected in DirectAdmin MultiPHP
|
||||
- [ ] VPS: Node.js 20 installed via fnm
|
||||
- [ ] VPS: Composer installed globally
|
||||
- [ ] VPS: Production database created in DirectAdmin
|
||||
- [ ] VPS: Project directory created, public_html symlinked
|
||||
- [ ] VPS: Repository cloned from Gitea
|
||||
- [ ] VPS: `.env` configured with production values
|
||||
- [ ] VPS: `php artisan key:generate` run
|
||||
- [ ] VPS: `deploy.sh` path updated (APP_DIR)
|
||||
- [ ] VPS: First `./deploy.sh` run successfully
|
||||
- [ ] VPS: Cron jobs added (scheduler + queue worker)
|
||||
- [ ] VPS: Permissions set on storage/ and bootstrap/cache/
|
||||
- [ ] VPS: SSL certificate active (Let's Encrypt via DirectAdmin)
|
||||
- [ ] VPS: Test the public URL in browser
|
||||
- [ ] VPS: Test login at /admin
|
||||
- [ ] VPS: Change the default superadmin password
|
||||
1079
documentation/Pregister-Development-Prompt.md
Normal file
1079
documentation/Pregister-Development-Prompt.md
Normal file
File diff suppressed because it is too large
Load Diff
117
documentation/Setup.md
Normal file
117
documentation/Setup.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# PreRegister — Quick Start (Docker)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- PHP >= 8.2 with extensions: mbstring, xml, curl, mysql, gd
|
||||
- Composer >= 2.7
|
||||
- Node.js >= 20
|
||||
- Docker & Docker Compose
|
||||
|
||||
## Step-by-step setup
|
||||
|
||||
### 1. Create the Laravel project
|
||||
|
||||
```bash
|
||||
composer create-project laravel/laravel preregister
|
||||
cd preregister
|
||||
```
|
||||
|
||||
### 2. Copy the project files into the Laravel root
|
||||
|
||||
Copy these files into the `preregister/` folder:
|
||||
|
||||
- `docker-compose.yml`
|
||||
- `Makefile`
|
||||
- `PreRegister-Development-Prompt.md`
|
||||
|
||||
### 3. Start the Docker containers
|
||||
|
||||
```bash
|
||||
make up
|
||||
# or: docker compose up -d
|
||||
```
|
||||
|
||||
This starts three services:
|
||||
|
||||
| Service | URL | Purpose |
|
||||
|---|---|---|
|
||||
| MySQL 8.0 | `localhost:3306` | Database |
|
||||
| phpMyAdmin | [http://localhost:8080](http://localhost:8080) | Database browser |
|
||||
| Mailpit | [http://localhost:8025](http://localhost:8025) | Local email catcher |
|
||||
|
||||
### 4. Configure .env
|
||||
|
||||
Open `.env` and replace the DB and MAIL sections with:
|
||||
|
||||
```env
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=preregister
|
||||
DB_USERNAME=preregister
|
||||
DB_PASSWORD=preregister
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=127.0.0.1
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
QUEUE_CONNECTION=database
|
||||
```
|
||||
|
||||
### 5. Install Breeze and build frontend
|
||||
|
||||
```bash
|
||||
composer require laravel/breeze --dev
|
||||
php artisan breeze:install blade
|
||||
npm install
|
||||
```
|
||||
|
||||
### 6. Run migrations and seed
|
||||
|
||||
```bash
|
||||
php artisan migrate
|
||||
php artisan db:seed # after seeders are created
|
||||
```
|
||||
|
||||
### 7. Start developing
|
||||
|
||||
```bash
|
||||
make dev
|
||||
# This runs php artisan serve + npm run dev in parallel
|
||||
# App: http://localhost:8000
|
||||
```
|
||||
|
||||
### 8. Start Claude Code
|
||||
|
||||
Open a second terminal in the project root:
|
||||
|
||||
```bash
|
||||
claude
|
||||
```
|
||||
|
||||
Then paste:
|
||||
|
||||
> Read the file `PreRegister-Development-Prompt.md` in this project root. This is the full specification. Docker containers are already running (MySQL on 3306, phpMyAdmin on 8080, Mailpit on 8025). Breeze is installed. Start from Phase 1, Step 2 (create migrations). Work step by step and confirm before moving to the next phase.
|
||||
|
||||
## Useful commands
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| `make up` | Start Docker containers |
|
||||
| `make down` | Stop Docker containers |
|
||||
| `make fresh` | Drop all tables, re-migrate, re-seed |
|
||||
| `make queue` | Start the queue worker (for Mailwizz sync) |
|
||||
| `make dev` | Start Laravel + Vite dev servers |
|
||||
| `make routes` | Show all registered routes |
|
||||
| `make clear` | Clear all Laravel caches |
|
||||
|
||||
## Service URLs
|
||||
|
||||
| Service | URL |
|
||||
|---|---|
|
||||
| Application | http://localhost:8000 |
|
||||
| phpMyAdmin | http://localhost:8080 |
|
||||
| Mailpit (email UI) | http://localhost:8025 |
|
||||
Reference in New Issue
Block a user