diff --git a/README.md b/README.md new file mode 100644 index 0000000..41cb382 --- /dev/null +++ b/README.md @@ -0,0 +1,359 @@ +# Rabbi Gerzi + +Rabbi Gerzi is the public website and Torah media application for Rabbi +Yehoshua Gerzi. The site presents Rabbi Gerzi's work, projects, and Torah +media, with an authenticated admin area for managing media sets, nested +elements, rich text, YouTube links, icons, and PDF uploads. + +The application is split into: + +- `backend/`: Laravel 13, PHP 8.3, PostgreSQL, PHPUnit. +- `frontend/rabbi_gerzi/`: Vue 3, Vite, TypeScript, Pinia, Cypress. +- `nix/`: Nix packages, checks, upload limits, and the NixOS service module. + +Production assumptions: + +- Website: `https://rabbigerzi.com` +- API: `https://api.rabbigerzi.com` + +All local and deployment workflows are Nix-first. Run commands from +`nix develop`, or use direnv with the checked-in `.envrc`. + +## Required Secrets and Environment + +Do not commit real secret values. Local examples can live in ignored `.env` +files, and production secrets should live outside the Nix store. + +### Required Production Secrets + +The NixOS module requires +`services.rabbi-gerzi.backend.environmentFile`. That file must contain: + +```dotenv +APP_KEY=base64:replace-with-laravel-app-key +RABBI_GERZI_INITIAL_ADMIN_EMAIL=admin@example.com +RABBI_GERZI_INITIAL_ADMIN_PASSWORD=replace-with-a-long-random-password +``` + +- `APP_KEY` encrypts and signs Laravel application data. +- `RABBI_GERZI_INITIAL_ADMIN_EMAIL` is the first admin login email. +- `RABBI_GERZI_INITIAL_ADMIN_PASSWORD` is used only to create that admin if + it does not already exist. + +Generate an app key inside the dev shell: + +```sh +cd backend +php artisan key:generate --show +``` + +### Public Frontend Config + +The frontend build needs the public API origin: + +```dotenv +VITE_API_BASE_URL=https://api.rabbigerzi.com +``` + +For NixOS deployment this is handled by +`services.rabbi-gerzi.frontend.apiBaseUrl`, which defaults to the backend +public URL. + +### NixOS Runtime Config + +The NixOS module supplies these non-secret runtime values: + +| Setting | Production value | +|---|---| +| `APP_ENV` | `production` | +| `APP_DEBUG` | `false` | +| `APP_URL` | `https://api.rabbigerzi.com` | +| `CORS_ALLOWED_ORIGINS` | `https://rabbigerzi.com` by default | +| `DB_CONNECTION` | `pgsql` | +| `DB_HOST` | `/run/postgresql` | +| `DB_DATABASE` | `rabbi-gerzi` by default | +| `DB_USERNAME` | `rabbi-gerzi` by default | +| `FILESYSTEM_DISK` | `public` | +| `LARAVEL_STORAGE_PATH` | `/var/lib/rabbi-gerzi/storage` by default | +| `SESSION_DRIVER` | `database` | +| `SESSION_DOMAIN` | empty by default, meaning host-only cookies | +| `SESSION_SAME_SITE` | `none` by default | +| `SESSION_SECURE_COOKIE` | `true` by default | +| `CACHE_STORE` | `file` | +| `QUEUE_CONNECTION` | `sync` | +| `MAIL_MAILER` | `log` | + +The module also manages PostgreSQL, php-fpm, nginx, writable storage/cache +directories, and the 6 MB upload limit for nginx and PHP. + +### Local Environment Files + +Backend local configuration starts from: + +```sh +cd backend +cp .env.example .env +php artisan key:generate +``` + +The checked-in example already targets the Nix dev PostgreSQL socket through +`PGHOST`, and uses the `postgres` local database/user. + +Frontend local configuration should point Vite at the local backend: + +```sh +cd frontend/rabbi_gerzi +printf '%s\n' 'VITE_API_BASE_URL=http://127.0.0.1:8000' > .env.local +``` + +## Local Development + +Enter the Nix dev shell before running local development commands: + +```sh +nix develop +``` + +If direnv is installed: + +```sh +direnv allow +``` + +The dev shell provides PHP, Composer, Node, PostgreSQL, Cypress, +process-compose, TypeScript tooling, formatters, linters, and Nix formatters. +It also initializes a local PostgreSQL cluster in `.postgres` when needed. + +Install dependencies: + +```sh +cd backend +composer install + +cd ../frontend/rabbi_gerzi +npm install --legacy-peer-deps +``` + +Create local environment files: + +```sh +cd ../../backend +cp .env.example .env +php artisan key:generate + +cd ../frontend/rabbi_gerzi +printf '%s\n' 'VITE_API_BASE_URL=http://127.0.0.1:8000' > .env.local +``` + +Start the local services from the repo root: + +```sh +process-compose up +``` + +This starts: + +- PostgreSQL on the local Unix socket under `.postgres`. +- Laravel at `http://127.0.0.1:8000`. +- Vite at `http://localhost:5173`. + +In another dev-shell terminal, prepare the database: + +```sh +cd backend +php artisan migrate:fresh --seed +``` + +The seed admin login is: + +```text +admin@rabbigerzi.test +password123!@# +``` + +## Testing + +Run local tests from `nix develop`. To run the entire local test suite, keep +the app stack running in one dev-shell terminal: + +```sh +nix develop +process-compose up +``` + +Then run backend, frontend, and Cypress checks from another dev-shell +terminal. `process-compose` provides the PostgreSQL database, Laravel backend, +and Vite frontend needed by the full suite. + +Backend tests live under `backend/tests`. + +- Unit tests exercise domain entities, use cases, middleware, controllers, and + fake repositories without requiring PostgreSQL. +- Feature tests exercise HTTP endpoints, Laravel routing, migrations, seed + data, and real framework integration. +- PHPUnit is configured to use an in-memory SQLite database for test runs. + +Run backend tests: + +```sh +cd backend +./vendor/bin/phpunit tests +``` + +Run backend style checks: + +```sh +cd backend +phpcs app tests routes database +``` + +Frontend quality checks live under `frontend/rabbi_gerzi`. + +- `npm run format` checks and formats Vue and TypeScript source with oxfmt. +- `npm run lint` runs oxlint and eslint. +- `npm run type-check` runs vue-tsc against the Vite application. + +Run frontend checks: + +```sh +cd frontend/rabbi_gerzi +npm run format +npm run lint +npm run type-check +``` + +Cypress E2E tests live under `frontend/rabbi_gerzi/cypress/e2e`. + +- Specs drive the UI through the Vite frontend at `http://localhost:5173`. +- The Laravel backend must be running at `http://127.0.0.1:8000`. +- The Cypress config creates a seeded PostgreSQL template database before the + run and resets the app database between specs with the `db:reset` task. +- Seeded media assets are copied into `backend/storage/app/public` for each + reset. + +Run E2E tests after `process-compose up` is healthy: + +```sh +cd frontend/rabbi_gerzi +npm run test:e2e +``` + +Open the Cypress runner: + +```sh +cd frontend/rabbi_gerzi +npm run test:e2e:open +``` + +## Verification + +Run the full local suite from a second dev-shell terminal while +`process-compose up` is running: + +```sh +cd backend +phpcs app tests routes database +./vendor/bin/phpunit tests + +cd ../frontend/rabbi_gerzi +npm run format +npm run lint +npm run type-check +npm run test:e2e +``` + +Run the full Nix package and module checks: + +```sh +nix flake check +``` + +## Deployment + +Deploy through the flake's NixOS module. The module builds the frontend with +`VITE_API_BASE_URL=https://api.rabbigerzi.com`, serves it from nginx, runs the +Laravel backend with php-fpm, provisions PostgreSQL, creates writable storage +and cache directories, runs migrations, and ensures the initial admin exists. + +Example host configuration: + +```nix +{ + inputs.rabbi-gerzi.url = "git+ssh://git@example.com/rabbi-gerzi.git"; + + outputs = + { nixpkgs, rabbi-gerzi, ... }: + { + nixosConfigurations.rabbigerzi = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + rabbi-gerzi.nixosModules.default + { + services.rabbi-gerzi = { + enable = true; + + frontend.hostName = "rabbigerzi.com"; + + backend = { + hostName = "api.rabbigerzi.com"; + environmentFile = "/run/secrets/rabbi-gerzi.env"; + }; + }; + } + ]; + }; + }; +} +``` + +If the API origin must be set explicitly, use: + +```nix +services.rabbi-gerzi.frontend.apiBaseUrl = + "https://api.rabbigerzi.com"; +``` + +Create the production environment file on the server: + +```dotenv +APP_KEY=base64:replace-with-laravel-app-key +RABBI_GERZI_INITIAL_ADMIN_EMAIL=admin@example.com +RABBI_GERZI_INITIAL_ADMIN_PASSWORD=replace-with-a-long-random-password +``` + +Then rebuild the host with the deployment method used by the server, for +example: + +```sh +sudo nixos-rebuild switch --flake .#rabbigerzi +``` + +During activation, `rabbi-gerzi-setup` runs: + +```sh +php artisan migrate --force +php artisan rabbi-gerzi:ensure-initial-admin +``` + +The initial admin command is idempotent. If the configured admin email already +exists, it leaves the user unchanged. + +## Useful Nix Outputs + +Build the frontend package: + +```sh +nix build .#frontend +``` + +Build the backend package: + +```sh +nix build .#backend +``` + +Evaluate all checks: + +```sh +nix flake check +```