7 Commits

Author SHA1 Message Date
Karti Tripathi 82e5378658 feat(landing): beta "coming soon" CTAs + team credits & SEO
The app is in active development, not yet public — replace the "Launch app"
CTAs with a "Private beta — coming soon" state (nav, hero, and final CTA).

Add a "Built by" section crediting the team, each name linking to their
LinkedIn, plus JSON-LD SoftwareApplication + Person author markup, an author
meta tag, and a canonical link for name/entity SEO.

Team: Karti Tripathi, Ramis Hasanli, Yahya Alhinai, Shakthi Bachala.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 03:31:37 +00:00
Karti Tripathi 26c851e2bb feat(frontend): add podman.live landing page + route split
Add a public marketing landing at "/" celebrating the Top-3 finish at the
AI Engineer World's Fair 2026 hackathon (2nd overall of 95+ teams, LiveKit
track + DigitalOcean Best Use), with a scroll-to-read hero, feature/tech
sections, and the demo embed.

Introduce react-router: "/" serves the public landing (no auth) and "/app"
mounts the existing Clerk-gated app. The app route degrades gracefully to a
"deploying" placeholder when no Clerk publishable key is configured, so the
site renders without secrets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 03:15:36 +00:00
Ramis 28f3236d76 docs(demo): tighten 1-min script to a scannable half-page 2026-06-28 11:28:13 -07:00
Ramis 70b41104ad docs(demo): refocus 1-min script on on-device Gemma + self-improvement
Restructure the 60s script to hit the judging tracks explicitly: real-time
multimodal perception (Gemini Vision + git fusion), live intervention voiced
by an on-device Gemma model (with Gemini TTS fallback + a pre-flight gate so
it's never debugged on stage), and the self-improvement stack narrated
(Atlas traces, vector recall, outcome-conditioned policy, 'Seen before'
escalation, recursive self-tuning). Adds a track-callout table and fallbacks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
2026-06-28 11:26:07 -07:00
Yahya Alhinai a97142cf09 docs: simplify Modular MAX README 2026-06-28 18:19:09 +00:00
Ramis bc50406587 docs(demo): lead with agent-scale coordination thesis + add 1-min script
Reframe the demo around the real shift: AI collapses the cost of writing
code (humans-with-AI now, agent swarms next), so the bottleneck moves from
engineering to coordination/management — and at agent scale no human can
track progress or avoid collisions by hand. Add a dedicated 1-minute live
script for showing real-time card+voice interventions with teammates, and
align the 4-min opening/close with the thesis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
2026-06-28 11:14:50 -07:00
Yahya Alhinai 88abd8efb7 docs: update README with Modular MAX architecture 2026-06-28 18:10:27 +00:00
11 changed files with 856 additions and 117 deletions
+151 -30
View File
@@ -7,9 +7,55 @@ each engineer is doing, remembers which interventions helped, and nudges the
team before duplicated work, merge collisions, or missed handoffs slow everyone
down.
<p align="center">
<a href="https://podman.live/">
<img
alt="Try PodMan live in production"
src="https://img.shields.io/badge/TRY%20PODMAN%20LIVE-https%3A%2F%2Fpodman.live-1f6feb?style=for-the-badge"
/>
</a>
</p>
<h2 align="center">
<a href="https://podman.live/">Open the live production app: https://podman.live/</a>
</h2>
<p align="center">
PodMan is already deployed. Click the link above and try the production app.
</p>
<h2 align="center">
<a href="https://youtu.be/bWJIsIWTgr0">Watch the demo video</a>
</h2>
<p align="center">
<a href="https://youtu.be/bWJIsIWTgr0">
<img
src="https://img.youtube.com/vi/bWJIsIWTgr0/maxresdefault.jpg"
alt="PodMan demo video thumbnail"
width="760"
/>
</a>
</p>
[LiveKit](https://livekit.io/) · [MongoDB](https://www.mongodb.com/) ·
[Gemini](https://ai.google.dev/) · [Hermes](https://hermes-agent.nousresearch.com/) ·
[vLLM](https://vllm.ai/) · [DigitalOcean](https://www.digitalocean.com/)
[Modular MAX](https://www.modular.com/max) ·
[DigitalOcean](https://www.digitalocean.com/)
<p align="center">
<img
src="docs/assets/interruption-flow-recovery.jpg"
alt="A chart showing that a five minute interruption can create a much longer recovery period before a developer returns to flow state."
width="760"
/>
</p>
> PodMan exists to prevent the five-minute interruption from becoming a
> half-hour recovery tax.
Source image: `~/pic.jpg`, committed as
`docs/assets/interruption-flow-recovery.jpg` so it renders on GitHub.
## Read This First
@@ -19,10 +65,68 @@ down.
| Check the app | `curl https://podman.live/health` |
| Check pods and memory | `curl https://podman.live/api/pods && curl https://podman.live/api/memory/stats` |
| Use the LLM externally | Base URL `https://llm.alhinai.dev/v1`, model `gemma-4-31B-it` |
| Test Hermes | `hermes -z 'Reply with exactly: working' --provider gemma4-31b-vllm --model gemma-4-31B-it` |
| Test Hermes | `hermes -z 'Reply with exactly: working' --provider gemma4-31b-max --model gemma-4-31B-it` |
| Start local development | API, vision agent, and frontend commands are in [Local Development](#local-development) |
| Debug production | Public checks first, then systemd services in [Production Operations](#production-operations) |
## Hackathon Fit
PodMan is built for the **2026 AI Engineer World's Fair Hackathon** theme:
**Continual Learning**.
It is not a wrapper chatbot or static dashboard. It is a production-running
agentic coordination system that gets better from real use: every observation,
collision, intervention, accept, dismiss, suppression, and conversation note
feeds MongoDB-backed memory so future interventions become sharper and less
annoying.
| Hackathon target | How PodMan addresses it |
| ---------------------- | ---------------------------------------------------------------------------------------- |
| Continual Learning | Learns from real team behavior and accepted/dismissed interventions. |
| Self-Improvement Stack | Uses memory stats, Hermes jobs, production watchdogs, and deployment checks. |
| Recursive Intelligence | Gives agents operational memory and feedback loops for improving future coordination. |
| Live Demo | Already deployed at [`https://podman.live/`](https://podman.live/). |
| Technicality | Combines realtime media, vision, vector recall, graph traversal, memory, and ops agents. |
| Creativity | Solves the coordination cost around AI-assisted engineering teams. |
### Sponsor Tech Used
| Sponsor / tech | Usage in PodMan |
| -------------- | -------------------------------------------------------------------------------- |
| DigitalOcean | Hosts the production app, API, workers, Caddy, and systemd-supervised services. |
| LiveKit | Realtime room layer for screen share, audio, data messages, and agent presence. |
| Gemini | Screen understanding, live room conversation, urgent TTS, embeddings, and music. |
| MongoDB Atlas | Durable memory, `$vectorSearch`, `$graphLookup`, user learning, and job logs. |
| Modular MAX | Serves `gemma-4-31B-it` as the long-context reasoning model. |
### What To Try
```mermaid
flowchart LR
A["Open podman.live"] --> B["Join a pod"]
B --> C["Share screen via LiveKit"]
C --> D["Gemini extracts work context"]
D --> E["MongoDB recalls prior outcomes"]
E --> F["PodMan nudges only when useful"]
F --> G["Accept or dismiss"]
G --> H["Memory improves next run"]
classDef action fill:#e8f1ff,stroke:#3366cc,color:#0b1f44;
classDef ai fill:#f4edff,stroke:#805ad5,color:#2d1857;
classDef memory fill:#fff6df,stroke:#c47f00,color:#3d2b00;
class A,B,C,F,G action;
class D ai;
class E,H memory;
```
1. Open [`https://podman.live/`](https://podman.live/).
2. Create or join a pod.
3. Add teammates and share screens.
4. Watch PodMan build live context, detect overlap, and surface intervention
cards.
5. Accept or dismiss a card; that feedback becomes memory for the next similar
event.
---
## Current Live System
@@ -33,10 +137,10 @@ down.
| API | `https://podman.live/api/*` | Pods, tokens, outcomes, memory |
| Health | `https://podman.live/health` | Backend readiness |
| Local API | `127.0.0.1:8787` | Express service behind Caddy |
| Reasoning LLM | `https://llm.alhinai.dev/v1` | OpenAI-compatible Gemma/vLLM endpoint |
| Reasoning LLM | `https://llm.alhinai.dev/v1` | OpenAI-compatible Modular/MAX endpoint |
| API key | `not-needed` | Placeholder key for OpenAI clients |
| Hermes model | `gemma-4-31B-it` | 262K-context tool-using agent |
| Hermes config | `gemma4-31b-vllm` | Custom provider used by Hermes locally |
| Hermes config | `gemma4-31b-max` | Custom provider used by Hermes locally |
```mermaid
flowchart TB
@@ -66,8 +170,8 @@ flowchart TB
subgraph Reasoning["External Reasoning Endpoint"]
Tunnel["Cloudflare Tunnel<br/>llm.alhinai.dev"]
VLLM["vLLM OpenAI Server<br/>gemma-4-31B-it<br/>262144 context"]
Hermes["Hermes Agent<br/>provider: gemma4-31b-vllm"]
MaxServe["MAX OpenAI Server<br/>gemma-4-31B-it<br/>262144 context"]
Hermes["Hermes Agent<br/>provider: gemma4-31b-max"]
end
Browser --> Caddy --> API
@@ -84,7 +188,8 @@ flowchart TB
Voice --> GeminiVoice
Vision --> GeminiEmbed
Voice --> GeminiEmbed
Ops --> Hermes --> Tunnel --> VLLM
Ops --> Hermes --> Tunnel --> MaxServe
Tunnel -. "public route<br/>llm.alhinai.dev/v1" .-> MaxServe
API --> Hermes
Lyria --> Voice
@@ -95,7 +200,7 @@ flowchart TB
class Browser,Room user;
class Caddy,API,Vision,Voice,Ops app;
class Observations,State,Outcomes data;
class GeminiVision,GeminiVoice,GeminiEmbed,Lyria,Tunnel,VLLM,Hermes ai;
class GeminiVision,GeminiVoice,GeminiEmbed,Lyria,Tunnel,MaxServe,Hermes ai;
```
## What It Does
@@ -138,7 +243,7 @@ flowchart LR
VisionRoute --> Gemini20["gemini-2.0-flash<br/>screen understanding"]
ConversationRoute --> GeminiLive["gemini-3.1-flash-live-preview<br/>live Q&A"]
ConversationRoute --> GeminiTTS["gemini-3.1-flash-tts-preview<br/>urgent speech"]
HermesRoute --> Gemma["gemma-4-31B-it<br/>Hermes + vLLM + tools"]
HermesRoute --> Gemma["gemma-4-31B-it<br/>served by Modular MAX"]
EmbedRoute --> Voyage["voyage-4-lite<br/>primary embeddings"]
EmbedRoute --> GeminiEmbed["gemini-embedding-001<br/>fallback embeddings"]
MusicRoute --> Lyria["lyria-3-clip-preview<br/>background music"]
@@ -151,7 +256,7 @@ flowchart LR
class Gemini20,GeminiLive,GeminiTTS,Gemma,Voyage,GeminiEmbed,Lyria model;
```
### Gemma 4 31B via vLLM
### Gemma 4 31B via Modular MAX
Hermes uses the external OpenAI-compatible endpoint:
@@ -162,17 +267,16 @@ Model: gemma-4-31B-it
Context: 262144 tokens
```
The vLLM server is configured for Hermes-style tool use:
The Modular/MAX server is configured for long-context Gemma 4 serving:
```text
--max-model-len 262144
--max-num-seqs 1
--max-num-batched-tokens 16384
--gpu-memory-utilization 0.85
--kv-cache-dtype fp8
--enable-auto-tool-choice
--tool-call-parser gemma4
--max-length 262144
--device-memory-utilization 0.85
--kv-cache-format float8_e4m3fn
--enable-prefix-caching
--enable-chunked-prefill
--max-batch-size 1
--max-batch-input-tokens 16384
```
Hermes should point at that endpoint with this provider shape:
@@ -180,11 +284,11 @@ Hermes should point at that endpoint with this provider shape:
```yaml
model:
default: gemma-4-31B-it
provider: gemma4-31b-vllm
provider: gemma4-31b-max
providers:
gemma4-31b-vllm:
name: Gemma 4 31B vLLM (256K)
gemma4-31b-max:
name: Gemma 4 31B Modular MAX (256K)
api: https://llm.alhinai.dev/v1
api_key: not-needed
transport: chat_completions
@@ -199,8 +303,25 @@ agent:
```
Why this matters: Hermes sends OpenAI tool schemas and `tool_choice: "auto"`.
Without `--enable-auto-tool-choice` and `--tool-call-parser gemma4`, vLLM returns
HTTP 400 before Hermes can initialize an agent.
The model endpoint must support automatic tool choice so Hermes can initialize
the agent without a client-side workaround.
### Modular MAX
Gemma 4 is served through Modular MAX on the GB10 machine.
| MAX support | Value |
| ------------ | ---------------------------------------- |
| Architecture | `Gemma4ForConditionalGeneration` |
| Example | `google/gemma-4-31B-it` |
| Encodings | `float4_e2m1fnx2`, `float16`, `bfloat16` |
| Runtime | Role |
| ----------------- | ----------------------------------------- |
| Modular MAX | OpenAI-compatible Gemma 4 serving runtime |
| `gemma-4-31B-it` | Primary long-context reasoning model |
| `262144` tokens | Reported model context window |
| `llm.alhinai.dev` | Public Cloudflare-routed model endpoint |
### Gemini Surfaces
@@ -251,7 +372,7 @@ observe -> detect -> recall prior outcomes -> policy gate -> act -> record outco
| Vision agent | Node + `@livekit/rtc-node` | Subscribes to screen tracks, samples frames, publishes interventions |
| Live voice agent | Python LiveKit Agents + Gemini Live | Real-time voice Q&A in a pod room |
| Memory | MongoDB Atlas | Observations, engineer state, collisions, interventions, outcomes |
| Reasoning agent | Hermes + Gemma vLLM | Tool-using autonomous assistant and ops layer |
| Reasoning agent | Hermes + Gemma Modular/MAX | Tool-using autonomous assistant and ops layer |
| Realtime transport | LiveKit Cloud | Screen tracks, audio tracks, data messages |
| Hosting | DigitalOcean + Caddy + systemd | Static frontend, API, workers, watchdog timers |
@@ -433,7 +554,7 @@ pnpm hermes:sync-deploy
pnpm deploy:doctor:strict
```
Gemma/vLLM endpoint checks:
Gemma Modular/MAX endpoint checks:
```bash
curl https://llm.alhinai.dev/v1/models \
@@ -481,7 +602,7 @@ POD_ROOM=demo-pod
Gemma/Hermes provider values live in Hermes config, not PodMan `.env`:
```text
provider: gemma4-31b-vllm
provider: gemma4-31b-max
model: gemma-4-31B-it
base_url: https://llm.alhinai.dev/v1
api_key: not-needed
@@ -514,7 +635,7 @@ For Hermes/Gemma:
```bash
hermes -z 'Reply with exactly: working' \
--provider gemma4-31b-vllm \
--provider gemma4-31b-max \
--model gemma-4-31B-it
```
@@ -529,14 +650,14 @@ working
## Troubleshooting
| Symptom | Likely cause | Check |
| ---------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------ |
| ----------------------------- | ------------------------------------------------ | ---------------------------------------------------- |
| Frontend loads but API fails | Backend or Caddy proxy issue | `systemctl status podman-platform-api caddy` |
| `/api/*` returns 502 | API not listening on `8787` | `ss -ltnp`, `curl http://127.0.0.1:8787/health` |
| No screen observations | Vision agent not in LiveKit room | `journalctl -u podman-platform-agent -n 80` |
| Live voice missing | Python conversation agent down | `journalctl -u podman-live-conversation-agent -n 80` |
| Memory empty | MongoDB unavailable or env missing | `curl /api/memory/stats`, backend logs |
| Hermes says tool auto-choice is disabled | vLLM missing tool flags | verify `--enable-auto-tool-choice --tool-call-parser gemma4` |
| `llm.alhinai.dev` returns 502 | Gemma vLLM still loading or tunnel target down | `curl /v1/models`, vLLM logs on Gemma host |
| Hermes tool calls fail | Modular/MAX endpoint does not accept tool schema | verify Hermes provider and `/v1/chat/completions` |
| `llm.alhinai.dev` returns 502 | Gemma server still loading or tunnel target down | `curl /v1/models`, MAX logs on Gemma host |
---
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

+127 -52
View File
@@ -1,72 +1,133 @@
# PodMan — 4-Minute Demo Script
# PodMan — Demo Scripts
**Theme:** Continual Learning. **Hard limit:** 4:00. Practice to land at 3:45.
**Theme:** Continual Learning. Two scripts below: a **1-minute live script**
(§ first) for showing real-time interventions fast with teammates, and the full
**4-minute script** for the complete story. Practice the 4-min to land at 3:45.
**The one-line story:** writing code isn't the bottleneck anymore — _coordinating
who's writing what_ is. PodMan is a pair programmer for the whole team: it watches
every member's work in real time, gives everyone live status without anyone having
to interrupt anyone, and learns your team's dynamics so it nudges less and helps
more over time.
**The thesis (say this first, in either script):** AI is collapsing the cost of
*writing* code. More and more of every codebase is authored with AI assist — and
increasingly by **autonomous agents**. So the bottleneck of software engineering
is shifting away from engineering itself toward **organization, management, and
project coordination**. Pair a team with hundreds of agents all committing to the
same repo at once and it becomes **physically impossible for a human to track
progress or avoid stepping on someone else's work.** Code generation scaled;
human coordination did not. That gap is the new bottleneck.
**The one-line story:** writing code isn't the bottleneck anymore — *coordinating
who (and what) is writing what* is. PodMan is a pair programmer for the whole
team — humans **and** agents: it watches every actor's work in real time, gives
everyone live status without anyone having to interrupt anyone, catches collisions
before they land, and learns your team's dynamics so it nudges less and helps more
over time.
**The hook to land:** a "quick five-minute question" actually costs ~25 minutes of
lost focus — for two people. PodMan removes the reason to ask. Multiply the saved
recovery time across every teammate, every day, and that is the value.
lost focus — for two people. Now multiply that across a team plus a swarm of
agents nobody can watch. PodMan removes the reason to ask and surfaces the
collision no human could have caught in time. That recovery time, saved across
every actor, every day, is the value.
---
## 1-Minute Live Script (you + teammates — real-time interventions)
**Hard limit 1:00.** Hits the tracks: real-time multimodal, on-device Gemma,
Continual Learning, Self-Improvement, Recursive Intelligence.
**Pre-flight:** pod open on `podman.live`, all joined, screen share + **sound on**;
git watchers running; everyone has `README.md` open. On-device **Gemma** must be
up as Hermes's voice (else Gemini TTS auto-falls-back — just drop the "on-device"
word).
**0:000:12 — Thesis**
> "Code is almost free to write now — humans with AI, soon swarms of agents, all
> on one repo. No human can track that. The bottleneck is coordination — and it
> has to fix itself, live. Watch."
**0:120:35 — Collision caught live (money shot)**
- You + a teammate both edit `README.md`, save (unpushed).
- Card appears on every screen + voice fires: _"<you> and <teammate> are both
editing README.md. Sync before pushing."_
- Say: "Gemini Vision reads our screens, fused with local git, in real time —
and the alert is **spoken by a Gemma model on-device**. Neither of us asked."
**0:350:52 — Self-improving (narrate)**
- Third teammate edits too → **new** card + voice for the new pair (never goes
silent).
- Say: "Every trace lands in **Atlas**; vector search recalls past collisions,
repeats come back tagged **'Seen before'** and escalate — no retraining. It
tunes its own coordination from its own outcomes."
**0:521:00 — Close**
> "Real-time awareness, on-device voice, a coordination layer that improves
> itself — for humans and agents, zero interruptions."
_Fallback:_ Gemma down → drop the on-device line. Voice silent → read it, point
at the card. No card → switch the pair to a fresh file and re-save.
---
## The script (4:00)
### 0:000:30 — The problem + hook
> "AI made writing code easy. The thing still slowing teams down is coordination
> — checking each other's work, re-planning collisions, and the constant 'what
> are you working on?' A five-minute question really costs both people 25 minutes
> of lost focus. PodMan is a pair programmer for the whole team: it watches
> everyone's work live, so anyone can see another's status without interrupting
> them — and it learns your team as it goes."
> "AI made writing code almost free — humans with AI today, swarms of autonomous
> agents tomorrow, all committing to the same repo. The bottleneck stopped being
> engineering and became coordination: checking each other's work, re-planning
> collisions, the constant 'what are you working on?' At agent scale no human can
> even track it. A five-minute question already costs both people 25 minutes of
> lost focus. PodMan is a pair programmer for the whole team — humans and agents:
> it watches everyone's work live, so anyone sees another's status without
> interrupting them, catches collisions before they land, and learns your team as
> it goes."
_On screen:_ the pod view, two teammates joined, screen-share tiles live.
*On screen:* the pod view, two teammates joined, screen-share tiles live.
### 0:301:05 — Real-time team awareness (LiveKit + Gemini Vision)
- Point at the two live screen tiles. "These are real screen shares over
**LiveKit**. Our agent subscribes to the tracks and samples frames."
**LiveKit**. Our agent subscribes to the tracks and samples frames."
- "Each frame goes to **Gemini Vision**, which returns structured context — file,
symbol, activity — not a chatbot, a perception layer."
symbol, activity — not a chatbot, a perception layer."
- Show the live activity stream filling in (Signals vs Reasoning sections).
- Land the value: "This is the part that replaces 'what are you working on?' —
every teammate's current work is just _visible_, in real time. Nobody had to
ask."
every teammate's current work is just *visible*, in real time. Nobody had to
ask."
_Built-by-us callout:_ `backend/src/vision/gemini.ts`, the LiveKit agent worker.
*Built-by-us callout:* `backend/src/vision/gemini.ts`, the LiveKit agent worker.
### 1:051:40 — The catch (detection + first intervention)
- Have alice and bob both edit the **same file** with unpushed changes.
- "Normally nobody notices until merge time. GitHub can't see this — nothing's
pushed. Our detector fuses live screen context with **local git truth** from a
watcher on each laptop."
- A collision card appears: _"alice + bob both on detector.ts (unpushed)."_
- Let the **Gemini TTS** urgent voice fire once over LiveKit: _"alice and bob are
both editing detector.ts. Please sync before pushing."_
pushed. Our detector fuses live screen context with **local git truth** from a
watcher on each laptop."
- A collision card appears: *"alice + bob both on detector.ts (unpushed)."*
- Let the **Gemini TTS** urgent voice fire once over LiveKit: *"alice and bob are
both editing detector.ts. Please sync before pushing."*
- Land the value: "That's a merge conflict and a wasted afternoon caught before it
happened — and neither of them had to be tracking the other."
happened — and neither of them had to be tracking the other."
_Built-by-us callout:_ `collision/detector.ts`, `action/hermes.ts`,
*Built-by-us callout:* `collision/detector.ts`, `action/hermes.ts`,
`voice/live.ts`.
### 1:402:10 — Cross-channel overlap (research + code)
- Keep alice editing `livekit.py`.
- Have bob share a browser tab on LiveKit docs/SDK pages.
- A collaboration nudge appears: _"🤝 bob is researching LiveKit agents
(docs.livekit.io) while alice edits livekit.py — sync up before duplicating
effort."_
- A collaboration nudge appears: *"🤝 bob is researching LiveKit agents
(docs.livekit.io) while alice edits livekit.py — sync up before duplicating
effort."*
- Land the value: "This is not a merge conflict. PodMan caught duplicated effort
across channels — code on one screen, research on another — and nudged the team
before two people solved the same problem twice."
across channels — code on one screen, research on another — and nudged the team
before two people solved the same problem twice."
_Built-by-us callout:_ `vision/gemini.ts`, `collision/research.ts`,
*Built-by-us callout:* `vision/gemini.ts`, `collision/research.ts`,
`memory/vectors.ts`.
### 2:102:50 — Continual learning (the theme — the money shot)
@@ -81,45 +142,51 @@ This is the differentiator. Two beats, both from pre-seeded memory:
the spoken urgent cue.
- "The only input was one accept/dismiss tap. No retraining, no labeling. This is
**MongoDB Atlas vector search** recalling similar past events plus a policy
that adapts on the recalled outcome."
**MongoDB Atlas vector search** recalling similar past events plus a policy
that adapts on the recalled outcome."
- Optional: show `/api/memory/stats` counts climbing — accumulated experience.
_Built-by-us callout:_ `memory/vectors.ts` ($vectorSearch), `memory/policy.ts`
*Built-by-us callout:* `memory/vectors.ts` ($vectorSearch), `memory/policy.ts`
(outcome-conditioned gate), `memory/store.ts`.
### 2:503:30 — The five-minute meeting, killed (Gemini Live API)
- Frame it: "Instead of breaking a teammate's focus to ask what they're up to,
you ask PodMan."
- Open the live voice conversation. Ask out loud: _"PodMan, what is everyone
working on, and where is the collision detector implemented?"_
you ask PodMan."
- Open the live voice conversation. Ask out loud: *"PodMan, what is everyone
working on, and where is the collision detector implemented?"*
- It answers with **real tool calls**`search_repo`, git history, current
collisions — not guesses.
collisions — not guesses.
- "This is the **Gemini Live API**, streaming speech-to-speech over LiveKit, with
custom function tools we wrote so it grounds every answer in the actual repo
and live state. That's the status sync, answered in seconds, with zero recovery
tax on anyone else."
custom function tools we wrote so it grounds every answer in the actual repo
and live state. That's the status sync, answered in seconds, with zero recovery
tax on anyone else."
_Built-by-us callout:_ `agents/podman-live-conversation/agent.py`.
*Built-by-us callout:* `agents/podman-live-conversation/agent.py`.
### 3:303:50 — Stack + close
- "All on **DigitalOcean** — static frontend, API, and agent workers, supervised
by systemd. The ambient score is **Gemini Lyria** generated per pod through the
Interactions API."
- Close: "Engineering ability stopped being the bottleneck — coordination is.
PodMan gives a whole team real-time awareness without the interruptions, catches
collisions before they cost an afternoon, and learns each team's dynamics so it
helps more over time. Saved focus, multiplied across every teammate. That's
continual learning, shipped."
by systemd. The ambient score is **Gemini Lyria** generated per pod through the
Interactions API."
- Close: "Engineering ability stopped being the bottleneck — coordination is, and
it only gets worse as agents start writing alongside us. PodMan gives a whole
team, humans and agents, real-time awareness without the interruptions, catches
collisions before they cost an afternoon, and learns each team's dynamics so it
helps more over time. Saved focus, multiplied across every actor. That's
continual learning, shipped."
### 3:504:00 — Buffer / Q&A handoff
---
## Sponsor-prize coverage (say each at least once)
| Prize | Spoken moment | Segment |
| ---------------- | -------------------------------------------------------------------------------- | ---------------------- |
| **Gemini** | Vision perception, Live API agent w/ tools, TTS voice, Lyria score | 0:30, 1:05, 2:50, 3:30 |
@@ -127,10 +194,14 @@ _Built-by-us callout:_ `agents/podman-live-conversation/agent.py`.
| **MongoDB** | "Atlas vector search recalling past events" | 1:50 |
| **DigitalOcean** | "all on DigitalOcean, systemd-supervised workers" | 3:30 |
---
## If something breaks (live recovery)
| Failure | Recovery |
| ----------------------- | ----------------------------------------------------------------------- |
| Voice doesn't fire | Cut to the card; say the line aloud; cards are the default path anyway. |
@@ -138,12 +209,16 @@ _Built-by-us callout:_ `agents/podman-live-conversation/agent.py`.
| Collision won't trigger | Use the backup recording for that beat; keep narrating. |
| Agent flapping | Pre-checked — but if so, `systemctl restart podman-platform-agent`. |
**Rule:** never debug on stage. Narrate, fall back to recording, keep moving.
---
## Tight timing summary
| Time | Beat |
| ---- | ---------------------------------------------------------- |
| 0:00 | Problem (coordination cost) + hook + original-work line |
+39 -1
View File
@@ -8,8 +8,10 @@
<title>PodMan — the teammate that sees what git cant</title>
<meta
name="description"
content="PodMan is an ambient AI teammate that watches your pod's screens in realtime and catches merge collisions before anyone pushes."
content="PodMan is an ambient AI teammate that watches your pod's screens in realtime and catches merge collisions before anyone pushes. Top 3 at the AI Engineer World's Fair 2026 Hackathon — built by Karti Tripathi, Ramis Hasanli, Yahya Alhinai, and Shakthi Bachala."
/>
<meta name="author" content="Karti Tripathi, Ramis Hasanli, Yahya Alhinai, Shakthi Bachala" />
<link rel="canonical" href="https://podman.live/" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="PodMan" />
@@ -31,6 +33,42 @@
/>
<meta name="twitter:image" content="https://www.podman.live/og.png" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "PodMan",
"url": "https://podman.live",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Web",
"description": "An ambient AI teammate that watches your pod's screens in realtime and catches merge collisions, duplicated work, and missed handoffs before anyone pushes.",
"award": "Top 3 — AI Engineer World's Fair 2026 Hackathon (2nd overall of 95+ teams, LiveKit track winner, DigitalOcean Best Use)",
"author": [
{
"@type": "Person",
"name": "Karti Tripathi",
"url": "https://karti.ai",
"sameAs": "https://www.linkedin.com/in/kartitripathi/"
},
{
"@type": "Person",
"name": "Ramis Hasanli",
"sameAs": "https://www.linkedin.com/in/hasanliramis/"
},
{
"@type": "Person",
"name": "Yahya Alhinai",
"sameAs": "https://www.linkedin.com/in/yhinai/"
},
{
"@type": "Person",
"name": "Shakthi Bachala",
"sameAs": "https://www.linkedin.com/in/shakthi-bachala-09401510a/"
}
]
}
</script>
<script>
// Tear down any service worker we shipped earlier (vite-plugin-pwa).
// PodMan runs no PWA in production: we deploy continuously and SW-driven
+1
View File
@@ -30,6 +30,7 @@
"react-day-picker": "^10.0.1",
"react-dom": "^19.2.7",
"react-resizable-panels": "^4.11.2",
"react-router-dom": "^7.18.1",
"recharts": "3.8.0",
"shadcn": "^4.12.0",
"sonner": "^2.0.7",
+63 -6
View File
@@ -1,7 +1,64 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<rect width="32" height="32" rx="7" fill="#0b0f17" />
<circle cx="25" cy="6.6" r="2.4" fill="#34d399" />
<text x="14.5" y="24.5" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
font-weight="700" font-size="24" fill="#34d399">P</text>
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc">
<title id="title">PodMan Logo Mark</title>
<desc id="desc">A minimal rounded robot head with glowing eyes and a blue-violet antenna orb, optimized for white backgrounds.</desc>
<defs>
<filter id="softShadow" x="44" y="90" width="424" height="360" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feDropShadow dx="0" dy="14" stdDeviation="20" flood-color="#94A3B8" flood-opacity="0.22"/>
<feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#C7D2FE" flood-opacity="0.20"/>
</filter>
<filter id="eyeGlow" x="138" y="234" width="236" height="96" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feColorMatrix in="blur" type="matrix" values="0 0 0 0 0.27 0 0 0 0 0.42 0 0 0 0 1 0 0 0 0.78 0" result="glow"/>
<feMerge>
<feMergeNode in="glow"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<linearGradient id="shell" x1="122" y1="144" x2="390" y2="420" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#FFFFFF"/>
<stop offset="0.56" stop-color="#F7FAFF"/>
<stop offset="1" stop-color="#EDF3FF"/>
</linearGradient>
<linearGradient id="face" x1="154" y1="220" x2="358" y2="334" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#050A1F"/>
<stop offset="0.48" stop-color="#081038"/>
<stop offset="1" stop-color="#10237A"/>
</linearGradient>
<linearGradient id="orb" x1="218" y1="38" x2="292" y2="113" gradientUnits="userSpaceOnUse">
<stop stop-color="#65D5FF"/>
<stop offset="0.46" stop-color="#6A65FF"/>
<stop offset="1" stop-color="#9A5CFF"/>
</linearGradient>
<radialGradient id="eye" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(256 280) rotate(90) scale(18)">
<stop offset="0" stop-color="#FFFFFF"/>
<stop offset="0.55" stop-color="#F6FBFF"/>
<stop offset="1" stop-color="#C8DDFF"/>
</radialGradient>
<linearGradient id="antenna" x1="256" y1="86" x2="256" y2="158" gradientUnits="userSpaceOnUse">
<stop stop-color="#4F63FF"/>
<stop offset="1" stop-color="#1E3A8A"/>
</linearGradient>
</defs>
<!-- transparent background; tuned to read clearly on white surfaces -->
<!-- Antenna -->
<rect x="250" y="87" width="12" height="82" rx="6" fill="url(#antenna)"/>
<circle cx="256" cy="70" r="31" fill="url(#orb)"/>
<circle cx="244" cy="56" r="9" fill="white" opacity="0.38"/>
<!-- Head shell -->
<g filter="url(#softShadow)">
<rect x="96" y="146" width="320" height="260" rx="92" fill="url(#shell)" stroke="#DDE6F3" stroke-width="2"/>
<rect x="104" y="154" width="304" height="244" rx="84" stroke="white" stroke-opacity="0.84" stroke-width="12"/>
</g>
<!-- Face visor -->
<g filter="url(#eyeGlow)">
<rect x="146" y="226" width="220" height="104" rx="46" fill="url(#face)"/>
<circle cx="202" cy="278" r="18" fill="url(#eye)"/>
<circle cx="310" cy="278" r="18" fill="url(#eye)"/>
<circle cx="202" cy="278" r="8" fill="white" opacity="0.96"/>
<circle cx="310" cy="278" r="8" fill="white" opacity="0.96"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 3.3 KiB

+64
View File
@@ -0,0 +1,64 @@
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc">
<title id="title">PodMan Logo Mark</title>
<desc id="desc">A minimal rounded robot head with glowing eyes and a blue-violet antenna orb, optimized for white backgrounds.</desc>
<defs>
<filter id="softShadow" x="44" y="90" width="424" height="360" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feDropShadow dx="0" dy="14" stdDeviation="20" flood-color="#94A3B8" flood-opacity="0.22"/>
<feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#C7D2FE" flood-opacity="0.20"/>
</filter>
<filter id="eyeGlow" x="138" y="234" width="236" height="96" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feColorMatrix in="blur" type="matrix" values="0 0 0 0 0.27 0 0 0 0 0.42 0 0 0 0 1 0 0 0 0.78 0" result="glow"/>
<feMerge>
<feMergeNode in="glow"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<linearGradient id="shell" x1="122" y1="144" x2="390" y2="420" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#FFFFFF"/>
<stop offset="0.56" stop-color="#F7FAFF"/>
<stop offset="1" stop-color="#EDF3FF"/>
</linearGradient>
<linearGradient id="face" x1="154" y1="220" x2="358" y2="334" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#050A1F"/>
<stop offset="0.48" stop-color="#081038"/>
<stop offset="1" stop-color="#10237A"/>
</linearGradient>
<linearGradient id="orb" x1="218" y1="38" x2="292" y2="113" gradientUnits="userSpaceOnUse">
<stop stop-color="#65D5FF"/>
<stop offset="0.46" stop-color="#6A65FF"/>
<stop offset="1" stop-color="#9A5CFF"/>
</linearGradient>
<radialGradient id="eye" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(256 280) rotate(90) scale(18)">
<stop offset="0" stop-color="#FFFFFF"/>
<stop offset="0.55" stop-color="#F6FBFF"/>
<stop offset="1" stop-color="#C8DDFF"/>
</radialGradient>
<linearGradient id="antenna" x1="256" y1="86" x2="256" y2="158" gradientUnits="userSpaceOnUse">
<stop stop-color="#4F63FF"/>
<stop offset="1" stop-color="#1E3A8A"/>
</linearGradient>
</defs>
<!-- transparent background; tuned to read clearly on white surfaces -->
<!-- Antenna -->
<rect x="250" y="87" width="12" height="82" rx="6" fill="url(#antenna)"/>
<circle cx="256" cy="70" r="31" fill="url(#orb)"/>
<circle cx="244" cy="56" r="9" fill="white" opacity="0.38"/>
<!-- Head shell -->
<g filter="url(#softShadow)">
<rect x="96" y="146" width="320" height="260" rx="92" fill="url(#shell)" stroke="#DDE6F3" stroke-width="2"/>
<rect x="104" y="154" width="304" height="244" rx="84" stroke="white" stroke-opacity="0.84" stroke-width="12"/>
</g>
<!-- Face visor -->
<g filter="url(#eyeGlow)">
<rect x="146" y="226" width="220" height="104" rx="46" fill="url(#face)"/>
<circle cx="202" cy="278" r="18" fill="url(#eye)"/>
<circle cx="310" cy="278" r="18" fill="url(#eye)"/>
<circle cx="202" cy="278" r="8" fill="white" opacity="0.96"/>
<circle cx="310" cy="278" r="8" fill="white" opacity="0.96"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

+15 -13
View File
@@ -9,11 +9,7 @@ import {
useUser,
} from '@clerk/react';
import type { Room } from 'livekit-client';
import {
AlertCircleIcon,
RefreshCwIcon,
SparklesIcon,
} from 'lucide-react';
import { AlertCircleIcon, RefreshCwIcon, SparklesIcon } from 'lucide-react';
import type { Pod, PodInput } from '@podman/shared';
import { joinPod } from './lib/pod.js';
import * as api from './lib/api.js';
@@ -342,9 +338,12 @@ export default function App() {
<header className="sticky top-0 z-10 -mx-4 border-b bg-background/86 px-4 pb-4 pt-2 backdrop-blur-xl sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div className="flex min-w-0 items-center gap-3">
<div className="grid size-10 place-items-center rounded-lg bg-primary text-sm font-semibold text-primary-foreground shadow-sm">
PM
</div>
<img
src="/podman-logo.svg"
alt=""
className="size-11 shrink-0 rounded-lg"
aria-hidden="true"
/>
<div className="min-w-0">
<h1 className="text-[1.95rem] font-semibold leading-none tracking-tight">PodMan</h1>
</div>
@@ -468,9 +467,12 @@ function AuthGate() {
<div className="mx-auto flex min-h-screen w-full max-w-[1120px] flex-col px-4 py-4 sm:px-6 lg:px-8">
<header className="flex items-center justify-between border-b pb-4 pt-2">
<div className="flex min-w-0 items-center gap-3">
<div className="grid size-10 place-items-center rounded-lg bg-primary text-sm font-semibold text-primary-foreground shadow-sm">
PM
</div>
<img
src="/podman-logo.svg"
alt=""
className="size-11 shrink-0 rounded-lg"
aria-hidden="true"
/>
<h1 className="text-[1.95rem] font-semibold leading-none tracking-tight">PodMan</h1>
</div>
<SignInButton mode="modal">
@@ -485,8 +487,8 @@ function AuthGate() {
Create your account to enter PodMan
</h2>
<p className="mt-3 text-base text-muted-foreground">
PodMan saves your context across pods so agents can learn from your work in every
room you join.
PodMan saves your context across pods so agents can learn from your work in every room
you join.
</p>
</section>
+307
View File
@@ -0,0 +1,307 @@
import { useCallback } from 'react';
import {
TrophyIcon,
ChevronDownIcon,
EyeIcon,
GitMergeIcon,
UsersIcon,
BellIcon,
RadioIcon,
DatabaseIcon,
SparklesIcon,
PlayIcon,
MicIcon,
} from 'lucide-react';
/**
* Public marketing landing page for podman.live.
* Rendered at "/" without ClerkProvider — needs no secrets.
* The app (private beta) lives at "/app".
*/
const TEAM = [
{ name: 'Karti Tripathi', url: 'https://www.linkedin.com/in/kartitripathi/' },
{ name: 'Ramis Hasanli', url: 'https://www.linkedin.com/in/hasanliramis/' },
{ name: 'Yahya Alhinai', url: 'https://www.linkedin.com/in/yhinai/' },
{ name: 'Shakthi Bachala', url: 'https://www.linkedin.com/in/shakthi-bachala-09401510a/' },
];
export function Landing() {
const scrollToStory = useCallback(() => {
document.getElementById('story')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, []);
return (
<div className="min-h-screen scroll-smooth bg-[#0b0f17] text-white/90 antialiased">
{/* ambient glows */}
<div className="pointer-events-none fixed inset-0 overflow-hidden">
<div className="absolute -top-40 left-1/2 h-[38rem] w-[38rem] -translate-x-1/2 rounded-full bg-indigo-600/20 blur-[120px]" />
<div className="absolute top-1/3 -right-32 h-[26rem] w-[26rem] rounded-full bg-cyan-500/10 blur-[110px]" />
</div>
{/* top nav */}
<header className="relative z-20 mx-auto flex max-w-6xl items-center justify-between px-6 py-5">
<a href="#top" className="flex items-center gap-2.5">
<img src="/podman-logo.svg" alt="PodMan" className="h-7 w-7" />
<span className="text-[15px] font-semibold tracking-tight text-white">PodMan</span>
</a>
<span className="inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/5 px-4 py-1.5 text-sm font-medium text-white/70">
<LiveDot />
Beta soon
</span>
</header>
{/* hero */}
<section id="top" className="relative z-10 mx-auto flex max-w-3xl flex-col items-center px-6 pt-16 pb-24 text-center sm:pt-24">
<button
onClick={scrollToStory}
className="group mb-8 inline-flex items-center gap-2 rounded-full border border-amber-300/30 bg-gradient-to-r from-amber-400/15 to-amber-200/5 px-4 py-1.5 text-sm font-medium text-amber-200 transition-colors hover:border-amber-300/50"
>
<TrophyIcon className="size-4" />
Top 3 AI Engineer World&apos;s Fair Hackathon 2026
<ChevronDownIcon className="size-4 transition-transform group-hover:translate-y-0.5" />
</button>
<h1 className="text-5xl font-semibold leading-[1.05] tracking-tight text-white sm:text-7xl">
PodMan
</h1>
<p className="mt-5 bg-gradient-to-r from-indigo-300 via-sky-300 to-cyan-200 bg-clip-text text-2xl font-medium text-transparent sm:text-3xl">
The teammate that sees what git can&apos;t.
</p>
<p className="mx-auto mt-6 max-w-xl text-base leading-relaxed text-white/60 sm:text-lg">
An ambient AI teammate that watches your pod&apos;s screens in realtime catching merge
collisions, duplicated work, and missed handoffs before anyone pushes.
</p>
{/* award chips */}
<div className="mt-9 flex flex-wrap items-center justify-center gap-2.5">
{[
{ label: '2nd Overall · 95+ teams', accent: 'text-amber-200 border-amber-300/25 bg-amber-400/10' },
{ label: 'LiveKit Track — Winner', accent: 'text-sky-200 border-sky-300/25 bg-sky-400/10' },
{ label: 'DigitalOcean — Best Use', accent: 'text-cyan-200 border-cyan-300/25 bg-cyan-400/10' },
].map((c) => (
<span
key={c.label}
className={`rounded-full border px-3.5 py-1.5 text-[13px] font-medium ${c.accent}`}
>
{c.label}
</span>
))}
</div>
{/* CTAs */}
<div className="mt-10 flex flex-col items-center gap-3 sm:flex-row">
<button
onClick={scrollToStory}
className="inline-flex h-11 items-center justify-center gap-2 rounded-full bg-gradient-to-r from-indigo-500 to-cyan-400 px-7 text-sm font-semibold text-[#0b0f17] shadow-lg shadow-indigo-500/20 transition-transform hover:scale-[1.02]"
>
Read the story <ChevronDownIcon className="size-4" />
</button>
<BetaPill />
</div>
<button
onClick={scrollToStory}
aria-label="Scroll to read"
className="mt-20 animate-bounce text-white/40 transition-colors hover:text-white/70"
>
<ChevronDownIcon className="size-7" />
</button>
</section>
{/* story */}
<Section id="story" eyebrow="How it happened" title="Built on stage, in about 24 hours.">
<div className="space-y-5 text-[15px] leading-relaxed text-white/70">
<p>
PodMan was built at the{' '}
<span className="text-white">AI Engineer World&apos;s Fair 2026 Hackathon</span> (June
2728) against 95+ teams. It took{' '}
<span className="text-amber-200">2nd place overall</span>, and won both the{' '}
<span className="text-sky-200">LiveKit</span> track and{' '}
<span className="text-cyan-200">DigitalOcean&apos;s Best Use</span> award.
</p>
<p>
We shipped the live demo in a single sprint a LiveKit room, Gemini watching the
screen-share, and a voice that speaks up the moment two engineers drift toward the same
code. There wasn&apos;t time on the clock to give it a proper home.
</p>
<p className="text-white/90">
So this is that home and we&apos;re actively building PodMan out from the hackathon
prototype into something a team can actually run every day.
</p>
</div>
</Section>
{/* what it does */}
<Section id="what" eyebrow="What it does" title="A teammate in the room, not another dashboard.">
<div className="grid gap-4 sm:grid-cols-2">
<Feature
icon={<EyeIcon className="size-5" />}
title="Ambient awareness"
body="Joins your pod's LiveKit room and samples every screen-share in realtime — no bots to invoke, no commands to remember."
/>
<Feature
icon={<GitMergeIcon className="size-5" />}
title="Merge-collision radar"
body="Recognizes when two people are converging on the same files or feature and warns them before the conflict ever reaches a push."
/>
<Feature
icon={<UsersIcon className="size-5" />}
title="Duplicated-work detection"
body="Notices when effort overlaps across the team and surfaces it early, so two engineers don't quietly build the same thing."
/>
<Feature
icon={<BellIcon className="size-5" />}
title="Handoff nudges"
body="Speaks up about missed handoffs and stalled threads — and learns which nudges actually helped, so it stays useful, not noisy."
/>
</div>
</Section>
{/* how it works */}
<Section id="how" eyebrow="Under the hood" title="Realtime vision, memory, and a voice.">
<div className="grid gap-4 sm:grid-cols-3">
<Stack icon={<RadioIcon className="size-5" />} name="LiveKit" note="Realtime transport for the shared room and voice delivery." />
<Stack icon={<SparklesIcon className="size-5" />} name="Gemini" note="Vision + event detection + the live voice that nudges the team." />
<Stack icon={<DatabaseIcon className="size-5" />} name="MongoDB" note="Engineer state, ownership map, events, and which nudges landed." />
</div>
<div className="mt-6 flex flex-wrap gap-2 text-[13px] text-white/50">
{['LiveKit', 'Gemini Live', 'MongoDB Atlas', 'Voyage embeddings', 'Modular MAX', 'Hermes ops'].map((t) => (
<span key={t} className="rounded-md border border-white/10 bg-white/[0.03] px-2.5 py-1">
{t}
</span>
))}
</div>
</Section>
{/* demo */}
<Section id="demo" eyebrow="See it" title="The 60-second demo.">
<div className="overflow-hidden rounded-2xl border border-white/10 bg-black/40 shadow-2xl">
<div className="relative w-full" style={{ paddingBottom: '56.25%' }}>
<iframe
className="absolute inset-0 h-full w-full"
src="https://www.youtube-nocookie.com/embed/bWJIsIWTgr0"
title="PodMan demo"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
/>
</div>
</div>
<div className="mt-4 flex items-center gap-2 text-sm text-white/40">
<PlayIcon className="size-4" /> Watch the pod get its warning before the collision.
</div>
</Section>
{/* built by / team */}
<Section id="team" eyebrow="Built by" title="The team behind PodMan.">
<div className="flex flex-wrap gap-3">
{TEAM.map((p) => (
<a
key={p.name}
href={p.url}
target="_blank"
rel="noopener noreferrer"
className="rounded-full border border-white/10 bg-white/[0.03] px-4 py-2 text-[15px] font-medium text-white/80 transition-colors hover:border-cyan-300/40 hover:text-white"
>
{p.name}
</a>
))}
</div>
</Section>
{/* final CTA — beta coming soon */}
<section className="relative z-10 mx-auto max-w-3xl px-6 py-24 text-center">
<div className="rounded-3xl border border-white/10 bg-gradient-to-b from-white/[0.06] to-transparent px-8 py-14">
<MicIcon className="mx-auto size-8 text-cyan-300" />
<h2 className="mt-5 text-3xl font-semibold tracking-tight text-white sm:text-4xl">
The private beta is coming soon.
</h2>
<p className="mx-auto mt-4 max-w-md text-[15px] leading-relaxed text-white/60">
We&apos;re building PodMan out from the hackathon prototype into something a team runs
every day. The private beta opens soon.
</p>
<div className="mt-8 flex justify-center">
<BetaPill className="px-6 py-3 text-[15px]" />
</div>
</div>
</section>
{/* footer */}
<footer className="relative z-10 border-t border-white/10">
<div className="mx-auto flex max-w-6xl flex-col items-center justify-between gap-3 px-6 py-8 text-sm text-white/40 sm:flex-row">
<div className="flex items-center gap-2">
<img src="/podman-logo.svg" alt="" className="h-5 w-5 opacity-70" />
<span>PodMan · podman.live</span>
</div>
<span>Built at AI Engineer World&apos;s Fair 2026 · 2nd Overall</span>
</div>
</footer>
</div>
);
}
function LiveDot() {
return (
<span className="relative flex size-1.5">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-cyan-400/70" />
<span className="relative inline-flex size-1.5 rounded-full bg-cyan-400" />
</span>
);
}
function BetaPill({ className = '' }: { className?: string }) {
return (
<span
className={`inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/5 px-5 py-2.5 text-sm font-medium text-white/70 ${className}`}
>
<LiveDot />
Private beta coming soon
</span>
);
}
function Section({
id,
eyebrow,
title,
children,
}: {
id: string;
eyebrow: string;
title: string;
children: React.ReactNode;
}) {
return (
<section id={id} className="relative z-10 border-t border-white/[0.06] py-20">
<div className="mx-auto max-w-3xl px-6">
<p className="text-sm font-medium tracking-wide text-cyan-300/80 uppercase">{eyebrow}</p>
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-white sm:text-4xl">{title}</h2>
<div className="mt-8">{children}</div>
</div>
</section>
);
}
function Feature({ icon, title, body }: { icon: React.ReactNode; title: string; body: string }) {
return (
<div className="rounded-2xl border border-white/10 bg-white/[0.03] p-6 transition-colors hover:border-white/20">
<div className="flex size-10 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-500/20 to-cyan-400/20 text-cyan-200">
{icon}
</div>
<h3 className="mt-4 text-lg font-semibold text-white">{title}</h3>
<p className="mt-2 text-[14px] leading-relaxed text-white/60">{body}</p>
</div>
);
}
function Stack({ icon, name, note }: { icon: React.ReactNode; name: string; note: string }) {
return (
<div className="rounded-2xl border border-white/10 bg-white/[0.03] p-6">
<div className="flex items-center gap-2.5 text-white">
<span className="text-cyan-200">{icon}</span>
<span className="text-base font-semibold">{name}</span>
</div>
<p className="mt-3 text-[14px] leading-relaxed text-white/60">{note}</p>
</div>
);
}
+36 -7
View File
@@ -1,24 +1,53 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { ClerkProvider } from '@clerk/react';
import { shadcn } from '@clerk/ui/themes';
import App from './App.js';
import { Landing } from './Landing.js';
import './index.css';
import '@clerk/ui/themes/shadcn.css';
import { TooltipProvider } from '@/components/ui/tooltip';
const clerkPublishableKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;
const hasClerk = typeof clerkPublishableKey === 'string' && clerkPublishableKey.startsWith('pk_');
if (!clerkPublishableKey) {
throw new Error('Missing VITE_CLERK_PUBLISHABLE_KEY');
}
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ClerkProvider publishableKey={clerkPublishableKey} appearance={{ theme: shadcn }}>
function AppRoute() {
if (!hasClerk) {
// Secrets not provisioned yet — show a graceful placeholder instead of crashing.
return (
<div className="flex min-h-screen flex-col items-center justify-center gap-3 bg-[#0b0f17] px-6 text-center text-white/80">
<img src="/podman-logo.svg" alt="PodMan" className="h-10 w-10" />
<h1 className="text-xl font-semibold text-white">PodMan is deploying</h1>
<p className="max-w-sm text-sm text-white/50">
The live app is being provisioned. Check back shortly.
</p>
<a href="/" className="mt-2 text-sm text-cyan-300 hover:underline">
Back to home
</a>
</div>
);
}
return (
<ClerkProvider
publishableKey={clerkPublishableKey}
appearance={{ theme: shadcn }}
afterSignOutUrl="/"
>
<TooltipProvider>
<App />
</TooltipProvider>
</ClerkProvider>
);
}
createRoot(document.getElementById('root')!).render(
<StrictMode>
<BrowserRouter>
<Routes>
<Route path="/" element={<Landing />} />
<Route path="/app/*" element={<AppRoute />} />
</Routes>
</BrowserRouter>
</StrictMode>,
);
+45
View File
@@ -154,6 +154,9 @@ importers:
react-resizable-panels:
specifier: ^4.11.2
version: 4.11.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react-router-dom:
specifier: ^7.18.1
version: 7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
recharts:
specifier: 3.8.0
version: 3.8.0(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@19.2.7)(react@19.2.7)(redux@5.0.1)
@@ -3838,6 +3841,10 @@ packages:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'}
cookie@1.1.1:
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
engines: {node: '>=18'}
copy-to-clipboard@3.3.3:
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
@@ -5784,6 +5791,23 @@ packages:
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
react-router-dom@7.18.1:
resolution: {integrity: sha512-KaZh+X/6UtEp28x51AUYZDMg9NGoz2ja3dNHa+ta/tk40vCzKhQ/RypCWBMLbmDr6//E24Vv5uPsrqXFozdkAg==}
engines: {node: '>=20.0.0'}
peerDependencies:
react: '>=18'
react-dom: '>=18'
react-router@7.18.1:
resolution: {integrity: sha512-GDLgg3i3uM0aeJO3Fm+TCS+sDQ7gu12T6x0qdTEzcwqEfleci7JwugVNIF3U//0FWKnJT7ptG+20B2jfDqnZAg==}
engines: {node: '>=20.0.0'}
peerDependencies:
react: '>=18'
react-dom: '>=18'
peerDependenciesMeta:
react-dom:
optional: true
react-style-singleton@2.2.3:
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
engines: {node: '>=10'}
@@ -5987,6 +6011,9 @@ packages:
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
set-cookie-parser@2.7.2:
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -10670,6 +10697,8 @@ snapshots:
cookie@0.7.2: {}
cookie@1.1.1: {}
copy-to-clipboard@3.3.3:
dependencies:
toggle-selection: 1.0.6
@@ -12806,6 +12835,20 @@ snapshots:
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
react-router-dom@7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
dependencies:
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
react-router: 7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react-router@7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
dependencies:
cookie: 1.1.1
react: 19.2.7
set-cookie-parser: 2.7.2
optionalDependencies:
react-dom: 19.2.7(react@19.2.7)
react-style-singleton@2.2.3(@types/react@19.2.17)(react@19.2.7):
dependencies:
get-nonce: 1.0.1
@@ -13104,6 +13147,8 @@ snapshots:
set-blocking@2.0.0: {}
set-cookie-parser@2.7.2: {}
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4