diff --git a/scripts/dev_test.py b/scripts/dev_test.py
index 3f43e56..79981b3 100755
--- a/scripts/dev_test.py
+++ b/scripts/dev_test.py
@@ -145,7 +145,7 @@ def prepare_serve() -> None:
# ── 4. Hand off to bincio dev ─────────────────────────────────────────────────
-def start_dev(mobile: bool = False) -> None:
+def start_dev(mobile: bool = False, hub: bool = False) -> None:
section("Starting bincio dev")
print()
print(" \033[1mCredentials\033[0m")
@@ -162,9 +162,10 @@ def start_dev(mobile: bool = False) -> None:
cmd += ["--api-host", "0.0.0.0"]
env = os.environ.copy()
- # Show the wiki link in the nav during local dev (wiki typically lands on 4322
- # when activity already holds 4321). Override with WIKI_DEV_URL if needed.
env.setdefault("PUBLIC_WIKI_URL", os.environ.get("WIKI_DEV_URL", "http://localhost:4322"))
+ # --hub: simulate bincio.org hub mode (/ becomes login + app selector)
+ if hub:
+ env.setdefault("PUBLIC_ACTIVITY_URL", "http://localhost:4321")
try:
subprocess.run(cmd, cwd=PROJECT_DIR, env=env)
@@ -192,6 +193,7 @@ def main() -> None:
parser.add_argument("--fresh", action="store_true", help="Wipe DATA_DIR before starting")
parser.add_argument("--no-dev", action="store_true", help="Stop after extract, skip bincio dev")
parser.add_argument("--mobile", action="store_true", help="Bind API to 0.0.0.0 for local mobile testing")
+ parser.add_argument("--hub", action="store_true", help="Simulate hub mode: / becomes login+app selector")
args = parser.parse_args()
raise_open_file_limit()
@@ -209,7 +211,7 @@ def main() -> None:
prepare_serve()
if not args.no_dev:
- start_dev(mobile=args.mobile)
+ start_dev(mobile=args.mobile, hub=args.hub)
else:
print(f"\n\033[32mDone.\033[0m Data ready at {DATA_DIR}")
print(f"Run: uv run bincio dev --data-dir {DATA_DIR}\n")
diff --git a/site/src/pages/index.astro b/site/src/pages/index.astro
index 2adc560..56e305b 100644
--- a/site/src/pages/index.astro
+++ b/site/src/pages/index.astro
@@ -3,20 +3,165 @@ import Base from '../layouts/Base.astro';
import ActivityFeed from '../components/ActivityFeed.svelte';
import { readShardHandles, isInstancePrivate } from '../lib/manifest';
-const base = import.meta.env.BASE_URL;
-const shards = readShardHandles();
+const base = import.meta.env.BASE_URL;
+const activityUrl = import.meta.env.PUBLIC_ACTIVITY_URL ?? '';
+const wikiUrl = import.meta.env.PUBLIC_WIKI_URL ?? '';
+
+const shards = readShardHandles();
const isSingleUser = shards.length === 1 && !isInstancePrivate();
const singleHandle = isSingleUser ? shards[0].handle : null;
---
-{isSingleUser ? (
+
+{activityUrl ? (
+
+