Compare commits

...

1 Commits

Author SHA1 Message Date
Timmy
0e32027bb4 feat(#1339): Deploy Nexus to proper URL for preview
Some checks failed
CI / test (pull_request) Failing after 51s
Review Approval Gate / verify-review (pull_request) Failing after 7s
CI / validate (pull_request) Failing after 50s
ES module imports fail via file:// or raw Forge URLs (CORS +
missing Content-Type headers). boot.js detects this and warns users.

Three deployment options:
  - ./preview.sh — local Python server, correct MIME types
  - docker compose up nexus-preview — nginx on :8080 + WS proxy
  - Push to main — GitHub Pages auto-deploy

Fixes #1339
2026-04-13 21:16:49 -04:00
7 changed files with 190 additions and 8 deletions

35
.github/workflows/pages.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Deploy Nexus Preview to Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- name: Prepare static assets
run: |
mkdir -p _site
cp index.html app.js style.css boot.js gofai_worker.js _site/
cp service-worker.js manifest.json robots.txt help.html _site/
cp portals.json vision.json _site/
cp -r nexus/ _site/nexus/
cp -r icons/ _site/icons/ 2>/dev/null || true
cp -r assets/ _site/assets/ 2>/dev/null || true
- uses: actions/upload-pages-artifact@v3
with:
path: '_site'
- id: deployment
uses: actions/deploy-pages@v4

9
Dockerfile.preview Normal file
View File

@@ -0,0 +1,9 @@
FROM nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY preview/nginx.conf /etc/nginx/conf.d/default.conf
COPY index.html app.js style.css boot.js gofai_worker.js /usr/share/nginx/html/
COPY service-worker.js manifest.json robots.txt help.html portals.json vision.json /usr/share/nginx/html/
COPY nexus/ /usr/share/nginx/html/nexus/
COPY icons/ /usr/share/nginx/html/icons/
COPY assets/ /usr/share/nginx/html/assets/
EXPOSE 8080

26
PREVIEW.md Normal file
View File

@@ -0,0 +1,26 @@
# Nexus Preview
ES module imports fail via `file://` or raw Forge URLs. `boot.js` already warns: _"Serve over HTTP to initialize Three.js."_
## Quick Start
```bash
./preview.sh # http://localhost:8080 (Python, no deps)
./preview.sh docker # http://localhost:8080 (nginx + WS proxy)
docker compose up -d nexus-preview nexus-backend # full stack
```
## Options
| Method | Command | Port |
|--------|---------|------|
| Local Python | `./preview.sh` | 8080 |
| Docker nginx | `docker compose up nexus-preview` | 8080 |
| GitHub Pages | push to main | auto |
## Files
- `Dockerfile.preview` — nginx container
- `preview/nginx.conf` — MIME types + WebSocket proxy
- `preview.sh` — Python preview server
- `.github/workflows/pages.yml` — GitHub Pages CI/CD

View File

@@ -1,17 +1,26 @@
#!/usr/bin/env bash
# deploy.sh — spin up (or update) the Nexus staging environment
# Usage: ./deploy.sh — rebuild and restart nexus-main (port 4200)
# ./deploy.sh staging — rebuild and restart nexus-staging (port 4201)
# deploy.sh — Nexus environment
# ./deploy.sh — nexus-main (port 8765)
# ./deploy.sh staging — nexus-staging (port 8766)
# ./deploy.sh preview — static preview (port 8080)
# ./deploy.sh full — preview + backend
set -euo pipefail
SERVICE="${1:-nexus-main}"
case "$SERVICE" in
staging) SERVICE="nexus-staging" ;;
main) SERVICE="nexus-main" ;;
preview)
echo "==> Preview on http://localhost:8080"
docker compose build nexus-preview
docker compose up -d --force-recreate nexus-preview
exit 0 ;;
full)
echo "==> Full stack (preview + backend)"
docker compose build nexus-preview nexus-backend
docker compose up -d --force-recreate nexus-preview nexus-backend
exit 0 ;;
esac
echo "==> Deploying $SERVICE"
docker compose build "$SERVICE"
docker compose up -d --force-recreate "$SERVICE"
echo "==> Done. Container: $SERVICE"
echo "==> Done: $SERVICE"

View File

@@ -7,9 +7,28 @@ services:
restart: unless-stopped
ports:
- "8765:8765"
nexus-staging:
build: .
container_name: nexus-staging
restart: unless-stopped
ports:
- "8766:8765"
- "8766:8765"
nexus-backend:
build: .
container_name: nexus-backend
restart: unless-stopped
expose:
- "8765"
nexus-preview:
build:
context: .
dockerfile: Dockerfile.preview
container_name: nexus-preview
restart: unless-stopped
ports:
- "8080:8080"
depends_on:
- nexus-backend

33
preview.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
# preview.sh — One-command preview for The Nexus
# ./preview.sh — http://localhost:8080
# ./preview.sh 3000 — custom port
# ./preview.sh docker — Docker/nginx
set -euo pipefail
PORT="${1:-8080}"
if [ "$PORT" = "docker" ]; then
echo "==> Nexus preview via Docker/nginx..."
docker compose up -d nexus-preview
echo "==> http://localhost:8080"
exit 0
fi
if ! command -v python3 &> /dev/null; then
echo "Error: python3 not found. Use './preview.sh docker'"
exit 1
fi
echo "==> Nexus preview on http://localhost:$PORT"
python3 -c "
import http.server, socketserver
class H(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header('Access-Control-Allow-Origin','*')
super().end_headers()
def guess_type(self,p):
if p.endswith('.js') or p.endswith('.mjs'): return 'application/javascript'
if p.endswith('.css'): return 'text/css'
if p.endswith('.json'): return 'application/json'
return super().guess_type(p)
with socketserver.TCPServer(('', $PORT), H) as s:
print(f'Serving http://localhost:{$PORT}')
s.serve_forever()
"

51
preview/nginx.conf Normal file
View File

@@ -0,0 +1,51 @@
server {
listen 8080;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
}
location ~* \.js$ {
types { application/javascript js; }
add_header Cache-Control "public, max-age=3600";
}
location ~* \.css$ {
types { text/css css; }
add_header Cache-Control "public, max-age=3600";
}
location ~* \.json$ {
types { application/json json; }
add_header Cache-Control "no-cache";
}
location /api/world/ws {
proxy_pass http://nexus-backend:8765;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
location /ws {
proxy_pass http://nexus-backend:8765;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
location /health {
return 200 '{"status":"ok","service":"nexus-preview"}';
add_header Content-Type application/json;
}
}