From 578812a7274d6f3ab206073f4b696caec2b1d97b Mon Sep 17 00:00:00 2001 From: jenstandstad Date: Sun, 12 Apr 2026 00:17:29 +0200 Subject: [PATCH] Adding a few --- deploy.sh | 2 +- dev.log | 112 +++++++++++++++++++++++++++ dev.sh | 163 ++++++++++++++++++++++++++++++++++++++++ docker-compose.prod.yml | 7 +- docker-compose.yml | 73 +++--------------- package.json | 7 +- src/app.css | 42 +++++------ src/index.css | 2 +- start.sh | 27 +++++++ 9 files changed, 339 insertions(+), 96 deletions(-) create mode 100644 dev.log create mode 100755 dev.sh create mode 100755 start.sh diff --git a/deploy.sh b/deploy.sh index 522d5c5..9783971 100755 --- a/deploy.sh +++ b/deploy.sh @@ -36,7 +36,7 @@ ssh ${SERVER} "docker exec gnommo-db psql -U \$(grep ^POSTGRES_USER ${REMOTE_DIR # Build and restart containers echo "==> Building and restarting containers..." -ssh ${SERVER} "cd ${REMOTE_DIR} && docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --build" +ssh ${SERVER} "cd ${REMOTE_DIR} && bash start.sh --build" # Wait for backend to be ready echo "==> Waiting for backend to start..." diff --git a/dev.log b/dev.log new file mode 100644 index 0000000..f7f3cc4 --- /dev/null +++ b/dev.log @@ -0,0 +1,112 @@ +=== dev.sh started 2026-04-11 22:15:47 UTC === +Starting GnommoEditor... + Frontend : http://localhost:5173 + Backend : http://localhost:3001 + Log file : /Users/jenstandstad/Projects/gnommoeditor/dev.log +✓ Node v21 +✓ Loaded .env +✓ PostgreSQL is running +✓ MinIO is running +✓ Database gnommoeditor already exists +Running migrations... + +> gnommoeditor-backend@1.0.0 migrate:up +> node run-migrations.cjs up + +Can't determine timestamp for 002 +Can't determine timestamp for 001 +Can't determine timestamp for 003 +Can't determine timestamp for 002 +Can't determine timestamp for 004 +Can't determine timestamp for 003 +Can't determine timestamp for 005 +Can't determine timestamp for 004 +Can't determine timestamp for 006 +Can't determine timestamp for 005 +Can't determine timestamp for 007 +Can't determine timestamp for 006 +Can't determine timestamp for 008 +Can't determine timestamp for 007 +Can't determine timestamp for 009 +Can't determine timestamp for 008 +Can't determine timestamp for 010 +Can't determine timestamp for 009 +Can't determine timestamp for 011 +Can't determine timestamp for 010 +Can't determine timestamp for 012 +Can't determine timestamp for 011 +Can't determine timestamp for 013 +Can't determine timestamp for 012 +Can't determine timestamp for 014 +Can't determine timestamp for 013 +Can't determine timestamp for 015 +Can't determine timestamp for 014 +Can't determine timestamp for 016 +Can't determine timestamp for 015 +Can't determine timestamp for 017 +Can't determine timestamp for 016 +Can't determine timestamp for 018 +Can't determine timestamp for 017 +Can't determine timestamp for 019 +Can't determine timestamp for 018 +Can't determine timestamp for 001 +Can't determine timestamp for 002 +Can't determine timestamp for 003 +Can't determine timestamp for 004 +Can't determine timestamp for 005 +Can't determine timestamp for 006 +Can't determine timestamp for 007 +Can't determine timestamp for 008 +Can't determine timestamp for 009 +Can't determine timestamp for 010 +Can't determine timestamp for 011 +Can't determine timestamp for 012 +Can't determine timestamp for 013 +Can't determine timestamp for 014 +Can't determine timestamp for 015 +Can't determine timestamp for 016 +Can't determine timestamp for 017 +Can't determine timestamp for 018 +Can't determine timestamp for 019 +No migrations to run! +Migrations complete! +✓ Migrations up to date +Starting backend on port 3001... + +> gnommoeditor-backend@1.0.0 dev +> node --watch src/index.js + +(node:16183) ExperimentalWarning: Watch mode is an experimental feature and might change at any time +(Use `node --trace-warnings ...` to show where the warning was created) +node:internal/modules/esm/resolve:844 + throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null); + ^ + +Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonwebtoken' imported from /Users/jenstandstad/Projects/gnommoeditor/backend/src/middleware/jwtAuth.js + at packageResolve (node:internal/modules/esm/resolve:844:9) + at moduleResolve (node:internal/modules/esm/resolve:901:20) + at defaultResolve (node:internal/modules/esm/resolve:1121:11) + at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:396:12) + at ModuleLoader.resolve (node:internal/modules/esm/loader:365:25) + at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:240:38) + at ModuleWrap. (node:internal/modules/esm/module_job:85:39) + at link (node:internal/modules/esm/module_job:84:36) { + code: 'ERR_MODULE_NOT_FOUND' +} + +Node.js v21.5.0 +Failed running 'src/index.js' +Starting frontend on port 5173... + +> gnommoeditor@0.1.0 dev +> vite --port 5173 + + + VITE v5.4.21 ready in 150 ms + + ➜ Local: http://localhost:5173/ + ➜ Network: http://192.168.10.57:5173/ + ➜ Network: http://192.168.64.1:5173/ +Shutting down... +=== dev.sh stopped 2026-04-11 22:16:25 UTC === +gu_common services left running. diff --git a/dev.sh b/dev.sh new file mode 100755 index 0000000..58896df --- /dev/null +++ b/dev.sh @@ -0,0 +1,163 @@ +#!/bin/bash +# dev.sh — GnommoEditor local development +# Requires gu_common to be running (postgres :5432, minio :9000). +# +# Usage: +# ./dev.sh [--port ] [--api-port ] +# +# Services (gu_common): This script runs natively: +# - PostgreSQL :5432 - Express backend : +# - MinIO :9000 - Vite frontend : + +set -e + +# ── Args ─────────────────────────────────────────────────────────────────────── + +FRONTEND_PORT=5173 +BACKEND_PORT=3001 + +while [[ $# -gt 0 ]]; do + case "$1" in + --port) FRONTEND_PORT="$2"; shift 2 ;; + --api-port) BACKEND_PORT="$2"; shift 2 ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac +done + +# ── Setup ────────────────────────────────────────────────────────────────────── + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOG_FILE="$SCRIPT_DIR/dev.log" + +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' + +log() { local c="$1"; shift; echo -e "${c}$*${NC}"; echo "$*" >> "$LOG_FILE"; } + +echo "=== dev.sh started $(date -u '+%Y-%m-%d %H:%M:%S UTC') ===" > "$LOG_FILE" +log "$GREEN" "Starting GnommoEditor..." +log "$GREEN" " Frontend : http://localhost:${FRONTEND_PORT}" +log "$GREEN" " Backend : http://localhost:${BACKEND_PORT}" +log "$GREEN" " Log file : ${LOG_FILE}" + +# ── Node version guard ───────────────────────────────────────────────────────── + +REQUIRED_NODE=20 +CURRENT_NODE=$(node --version 2>/dev/null | sed 's/v//' | cut -d. -f1) + +if [ -z "$CURRENT_NODE" ]; then + log "$RED" "Error: node not found."; log "$YELLOW" "Run: nvm use ${REQUIRED_NODE}"; exit 1 +fi +if [ "$CURRENT_NODE" -lt "$REQUIRED_NODE" ]; then + log "$RED" "Error: Node ${CURRENT_NODE} too old (need >= ${REQUIRED_NODE})." + log "$YELLOW" "Fix: nvm use ${REQUIRED_NODE}"; exit 1 +fi +log "$GREEN" "✓ Node v${CURRENT_NODE}" + +# ── Load .env ────────────────────────────────────────────────────────────────── + +if [ -f "$SCRIPT_DIR/.env" ]; then + set -a; source "$SCRIPT_DIR/.env"; set +a + log "$GREEN" "✓ Loaded .env" +fi + +# ── npm install ──────────────────────────────────────────────────────────────── + +if [ ! -d "$SCRIPT_DIR/node_modules" ]; then + log "$YELLOW" "Installing frontend dependencies..." + npm install --prefix "$SCRIPT_DIR" >> "$LOG_FILE" 2>&1 + log "$GREEN" "✓ Frontend deps installed" +fi +if [ ! -d "$SCRIPT_DIR/backend/node_modules" ]; then + log "$YELLOW" "Installing backend dependencies..." + npm install --prefix "$SCRIPT_DIR/backend" >> "$LOG_FILE" 2>&1 + log "$GREEN" "✓ Backend deps installed" +fi + +# ── Check gu_common services ─────────────────────────────────────────────────── + +if ! docker ps --format "{{.Names}}" | grep -qE "gnommo.?db"; then + log "$RED" "Error: postgres (gnommo-db) is not running." + log "$YELLOW" "Start gu_common first: cd ../gu_common && ./dev.sh" + exit 1 +fi +log "$GREEN" "✓ PostgreSQL is running" + +if ! docker ps --format "{{.Names}}" | grep -q "gnommo-minio"; then + log "$YELLOW" "⚠ MinIO not running — file uploads won't work" +else + log "$GREEN" "✓ MinIO is running" +fi + +# ── Ensure gnommoeditor database exists ──────────────────────────────────────── + +DB_CONTAINER=$(docker ps --format "{{.Names}}" | grep -E "gnommo.?db" | head -1) +docker exec "$DB_CONTAINER" psql -U gnommo \ + -c "CREATE DATABASE gnommoeditor;" 2>/dev/null \ + && log "$GREEN" "✓ Database gnommoeditor created" \ + || log "$GREEN" "✓ Database gnommoeditor already exists" + +# ── Environment ──────────────────────────────────────────────────────────────── + +export NODE_ENV=development +export PORT=$BACKEND_PORT +export DATABASE_URL="postgresql://gnommo:${POSTGRES_PASSWORD:-gnommo_secret}@localhost:5432/gnommoeditor" +export CORS_ORIGIN="http://localhost:${FRONTEND_PORT}" +export INGEST_API_KEY="${INGEST_API_KEY:-dev-ingest-key-change-me}" +export JWT_SECRET="${JWT_SECRET:-dev-jwt-secret-change-me}" +export MINIO_ENDPOINT="http://localhost:9000" +export MINIO_PUBLIC_URL="http://localhost:9000" +export MINIO_BUCKET="${MINIO_BUCKET:-glitch-university}" +export MINIO_ROOT_USER="${MINIO_ROOT_USER:-minioadmin}" +export MINIO_ROOT_PASSWORD="${MINIO_ROOT_PASSWORD:-minioadmin}" + +# ── Cleanup trap ─────────────────────────────────────────────────────────────── + +cleanup() { + echo "" + log "$YELLOW" "Shutting down..." + kill $BACKEND_PID 2>/dev/null || true + kill $FRONTEND_PID 2>/dev/null || true + echo "=== dev.sh stopped $(date -u '+%Y-%m-%d %H:%M:%S UTC') ===" >> "$LOG_FILE" + log "$YELLOW" "gu_common services left running." + exit 0 +} +trap cleanup SIGINT SIGTERM + +# ── Migrations ───────────────────────────────────────────────────────────────── + +log "$GREEN" "Running migrations..." +cd "$SCRIPT_DIR/backend" +npm run migrate:up >> "$LOG_FILE" 2>&1 \ + && log "$GREEN" "✓ Migrations up to date" \ + || { log "$RED" "Migration failed — check dev.log"; exit 1; } + +# ── Start backend ────────────────────────────────────────────────────────────── + +log "$GREEN" "Starting backend on port ${BACKEND_PORT}..." +npm run dev >> "$LOG_FILE" 2>&1 & +BACKEND_PID=$! + +sleep 2 + +# ── Start frontend ───────────────────────────────────────────────────────────── + +log "$GREEN" "Starting frontend on port ${FRONTEND_PORT}..." +cd "$SCRIPT_DIR" +npm run dev -- --port "$FRONTEND_PORT" >> "$LOG_FILE" 2>&1 & +FRONTEND_PID=$! + +echo "" +echo -e "${GREEN}============================================${NC}" +echo -e "${GREEN} GnommoEditor is running!${NC}" +echo -e "${GREEN}============================================${NC}" +echo "" +echo -e " Frontend : ${YELLOW}http://localhost:${FRONTEND_PORT}${NC}" +echo -e " Backend : ${YELLOW}http://localhost:${BACKEND_PORT}${NC}" +echo -e " Database : ${YELLOW}localhost:5432 / gnommoeditor${NC}" +echo -e " MinIO : ${YELLOW}localhost:9000${NC}" +echo -e " Log file : ${YELLOW}${LOG_FILE}${NC}" +echo "" +echo -e " Press ${RED}Ctrl+C${NC} to stop (gu_common keeps running)" +echo "" + +wait diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index b101da5..fbbe2f0 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,8 +1,7 @@ # GnommoEditor — Production -# Usage: ./deploy.sh -# Prerequisites: -# docker network create gnommo (run once on the server — shared with gu_common/gnommoweb) -# gu_common must be running (provides gnommo-db postgres and gnommo-minio) +# Usage: ./deploy.sh (local) or bash start.sh (on the server) +# The `gnommo` network is created automatically by start.sh if it doesn't exist. +# gu_common must be running to provide gnommo-db (postgres) and gnommo-minio. services: backend: diff --git a/docker-compose.yml b/docker-compose.yml index 0cf2de3..2480576 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,25 +1,8 @@ -# GnommoEditor — standalone development +# GnommoEditor — development +# Requires gu_common to be running (provides gnommo-db and gnommo-minio). # Usage: docker compose up services: - db: - image: postgres:16-alpine - container_name: gnommoeditor-db - restart: unless-stopped - environment: - POSTGRES_DB: gnommoeditor - POSTGRES_USER: gnommoeditor - POSTGRES_PASSWORD: gnommoeditor_secret - volumes: - - postgres_data:/var/lib/postgresql/data - ports: - - "5433:5432" - healthcheck: - test: ["CMD-SHELL", "pg_isready -U gnommoeditor"] - interval: 5s - timeout: 5s - retries: 5 - backend: build: context: ./backend @@ -33,58 +16,22 @@ services: - ./backend/migrations:/app/migrations command: npm run dev environment: - DATABASE_URL: postgresql://gnommoeditor:gnommoeditor_secret@db:5432/gnommoeditor?sslmode=disable + DATABASE_URL: postgresql://${POSTGRES_USER:-gnommo}:${POSTGRES_PASSWORD:-gnommo_secret}@gnommo_db:5432/gnommoeditor?sslmode=disable INGEST_API_KEY: ${INGEST_API_KEY:-dev-ingest-key-change-me} JWT_SECRET: ${JWT_SECRET:-dev-jwt-secret-change-me} CORS_ORIGIN: http://localhost:5173 PORT: 3001 - MINIO_ENDPOINT: http://minio:9000 + MINIO_ENDPOINT: http://gnommo-minio:9000 MINIO_PUBLIC_URL: http://localhost:9000 MINIO_BUCKET: glitch-university MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin} ports: - "3001:3001" - depends_on: - db: - condition: service_healthy - minio: - condition: service_healthy + networks: + - default + - gnommo - minio: - image: minio/minio:latest - container_name: gnommoeditor-minio - restart: unless-stopped - environment: - MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} - MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin} - command: server /data --console-address ":9001" - ports: - - "9000:9000" # S3 API - - "9001:9001" # Web console http://localhost:9001 - volumes: - - minio_data:/data - healthcheck: - test: ["CMD", "mc", "ready", "local"] - interval: 10s - timeout: 5s - retries: 5 - - minio-setup: - image: minio/mc - depends_on: - minio: - condition: service_healthy - entrypoint: > - /bin/sh -c " - mc alias set local http://minio:9000 $${MINIO_ROOT_USER:-minioadmin} $${MINIO_ROOT_PASSWORD:-minioadmin}; - mc mb --ignore-existing local/glitch-university; - mc anonymous set download local/glitch-university; - echo 'MinIO bucket ready.'; - exit 0; - " - restart: on-failure - -volumes: - postgres_data: - minio_data: +networks: + gnommo: + external: true diff --git a/package.json b/package.json index 702479c..d2ab8a4 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,7 @@ "scripts": { "dev": "vite", "build": "vite build", - "preview": "vite preview", - "services": "docker compose up", - "services:down": "docker compose down", - "services:logs": "docker compose logs -f", - "migrate": "docker compose exec backend npm run migrate:up", - "migrate:down": "docker compose exec backend npm run migrate:down" + "preview": "vite preview" }, "dependencies": { "react": "^18.2.0", diff --git a/src/app.css b/src/app.css index fe481a8..42e44fc 100644 --- a/src/app.css +++ b/src/app.css @@ -150,7 +150,7 @@ .btn-delete { background: transparent; border: none; - color: #444444; + color: #666666; cursor: pointer; font-size: 10px; padding: 2px 6px; @@ -343,7 +343,7 @@ line-height: 2; } -.td-id { color: #555555; font-size: 8px; } +.td-id { color: #888888; font-size: 9px; } .td-count { color: #ffff00; } .td a { color: #ffffff; text-decoration: none; } @@ -353,7 +353,7 @@ .td-course { margin-left: 10px; font-size: 8px; - color: #555555; + color: #888888; } .status-badge { @@ -417,7 +417,7 @@ } .muted { - color: #444444; + color: #777777; font-size: 8px; margin: 0; line-height: 2; @@ -476,23 +476,23 @@ } .strip-num { - font-size: 7px; - color: #444444; + font-size: 8px; + color: #666666; min-width: 16px; text-align: right; flex-shrink: 0; } .strip-id { - font-size: 7px; + font-size: 8px; color: #ffff00; font-weight: 700; flex-shrink: 0; } .strip-type { - font-size: 7px; - color: #444444; + font-size: 8px; + color: #666666; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -520,12 +520,12 @@ flex-shrink: 0; } .strip-confirm-yes { - font-size: 7px; padding: 1px 4px; + font-size: 8px; padding: 1px 4px; background: #ff0000; color: #000; border: none; cursor: pointer; } .strip-confirm-no { - font-size: 7px; padding: 1px 4px; - background: transparent; color: #888; border: 1px solid #444; cursor: pointer; + font-size: 8px; padding: 1px 4px; + background: transparent; color: #888; border: 1px solid #555; cursor: pointer; } .strip-add { @@ -557,8 +557,8 @@ .slide-editor-empty { padding: 24px 0; - color: #444444; - font-size: 8px; + color: #666666; + font-size: 9px; line-height: 2; } @@ -592,7 +592,7 @@ .slide-num { font-size: 8px; - color: #444444; + color: #666666; min-width: 20px; text-align: right; font-weight: 700; @@ -757,7 +757,7 @@ .tmpl-thumbnail--fullscreen .glitch-slide-thumbnail__surface { aspect-ratio: 16 / 9; } .tmpl-label { font-size: 8px; font-weight: 700; color: #ffffff; padding: 5px 8px 2px; line-height: 1.8; } -.tmpl-desc { font-size: 7px; color: #888888; padding: 0 8px 6px; line-height: 1.8; } +.tmpl-desc { font-size: 8px; color: #aaaaaa; padding: 0 8px 6px; line-height: 1.8; } /* ── Asset picker ────────────────────────────────────────────────────────────── */ @@ -789,8 +789,8 @@ image-rendering: pixelated; } -.asset-name { font-size: 7px; color: #888888; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.asset-meta { font-size: 7px; color: #444444; margin-top: 2px; } +.asset-name { font-size: 8px; color: #aaaaaa; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.asset-meta { font-size: 8px; color: #777777; margin-top: 2px; } .check-badge { position: absolute; @@ -831,7 +831,7 @@ .auth-indicator:hover { border-color: #555555; } .auth-indicator__name { color: #00ffff; } -.auth-indicator__guest { color: #555555; } +.auth-indicator__guest { color: #888888; } .auth-token-popup { position: absolute; @@ -890,8 +890,8 @@ } .proposal-card__by { - font-size: 7px; - color: #888888; + font-size: 8px; + color: #aaaaaa; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/src/index.css b/src/index.css index 2ee2ad5..a19f5ad 100644 --- a/src/index.css +++ b/src/index.css @@ -16,7 +16,7 @@ html, body { background: #000000; color: #ffffff; font-family: 'Press Start 2P', 'Courier New', monospace; - font-size: 10px; + font-size: 11px; line-height: 2.2; image-rendering: pixelated; } diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..ef63781 --- /dev/null +++ b/start.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# start.sh — Start GnommoEditor on the server. +# Safe to run repeatedly (e.g. after a reboot). +# The `gnommo` network is shared with gu_common/gnommoweb; create it here +# if it doesn't already exist so startup is not order-dependent. + +set -e + +# Ensure shared external volumes exist +for vol in glitch_postgres_data glitch_minio_data; do + if ! docker volume inspect "$vol" >/dev/null 2>&1; then + echo "==> Creating volume: $vol" + docker volume create "$vol" + fi +done + +# Ensure the shared gnommo network exists +if ! docker network inspect gnommo >/dev/null 2>&1; then + echo "==> Creating shared Docker network: gnommo" + docker network create gnommo +fi + +# Bring up services +echo "==> Starting GnommoEditor..." +docker compose -f docker-compose.prod.yml --env-file .env.prod up -d "$@" + +echo "==> Done."