Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { defineConfig } from 'vite'

// https://vite.dev/config/
export default defineConfig({
// Served from a subfolder of the web root; must match PROJECT_NAME in deploy.sh
base: '/project2/',
plugins: [
react(),
babel({ presets: [reactCompilerPreset()] })
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,10 @@ For documentation in this repository, check the `docs` folder.
Each file will contain a short description of what it documents.

### Website plan (submisson 1.)

For reviewing the first submisson we recommend reading PRD.md first, then the Spec.md and the rest of the docs.

### Backend configured (submission 2.)

The API and database are now up and running, though without any data being loaded into the frontend (for now).
In the next handin, this will be handled.
109 changes: 109 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env bash

#
# This script can be triggered with a CRON job for polling.
# This will keep the webpage always up to date.
#

# Sets the failure mode (if one command fails, dont continue)
set -euo pipefail


# Set to wherever the repo is stored on the server
REPO_DIR="/IT2810/T11-Project-2"
REPO_PROJECT_DIR="$REPO_DIR/Frontend"
REPO_BUILD_RESULT="$REPO_PROJECT_DIR/dist"
REPO_BACKEND_DIR="$REPO_DIR/backend"

# /var/www/html is the web root. Each project is deployed to its own
# subfolder: project2 -> /var/www/html/project2
PROJECT_NAME="project2"
DEST_DIR="/var/www/html/$PROJECT_NAME"

cd "$REPO_DIR"

echo "Fetching latest from main..."
git fetch origin main

# Get local commit and Remote commit
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/main)

# Decreasing how often the script runs. An additional pull does no harm
# If they are the same, no new commits are in. Exit
#if [ "$LOCAL" = "$REMOTE" ]; then
# echo "Already up to date ($LOCAL). Nothing to deploy."
# exit 0
#fi

# Otherwise, pull from origin
#echo "Updating $LOCAL -> $REMOTE"
#git reset --hard origin/main

cd "$REPO_PROJECT_DIR"

echo "==== Frontend ===="

echo "Do a clean NPM install..."
npm ci

# Building the docker image from the new source code
echo "Building site..."
npm run build

echo "Build complete."

echo "Removing current web-page..."
rm -rf "$DEST_DIR"

echo "Moving files..."
mv $REPO_BUILD_RESULT $DEST_DIR

echo "Deployed $REMOTE frontend"

echo "==== Backend API ===="

# The API is only deployed once backend/ exists on main.
if [ -f "$REPO_BACKEND_DIR/package.json" ]; then
cd "$REPO_BACKEND_DIR"

echo "Do a clean NPM install..."
npm ci

# Run the API as a systemd service so it keeps running between
# deploys and across reboots. Needs passwordless sudo for systemctl.
echo "Installing systemd service..."
NPM_BIN="$(command -v npm)"
# systemd services get a minimal PATH, so npm's '#!/usr/bin/env node'
# shebang cannot find node. Point the service at the node this script sees.
NODE_BIN_DIR="$(dirname "$(command -v node)")"
sudo tee /etc/systemd/system/t11-api.service > /dev/null <<EOF
[Unit]
Description=T11-Project-2 GraphQL API
After=network.target postgresql.service
[Service]
Type=simple
WorkingDirectory=$REPO_BACKEND_DIR
Environment="PATH=$NODE_BIN_DIR:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ExecStart=$NPM_BIN start
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable t11-api.service

echo "Restarting API..."
sudo systemctl restart t11-api.service

sleep 2
sudo systemctl is-active t11-api.service

echo "Deployed $REMOTE backend API"
else
echo "No backend in $REPO_BACKEND_DIR — skipping API deploy."
fi
1 change: 1 addition & 0 deletions docs/AI-Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ Different group members use different harnesses and models, according to persona
| 14.10.2026 | Anton | Microsoft Copilot | Used to help "convert" a html/css design i made based on figma sketch to react/typescript components. |
| 15.10.2026 | Anton | Microsoft Copilot | Used to make the foundation for filterPanel component based on picture from Figma, but it was very bad so most was changed. |
| 2026-10-16 | Henrik | Mistral Vibe Code | Improve the helper script for parsing the dataset, to get a smaller dataset with less duplicates. |
| 2026-10-16 | Henrik | Mistral Vibe Code | Improve the deployment script to also deploy the backend. Also helped writing the docs for this. |
60 changes: 60 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Deployment

The project is deployed to the NTNU VM (`it2810-11`) by `deploy.sh` in the repo root. Running the script deploys two things:

- **Frontend** — static files built from `Frontend/`, served from `/var/www/html/project2`
- **Backend API** — the GraphQL server in `backend/`, run as the systemd service `t11-api`

## What a deploy does

1. `git fetch origin main` and compares local and remote commits.
2. **Frontend**: `npm ci` + `npm run build` in `Frontend/`, then replaces `/var/www/html/project2` with the fresh `dist/`.
3. **Backend** (skipped unless `backend/package.json` exists): `npm ci` in `backend/`, then installs and restarts the `t11-api` systemd service.

## The API service

The script writes this unit to `/etc/systemd/system/t11-api.service` (node/npm paths are resolved at deploy time):

```ini
[Unit]
Description=T11-Project-2 GraphQL API
After=network.target postgresql.service

[Service]
Type=simple
WorkingDirectory=/IT2810/T11-Project-2/backend
Environment="PATH=<node bin dir>:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ExecStart=<npm path> start
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
```

```bash
sudo systemctl daemon-reload
sudo systemctl enable t11-api.service
sudo systemctl restart t11-api.service
```

- The `PATH` line is required. systemd gives services a minimal default `PATH`, so npm's `#!/usr/bin/env node` shebang fails with `env: 'node': No such file or directory` (exit 127). The script resolves node's directory with `command -v node` in the cron environment, where node is known to be available.
- The API port comes from `backend/.env` (`GRAPHQL_PORT`, default `3001`). The deploy script does not override it.
- `enable` starts the API on boot, `Restart=on-failure` restarts it after crashes, and each deploy restarts it to pick up new code.
- The cron user needs passwordless sudo for `systemctl` and for writing the unit file.

## Useful commands

```bash
# Run a deploy manually
/IT2810/T11-Project-2/deploy.sh

# API status and logs
sudo systemctl status t11-api
sudo journalctl -u t11-api -f

# Restart the API without a full deploy
sudo systemctl restart t11-api
```

See also: `github-runners.md` (self-hosted runner), `postgresql-setup.md` (database on the VM).
File renamed without changes.
7 changes: 7 additions & 0 deletions docs/technical-choices.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,10 @@ The result is 12,505 releases and 268,159 tracks across 10 tables (~19 MB of SQL
The subset is reproducible: one command (`bash scripts/make_subset.sh` in `Database/`) regenerates it from the raw dump and re-validates it against the schema with foreign keys enabled. The full pipeline, every decision and the pitfalls encountered are documented in `Database/AI-context.md`.

There is more de-duplication that still needs to be done (e.g. the same album appearing under slightly different titles, or a 15-artist release counting towards several catalogues), but treating the different mediums of the same release (CD and Vinyl) as one already brings the data down to a workable size.

## Deployment

Deployment is handled by `deploy.sh` in the repo root, triggered by a cron job on the VM that polls the repository. This keeps the site up to date without a CI/CD workflow - the self-hosted runner (see `github-runners.md`) is not involved in deployment. The mechanics are documented in `deployment.md`; the choices behind them:

- **Frontend as static files.** The Vite build output (`Frontend/dist`) is moved to `/var/www/html/project2`, where the web server serves it. The VM hosts several projects, so each gets its own subfolder of the web root. A deploy is therefore just "build, delete old, move new".
- **Backend as a systemd service.** The GraphQL API runs as the `t11-api` systemd unit, matching how PostgreSQL is already managed on the VM. `enable` starts it on boot, `Restart=on-failure` keeps it alive after crashes, and every deploy restarts it to pick up new code. We chose systemd over pm2 or Docker because the VM already uses it and it needs no extra tooling.