Add stage 2: Vue/TypeScript PWA shell with auth-gated routing
Backend: new migration adds users.email_verified_at (null = unverified); registration leaves it null, and the register/login/me payloads now expose email_verified and email_verified_at. Frontend (web/): Vite + Vue 3 + TypeScript PWA (vite-plugin-pwa). Pinia auth store keeps the token in localStorage and validates it via GET /api/me on load. vue-router guards redirect unauthenticated visitors to /login, preserving the intended path; /register creates an account and signs in immediately (with the email unverified). Placeholder home page, minimal styling, generated icons. Dev server proxies /api to the API. docker-compose.yml gains an optional "web" service (profile: frontend) so `docker compose --profile frontend up -d` runs the dev server alongside the API; `docker compose up -d` still starts the API alone. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
# PHP Todo List
|
||||
|
||||
A small todo-list application: a REST API written in PHP (Slim 4) backed by an
|
||||
SQLite file, plus a single-page frontend (added in a later stage).
|
||||
SQLite file, plus a Vue 3 + TypeScript PWA frontend in [web/](web/).
|
||||
|
||||
## Status
|
||||
|
||||
| Stage | Scope | State |
|
||||
|-------|-------|-------|
|
||||
| 1 | Auth API — register, login, `GET /me` | ✅ done |
|
||||
| 2 | Todo CRUD API | planned |
|
||||
| 3 | Single-page frontend | planned |
|
||||
| 2 | Frontend shell — Vite PWA, auth-gated routing, register/login pages | ✅ done |
|
||||
| 3 | Todo CRUD (API + UI) | planned |
|
||||
|
||||
Registration signs the user in immediately, with the account's email marked
|
||||
unverified (`user.email_verified` is `false` until a future stage adds a
|
||||
verification endpoint).
|
||||
|
||||
## Run with Docker
|
||||
|
||||
@@ -62,6 +66,26 @@ composer serve # http://localhost:8080 (php -S localhost:8080 -t pub
|
||||
Any web server can serve the app as long as the document root is `public/` and
|
||||
unknown paths fall through to `public/index.php`.
|
||||
|
||||
## Frontend
|
||||
|
||||
The Vue/TypeScript PWA lives in [web/](web/) and talks to this API. With the API
|
||||
running (`docker compose up -d`):
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npm install
|
||||
npm run dev # http://localhost:5173, proxies /api to localhost:8080
|
||||
```
|
||||
|
||||
Or run it inside Compose alongside the API:
|
||||
|
||||
```bash
|
||||
docker compose --profile frontend up -d
|
||||
```
|
||||
|
||||
Unauthenticated visitors are redirected to `/login`; `/register` creates an
|
||||
account and signs in immediately. See [web/README.md](web/README.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
All settings are optional environment variables (read from `.env` or the real
|
||||
@@ -97,12 +121,20 @@ Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"user": { "id": 1, "email": "ada@example.com", "created_at": "2026-09-03T12:00:00Z" },
|
||||
"user": {
|
||||
"id": 1,
|
||||
"email": "ada@example.com",
|
||||
"email_verified": false,
|
||||
"email_verified_at": null,
|
||||
"created_at": "2026-09-03T12:00:00Z"
|
||||
},
|
||||
"token": "<jwt>",
|
||||
"expires_at": "2026-09-04T12:00:00+00:00"
|
||||
}
|
||||
```
|
||||
|
||||
New accounts are created with an unverified email (`email_verified: false`).
|
||||
|
||||
Errors: `422` invalid input, `409` email already registered.
|
||||
|
||||
Validation: `email` must be a valid address (≤ 255 chars); `password` must be
|
||||
@@ -126,7 +158,15 @@ Requires `Authorization: Bearer <jwt>`.
|
||||
`200 OK`:
|
||||
|
||||
```json
|
||||
{ "user": { "id": 1, "email": "ada@example.com", "created_at": "2026-09-03T12:00:00Z" } }
|
||||
{
|
||||
"user": {
|
||||
"id": 1,
|
||||
"email": "ada@example.com",
|
||||
"email_verified": false,
|
||||
"email_verified_at": null,
|
||||
"created_at": "2026-09-03T12:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`401` if the header is missing, malformed, or the token is invalid/expired.
|
||||
@@ -178,8 +218,9 @@ src/Http/Controllers/ Request handlers
|
||||
src/Repository/ Database access
|
||||
migrations/*.sql Schema, applied by bin/migrate.php
|
||||
Dockerfile PHP 8.3 + Apache image
|
||||
docker-compose.yml One-command local stack
|
||||
docker-compose.yml One-command local stack (API; web via --profile frontend)
|
||||
docker/ Apache vhost + container entrypoint
|
||||
web/ Vue 3 + TypeScript + Vite PWA frontend
|
||||
```
|
||||
|
||||
## Provenance
|
||||
|
||||
Reference in New Issue
Block a user