This repository has no description
3.9 kB
118 lines
1{ ... }:
2{
3 perSystem =
4 { pkgs, ... }:
5 let
6 version = "0-unstable-2026-05-03";
7 rev = "f325daad229bb15f6a1d1d3d1e9f76a744d2b2c4";
8 src = pkgs.fetchFromGitHub {
9 owner = "audibleblink";
10 repo = "worldview";
11 inherit rev;
12 hash = "sha256-L18lWcK5gEEiLyYSETk3+7KacBjxpr4SwrolcWXu4sc=";
13 };
14 in
15 {
16 packages.worldview = pkgs.writeShellApplication {
17 name = "worldview";
18 passthru = {
19 inherit version;
20 updateScript = ./update.sh;
21 };
22 runtimeInputs = [
23 pkgs.bun
24 pkgs.ungoogled-chromium
25 pkgs.python3
26 pkgs.curl
27 pkgs.gnused
28 ];
29 text = ''
30 # Required env vars
31 if [ -z "''${GOOGLE_MAPS_TILE_API_KEY:-}" ]; then
32 echo "ERROR: GOOGLE_MAPS_TILE_API_KEY is not set" >&2
33 echo "Get one at: https://console.cloud.google.com/google/maps-apis/credentials" >&2
34 echo "Export it: export GOOGLE_MAPS_TILE_API_KEY=your_key_here" >&2
35 exit 1
36 fi
37
38 get_free_port() {
39 python3 -c 'import socket; s=socket.socket(); s.bind(("",0)); print(s.getsockname()[1]); s.close()'
40 }
41
42 FRONTEND_PORT=$(get_free_port)
43 BACKEND_PORT=$(get_free_port)
44
45 WORKDIR="''${XDG_DATA_HOME:-$HOME/.local/share}/worldview"
46 mkdir -p "$WORKDIR"
47
48 # Copy source if not yet present or if version changed
49 MARKER="$WORKDIR/.version"
50 CURRENT_REV="${rev}"
51 if [ ! -f "$MARKER" ] || [ "$(cat "$MARKER")" != "$CURRENT_REV" ]; then
52 echo "Setting up worldview source..."
53 rm -rf "$WORKDIR/src"
54 cp -r ${src} "$WORKDIR/src"
55 chmod -R u+w "$WORKDIR/src"
56 echo "$CURRENT_REV" > "$MARKER"
57 rm -f "$WORKDIR/.installed"
58 fi
59
60 cd "$WORKDIR/src"
61
62 # Install dependencies if needed
63 if [ ! -f "$WORKDIR/.installed" ]; then
64 echo "Installing dependencies..."
65 bun install
66 touch "$WORKDIR/.installed"
67 fi
68
69 # Patch hardcoded ports in source
70 sed -i 's|const PORT = [0-9]*;|const PORT = '"$FRONTEND_PORT"';|' src/server.ts
71 sed -i 's|http://localhost:[0-9]*"|http://localhost:'"$BACKEND_PORT"'"|g' src/config.ts
72
73 cleanup() {
74 echo "Shutting down..."
75 # Kill entire process group to catch bun child processes
76 kill -- -$$ 2>/dev/null || true
77 }
78 trap cleanup EXIT INT TERM
79
80 export GOOGLE_MAPS_TILE_API_KEY
81 export SERVER_PORT="$BACKEND_PORT"
82 ''${AISSTREAM_API_KEY:+export AISSTREAM_API_KEY}
83
84 # Start backend server
85 bun run --hot src/server/index.ts &
86
87 # Start frontend dev server
88 bun run --hot src/server.ts &
89
90 # Wait for frontend to be ready
91 for _ in $(seq 1 30); do
92 if curl -s "http://localhost:$FRONTEND_PORT" > /dev/null 2>&1; then
93 break
94 fi
95 sleep 1
96 done
97
98 echo "WorldView is running at http://localhost:$FRONTEND_PORT"
99
100 # Open in chromium app mode with a dedicated profile
101 CHROME_DIR="$WORKDIR/chromium-profile"
102 # Remove stale singleton locks from crashed sessions
103 rm -f "$CHROME_DIR/SingletonLock" "$CHROME_DIR/SingletonCookie" "$CHROME_DIR/SingletonSocket"
104 mkdir -p "$CHROME_DIR"
105 chromium \
106 --user-data-dir="$CHROME_DIR" \
107 --no-first-run \
108 --no-default-browser-check \
109 --disable-gpu-compositing \
110 --app="http://localhost:$FRONTEND_PORT" &
111 CHROME_PID=$!
112
113 # Wait for chromium to exit (closing the window kills the process)
114 wait "$CHROME_PID" 2>/dev/null || true
115 '';
116 };
117 };
118}