# home Home page for monoexp.com. Showcase linking to different projects. Plain HTML and CSS, no build step and no JavaScript. ## Layout ``` public/ what gets deployed (the site root) index.html the page: about section, then project cards style.css all styles, light and dark via prefers-color-scheme favicon.svg nginx/ monoexp.com.conf reference copy of the server's vhost file pull-releases/ one record per pull request, with screenshots ``` ## Adding a project Copy one `
  • ` block in `public/index.html` and change: - the title in `

    ` - the tag (language or kind), e.g. `Go` - the one- or two-sentence description - the **Visit** link to `https://.monoexp.com/` (leave it out for source-only projects) - the **Source** link to `https://git.monoexp.com/bajdev/` Open a PR; merging it deploys the page once the site is on the pipeline. ## Hosting | | | |---|---| | Canonical URL | `https://monoexp.com` | | `www.monoexp.com` | 301 redirect to the apex | | Site root | `/srv/www/vhosts/monoexp.com` | | nginx file | `/etc/nginx/vhosts.d/monoexp.com.conf` | | Certificate | `monoexp-home` (covers `monoexp.com` and `www.monoexp.com`) | DNS needs no change: the `@` and `*` A records at Hover already point here. ## First-time setup (as the Admin over SSH) 1. **Certificate.** The `issue-cert` wrapper only accepts subdomains, so the apex goes through certbot directly: ```bash sudo certbot certonly --webroot -w /srv/www/acme --cert-name monoexp-home \ -d monoexp.com -d www.monoexp.com --deploy-hook 'systemctl reload nginx' ``` Port 80 already serves `/.well-known/acme-challenge/` for every `.monoexp.com` name, the apex included. 2. **Site folder and first deploy.** Create the folder group-writable. It inherits the `webops` group from `/srv/www/vhosts`, and mode `2775` lets every `webops` member, Claude included, write to it: ```bash mkdir -m 2775 /srv/www/vhosts/monoexp.com ``` Then do the first deploy, **either** yourself: ```bash git clone git@git.monoexp.com:bajdev/home.git ~/src/home rsync -a --delete ~/src/home/public/ /srv/www/vhosts/monoexp.com/ ``` **or** by asking Claude, which runs `deploy-static monoexp.com ~/src/home/public` from its own account. Pass the source folder explicitly, because the script's default would look for `~/src/monoexp/public`. Pick one, not both: whoever deploys first owns the files, and the other account then can't update them. Merge-to-deploy hands them to the `deploy` user afterwards either way. 3. **nginx.** ```bash sudo install -o root -g root -m 644 ~/src/home/nginx/monoexp.com.conf /etc/nginx/vhosts.d/ sudo nginx -t && sudo systemctl reload nginx ``` 4. **Check.** ```bash curl -sI https://monoexp.com | head -1 # HTTP/2 200 curl -sI https://www.monoexp.com | grep -i location # https://monoexp.com/ curl -sI http://monoexp.com | grep -i location # https://monoexp.com/ ``` ## Merge-to-deploy Same steps as any other site on the pipeline (see the VPS setup plan, Phase 7): 1. In `bajdev/devops`, add `bajdev/home` to `sites.json` through a PR, as a static site: ```json "bajdev/home": { "kind": "static", "host": "monoexp.com" } ``` A static site publishes the repo's `public/` folder by default. To publish a different folder, add `"dir": ""`. Merge, then reinstall the file: `sudo install -o root -g root -m 644 sites.json /etc/deployd/sites.json` 2. Hand the deployed files to the deploy user: `sudo chown -R deploy /srv/www/vhosts/monoexp.com` 3. In Gogs, on `bajdev/home`: add `deploy` (and `claude`, if Claude will work on it) as Write collaborators, turn on branch protection for `main`, and add a webhook: payload URL `http://127.0.0.1:9000/deploy`, content type `application/json`, the secret from `/etc/deployd/secret.env`, and only the **Pull Request** event. 4. Merge a small test PR and check for a `deploy/…` tag and a line in `/var/log/deploys.log`.