#!/usr/bin/env bash # # Freezmo setup — install dependencies, create a local env file and (by default) # produce a production build. # # Usage: # ./setup.sh install + create .env.local + production build # ./setup.sh --dev install + create .env.local, but no build (for `npm run dev`) # ./setup.sh --no-build install + create .env.local only # # Requires: Node.js 20+ and npm. Nothing here needs sudo or a global install. set -euo pipefail # --- pretty output --------------------------------------------------------- bold="$(printf '\033[1m')" dim="$(printf '\033[2m')" green="$(printf '\033[32m')" yellow="$(printf '\033[33m')" red="$(printf '\033[31m')" reset="$(printf '\033[0m')" info() { printf '%s[freezmo]%s %s\n' "$green" "$reset" "$1"; } warn() { printf '%s[freezmo]%s %s\n' "$yellow" "$reset" "$1"; } fail() { printf '%s[freezmo]%s %s\n' "$red" "$reset" "$1" >&2; exit 1; } # --- arguments ------------------------------------------------------------- mode="build" for arg in "$@"; do case "$arg" in --dev|dev) mode="dev" ;; --no-build|--install-only) mode="install" ;; -h|--help) sed -n '2,11p' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; *) fail "Unknown argument: $arg (try --help)" ;; esac done # Run from the directory that contains this script, so `./setup.sh` works from # anywhere. cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" info "Setting up Freezmo in ${bold}$PWD${reset}" # --- prerequisites --------------------------------------------------------- command -v node >/dev/null 2>&1 || fail "Node.js is not installed. Install Node.js 20+ and try again." command -v npm >/dev/null 2>&1 || fail "npm is not installed. It ships with Node.js." node_major="$(node -p 'process.versions.node.split(".")[0]')" if [ "$node_major" -lt 20 ]; then fail "Node.js 20+ is required (found $(node -v))." fi info "Node $(node -v) · npm $(npm -v)" # --- environment file ------------------------------------------------------ if [ ! -f .env.local ]; then if [ -f .env.example ]; then cp .env.example .env.local info "Created ${bold}.env.local${reset} from .env.example (bring-your-own-key mode by default)." else warn ".env.example is missing — the app will fall back to built-in defaults." fi else info "Keeping the existing .env.local (nothing overwritten)." fi # --- dependencies ---------------------------------------------------------- info "Installing dependencies with npm…" if [ -f package-lock.json ]; then npm ci else npm install fi # --- build ----------------------------------------------------------------- if [ "$mode" = "install" ]; then info "Dependencies installed. Skipping the build (--no-build)." elif [ "$mode" = "dev" ]; then info "Dependencies installed. Skipping the build (--dev)." else info "Building the production bundle…" npm run build fi # --- next steps ------------------------------------------------------------ printf '\n%sFreezmo is ready.%s\n\n' "$bold$green" "$reset" if [ "$mode" = "dev" ] || [ "$mode" = "install" ]; then printf ' Start the dev server: %snpm run dev%s → http://localhost:3207\n' "$bold" "$reset" else printf ' Start production: %snpm start%s → http://localhost:3207\n' "$bold" "$reset" printf ' Or for development: %snpm run dev%s\n' "$bold" "$reset" fi printf '\n' printf '%sAuthentication%s (edit .env.local, restart the server afterwards):\n' "$dim" "$reset" printf ' OLLAMA_AUTH=user-key each browser pastes its own key in Settings (default)\n' printf ' OLLAMA_AUTH=server one key from OLLAMA_API_KEY in .env.local\n' printf ' OLLAMA_AUTH=local a local daemon signed in with `ollama signin`\n' printf '\n' printf 'Models are chosen in .env.local: VISION_MODEL (multimodal) and TEXT_MODEL.\n' printf 'The app is served on 0.0.0.0:3207, so phones on the same network can reach it.\n' printf 'Details: %sREADME.md%s\n' "$bold" "$reset"