# Project export: POKE ULTRA UNIVERSE

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2026
- Tagline: giving Poke an identity
- Devpost: https://devpost.com/software/poke-ultra-universe
- GitHub: https://github.com/dourian/POKE-ULTRA-UNIVERSE
- Demo: https://poke-ultra-universe-3xqm.vercel.app/
- Video: https://www.youtube.com/embed/rOFSG4O1E-I?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 5 GitHub contributor(s) — dorian (34 commits), Jasmine Jiang (12 commits), Claude Opus 4.6 (11 commits), Jesse Huang (11 commits), reebxu459 (4 commits)

## Devpost submission (written by the team)

### Inspiration

Poke dramatically simplifies our life, but the experience is very isolating. My Poke agent doesn’t recognize or care that other people also have agents, so it only interacts with humans and treats everything else as external. When we want to give Poke a new skill, we have to go through the setup process of setting up the MCP, and then adding it as a custom integration to Poke each time. But, what if there was a better way? A way where Poke agents can be identified across services, and a marketplace to opt-into Poke optimized applications and exist in a world with other Poke agents? We have a vision where we can claim a username, and then it gives us access to: Facebook for all Poke users where people can have a profile and be discovered by other Poke users. Facebook for all Poke users where people can have a profile and be discovered by other Poke users. Splitwise for all Poke users where people can split expenses with other Poke users Splitwise for all Poke users where people can split expenses with other Poke users No more appstore, no more different social media accounts. Everything is under your Poke identity and everything is done through Poke.

### What it does

We've built the identity layer for Poke. It allows users to claim unique usernames and use any Poke applications under that identity with minimal setup (hardest part is copy-and-pasting)! For application developers, we’ve derived a standard protocol to easily create apps for our market place, becoming instantly available to any Poke agent that uses POKE ULTRA UNIVERSE. Use case 1 Imagine I’m a new user on Poke. What is the first thing I want to do? I want to know who else is using Poke. There is no good way to do that. I could post on social media? Ask my friends? Maybe. With the identity layer, this becomes insanely simple. We claim a username on POKE ULTRA UNIVERSE, opt into Faceduotang (Canadian version of facebook, Poke native app), and we can instantly be connected to everyone else who is using Faceduotang. Use case 2 Imagine I just paid the bill for 5 people, and we want to split it. If we want to split the bill, we need to be all connected on the same service. It's annoying, and it changes for every group. With POKE ULTRA UNIVERSE, we can simply opt-into the Splitwiser application, and it will allow me to manage funds with any other Poke users who have also opted in. This is all done under the same identity.

### Challenges we ran into

Poke stands out for their commitment on user privacy, which became a challenge when our premise was to build a platform for interconnectivity and simply sharing your information with others (assuming consent!). As such, we focused on making the whole sharing model opt-in only, so information will only be shared if given explicit permission by the user.

### What we learned

We wanted to build this project because we all saw a vision with what Poke could do with our personal lives. Building something you have passion for made this worth beyond just a project and is something we will strive for in all future hackathons.

### What's next

for us Poke has strong measures against leaking information, so we want to focus on security refinement because of our use case. For example, with an admin-level authorization, we can control which extensions get approved onto the marketplace to ensure users only use legitimate apps. We believe the POKE ULTRA UNIVERSE is the grand step towards interconnectivity for both Poke and the world of communication, and it all starts with simplifying our lives.

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 65 recognized source files, 230 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- Next.js (technology) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Supabase (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Vercel (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (120 of 257)

```
.gitignore
earth/.gitignore
earth/frontend/.gitignore
earth/frontend/components.json
earth/frontend/eslint.config.mjs
earth/frontend/next.config.ts
earth/frontend/package.json
earth/frontend/postcss.config.mjs
earth/frontend/public/frames-hands/frame_0001.txt
earth/frontend/public/frames-hands/frame_0002.txt
earth/frontend/public/frames-hands/frame_0003.txt
earth/frontend/public/frames-hands/frame_0004.txt
earth/frontend/public/frames-hands/frame_0005.txt
earth/frontend/public/frames-hands/frame_0006.txt
earth/frontend/public/frames-hands/frame_0007.txt
earth/frontend/public/frames-hands/frame_0008.txt
earth/frontend/public/frames-hands/frame_0009.txt
earth/frontend/public/frames-hands/frame_0010.txt
earth/frontend/public/frames-hands/frame_0011.txt
earth/frontend/public/frames-hands/frame_0012.txt
earth/frontend/public/frames-hands/frame_0013.txt
earth/frontend/public/frames-hands/frame_0014.txt
earth/frontend/public/frames-hands/frame_0015.txt
earth/frontend/public/frames-hands/frame_0016.txt
earth/frontend/public/frames-hands/frame_0017.txt
earth/frontend/public/frames-hands/frame_0018.txt
earth/frontend/public/frames-hands/frame_0019.txt
earth/frontend/public/frames-hands/frame_0020.txt
earth/frontend/public/frames-hands/frame_0021.txt
earth/frontend/public/frames-hands/frame_0022.txt
earth/frontend/public/frames-hands/frame_0023.txt
earth/frontend/public/frames-hands/frame_0024.txt
earth/frontend/public/frames-hands/frame_0025.txt
earth/frontend/public/frames-hands/frame_0026.txt
earth/frontend/public/frames-hands/frame_0027.txt
earth/frontend/public/frames-hands/frame_0028.txt
earth/frontend/public/frames-hands/frame_0029.txt
earth/frontend/public/frames-hands/frame_0030.txt
earth/frontend/public/frames-hands/frame_0031.txt
earth/frontend/public/frames-hands/frame_0032.txt
earth/frontend/public/frames-hands/frame_0033.txt
earth/frontend/public/frames-hands/frame_0034.txt
earth/frontend/public/frames-hands/frame_0035.txt
earth/frontend/public/frames-hands/frame_0036.txt
earth/frontend/public/frames-hands/frame_0037.txt
earth/frontend/public/frames-hands/frame_0038.txt
earth/frontend/public/frames-hands/frame_0039.txt
earth/frontend/public/frames-hands/frame_0040.txt
earth/frontend/public/frames-hands/frame_0041.txt
earth/frontend/public/frames-hands/frame_0042.txt
earth/frontend/public/frames-hands/frame_0043.txt
earth/frontend/public/frames-hands/frame_0044.txt
earth/frontend/public/frames-hands/frame_0045.txt
earth/frontend/public/frames-hands/frame_0046.txt
earth/frontend/public/frames-hands/frame_0047.txt
earth/frontend/public/frames-hands/frame_0048.txt
earth/frontend/public/frames-hands/frame_0049.txt
earth/frontend/public/frames-hands/frame_0050.txt
earth/frontend/public/frames-hands/frame_0051.txt
earth/frontend/public/frames-hands/frame_0052.txt
earth/frontend/public/frames-hands/frame_0053.txt
earth/frontend/public/frames-hands/frame_0054.txt
earth/frontend/public/frames-hands/frame_0055.txt
earth/frontend/public/frames-hands/frame_0056.txt
earth/frontend/public/frames-hands/frame_0057.txt
earth/frontend/public/frames-hands/frame_0058.txt
earth/frontend/public/frames-hands/frame_0059.txt
earth/frontend/public/frames-hands/frame_0060.txt
earth/frontend/public/frames-hands/frame_0061.txt
earth/frontend/public/frames-hands/frame_0062.txt
earth/frontend/public/frames-hands/frame_0063.txt
earth/frontend/public/frames-hands/frame_0064.txt
earth/frontend/public/frames-hands/frame_0065.txt
earth/frontend/public/frames-hands/frame_0066.txt
earth/frontend/public/frames-hands/frame_0067.txt
earth/frontend/public/frames-hands/frame_0068.txt
earth/frontend/public/frames-hands/frame_0069.txt
earth/frontend/public/frames-hands/frame_0070.txt
earth/frontend/public/frames-hands/frame_0071.txt
earth/frontend/public/frames-hands/frame_0072.txt
earth/frontend/public/frames-hands/frame_0073.txt
earth/frontend/public/frames-hands/frame_0074.txt
earth/frontend/public/frames-hands/frame_0075.txt
earth/frontend/public/frames-hands/frame_0076.txt
earth/frontend/public/frames-hands/frame_0077.txt
earth/frontend/public/frames-hands/frame_0078.txt
earth/frontend/public/frames-hands/frame_0079.txt
earth/frontend/public/frames-hands/frame_0080.txt
earth/frontend/public/frames-hands/frame_0081.txt
earth/frontend/public/frames-hands/frame_0082.txt
earth/frontend/public/frames-hands/frame_0083.txt
earth/frontend/public/frames-hands/frame_0084.txt
earth/frontend/public/frames-hands/frame_0085.txt
earth/frontend/public/frames-hands/frame_0086.txt
earth/frontend/public/frames-hands/frame_0087.txt
earth/frontend/public/frames-hands/frame_0088.txt
earth/frontend/public/frames-hands/frame_0089.txt
earth/frontend/public/frames-hands/frame_0090.txt
earth/frontend/public/frames-hands/frame_0091.txt
earth/frontend/public/frames-hands/frame_0092.txt
earth/frontend/public/frames-hands/frame_0093.txt
earth/frontend/public/frames-hands/frame_0094.txt
earth/frontend/public/frames-hands/frame_0095.txt
earth/frontend/public/frames-hands/frame_0096.txt
earth/frontend/public/frames-hands/frame_0097.txt
earth/frontend/public/frames-hands/frame_0098.txt
earth/frontend/public/frames-hands/frame_0099.txt
earth/frontend/public/frames-hands/frame_0100.txt
earth/frontend/public/frames-hands/frame_0101.txt
earth/frontend/public/frames-hands/frame_0102.txt
earth/frontend/public/frames-hands/frame_0103.txt
earth/frontend/public/frames-hands/frame_0104.txt
earth/frontend/public/frames-hands/frame_0105.txt
earth/frontend/public/frames-hands/frame_0106.txt
earth/frontend/public/frames-hands/frame_0107.txt
earth/frontend/public/frames-hands/frame_0108.txt
earth/frontend/public/frames-hands/frame_0109.txt
earth/frontend/public/frames-hands/frame_0110.txt
earth/frontend/public/frames-hands/frame_0111.txt
earth/frontend/public/frames-hands/frame_0112.txt
[137 more files omitted for size]
```

### Dependencies

- earth/frontend/package.json: @tailwindcss/postcss@^4, @types/node@^20, @types/react@^19, @types/react-dom@^19, class-variance-authority@^0.7.1, clsx@^2.1.1, eslint@^9, eslint-config-next@16.1.6, lucide-react@^0.564.0, next@16.1.6, radix-ui@^1.4.3, react@19.2.3, react-dom@19.2.3, shadcn@^3.8.4, tailwind-merge@^3.4.0, tailwindcss@^4, tw-animate-css@^1.4.0, typescript@^5
- earth/mcp/package.json: @modelcontextprotocol/sdk@^1.0.0, @supabase/supabase-js@^2.95.3, @types/cors@^2.8.19, @types/express@^4.17.0, @types/node@^20.0.0, cors@^2.8.6, dotenv@^16.0.0, express@^4.18.0, ts-node-dev@^2.0.0, typescript@^5.4.0, zod@^4.3.6
- faceduotang/package.json: @supabase/supabase-js@^2.95.3, @types/express@^4.17.0, @types/node@^20.0.0, dotenv@^16.0.0, express@^4.18.0, ts-node-dev@^2.0.0, typescript@^5.4.0
- firewood/package.json: @supabase/supabase-js@^2.95.3, @types/body-parser@^1.19.6, @types/cors@^2.8.0, @types/express@^4.17.0, @types/http-errors@^2.0.5, @types/node@^20.0.0, @types/qs@^6.14.0, @types/range-parser@^1.2.7, @types/send@^1.2.1, cors@^2.8.5, dotenv@^16.0.0, express@^4.18.0, ts-node-dev@^2.0.0, typescript@^5.4.0
- secretsanta/package.json: @supabase/supabase-js@^2.95.3, @types/body-parser@^1.19.6, @types/cors@^2.8.0, @types/express@^4.17.0, @types/http-errors@^2.0.5, @types/node@^20.0.0, @types/qs@^6.14.0, @types/range-parser@^1.2.7, @types/send@^1.2.1, cors@^2.8.5, dotenv@^16.0.0, express@^4.18.0, ts-node-dev@^2.0.0, typescript@^5.4.0
- splitwiser/package.json: @supabase/supabase-js@^2.95.3, @types/cors@^2.8.0, @types/express@^4.17.0, @types/node@^20.0.0, cors@^2.8.5, dotenv@^16.0.0, express@^4.18.0, ts-node-dev@^2.0.0, typescript@^5.4.0

### Recent commits (newest first)

- Update README.md
- extensions
- Update README.md
- fix
- extension guide nit
- Update MarketplacePage.tsx
- Update MarketplacePage.tsx
- Update mcp.ts
- fix
- Update MarketplacePage.tsx
- fix
- Merge branch 'main' of https://github.com/dourian/POKE-ULTRA-UNIVERSE
- update
- Apply gradient colors to logo and set as favicon
- Update wizard integration step copy and remove View all link
- Update README.md
- Update marketplace button to "Add" and iMessage to authorize format
- Merge branch 'main' of https://github.com/dourian/POKE-ULTRA-UNIVERSE
- Update README.md
- everything

## Key source files (fetched from GitHub, selected and truncated for size)

### EXTENSION_GUIDE.md

```markdown
# Building a POKE Universe Extension

This guide covers everything you need to build an app that integrates with POKE Universe. Once registered, POKE Universe users can connect to your app and their AI agents can call your app's actions through the POKE Universe MCP.

---

## How It Works

POKE Universe is a universal identity layer for AI agents. Every user has a POKE Universe `@username`. When a user connects their AI client (e.g. Claude Desktop) to the POKE Universe MCP server, their agent can:

1. Discover your app via `list_apps`
2. Grant your app access via `connect_app`
3. Execute actions on your app via `use_app`

When an agent calls `use_app`, POKE Universe:
- Verifies the agent's identity via their Bearer token
- Confirms the user has granted your app access
- Forwards the request to your app's `/poke_ultra_universe/execute` endpoint with the verified `agent_username`

**Your app trusts `agent_username` — POKE Universe has already verified it.**

---

## Required Endpoints

Your app must expose four endpoints under the `/poke_ultra_universe` prefix.

### `GET /poke_ultra_universe/info`

Returns metadata about your app. POKE Universe fetches this when you register.

```json
{
  "app_id": "your-app",
  "title": "Your App",
  "description": "What your app does",
  "version": "1.0.0",
  "author": "You",
  "homepage_url": "https://your-app.com"
}
```

| Field | Type | Required |
|---|---|---|
| `app_id` | string | yes — machine-readable, lowercase, unique (e.g. `"splitwiser"`) |
| `title` | string | yes — display name |
| `description` | string | yes |
| `version` | string | yes — semver |
| `author` | string | no |
| `icon_url` | string | no |
| `homepage_url` | string | no |

---

### `GET /poke_ultra_universe/health`

Returns operational status.

```json
{ "status": "ok" }
```

`status` must be one of: `"ok"`, `"degraded"`, `"down"`.

---

### `GET /poke_ultra_universe/capabilities`

Returns the list of actions your app supports. The agent reads this to know what to call.

```json
[
  {
    "name": "split_expense",
    "description": "Split an expense between a group of POKE Universe users.",
    "parameters": [
      { "name": "amount", "type": "number", "description": "Total in dollars", "required": true },
      { "name": "split_between", "type": "array", "description": "Array of POKE Universe @usernames", "required": true },
      { "name": "description", "type": "string", "description": "What the expense was for", "required": false }
    ],
    "returns": "The created expense records and what each person owes"
  }
]
```

Parameter `type` must be one of: `"string"`, `"number"`, `"boolean"`, `"object"`, `"array"`.

---

### `POST /poke_ultra_universe/execute`

Executes an action. Called by POKE on behalf of the agent.

**Request body:**
```json
{
  "action": "split_expense",
  "parameters": { "amount": 10, "split_between": ["@dorian", "@reebneeb"] },
  "agent_username": "@dorian"
}
```

**Success response:**
```json
{ "success": true, 
[truncated — 3779 more characters]
```

### earth/mcp/usage_examples/SPLIT.MD

```markdown
so for example, if i want an expense splitting app:

a 3rd party builds that app using our protocol

now, a user goes on the marketplace and opt in

now, when @jesse says to the agent to split $10 with @rebecca, we can forward the request to the splitwise with that username, and then splitwise handles the logic for managing the split

then, when rebecca asks her agent how much she owes, it knows that they owe @jesse

there is definitely needs to be some more security involved, but we can keep it open for now

```

### faceduotang/package.json

```
{
  "name": "faceduotang",
  "version": "0.0.1",
  "private": true,
  "main": "dist/index.js",
  "scripts": {
    "dev": "ts-node-dev --respawn src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@supabase/supabase-js": "^2.95.3",
    "dotenv": "^16.0.0",
    "express": "^4.18.0"
  },
  "devDependencies": {
    "@types/express": "^4.17.0",
    "@types/node": "^20.0.0",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.4.0"
  }
}

```

### splitwiser/package.json

```
{
  "name": "splitwiser",
  "version": "1.0.0",
  "private": true,
  "main": "dist/index.js",
  "scripts": {
    "dev": "ts-node-dev --respawn src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@supabase/supabase-js": "^2.95.3",
    "cors": "^2.8.5",
    "dotenv": "^16.0.0",
    "express": "^4.18.0"
  },
  "devDependencies": {
    "@types/cors": "^2.8.0",
    "@types/express": "^4.17.0",
    "@types/node": "^20.0.0",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.4.0"
  }
}

```

### firewood/package.json

```
{
  "name": "firewood",
  "version": "1.0.0",
  "private": true,
  "main": "dist/index.js",
  "scripts": {
    "dev": "ts-node-dev --respawn src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@supabase/supabase-js": "^2.95.3",
    "cors": "^2.8.5",
    "dotenv": "^16.0.0",
    "express": "^4.18.0"
  },
  "devDependencies": {
    "@types/body-parser": "^1.19.6",
    "@types/cors": "^2.8.0",
    "@types/express": "^4.17.0",
    "@types/http-errors": "^2.0.5",
    "@types/node": "^20.0.0",
    "@types/qs": "^6.14.0",
    "@types/range-parser": "^1.2.7",
    "@types/send": "^1.2.1",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.4.0"
  }
}

```

### secretsanta/package.json

```
{
  "name": "secretsanta",
  "version": "1.0.0",
  "private": true,
  "main": "dist/index.js",
  "scripts": {
    "dev": "ts-node-dev --respawn src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@supabase/supabase-js": "^2.95.3",
    "cors": "^2.8.5",
    "dotenv": "^16.0.0",
    "express": "^4.18.0"
  },
  "devDependencies": {
    "@types/body-parser": "^1.19.6",
    "@types/cors": "^2.8.0",
    "@types/express": "^4.17.0",
    "@types/http-errors": "^2.0.5",
    "@types/node": "^20.0.0",
    "@types/qs": "^6.14.0",
    "@types/range-parser": "^1.2.7",
    "@types/send": "^1.2.1",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.4.0"
  }
}

```

### earth/mcp/package.json

```
{
  "name": "poke-mcp-service",
  "version": "0.0.1",
  "private": true,
  "main": "dist/index.js",
  "scripts": {
    "dev": "ts-node-dev --respawn src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "@supabase/supabase-js": "^2.95.3",
    "@types/cors": "^2.8.19",
    "cors": "^2.8.6",
    "dotenv": "^16.0.0",
    "express": "^4.18.0",
    "zod": "^4.3.6"
  },
  "devDependencies": {
    "@types/express": "^4.17.0",
    "@types/node": "^20.0.0",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.4.0"
  }
}

```

### earth/frontend/package.json

```
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint"
  },
  "dependencies": {
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "lucide-react": "^0.564.0",
    "next": "16.1.6",
    "radix-ui": "^1.4.3",
    "react": "19.2.3",
    "react-dom": "19.2.3",
    "tailwind-merge": "^3.4.0"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "16.1.6",
    "shadcn": "^3.8.4",
    "tailwindcss": "^4",
    "tw-animate-css": "^1.4.0",
    "typescript": "^5"
  }
}

```

### faceduotang/src/index.ts

```typescript
import "dotenv/config";
import { createServer } from "./server";

const PORT = Number(process.env.PORT) || 3002;

const app = createServer();

app.listen(PORT, () => {
  console.log(`Faceduotang running on port ${PORT}`);
});

```

### firewood/src/index.ts

```typescript
import "dotenv/config";
import express from "express";
import cors from "cors";
import { pokeRouter } from "./routes/poke";

const PORT = Number(process.env.PORT) || 3002;

const app = express();
app.use(cors());
app.use(express.json());

app.get("/health", (_req, res) => res.json({ status: "ok" }));
app.use("/poke_ultra_universe", pokeRouter);

app.listen(PORT, () => {
  console.log(`firewood running on port ${PORT}`);
});

```

[54 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]