diff --git a/.env.example b/.env.example index c92c023..1643766 100644 --- a/.env.example +++ b/.env.example @@ -42,3 +42,63 @@ VITE_MARKET_NADDR=naddr1qqjxgdp4vv6rydej943n2dny956rwwf4943xzwfc95ekyd3evenrsvrr # VITE_LIGHTNING_ENABLED=true # OBSOLETE: Not used in codebase - config.market.defaultCurrency is never consumed # VITE_MARKET_DEFAULT_CURRENCY=sat + +# ─────────────────────────────────────────────────────────────────────── +# Hub → standalone navigation URLs +# +# Each chakra tile in the hub builds an from these env vars and +# (when authenticated) appends ?token= so the destination +# auto-logs in via acceptTokenFromUrl(). +# +# Trailing slash matters under path-mode deployment: +# ✓ https://demo.example.com/market/ asset URLs resolve correctly +# ✗ https://demo.example.com/market relies on nginx 301 to add the +# slash; brittle, extra round trip. +# +# In LOCAL DEV with `npm run dev:all` use the per-app dev ports (defined +# in the vite configs): +# VITE_HUB_ACTIVITIES_URL=http://localhost:5181 +# VITE_HUB_CASTLE_URL=http://localhost:5180 +# VITE_HUB_WALLET_URL=http://localhost:5182 +# VITE_HUB_CHAT_URL=http://localhost:5183 +# VITE_HUB_FORUM_URL=http://localhost:5184 +# VITE_HUB_MARKET_URL=http://localhost:5185 +# VITE_HUB_TASKS_URL=http://localhost:5186 +# +# In PATH-MODE production (recommended for demo) — note the trailing slash: +# VITE_HUB_ACTIVITIES_URL=https://demo.example.com/activities/ +# VITE_HUB_CASTLE_URL=https://demo.example.com/castle/ +# VITE_HUB_WALLET_URL=https://demo.example.com/wallet/ +# VITE_HUB_CHAT_URL=https://demo.example.com/chat/ +# VITE_HUB_FORUM_URL=https://demo.example.com/forum/ +# VITE_HUB_MARKET_URL=https://demo.example.com/market/ +# VITE_HUB_TASKS_URL=https://demo.example.com/tasks/ +# +# In SUBDOMAIN-MODE production: +# VITE_HUB_ACTIVITIES_URL=https://sortir.example.com +# VITE_HUB_CASTLE_URL=https://castle.example.com +# ...etc +# ─────────────────────────────────────────────────────────────────────── +VITE_HUB_ACTIVITIES_URL= +VITE_HUB_CASTLE_URL= +VITE_HUB_WALLET_URL= +VITE_HUB_CHAT_URL= +VITE_HUB_FORUM_URL= +VITE_HUB_MARKET_URL= +VITE_HUB_TASKS_URL= + +# ─────────────────────────────────────────────────────────────────────── +# VITE_BASE_PATH — build-time only, NOT per .env +# +# Each standalone vite config (vite..config.ts) reads VITE_BASE_PATH +# at build time. For path-mode deployment, set it as a shell variable when +# you build, NOT in this .env file (which is read at runtime by the +# bundle): +# +# VITE_BASE_PATH=/market/ npm run build:market +# VITE_BASE_PATH=/wallet/ npm run build:wallet +# ... +# +# The default '/' (no override) is what you want for subdomain-mode and +# for `npm run dev:all`. +# ─────────────────────────────────────────────────────────────────────── diff --git a/nginx.conf.example b/nginx.conf.example index 05cf1f6..662b4c9 100644 --- a/nginx.conf.example +++ b/nginx.conf.example @@ -11,115 +11,159 @@ http { real_ip_header X-Forwarded-For; real_ip_recursive on; - # Reusable location blocks - # JS / CSS / image MIME and caching - map $sent_http_content_type $cache_static { - default "off"; - ~image/ "6M"; - } - - # ─────────────────────────────────────────────────────────────── - # AIO hub — minimal app at app. - # Serves only the chakra icon hub + base infra (profile, relays). - # ─────────────────────────────────────────────────────────────── + # ─────────────────────────────────────────────────────────────────────── + # PATH-MODE deployment (recommended) + # + # demo../ — minimal AIO chakra hub + # demo../activities/ — Sortir / activities standalone + # demo../market/ — marketplace standalone + # demo../wallet/ — wallet standalone + # demo../chat/ — chat standalone + # demo../forum/ — forum standalone + # demo../tasks/ — tasks standalone + # demo../castle/ — castle (accounting) standalone + # + # Each standalone is built with VITE_BASE_PATH=// so its asset URLs + # are prefixed correctly. The hub's chakra tiles point at the canonical + # trailing-slash path (VITE_HUB__URL=https://demo.//). + # + # Per-app no-trailing-slash → with-slash 301 redirects exist for users + # who hand-type the URL or follow a stripped-slash link. + # + # All static assets (JS / CSS / images / SVGs) are MIME-typed and image + # types get a 6-month cache-control. + # ─────────────────────────────────────────────────────────────────────── server { listen 8080; - server_name app..; + server_name demo..; + # Hub at the root root /var/www/aio/dist; index index.html; + location = / { try_files $uri /index.html; } + location / { + # Default: serve from hub bundle if no // prefix matched. + try_files $uri $uri/ /index.html; + } - location / { try_files $uri $uri/ /index.html; } + # ── Activities (Sortir) ────────────────────────────────────────── + location = /activities { return 301 /activities/$is_args$args; } + location /activities/ { + alias /var/www/aio/dist-activities/; + try_files $uri $uri/ /activities.html; + } + + # ── Market ─────────────────────────────────────────────────────── + location = /market { return 301 /market/$is_args$args; } + location /market/ { + alias /var/www/aio/dist-market/; + try_files $uri $uri/ /market.html; + } + + # ── Wallet ─────────────────────────────────────────────────────── + location = /wallet { return 301 /wallet/$is_args$args; } + location /wallet/ { + alias /var/www/aio/dist-wallet/; + try_files $uri $uri/ /wallet.html; + } + + # ── Chat ───────────────────────────────────────────────────────── + location = /chat { return 301 /chat/$is_args$args; } + location /chat/ { + alias /var/www/aio/dist-chat/; + try_files $uri $uri/ /chat.html; + } + + # ── Forum ──────────────────────────────────────────────────────── + location = /forum { return 301 /forum/$is_args$args; } + location /forum/ { + alias /var/www/aio/dist-forum/; + try_files $uri $uri/ /forum.html; + } + + # ── Tasks ──────────────────────────────────────────────────────── + location = /tasks { return 301 /tasks/$is_args$args; } + location /tasks/ { + alias /var/www/aio/dist-tasks/; + try_files $uri $uri/ /tasks.html; + } + + # ── Castle (accounting) ────────────────────────────────────────── + location = /castle { return 301 /castle/$is_args$args; } + location /castle/ { + alias /var/www/aio/dist-castle/; + try_files $uri $uri/ /castle.html; + } + + # ── Static asset MIME / cache (applies to all bundles) ─────────── location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } location ~* \.css$ { types { text/css css; } default_type text/css; } location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } } - # ─────────────────────────────────────────────────────────────── - # Standalone module PWAs — one server block per subdomain - # ─────────────────────────────────────────────────────────────── - - # Marketplace — Muladhara + # ─────────────────────────────────────────────────────────────────────── + # Optional subdomain shortcuts → canonical path + # + # If you want pretty subdomain URLs that funnel into the path-mode + # canonical, add 301 redirects per app. Example: + # + # events.demo.. → demo../activities/ + # market.demo.. → demo../market/ + # ─────────────────────────────────────────────────────────────────────── server { listen 8080; - server_name market..; - root /var/www/aio/dist-market; - index market.html; - location / { try_files $uri $uri/ /market.html; } - location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } - location ~* \.css$ { types { text/css css; } default_type text/css; } - location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } + server_name events.demo..; + return 301 https://demo../activities/$request_uri; } - - # Activities — Swadhisthana server { listen 8080; - server_name sortir..; - root /var/www/aio/dist-activities; - index activities.html; - location / { try_files $uri $uri/ /activities.html; } - location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } - location ~* \.css$ { types { text/css css; } default_type text/css; } - location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } + server_name market.demo..; + return 301 https://demo../market/$request_uri; } - - # Wallet — Manipura server { listen 8080; - server_name wallet..; - root /var/www/aio/dist-wallet; - index wallet.html; - location / { try_files $uri $uri/ /wallet.html; } - location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } - location ~* \.css$ { types { text/css css; } default_type text/css; } - location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } + server_name wallet.demo..; + return 301 https://demo../wallet/$request_uri; } - - # Chat — Anahata server { listen 8080; - server_name chat..; - root /var/www/aio/dist-chat; - index chat.html; - location / { try_files $uri $uri/ /chat.html; } - location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } - location ~* \.css$ { types { text/css css; } default_type text/css; } - location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } + server_name chat.demo..; + return 301 https://demo../chat/$request_uri; } - - # Forum — Vishuddha server { listen 8080; - server_name forum..; - root /var/www/aio/dist-forum; - index forum.html; - location / { try_files $uri $uri/ /forum.html; } - location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } - location ~* \.css$ { types { text/css css; } default_type text/css; } - location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } + server_name forum.demo..; + return 301 https://demo../forum/$request_uri; } - - # Tasks — Ajna server { listen 8080; - server_name tasks..; - root /var/www/aio/dist-tasks; - index tasks.html; - location / { try_files $uri $uri/ /tasks.html; } - location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } - location ~* \.css$ { types { text/css css; } default_type text/css; } - location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } + server_name tasks.demo..; + return 301 https://demo../tasks/$request_uri; } - - # Castle — Sahasrara (accounting) server { listen 8080; - server_name castle..; - root /var/www/aio/dist-castle; - index castle.html; - location / { try_files $uri $uri/ /castle.html; } - location ~* \.js$ { types { application/javascript js; } default_type application/javascript; } - location ~* \.css$ { types { text/css css; } default_type text/css; } - location ~* \.(png|jpe?g|webp|ico|svg)$ { expires 6M; access_log off; } + server_name castle.demo..; + return 301 https://demo../castle/$request_uri; } + + # ─────────────────────────────────────────────────────────────────────── + # SUBDOMAIN-MODE deployment (alternative — pure subdomains, no /path/) + # + # If you'd rather give each standalone its own subdomain and skip the + # path-mode entirely: + # + # server { server_name app.; root /var/www/aio/dist; ... } + # server { server_name market.; root /var/www/aio/dist-market; ... } + # server { server_name sortir.; root /var/www/aio/dist-activities; ... } + # server { server_name wallet.; root /var/www/aio/dist-wallet; ... } + # server { server_name chat.; root /var/www/aio/dist-chat; ... } + # server { server_name forum.; root /var/www/aio/dist-forum; ... } + # server { server_name tasks.; root /var/www/aio/dist-tasks; ... } + # server { server_name castle.; root /var/www/aio/dist-castle; ... } + # + # Each block uses `location / { try_files $uri $uri/ /.html; }`. + # In subdomain mode, build each standalone WITHOUT VITE_BASE_PATH (the + # default `/` is correct), and set VITE_HUB__URL to the subdomain + # in the hub's env (e.g. VITE_HUB_MARKET_URL=https://market.). + # ─────────────────────────────────────────────────────────────────────── }