- TypeScript 90.2%
- Svelte 6.4%
- Nix 1.8%
- JavaScript 1.3%
- HTML 0.2%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| nixos | ||
| prisma | ||
| src | ||
| static | ||
| .example.env | ||
| .gitignore | ||
| .npmrc | ||
| .prettierignore | ||
| .prettierrc | ||
| eslint.config.js | ||
| flake.lock | ||
| flake.nix | ||
| package-lock.json | ||
| package.json | ||
| prisma.config.ts | ||
| README.md | ||
| svelte.config.js | ||
| tsconfig.json | ||
| vite.config.ts | ||
Signup.RhemaWaveTech.com
Referral signup site for RhemaWave. Built with SvelteKit (adapter-node), Prisma, and Tailwind CSS. Generates referral links and QR codes for new signups and sends data to MailerLite.
Local development
-
Copy
.example.envto.envand fill in your values:cp .example.env .env # Edit .env -- you need at minimum a DATABASE_URL -
Install dependencies and generate the Prisma client:
npm install npx prisma generate -
Start the dev server:
npm run devThe site will be at
http://localhost:5173. Changes hot-reload automatically.
The .env file is only for local development. On the server, environment variables are injected by the systemd service defined in this repo's NixOS module.
Building with Nix
The project has a flake.nix that packages the entire app into a Nix derivation. This is what gets deployed to the server -- you don't rsync files or run npm install on the server.
What nix build does
- Installs all npm dependencies from
package-lock.json(pinned by hash) - Runs
svelte-kit syncto generate SvelteKit's type scaffolding - Runs
prisma generateto create the Prisma client (uses nixpkgs'prisma-enginesso it works in the Nix sandbox without network access) - Runs
npm run build(SvelteKit build via Vite) - Copies
build/, production-onlynode_modules/,package.json, andprisma/into a Nix store path
The output is a self-contained directory in /nix/store/ that has everything needed to run the app with node build.
Building locally
nix build
This creates a ./result symlink pointing to the store path. You can run it locally to test:
DATABASE_URL="your-connection-string" \
ORIGIN="http://localhost:3000" \
HOST=0.0.0.0 \
PORT=3000 \
node ./result/build
If nix build succeeds on your machine, it will succeed on the server too.
When you change dependencies
If you add, remove, or update packages in package.json / package-lock.json, the npmDepsHash in flake.nix will be wrong and nix build will fail. To fix it:
nix run nixpkgs#prefetch-npm-deps -- package-lock.json
Paste the new hash into the npmDepsHash field in flake.nix.
NixOS module
This flake exports a NixOS module at nixosModules.default. It defines everything the server needs to run the signup service:
signupuser and group- systemd service (runs
node buildfrom/var/lib/signup/current) - tmpfiles rule for
/var/lib/signup - sudo rules for the
forgejo-runneruser to deploy and restart
Module options
| Option | Type | Description |
|---|---|---|
services.signup.enable |
bool | Enable the signup service |
services.signup.databaseUrlFile |
path | Path to a file containing the DATABASE_URL |
Environment variables set by the service
| Variable | Value |
|---|---|
DATABASE_URL |
Read from databaseUrlFile |
ORIGIN |
https://signup.rhemawavetech.com |
HOST |
0.0.0.0 |
PORT |
3000 |
DO_CA_CERTIFICATE |
/etc/ssl/certs/do-ca-certificate.crt |
Adding to a server config for the first time
In your server's flake.nix, add the input and module:
# flake.nix
{
inputs = {
signup.url = "git+https://git.rhemawavetech.com/NeilClack/Signup.RhemaWaveTech.com";
signup.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { nixpkgs, signup, ... }: {
nixosConfigurations.my-server = nixpkgs.lib.nixosSystem {
modules = [
signup.nixosModules.default
./configuration.nix
];
};
};
}
Then in configuration.nix:
services.signup = {
enable = true;
databaseUrlFile = config.sops.secrets."signup/database-url".path;
};
After adding, run nixos-rebuild switch on the server.
When you change the service config
If you modify the NixOS module (e.g. add an environment variable, change the port), you need to update the flake input on the server and rebuild:
# In Webserver-Infra
nix flake update signup
nixos-rebuild switch
This is separate from app deployments -- changing the module changes the systemd service definition, not the app code.
Deployment (CI/CD)
Every push to main triggers .forgejo/workflows/deploy.yml. The self-hosted runner on the server:
nix build-- builds the derivation on the server. Output lands in/nix/store/.sudo nix-env -p /var/lib/signup/current --set ./result-- atomically swaps the profile symlink to the new build.sudo systemctl restart signup-- restarts the service to pick up the new build.
What "atomic" means
/var/lib/signup/current is a Nix profile (a symlink chain). nix-env --set creates the new store path first, then swaps the symlink in one atomic filesystem operation. The old build stays in /nix/store/ until garbage collected.
- If
nix buildfails, nothing changes. - If you need to roll back, the old build is still in the store.
Day-to-day workflow
- Edit code locally, test with
npm run dev - Run
nix buildto verify the production build - Commit and push to
main - Forgejo Actions builds and deploys automatically
- Check https://signup.rhemawavetech.com
Rolling back
SSH into the server:
sudo nix-env -p /var/lib/signup/current --rollback
sudo systemctl restart signup
To see profile history:
nix-env -p /var/lib/signup/current --list-generations
Database migrations
Prisma manages the schema. Migrations are not run automatically during deployment -- you run them manually.
# Create a new migration (local dev)
npx prisma migrate dev
# Apply pending migrations to production
DATABASE_URL="your-production-url" npx prisma migrate deploy
The Prisma schema is at prisma/schema.prisma.