Compare commits
No commits in common. "3e02a83dd48de378d3763fb27df3a665cca6cb18" and "04aad89124c4d4c6347fd741f76ca163941292b9" have entirely different histories.
3e02a83dd4
...
04aad89124
1 changed files with 0 additions and 456 deletions
456
README.md
456
README.md
|
|
@ -1,456 +0,0 @@
|
||||||
# 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`.
|
|
||||||
|
|
||||||
## How the Application Works
|
|
||||||
|
|
||||||
### Content and Public Browsing
|
|
||||||
|
|
||||||
Torah media is organized into sets. Each set has a name, description, icon,
|
|
||||||
and one root element. Elements form an ordered tree: the root can have child
|
|
||||||
elements, and each child can have further children.
|
|
||||||
|
|
||||||
Visitors browse the available sets at `/media`. Opening a set loads its root
|
|
||||||
element, where the visitor can move through parent, child, and sibling links.
|
|
||||||
An element can present an icon, formatted rich text, an embedded YouTube video,
|
|
||||||
and short or long PDFs. The PDF viewer supports page navigation, zoom, search,
|
|
||||||
download, printing, and opening the source document in a new tab.
|
|
||||||
|
|
||||||
### Admin Editing
|
|
||||||
|
|
||||||
Administrators sign in at `/login`. An authenticated session reveals the
|
|
||||||
management controls on `/media` and protects all content-changing API calls.
|
|
||||||
|
|
||||||
From the media page, an administrator can:
|
|
||||||
|
|
||||||
- Create a set with a name, description, and icon. This also creates its root
|
|
||||||
element and opens that element in edit mode.
|
|
||||||
- Edit an existing set's card details or replace its icon.
|
|
||||||
- Delete a set together with its complete element tree and managed uploads.
|
|
||||||
|
|
||||||
The `Edit Element` action on a public element opens its admin editor. The
|
|
||||||
editor supports:
|
|
||||||
|
|
||||||
- Editing the title, description, rich text, and YouTube URL. Rich text
|
|
||||||
includes headings, inline formatting, alignment, lists, links, and tables.
|
|
||||||
- Uploading or removing an icon, a short PDF, and a long PDF.
|
|
||||||
- Adding child elements, moving direct children up or down, and opening a
|
|
||||||
child directly in edit mode.
|
|
||||||
- Removing a child together with all of its descendants and managed uploads.
|
|
||||||
|
|
||||||
Title, description, rich text, and YouTube changes are written by the `Save`
|
|
||||||
action. Icon and PDF changes are uploaded or removed immediately. The
|
|
||||||
`View Element` action returns to the public presentation, and `Logout` ends
|
|
||||||
the admin session. Development login credentials are listed under
|
|
||||||
[Local Development](#local-development).
|
|
||||||
|
|
||||||
## 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 = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
||||||
rabbi-gerzi.url = "git+ssh://git@example.com/rabbi-gerzi.git";
|
|
||||||
|
|
||||||
sops-nix = {
|
|
||||||
url = "github:Mic92/sops-nix";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs =
|
|
||||||
{
|
|
||||||
nixpkgs,
|
|
||||||
rabbi-gerzi,
|
|
||||||
sops-nix,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
nixosConfigurations.rabbigerzi = nixpkgs.lib.nixosSystem {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
rabbi-gerzi.nixosModules.default
|
|
||||||
sops-nix.nixosModules.sops
|
|
||||||
(
|
|
||||||
{ config, ... }:
|
|
||||||
let
|
|
||||||
appKey = config.sops.placeholder."app-key";
|
|
||||||
initialAdminEmail =
|
|
||||||
config.sops.placeholder."admin-email";
|
|
||||||
initialAdminPassword =
|
|
||||||
config.sops.placeholder."admin-password";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets/rabbi-gerzi.yaml;
|
|
||||||
age.sshKeyPaths = [
|
|
||||||
"/etc/ssh/ssh_host_ed25519_key"
|
|
||||||
];
|
|
||||||
|
|
||||||
secrets = {
|
|
||||||
"app-key" = { };
|
|
||||||
"admin-email" = { };
|
|
||||||
"admin-password" = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
templates."rabbi-gerzi.env".content = ''
|
|
||||||
APP_KEY=${appKey}
|
|
||||||
RABBI_GERZI_INITIAL_ADMIN_EMAIL=${initialAdminEmail}
|
|
||||||
RABBI_GERZI_INITIAL_ADMIN_PASSWORD=${initialAdminPassword}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
services.rabbi-gerzi = {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
frontend.hostName = "rabbigerzi.com";
|
|
||||||
|
|
||||||
backend = {
|
|
||||||
hostName = "api.rabbigerzi.com";
|
|
||||||
environmentFile =
|
|
||||||
config.sops.templates."rabbi-gerzi.env".path;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If the API origin must be set explicitly, use:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
services.rabbi-gerzi.frontend.apiBaseUrl =
|
|
||||||
"https://api.rabbigerzi.com";
|
|
||||||
```
|
|
||||||
|
|
||||||
Configure `.sops.yaml` with age recipients for each administrator and the
|
|
||||||
server's SSH Ed25519 host key. Then create the encrypted secrets file:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sops secrets/rabbi-gerzi.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
Add these values in the editor opened by `sops`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
app-key: base64:replace-with-laravel-app-key
|
|
||||||
admin-email: admin@example.com
|
|
||||||
admin-password: replace-with-a-long-random-password
|
|
||||||
```
|
|
||||||
|
|
||||||
Commit only the encrypted file written by `sops`. At activation time,
|
|
||||||
`sops-nix` decrypts these values and renders the runtime environment file
|
|
||||||
outside the Nix store.
|
|
||||||
|
|
||||||
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
|
|
||||||
```
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue