From 826bd6cfe3b3339a4dcbea2cc35a0e36e72c77a0 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 26 Mar 2026 23:19:04 -0400 Subject: [PATCH] feat: /{username} persona picker landing page Visiting /scott (or any user root) now shows a clean card page listing all their personas with emoji + name, each linking to /{user}/{persona}. Previously the route was unhandled (404 or wildcard match). Co-Authored-By: Claude Sonnet 4.6 --- cortex/routers/ui.py | 106 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/cortex/routers/ui.py b/cortex/routers/ui.py index cacc98a..64599a3 100644 --- a/cortex/routers/ui.py +++ b/cortex/routers/ui.py @@ -123,6 +123,112 @@ async def logout(): return resp +# --------------------------------------------------------------------------- +# User landing — /{username} → persona picker +# --------------------------------------------------------------------------- + +@router.get("/{username}", include_in_schema=False) +async def user_landing(username: str, request: Request): + session_user = _get_session_user(request) + if not session_user: + return RedirectResponse("/login", status_code=302) + if session_user != username: + return RedirectResponse(f"/{session_user}", status_code=302) + + personas = list_user_personas(username) + if not personas: + return HTMLResponse("

No personas configured.

", status_code=404) + + cards_html = "" + for p in personas: + emoji = "✨" + identity_path = persona_path(username, p) / "IDENTITY.md" + if identity_path.exists(): + m = re.search(r"\|\s*Emoji\s*\|\s*(.+?)\s*\|", identity_path.read_text()) + if m: + emoji = m.group(1).strip() + cards_html += ( + f'' + f'{emoji}' + f'{p.capitalize()}' + f'\n' + ) + + html = f""" + + + + + Cortex — {username} + + + + + + +
+

Cortex

+

Signed in as {username} — choose a persona

+
+{cards_html}
+ Account settings +
+ +""" + return HTMLResponse(html) + + # --------------------------------------------------------------------------- # Main UI — /{username}/{persona} # ---------------------------------------------------------------------------