From e54675b95915cc9eb9254b4c285d5c743c232f21 Mon Sep 17 00:00:00 2001 From: Andreas Bok Andersen Date: Sun, 19 Apr 2026 21:03:28 +0200 Subject: [PATCH] docs(synkronus-portal): fix formatting --- synkronus-portal/README.md | 837 ++++++++++++++++++++++++++++++++++++- 1 file changed, 836 insertions(+), 1 deletion(-) diff --git a/synkronus-portal/README.md b/synkronus-portal/README.md index 849210aee..2c3d53f05 100644 --- a/synkronus-portal/README.md +++ b/synkronus-portal/README.md @@ -1 +1,836 @@ -# Synkronus PortalFrontend service for Synkronus, built with React + TypeScript + Vite.## OverviewThe Synkronus Portal provides a web-based interface for managing app bundles, users, observations, and data exports. It supports both development (hot reload) and production (optimized build) modes.## PrerequisitesBefore starting, ensure you have:### For Docker-based Setup (Recommended)- **Docker** (version 20.10+) and **Docker Compose** (version 2.0+) - Check: `docker --version` and `docker compose version`- **Git** (for cloning the repository)- **4GB+ free disk space** (for Docker images and volumes)**Note for Windows users:** Ensure WSL2 is enabled if using Docker Desktop.### For Dockerless Development Setup- **Node.js** 20+ and **npm** or **yarn**- **Go** 1.22+ (for running the backend API)- **PostgreSQL** 17+ (installed locally or accessible)- **Git** (for cloning the repository)---## Quick Reference| Mode | Command | URL | Hot Reload | Docker Required ||------|---------|-----|------------|-----------------|| **Production** | `docker compose up -d --build` | http://localhost:5173 | ❌ No | ✅ Yes || **Development (Docker)** | `docker compose up -d postgres synkronus`
`npm run dev` | http://localhost:5174 | ✅ Yes | ✅ Partial || **Development (Dockerless)** | See [Dockerless Setup](#dockerless-development-setup) | http://localhost:5174 | ✅ Yes | ❌ No |**Default Login Credentials:**- Username: `admin`- Password: `admin`---## Quick Start (First Time)**For users who just want to get it running:**### Option 1: Production Mode (Docker - Easiest)1. **Navigate to directory:** ```bash cd synkronus-portal ```2. **Start everything:** ```bash docker compose up -d --build ```3. **Wait ~30 seconds** for services to start4. **Open in browser:** - Portal: http://localhost:5173 - Login with: `admin` / `admin`That's it! 🎉### Option 2: Development Mode (Dockerless - No Docker Required)See the [Dockerless Development Setup](#dockerless-development-setup) section below for complete instructions.---## Production Mode (Optimized Build)**Step 1:** Navigate to the portal directory```bashcd synkronus-portal```**Step 2:** Build and start all services in production mode```bash# Option 1: Build and start in one command (recommended)docker compose up -d --build# Option 2: Build first, then start (if you prefer separate steps)docker compose builddocker compose up -d```**Note:** The `--build` flag ensures the frontend is built before starting. If you skip building, Docker will build automatically, but it's better to be explicit.**Step 3:** Wait for services to start (about 10-30 seconds)```bash# Check service statusdocker compose ps# View logs if neededdocker compose logs -f```**Step 4:** Access the portal- **Frontend Portal**: http://localhost:5173 (Nginx serving optimized production build)- **Backend API**: http://localhost:8080- **PostgreSQL**: localhost:5432- **Swagger UI**: http://localhost:8080/openapi/swagger-ui.html**Production Mode Features:**- ✅ Optimized production build (minified, tree-shaken)- ✅ Static file serving via Nginx (fast, efficient)- ✅ Persistent data storage (survives container restarts)- ✅ Production-ready performance- ❌ No hot reload (requires rebuild for changes)**To stop production mode:**```bashdocker compose down```**Note:** Stopping containers with `docker compose down` does **NOT** delete your data. Volumes persist automatically. Your database and app bundles remain safe.---## Development Mode (Hot Reload)### Development with Docker (Partial Docker)**Step 1:** Navigate to the portal directory```bashcd synkronus-portal```**Step 2:** Start backend services (PostgreSQL + API)```bash# Start only backend services (postgres + synkronus API)docker compose up -d postgres synkronus```**Step 3:** Wait for backend to be ready (about 10-20 seconds)```bash# Check backend healthcurl http://localhost:8080/health# Should return: OK```**Step 4:** Install dependencies (if not already done)```bashnpm install```**Step 5:** Start the Vite dev server```bashnpm run dev```**Step 6:** Access the portal- **Frontend Portal**: http://localhost:5174 (Vite dev server with hot reload)- **Backend API**: http://localhost:8080 (already running from Step 2)**Development Mode Features:**- ✅ Hot Module Replacement (HMR) - instant code updates without page refresh- ✅ Fast refresh - React components update instantly- ✅ Source maps for debugging- ✅ Same persistent storage as production - data is shared- ✅ Full debugging support in browser DevTools- ✅ Real-time error overlay in browser**To stop development mode:**```bash# Stop Vite dev server: Press Ctrl+C in the terminal running npm run dev# Stop backend servicesdocker compose down```**Note:** Stopping containers with `docker compose down` does **NOT** delete your data. Volumes persist automatically. Your database and app bundles remain safe.---## Dockerless Development Setup**Perfect for developers who prefer not to use Docker or want a fully local development environment.**### Prerequisites- **Node.js** 20+ and **npm**- **Go** 1.22+ ([Install Go](https://go.dev/doc/install))- **PostgreSQL** 17+ ([Install PostgreSQL](https://www.postgresql.org/download/))- **Git**### Step 1: Set Up PostgreSQL Database**Create the database and user:**```bash# Connect to PostgreSQL (as superuser)psql -U postgres# In PostgreSQL prompt, run:CREATE DATABASE synkronus;CREATE USER synkronus_user WITH PASSWORD 'dev_password_change_in_production';GRANT ALL PRIVILEGES ON DATABASE synkronus TO synkronus_user;# Connect to synkronus database\c synkronus# Grant schema privilegesGRANT ALL ON SCHEMA public TO synkronus_user;ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO synkronus_user;ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO synkronus_user;# Exit\q```**Windows PowerShell alternative:**```powershell# Using psql command line$env:PGPASSWORD='postgres'; psql -U postgres -c "CREATE DATABASE synkronus;"$env:PGPASSWORD='postgres'; psql -U postgres -c "CREATE USER synkronus_user WITH PASSWORD 'dev_password_change_in_production';"$env:PGPASSWORD='postgres'; psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE synkronus TO synkronus_user;"```### Step 2: Set Up Backend API (Synkronus)**Navigate to synkronus directory:**```bashcd ../synkronus```**Install dependencies:**```bashgo mod download```**Create environment file (`.env` in synkronus directory):**```bash# Create .env filecat > .env << EOFPORT=8080LOG_LEVEL=debugDB_CONNECTION=postgres://synkronus_user:dev_password_change_in_production@localhost:5432/synkronus?sslmode=disableJWT_SECRET=dev_jwt_secret_change_in_production_32charsADMIN_USERNAME=adminADMIN_PASSWORD=adminAPP_BUNDLE_PATH=./data/app-bundlesMAX_VERSIONS_KEPT=5EOF```**Windows PowerShell alternative:**```powershell@"PORT=8080LOG_LEVEL=debugDB_CONNECTION=postgres://synkronus_user:dev_password_change_in_production@localhost:5432/synkronus?sslmode=disableJWT_SECRET=dev_jwt_secret_change_in_production_32charsADMIN_USERNAME=adminADMIN_PASSWORD=adminAPP_BUNDLE_PATH=./data/app-bundlesMAX_VERSIONS_KEPT=5"@ | Out-File -FilePath .env -Encoding utf8```**Create app bundles directory:**```bashmkdir -p data/app-bundles```**Run the backend API:**```bash# Option 1: Run directly (recommended for development)go run cmd/synkronus/main.go# Option 2: Build and rungo build -o bin/synkronus cmd/synkronus/main.go./bin/synkronus```**Verify backend is running:**```bash# In another terminalcurl http://localhost:8080/health# Should return: OK```### Step 3: Set Up Frontend Portal**Navigate to portal directory:**```bashcd ../synkronus-portal```**Install dependencies:**```bashnpm install```**Start the Vite dev server:**```bashnpm run dev```**Access the portal:**- **Frontend Portal**: http://localhost:5174- **Backend API**: http://localhost:8080- **Login**: `admin` / `admin`### Step 4: Verify Everything Works1. **Check backend health:** ```bash curl http://localhost:8080/health # Should return: OK ```2. **Open frontend in browser:** - Navigate to http://localhost:5174 - You should see the login page3. **Test login:** - Username: `admin` - Password: `admin` - Should successfully log in and show the dashboard### Stopping Dockerless Development1. **Stop frontend:** Press `Ctrl+C` in the terminal running `npm run dev`2. **Stop backend:** Press `Ctrl+C` in the terminal running the Go server### Troubleshooting Dockerless Setup**Backend won't start:**- Verify PostgreSQL is running: `psql -U postgres -c "SELECT version();"`- Check database connection string in `.env` file- Ensure database and user were created correctly**Frontend can't connect to backend:**- Verify backend is running on port 8080: `curl http://localhost:8080/health`- Check `vite.config.ts` proxy configuration- Ensure no firewall is blocking localhost connections**Database connection errors:**- Verify PostgreSQL is running- Check connection string format: `postgres://user:password@host:port/database`- Ensure user has proper permissions---## Verification ChecklistAfter setting up (any mode), verify everything is working:1. **Check service status (Docker mode):** ```bash docker compose ps ``` All services should show "Up" status. Health checks may show "starting" for the first 30-60 seconds - this is normal.2. **Test API health:** ```bash curl http://localhost:8080/health ``` Should return: `OK`3. **Test frontend:** - Open http://localhost:5173 (production) or http://localhost:5174 (development) in your browser - Should show the login page4. **Test login:** - Username: `admin` - Password: `admin` - Should successfully authenticate and show dashboard5. **Check logs (if issues):** ```bash # Docker mode docker compose logs -f # Dockerless mode - check terminal output ```---## Common Issues### "cannot execute: required file not found" (init-db.sh)**Symptom:** PostgreSQL container fails to initialize database user.**Cause:** Windows line endings (CRLF) in shell scripts.**Solution:**```powershell# Convert line endings (PowerShell)$content = Get-Content init-db.sh -Raw$content = $content -replace "`r`n", "`n"[System.IO.File]::WriteAllText((Resolve-Path init-db.sh), $content, [System.Text.UTF8Encoding]::new($false))# Then restartdocker compose down -vdocker compose up -d --build```**Prevention:** The `.gitattributes` file enforces LF line endings. If you're on Windows, ensure Git is configured correctly:```bashgit config core.autocrlf false```### Port Already in Use**Production Mode (Port 5173):**```bash# Edit docker-compose.yml and change the port mapping:ports: - "5173:80" # Change 5173 to your desired port```**Development Mode (Port 5174):**```bash# Edit vite.config.ts and change the port:server: { port: 5174, # Change to your desired port}```**Backend API (Port 8080):**```bash# Docker mode: Edit docker-compose.ymlports: - "8080:8080" # Change 8080 to your desired port# Dockerless mode: Edit .env file in synkronus directoryPORT=8080 # Change to your desired port```### Health Checks Show "Unhealthy" or "Starting"**This is normal!** Health checks can take 30-60 seconds to pass on first startup. As long as:- Services show "Up" status- `curl http://localhost:8080/health` returns `OK`- Frontend loads in browserThen everything is working correctly. The health check status will update to "healthy" after a few cycles.### Hot Reload Not Working (Development Mode)1. Ensure you're running `npm run dev` (not Docker for frontend)2. Check that Vite is running on port 51743. Verify the browser is connected to the correct port (http://localhost:5174)4. Check browser console for HMR connection errors5. Try hard refresh (Ctrl+Shift+R or Cmd+Shift+R)6. **Windows users:** Ensure file watching is enabled. If using WSL2, files should be in the WSL filesystem, not Windows filesystem.### API Connection Issues1. **Docker mode:** - Verify backend is running: `docker compose ps` - Check backend logs: `docker compose logs synkronus` - Test API directly: `curl http://localhost:8080/health`2. **Dockerless mode:** - Verify backend process is running (check terminal) - Check backend logs in terminal output - Test API directly: `curl http://localhost:8080/health` - Verify PostgreSQL is running and accessible### App Bundles Not PersistingIf app bundles disappear after restarting containers:1. **Verify the volume exists (Docker mode):** ```bash docker volume ls | grep app-bundles ```2. **Check if bundles are in the volume:** ```bash # If containers are running docker compose exec synkronus ls -la /app/data/app-bundles # If containers are stopped docker run --rm -v synkronus-portal_app-bundles:/data alpine ls -la /data ```3. **Verify volume is mounted correctly:** ```bash docker compose config | grep -A 5 app-bundles ```4. **Check backend logs for app bundle initialization:** ```bash docker compose logs synkronus | grep -i "app bundle\|bundle path" ```5. **Ensure you're not using `docker compose down -v`:** - Use `docker compose down` (preserves volumes) ✅ - Avoid `docker compose down -v` (deletes volumes) ❌**Note:** App bundles are stored in the `app-bundles` volume (Docker) or `./data/app-bundles` directory (Dockerless). This persists across restarts. If bundles are missing, check that:- The volume/directory wasn't accidentally deleted- The backend has proper permissions to read/write- The `APP_BUNDLE_PATH` environment variable is set correctly### Windows-Specific Issues**Line Endings:**- Git should handle this automatically with `.gitattributes`- If issues persist: `git config core.autocrlf false`**File Watching (Dockerless):**- If hot reload doesn't work, files may need to be in WSL filesystem- Or use polling mode in `vite.config.ts` (already configured)**PowerShell vs Bash:**- Most commands work in both- Use backticks for line continuation in PowerShell: `` ` ``---## Architecture### Development Mode (Docker)```┌─────────────────────────────────────────────────────────────┐│ Development Environment (docker-compose.yml) │├─────────────────────────────────────────────────────────────┤│ ││ ┌──────────────────┐ ┌──────────────────┐ ││ │ synkronus-portal │ │ synkronus-api │ ││ │ (Frontend) │ │ (Backend) │ ││ │ │ │ │ ││ │ • Vite Dev │◄────►│ • Go Server │ ││ │ • Port 5174 │ │ • Port 8080 │ ││ │ • Hot Reload │ │ • App Bundles │ ││ │ • Source Mounted │ │ • PostgreSQL │ ││ └──────────────────┘ └────────┬───────────┘ ││ │ │ ││ │ │ ││ └───────────────────────────┼───────────────────────┘│ │ ││ ┌────────▼──────────┐ ││ │ PostgreSQL │ ││ │ Port 5432 │ ││ │ Persistent DB │ ││ └───────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘```### Development Mode (Dockerless)```┌─────────────────────────────────────────────────────────────┐│ Dockerless Development Environment │├─────────────────────────────────────────────────────────────┤│ ││ ┌──────────────────┐ ┌──────────────────┐ ││ │ Vite Dev Server │ │ Go API Server │ ││ │ (Frontend) │ │ (Backend) │ ││ │ │ │ │ ││ │ • npm run dev │◄────►│ • go run │ ││ │ • Port 5174 │ │ • Port 8080 │ ││ │ • Hot Reload │ │ • App Bundles │ ││ │ • Local Files │ │ • Local Files │ ││ └──────────────────┘ └────────┬───────────┘ ││ │ │ ││ │ │ ││ └───────────────────────────┼───────────────────────┘│ │ ││ ┌────────▼──────────┐ ││ │ PostgreSQL │ ││ │ (Local Install) │ ││ │ Port 5432 │ ││ └───────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘```### Production Mode```┌─────────────────────────────────────────────────────────────┐│ Production Environment (docker-compose.yml) │├─────────────────────────────────────────────────────────────┤│ ││ ┌──────────────────┐ ┌──────────────────┐ ││ │ synkronus-portal │ │ synkronus-api │ ││ │ (Frontend) │ │ (Backend) │ ││ │ │ │ │ ││ │ • Nginx │◄────►│ • Go Server │ ││ │ • Static Files │ │ • Port 8080 │ ││ │ • Port 5173 │ │ • App Bundles │ ││ │ • Optimized │ │ • PostgreSQL │ ││ └──────────────────┘ └────────┬───────────┘ ││ │ │ ││ │ │ ││ └───────────────────────────┼───────────────────────┘│ │ ││ ┌────────▼──────────┐ ││ │ PostgreSQL │ ││ │ Port 5432 │ ││ │ Persistent DB │ ││ └───────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘```---## API Proxy Configuration### Development ModeThe Vite dev server automatically proxies `/api/*` requests to the backend:- **Frontend → Backend**: `/api/*` → `http://localhost:8080/*` (via Vite proxy)- **Configuration**: See `vite.config.ts`### Production ModeNginx proxies `/api/*` requests to the backend:- **Frontend → Backend**: `/api/*` → `http://synkronus:8080/*` (via Nginx)- **Configuration**: See `Dockerfile` nginx config---## Storage Persistence### Docker ModeBoth development and production modes use the **same named Docker volumes**, ensuring your data persists across:- Container restarts- Mode switches (dev ↔ prod)- Container removal (with `docker compose down`)- System reboots**Volumes:**- **postgres-data**: PostgreSQL database files (users, observations, app bundles metadata)- **app-bundles**: App bundle ZIP files and versions (stored at `/app/data/app-bundles` in the container)**Important:** App bundles are stored in **both** places:- **Files**: Actual ZIP files and extracted content in the `app-bundles` volume- **Database**: Metadata about bundles (versions, manifest info) in the `postgres-data` volumeBoth volumes must persist for app bundles to work correctly after restart.**Volume Persistence Guarantee:**✅ **Volumes are NOT deleted when you:**- Stop containers: `docker compose down`- Restart containers: `docker compose restart`- Switch between dev/prod modes- Rebuild containers: `docker compose build`⚠️ **Volumes ARE deleted ONLY when you:**- Explicitly use: `docker compose down -v` (the `-v` flag removes volumes)- Manually delete: `docker volume rm `### Dockerless ModeData is stored in local directories:- **PostgreSQL**: Uses your local PostgreSQL data directory (configured during PostgreSQL installation)- **App Bundles**: Stored in `../synkronus/data/app-bundles` directory**Backup Recommendations:**- Regularly backup your PostgreSQL database- Backup the `data/app-bundles` directory---## Stopping Services### Docker Mode**Safe Stop (Preserves Data):**```bash# Stop all services - VOLUMES ARE PRESERVED ✅docker compose down```This command:- ✅ Stops all containers- ✅ Removes containers- ✅ **Keeps all volumes** (your data is safe!)- ✅ Removes networks**Complete Removal (⚠️ DELETES ALL DATA):**```bash# Stop services AND delete volumes - ⚠️ THIS DELETES ALL DATA!docker compose down -v```**⚠️ WARNING:** The `-v` flag removes volumes, which will:- Delete all database data (users, observations, etc.)- Delete all uploaded app bundles- **This action cannot be undone!****Restarting Services:**```bash# Start services (volumes are automatically reattached)docker compose up -d```Your data will be exactly as you left it!### Dockerless Mode**Stop Frontend:**- Press `Ctrl+C` in the terminal running `npm run dev`**Stop Backend:**- Press `Ctrl+C` in the terminal running the Go server**Stop PostgreSQL:**- Use your system's service manager (e.g., `systemctl stop postgresql` on Linux)---## Default Credentials- **Admin username**: `admin`- **Admin password**: `admin`**⚠️ Warning**: These are development credentials only. Change them before production use.---## Switching Between Modes### From Production to Development (Docker)1. Stop production containers: ```bash docker compose down ```2. Start backend services: ```bash docker compose up -d postgres synkronus ```3. Start dev server: ```bash npm run dev ```### From Development to Production (Docker)1. Stop Vite dev server (Ctrl+C)2. Stop backend containers: ```bash docker compose down ```3. Start production mode: ```bash docker compose up -d --build ```**Important:** Your data (database, app bundles) persists when switching between modes because both use the same Docker volumes.### From Docker to Dockerless (or vice versa)**Note:** Data is not automatically shared between Docker and Dockerless modes. You'll need to:- Export data from one mode- Import into the other mode- Or use the same PostgreSQL instance for both---## Building for Production### First Time SetupFor the first time, or after code changes:```bash# Build and start (recommended - does both in one command)docker compose up -d --build# Or build first, then start (if you prefer separate steps)docker compose builddocker compose up -d```### Rebuilding After Code ChangesIf you've made changes to the frontend code:```bash# Rebuild just the portal imagedocker compose build synkronus-portal# Restart the portal servicedocker compose up -d synkronus-portal```**Note:** The `--build` flag in `docker compose up -d --build` will:- Build images if they don't exist- Rebuild images if the Dockerfile or source code changed- Start all services after buildingThis is the easiest way to ensure everything is up-to-date!---## Environment Variables### Development- `VITE_API_URL`: Backend API URL (default: uses `/api` proxy)- `DOCKER_ENV`: Set to `true` when running in Docker### Production- `VITE_API_URL`: Backend API URL (default: `http://localhost:8080`)### Backend (Dockerless)See `../synkronus/README.md` for complete backend environment variable documentation.---## See Also- [SETUP_ANALYSIS.md](./SETUP_ANALYSIS.md) - Detailed setup analysis and recommendations- [../synkronus/README.md](../synkronus/README.md) - Backend API documentation- [../synkronus/DEPLOYMENT.md](../synkronus/DEPLOYMENT.md) - Production deployment guide \ No newline at end of file +# Synkronus Portal + +Frontend service for Synkronus, built with React + TypeScript + Vite. + +## Overview +The Synkronus Portal provides a web-based interface for managing app bundles, users, observations, and data exports. It supports both development (hot reload) and production (optimized build) modes. + +## Prerequisites + +Before starting, ensure you have: + +### For Docker-based Setup (Recommended) +- **Docker** (version 20.10+) and **Docker Compose** (version 2.0+) +- Check: `docker --version` and `docker compose version` +- **Git** (for cloning the repository) +- **4GB+ free disk space** (for Docker images and volumes) + +**Note for Windows users:** Ensure WSL2 is enabled if using Docker Desktop. + +### For Dockerless Development Setup +- **Node.js** 20+ and **npm** or **yarn** +- **Go** 1.22+ (for running the backend API) +- **PostgreSQL** 17+ (installed locally or accessible) +- **Git** (for cloning the repository) + +--- + +## Quick Reference +| Mode | Command | URL | Hot Reload | Docker Required | +| ---------------------------- | ---------------------------------------------------------- | --------------------- | ---------- | --------------- | +| **Production** | `docker compose up -d --build` | http://localhost:5173 | ❌ No | ✅ Yes | +| **Development (Docker)** | `docker compose up -d postgres synkronus`
`npm run dev` | http://localhost:5174 | ✅ Yes | ✅ Partial | +| **Development (Dockerless)** | See [Dockerless Setup](#dockerless-development-setup) | http://localhost:5174 | ✅ Yes | ❌ No | + +**Default Login Credentials:** +- Username: `admin` +- Password: `admin` + +--- + +## Quick Start (First Time) + +**For users who just want to get it running:** + +### Option 1: Production Mode (Docker - Easiest) +1. **Navigate to directory:** + + ```bash + cd synkronus-portal + ``` + +2. **Start everything:** + + ```bash + docker compose up -d --build + ``` + +3. **Wait ~30 seconds** for services to start + +4. **Open in browser:** + - Portal: http://localhost:5173 + +5. **Login with:** `admin` / `admin` + +That's it! 🎉 + + +### Option 2: Development Mode (Dockerless - No Docker Required) + +See the [Dockerless Development Setup](#dockerless-development-setup) section below for complete instructions. + +--- + +## Production Mode (Optimized Build) + +**Step 1:** Navigate to the portal directory + +```bash +cd synkronus-portal +``` + +**Step 2:** Build and start all services in production mode + +```bash +# Option 1: Build and start in one command (recommended) +docker compose up -d --build +# Option 2: Build first, then start (if you prefer separate steps) +docker compose build +docker compose up -d +``` + +**Note:** The `--build` flag ensures the frontend is built before starting. If you skip building, Docker will build automatically, but it's better to be explicit. + +**Step 3:** Wait for services to start (about 10-30 seconds) + +```bash +# Check service status +docker compose ps +# View logs if needed +docker compose logs -f +``` + +**Step 4:** Access the portal + +- **Frontend Portal**: http://localhost:5173 (Nginx serving optimized production build) +- **Backend API**: http://localhost:8080 +- **PostgreSQL**: localhost:5432 +- **Swagger UI**: http://localhost:8080/openapi/swagger-ui.html + +**Production Mode Features:** +- ✅ Optimized production build (minified, tree-shaken) +- ✅ Static file serving via Nginx (fast, efficient) +- ✅ Persistent data storage (survives container restarts) +- ✅ Production-ready performance +- ❌ No hot reload (requires rebuild for changes) + +**To stop production mode:** +```bash +docker compose down +``` + +**Note:** Stopping containers with `docker compose down` does **NOT** delete your data. Volumes persist automatically. Your database and app bundles remain safe. + +--- + +## Development Mode (Hot Reload) + +### Development with Docker (Partial Docker) + +**Step 1:** Navigate to the portal directory + +```bash +cd synkronus-portal +``` + +**Step 2:** Start backend services (PostgreSQL + API) + +```bash +# Start only backend services (postgres + synkronus API) +docker compose up -d postgres synkronus +# This starts the database and backend API, but not the frontend +# The frontend will be started separately with hot reload +``` + +**Step 3:** Wait for backend to be ready (about 10-20 seconds) + +```bash +# Check backend health +curl http://localhost:8080/health +# Should return JSON like: {"status":"ok",...} +``` + +**Step 4:** Install dependencies (if not already done) + +```bash +npm install +``` + +**Step 5:** Start the Vite dev server + +```bash +npm run dev +``` + +**Step 6:** Access the portal +- **Frontend Portal**: http://localhost:5174 (Vite dev server with hot reload) +- **Backend API**: http://localhost:8080 (already running from Step 2) + +**Development Mode Features:** +- ✅ Hot Module Replacement (HMR) - instant code updates without page refresh +- ✅ Fast refresh - React components update instantly +- ✅ Source maps for debugging +- ✅ Same persistent storage as production - data is shared +- ✅ Full debugging support in browser DevTools +- ✅ Real-time error overlay in browser + +**To stop development mode:** + +```bash +# Stop Vite dev server: Press Ctrl+C in the terminal running +npm run dev +# Stop backend services +docker compose down +``` + +**Note:** Stopping containers with `docker compose down` does **NOT** delete your data. Volumes persist automatically. Your database and app bundles remain safe. + +--- + +## Dockerless Development Setup + +**Perfect for developers who prefer not to use Docker or want a fully local development environment.** + +### Prerequisites +- **Node.js** 20+ and **npm** +- **Go** 1.22+ ([Install Go](https://go.dev/doc/install)) +- **PostgreSQL** 17+ ([Install PostgreSQL](https://www.postgresql.org/download/)) +- **Git** + +### Step 1: Set Up PostgreSQL Database + +**Create the database and user:** +```bash +# Connect to PostgreSQL (as superuser) +psql -U postgres +# In PostgreSQL prompt, run: +CREATE DATABASE synkronus; +CREATE USER synkronus_user WITH PASSWORD 'dev_password_change_in_production'; +GRANT ALL PRIVILEGES ON DATABASE synkronus TO synkronus_user; +# Connect to synkronus database +\c synkronus +# Grant schema privileges +GRANT ALL ON SCHEMA public TO synkronus_user; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO synkronus_user; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO synkronus_user; +# Exit +\q +``` + +**Windows PowerShell alternative:** + +```powershell +# Using psql command line +$env:PGPASSWORD='postgres'; psql -U postgres -c "CREATE DATABASE synkronus;" +$env:PGPASSWORD='postgres'; psql -U postgres -c "CREATE USER synkronus_user WITH PASSWORD 'dev_password_change_in_production';" +$env:PGPASSWORD='postgres'; psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE synkronus TO synkronus_user;" +``` + +### Step 2: Set Up Backend API (Synkronus) + +**Navigate to synkronus directory:** + +```bash +cd ../synkronus +``` + +**Install dependencies:** + +```bash +go mod download +``` + +**Create environment file (`.env` in synkronus directory):** + +```bash +# Create .env file +cat > .env << EOF +PORT=8080 +LOG_LEVEL=debug +DB_CONNECTION=postgres://synkronus_user:dev_password_change_in_production@localhost:5432/synkronus?sslmode=disable +JWT_SECRET=dev_jwt_secret_change_in_production_32chars +ADMIN_USERNAME=admin +ADMIN_PASSWORD=admin +APP_BUNDLE_PATH=./data/app-bundles +MAX_VERSIONS_KEPT=5 +EOF +``` + +**Windows PowerShell alternative:** + +```powershell +@"PORT=8080 +LOG_LEVEL=debug +DB_CONNECTION=postgres://synkronus_user:dev_password_change_in_production@localhost:5432/synkronus?sslmode=disable +JWT_SECRET=dev_jwt_secret_change_in_production_32chars +ADMIN_USERNAME=admin +ADMIN_PASSWORD=admin +APP_BUNDLE_PATH=./data/app-bundles +MAX_VERSIONS_KEPT=5"@ | Out-File -FilePath .env -Encoding utf8 +``` + +**Create app bundles directory:** + +```bash +mkdir -p data/app-bundles +``` + +**Run the backend API:** + +```bash +# Option 1: Run directly (recommended for development) +go run cmd/synkronus/main.go +# Option 2: Build and run +go build -o bin/synkronus cmd/synkronus/main.go +./bin/synkronus +``` + +**Verify backend is running:** + +```bash +# In another terminal +curl http://localhost:8080/health +# Should return JSON like: {"status":"ok",...} +``` + +### Step 3: Set Up Frontend Portal + +**Navigate to portal directory:** + +```bash +cd ../synkronus-portal +``` + +**Install dependencies:** + +```bash +npm install +``` + +**Start the Vite dev server:** + +```bash +npm run dev +``` + +**Access the portal:** +- **Frontend Portal**: http://localhost:5174 +- **Backend API**: http://localhost:8080 +- **Login**: `admin` / `admin` + +### Step 4: Verify Everything Works + +1. **Check backend health:** + + ```bash + curl http://localhost:8080/health + # Should return JSON like: {"status":"ok",...} + ``` + +2. **Open frontend in browser:** + - Navigate to http://localhost:5174 + - You should see the login page + +3. **Test login:** + - Username: `admin` + - Password: `admin` + - Should successfully log in and show the dashboard + +### Stopping Dockerless Development + +1. **Stop frontend:** Press `Ctrl+C` in the terminal running `npm run dev` +2. **Stop backend:** Press `Ctrl+C` in the terminal running the Go server + +### Troubleshooting Dockerless Setup + +**Backend won't start:** + +- Verify PostgreSQL is running: `psql -U postgres -c "SELECT version();"` +- Check database connection string in `.env` file +- Ensure database and user were created correctly + +**Frontend can't connect to backend:** +- Verify backend is running on port 8080: `curl http://localhost:8080/health` +- Check `vite.config.ts` proxy configuration +- Ensure no firewall is blocking localhost connections + +**Database connection errors:** +- Verify PostgreSQL is running +- Check connection string format: `postgres://user:password@host:port/database` +- Ensure user has proper permissions + +--- + +## Verification Checklist + +After setting up (any mode), verify everything is working: + +1. **Check service status (Docker mode):** + +```bash +docker compose ps +``` + +All services should show "Up" status. Health checks may show "starting" for the first 30-60 seconds - this is normal. + +2. **Test API health:** + +```bash +curl http://localhost:8080/health +``` + +Should return JSON like: `{\"status\":\"ok\",...}` + +3. **Test frontend:** +- Open http://localhost:5173 (production) or http://localhost:5174 (development) in your browser +- Should show the login page + +4. **Test login:** +- Username: `admin` +- Password: `admin` +- Should successfully authenticate and show dashboard + +5. **Check logs (if issues):** + +```bash +# Docker mode +docker compose logs -f +# Dockerless mode - check terminal output +``` + +--- + +## Common Issues + +### "cannot execute: required file not found" (init-db.sh) +**Symptom:** PostgreSQL container fails to initialize database user. + +**Cause:** Windows line endings (CRLF) in shell scripts. + +**Solution:** +```powershell +# Convert line endings (PowerShell) +$content = Get-Content init-db.sh -Raw +$content = $content -replace "`r`n", "`n" +[System.IO.File]::WriteAllText((Resolve-Path init-db.sh), $content, [System.Text.UTF8Encoding]::new($false)) +# Then restart +docker compose down -v +docker compose up -d --build +``` + +**Prevention:** The `.gitattributes` file enforces LF line endings. If you're on Windows, ensure Git is configured correctly: +```bash +git config core.autocrlf false +``` + +### Port Already in Use + +**Production Mode (Port 5173):** + +```bash +# Edit docker-compose.yml and change the port mapping: +ports: + - "5173:80" # Change 5173 to your desired port +``` + +**Development Mode (Port 5174):** + +```bash +# Edit vite.config.ts and change the port: +server: { + port: 5174, # Change to your desired port +} +``` + +**Backend API (Port 8080):** + +```bash +# Docker mode: Edit docker-compose.yml +ports: + - "8080:8080" # Change 8080 to your desired port +# Dockerless mode: Edit .env file in synkronus directory +PORT=8080 # Change to your desired port +``` + +### Health Checks Show "Unhealthy" or "Starting" + +**This is normal!** Health checks can take 30-60 seconds to pass on first startup. As long as: +- Services show "Up" status +- `curl http://localhost:8080/health` returns JSON with `"status":"ok"` +- Frontend loads in browser + +Then everything is working correctly. The health check status will update to "healthy" after a few cycles. + +### Hot Reload Not Working (Development Mode) + +1. Ensure you're running `npm run dev` (not Docker for frontend) +2. Check that Vite is running on port 5174 +3. Verify the browser is connected to the correct port (http://localhost:5174) +4. Check browser console for HMR connection errors +5. Try hard refresh (Ctrl+Shift+R or Cmd+Shift+R) +6. **Windows users:** Ensure file watching is enabled. If using WSL2, files should be in the WSL filesystem, not Windows filesystem. +7. Check `vite.config.ts` for correct HMR configuration (should be set up by default) + +### API Connection Issues +1. **Docker mode:** + - Verify backend is running: `docker compose ps` + - Check backend logs: `docker compose logs synkronus` + - Test API directly: `curl http://localhost:8080/health` + +2. **Dockerless mode:** + - Verify backend process is running (check terminal) + - Check backend logs in terminal output + - Test API directly: `curl http://localhost:8080/health` + - Verify PostgreSQL is running and accessible + +### App Bundles Not Persisting + +If app bundles disappear after restarting containers: + +1. **Verify the volume exists (Docker mode):** + +```bash +docker volume ls | grep app-bundles +``` + +2. **Check if bundles are in the volume:** + +```bash +# If containers are running +docker compose exec synkronus ls -la /app/data/app-bundles +# If containers are stopped +docker run --rm -v synkronus-portal_app-bundles:/data alpine ls -la /data +``` + +3. **Verify volume is mounted correctly:** + +```bash +docker compose config | grep -A 5 app-bundles +``` + +4. **Check backend logs for app bundle initialization:** + +```bash +docker compose logs synkronus | grep -i "app bundle\|bundle path" +``` + +5. **Ensure you're not using `docker compose down -v`:** +- Use `docker compose down` (preserves volumes) ✅ +- Avoid `docker compose down -v` (deletes volumes) ❌ + +**Note:** App bundles are stored in the `app-bundles` volume (Docker) or `./data/app-bundles` directory (Dockerless). + +This persists across restarts. If bundles are missing, check that: +- The volume/directory wasn't accidentally deleted +- The backend has proper permissions to read/write +- The `APP_BUNDLE_PATH` environment variable is set correctly + +### Windows-Specific Issues + +**Line Endings:** +- Git should handle this automatically with `.gitattributes` +- If issues persist: `git config core.autocrlf false` + +**File Watching (Dockerless):** +- If hot reload doesn't work, files may need to be in WSL filesystem +- Or use polling mode in `vite.config.ts` (already configured) + +**PowerShell vs Bash:** +- Most commands work in both +- Use backticks for line continuation in PowerShell: `` ` `` + +--- +## Architecture + +### Development Mode (Docker) + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Development Environment (docker-compose.yml) │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────┐ ┌───────────────────┐ │ +│ │ synkronus-portal │ │ synkronus-api │ │ +│ │ (Frontend) │ │ (Backend) │ │ +│ │ │ │ │ │ +│ │ • Vite Dev │◄────►│ • Go Server │ │ +│ │ • Port 5174 │ │ • Port 8080 │ │ +│ │ • Hot Reload │ │ • App Bundles │ │ +│ │ • Source Mounted │ │ • PostgreSQL │ │ +│ └───────────────────┘ └───────┬───────────┘ │ +│ │ │ │ +│ │ │ │ +│ └───────────────────────────┼───────────────────────┘ +│ │ │ +│ ┌────────▼──────────┐ │ +│ │ PostgreSQL │ │ +│ │ Port 5432 │ │ +│ │ Persistent DB │ │ +│ └───────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Development Mode (Dockerless) + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Dockerless Development Environment │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────┐ ┌───────────────────┐ │ +│ │ Vite Dev Server │ │ Go API Server │ │ +│ │ (Frontend) │ │ (Backend) │ │ +│ │ │ │ │ │ +│ │ • npm run dev │◄────►│ • go run │ │ +│ │ • Port 5174 │ │ • Port 8080 │ │ +│ │ • Hot Reload │ │ • App Bundles │ │ +│ │ • Local Files │ │ • Local Files │ │ +│ └───────────────────┘ └───────┬───────────┘ │ +│ │ │ │ +│ │ │ │ +│ └───────────────────────────┼───────────────────────┘ +│ │ │ +│ ┌────────▼──────────┐ │ +│ │ PostgreSQL │ │ +│ │ (Local Install) │ │ +│ │ Port 5432 │ │ +│ └───────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Production Mode + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Production Environment (docker-compose.yml) │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────┐ ┌───────────────────┐ │ +│ │ synkronus-portal │ │ synkronus-api │ │ +│ │ (Frontend) │ │ (Backend) │ │ +│ │ │ │ │ │ +│ │ • Nginx │◄────►│ • Go Server │ │ +│ │ • Static Files │ │ • Port 8080 │ │ +│ │ • Port 5173 │ │ • App Bundles │ │ +│ │ • Optimized │ │ • PostgreSQL │ │ +│ └───────────────────┘ └───────┬───────────┘ │ +│ │ │ │ +│ │ │ │ +│ └───────────────────────────┼───────────────────────┘ +│ │ │ +│ ┌────────▼──────────┐ │ +│ │ PostgreSQL │ │ +│ │ Port 5432 │ │ +│ │ Persistent DB │ │ +│ └───────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- +## API Proxy Configuration + +### Development Mode +The Vite dev server automatically proxies `/api/*` requests to the backend: +- **Frontend → Backend**: `/api/*` → `http://localhost:8080/*` (via Vite proxy) +- **Configuration**: See `vite.config.ts` + +### Production Mode +Nginx proxies `/api/*` requests to the backend: +- **Frontend → Backend**: `/api/*` → `http://synkronus:8080/*` (via Nginx) +- **Configuration**: See `Dockerfile` nginx config + +--- +## Storage Persistence + +### Docker Mode +Both development and production modes use the **same named Docker volumes**, ensuring your data persists across: +- Container restarts +- Mode switches (dev ↔ prod) +- Container removal (with `docker compose down`) +- System reboots + +**Volumes:** +- **postgres-data**: PostgreSQL database files (users, observations, app bundles metadata) +- **app-bundles**: App bundle ZIP files and versions (stored at `/app/data/app-bundles` in the container) + +**Important:** App bundles are stored in **both** places: +- **Files**: Actual ZIP files and extracted content in the `app-bundles` volume +- **Database**: Metadata about bundles (versions, manifest info) in the `postgres-data` volume + +Both volumes must persist for app bundles to work correctly after restart. + +**Volume Persistence Guarantee:** +✅ **Volumes are NOT deleted when you:** +- Stop containers: `docker compose down` +- Restart containers: `docker compose restart` +- Switch between dev/prod modes +- Rebuild containers: `docker compose build` + +⚠️ **Volumes ARE deleted ONLY when you:** +- Explicitly use: `docker compose down -v` (the `-v` flag removes volumes) +- Manually delete: `docker volume rm ` + +### Dockerless Mode + +Data is stored in local directories: +- **PostgreSQL**: Uses your local PostgreSQL data directory (configured during PostgreSQL installation) +- **App Bundles**: Stored in `../synkronus/data/app-bundles` directory + +**Backup Recommendations:** +- Regularly backup your PostgreSQL database +- Backup the `data/app-bundles` directory + +--- + +## Stopping Services + +### Docker Mode + +**Safe Stop (Preserves Data):** + +```bash +# Stop all services - VOLUMES ARE PRESERVED ✅ +docker compose down +``` + +This command: +- ✅ Stops all containers +- ✅ Removes containers +- ✅ **Keeps all volumes** (your data is safe!) +- ✅ Removes networks + +**Complete Removal (⚠️ DELETES ALL DATA):** +```bash +# Stop services AND delete volumes - ⚠️ THIS DELETES ALL DATA! +docker compose down -v +``` + +**⚠️ WARNING:** The `-v` flag removes volumes, which will: +- Delete all database data (users, observations, etc.) +- Delete all uploaded app bundles +- **This action cannot be undone!** + +**Restarting Services:** +```bash +# Start services (volumes are automatically reattached) +docker compose up -d +``` +Your data will be exactly as you left it! + +### Dockerless Mode +**Stop Frontend:** +- Press `Ctrl+C` in the terminal running `npm run dev` + +**Stop Backend:** +- Press `Ctrl+C` in the terminal running the Go server + +**Stop PostgreSQL:** +- Use your system's service manager (e.g., `systemctl stop postgresql` on Linux) + +--- + +## Default Credentials +- **Admin username**: `admin` +- **Admin password**: `admin` + +**⚠️ Warning**: These are development credentials only. Change them before production use. + +--- + +## Switching Between Modes + +### From Production to Development (Docker) +1. Stop production containers: + + ```bash + docker compose down + ``` + +2. Start backend services: + + ```bash + docker compose up -d postgres synkronus + ``` + +3. Start dev server: + + ```bash + npm run dev + ``` + +### From Development to Production (Docker) +1. Stop Vite dev server (`Ctrl+C`). + +2. Stop backend containers: + + ```bash + docker compose down + ``` + +3. Start production mode: + + ```bash + docker compose up -d --build + ``` + +**Important:** Your data (database, app bundles) persists when switching between modes because both use the same Docker volumes. + +### From Docker to Dockerless (or vice versa) +**Note:** Data is not automatically shared between Docker and Dockerless modes. You'll need to: +- Export data from one mode +- Import into the other mode +- Or use the same PostgreSQL instance for both + +--- + +## Building for Production + +### First Time Setup +For the first time, or after code changes: + +```bash +# Build and start (recommended - does both in one command) +docker compose up -d --build +# Or build first, then start (if you prefer separate steps) +docker compose build +docker compose up -d +``` + +### Rebuilding After Code Changes +If you've made changes to the frontend code: + +```bash +# Rebuild just the portal image +docker compose build synkronus-portal +# Restart the portal service +docker compose up -d synkronus-portal +``` +**Note:** The `--build` flag in `docker compose up -d --build` will: +- Build images if they don't exist +- Rebuild images if the Dockerfile or source code changed +- Start all services after building +This is the easiest way to ensure everything is up-to-date! + +--- + +## Environment Variables + +### Development +- `VITE_API_URL`: Backend API URL (default: uses `/api` proxy) +- `DOCKER_ENV`: Set to `true` when running in Docker + +### Production +- `VITE_API_URL`: Backend API URL (default: `http://localhost:8080`) + +### Backend (Dockerless) +See `../synkronus/README.md` for complete backend environment variable documentation. + +--- + +## See Also +- [SETUP_ANALYSIS.md](./SETUP_ANALYSIS.md) - Detailed setup analysis and recommendations +- [../synkronus/README.md](../synkronus/README.md) - Backend API documentation +- [../synkronus/DEPLOYMENT.md](../synkronus/DEPLOYMENT.md) - Production deployment guide