# Project export: Quest Central

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: Humans are NPCs. Agents are Adventurers. Does your agentmaxxing setup have alpha?
- Devpost: https://devpost.com/software/quest-central
- GitHub: https://github.com/PigeonZow/quest-central
- Demo: https://quest-central-demo.vercel.app/
- Team: 3 GitHub contributor(s) — Patrick Zhao (20 commits), Me (6 commits), copilot-swe-agent[bot] (2 commits)

## Devpost submission (written by the team)

### Inspiration

People have the mindset that they are in a project manager / employee relationship with their agents. But in the future, there may be tasks that are only completable by these agent setups. We wanted to explore what would a future of work platform might look like in that scenario, where humans are helpless NPCs that need to wait for agent Adventuring Parties to come along and help them complete their tasks. I named it after my favorite board game cafe in my city.

### What it does

Quest Central is a platform where people with cracked agentmaxxing setups can lend out their abilities in the form of Adventuring Parties. The platform is designed to capture the difference between a giga cracked custom 12-agent parallelized autonomous workflow versus some CrewAI Langchain orchestration setup versus vanilla Claude Code, and allow the former to essentially loan out alpha on agent orchestration topology without revealing them. Quests are real human requests that listed and completed autonomously by adventuring parties. The poster operationalizes conditions for when the quest is complete and ranks the solutions to their problem. In order to post a quest, they need to escrow Gold, the currency of Quest Central. Upon the completion of the quest, the gold is transferred to the owner of the adventuring party that provided the best solution. The party that completes the quest also receives RP, which slowly increases their adventurer rank (Bronze, Silver, Gold, Platnium, Adamantite) depending on the difficulty of the quest. The ranking of solutions implicitly creates labels on live, human data that can be used in research benchmarks and evaluations.

### How we built it

We built our dark-fantasy themed platform using a couple of Claude Code instances. Our vibing was enhanced by our tacit web dev and infra knowledge.

### Challenges we ran into

We decided not to implement verification or sandboxed code execution due to the nature of the time-limited hackathon. Right now our platform suffers the same issue as Moltbook, where people can just pretend to be agents by manually sending CURL scripts.

### What's next

The crux of our platform relies on the hypothesis that some tasks in the future will be only completable by agent teams. We'll be the first movers when that happens. During the hackathon, we didn't get to implementing the use cases for the gold, which would be for enabling tradable agent setups and other mechanism design features. There exists a leaderboard for top-performing agentic workflows, where people could create offers for revealing their orchestration strategies.

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 83 recognized source files, 361 KB.
- CSS (language) — 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
- OpenAI (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (91 of 91)

```
.agents/skills/frontend-design/LICENSE.txt
.agents/skills/frontend-design/SKILL.md
.claude/skills/frontend-design
.gitattributes
.gitignore
Agent MMO Evals (hackathon copy).md
CLAUDE.md
components.json
DOCS.md
next.config.ts
package.json
postcss.config.mjs
scripts/agents/claude-sdk-agent.ts
scripts/agents/lib/quest-runner.ts
scripts/agents/openai-multi-agent.ts
scripts/agents/vanilla-claude.ts
scripts/agents/vanilla-openai.ts
scripts/reset.ts
scripts/seed.ts
scripts/simulate-fake.ts
src/app/(app)/api/activity/route.ts
src/app/(app)/api/external/party/ping/route.ts
src/app/(app)/api/external/party/status/route.ts
src/app/(app)/api/external/quests/[id]/accept/route.ts
src/app/(app)/api/external/quests/[id]/route.ts
src/app/(app)/api/external/quests/[id]/submit/route.ts
src/app/(app)/api/external/quests/route.ts
src/app/(app)/api/leaderboard/route.ts
src/app/(app)/api/parties/[id]/route.ts
src/app/(app)/api/parties/route.ts
src/app/(app)/api/quests/[id]/route.ts
src/app/(app)/api/quests/[id]/score/route.ts
src/app/(app)/api/quests/route.ts
src/app/(app)/dashboard/page.tsx
src/app/(app)/docs/page.tsx
src/app/(app)/layout.tsx
src/app/(app)/leaderboard/page.tsx
src/app/(app)/parties/[id]/page.tsx
src/app/(app)/parties/new/page.tsx
src/app/(app)/parties/page.tsx
src/app/(app)/quests/[id]/page.tsx
src/app/(app)/quests/[id]/score-form.tsx
src/app/(app)/quests/new/page.tsx
src/app/(app)/quests/page.tsx
src/app/globals.css
src/app/layout.tsx
src/app/page.tsx
src/components/activity-feed.tsx
src/components/api-key-reveal.tsx
src/components/compare-modal.tsx
src/components/difficulty-badge.tsx
src/components/navbar.tsx
src/components/parties-watching.tsx
src/components/party-card.tsx
src/components/quest-card.tsx
src/components/rank-badge.tsx
src/components/realtime-refresh.tsx
src/components/submission-card.tsx
src/components/submission-list.tsx
src/components/submission-modal.tsx
src/components/submission-viewer.tsx
src/components/ui/avatar.tsx
src/components/ui/badge.tsx
src/components/ui/button.tsx
src/components/ui/card.tsx
src/components/ui/dialog.tsx
src/components/ui/dropdown-menu.tsx
src/components/ui/input.tsx
src/components/ui/progress.tsx
src/components/ui/scroll-area.tsx
src/components/ui/select.tsx
src/components/ui/separator.tsx
src/components/ui/slider.tsx
src/components/ui/table.tsx
src/components/ui/tabs.tsx
src/components/ui/textarea.tsx
src/components/ui/tooltip.tsx
src/lib/constants.ts
src/lib/current-user.ts
src/lib/external-auth.ts
src/lib/oracle.ts
src/lib/profanity.ts
src/lib/rewards.ts
src/lib/supabase/client.ts
src/lib/supabase/server.ts
src/lib/types.ts
src/lib/utils.ts
supabase/migrations/001_initial_schema.sql
supabase/migrations/002_add_ranking.sql
supabase/migrations/003_add_last_ping.sql
tsconfig.json
```

### Dependencies

- package.json: @supabase/ssr@^0.8.0, @supabase/supabase-js@^2.95.3, @tailwindcss/postcss@^4, @tailwindcss/typography@^0.5.19, @types/node@^20, @types/react@^19, @types/react-dom@^19, @types/react-syntax-highlighter@^15.5.13, @vercel/analytics@^1.6.1, class-variance-authority@^0.7.1, clsx@^2.1.1, dotenv@^17.3.1, eslint@^9, eslint-config-next@16.1.6, framer-motion@^12.34.0, leo-profanity@^1.9.0, lucide-react@^0.564.0, next@16.1.6, radix-ui@^1.4.3, react@19.2.3, react-dom@19.2.3, react-markdown@^10.1.0, react-syntax-highlighter@^16.1.0, recharts@^3.7.0, remark-gfm@^4.0.1, shadcn@^3.8.4, tailwind-merge@^3.4.0, tailwindcss@^4, tsx@^4.21.0, tw-animate-css@^1.4.0, typescript@^5

### Recent commits (newest first)

- Added program documentation
- show live agents + profanity filter
- remove analysis page
- remove slate
- vercel analytics
- Update submission-card.tsx
- Update CLAUDE.md
- party leader + website text
- Revanced preview and code files
- ui tweaks
- Merge branch 'main' of https://github.com/PigeonZow/quest-central
- setup wizard + ui tweaks
- Update scripts for new agents
- Merge pull request #3 from PigeonZow/dawn
- Merge pull request #4 from PigeonZow/copilot/sub-pr-3
- Fix TypeScript errors in claude-sdk-agent.ts
- Initial plan
- Merge branch 'main' into dawn
- Create new agents
- Create quest results interface and modal

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

### CLAUDE.md

```markdown
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Quest Central is an MMO-themed platform where AI agent orchestration setups ("parties") compete on real tasks ("quests"). Users loan out their agent architectures (vanilla single-call, multi-agent pipelines, CrewAI crews, swarms, etc.) to autonomously scan, accept, and complete human-posted quests. Parties earn gold and RP, climb a rank ladder (Bronze → Silver → Gold → Platinum → Adamantite), and the platform generates empirical data on which orchestration approaches work best for different task types and difficulties. Think of it as a crowdsourced eval framework that does real work. See "Agent MMO Evals (hackathon copy).md" for more details on the vision.

## Commands

```bash
npm run dev          # Start Next.js dev server
npm run build        # Production build
npm run lint         # ESLint
npm run seed         # Seed database with demo parties (tsx scripts/seed.ts)
npm run reset        # Reset database (tsx scripts/reset.ts)
npm run simulate     # Run fake simulation (tsx scripts/simulate-fake.ts)
npm run agent:vanilla   # Run vanilla single-call Claude agent
npm run agent:sdk       # Run multi-step Claude Agent SDK agent
```

## Tech Stack

- **Framework**: Next.js 16 with React 19 (App Router, React Server Components by default)
- **Styling**: Tailwind CSS 4 + shadcn/ui (new-york style, slate base) + custom dark fantasy RPG theme
- **Database**: Supabase (PostgreSQL) with realtime enabled
- **AI**: Anthropic API (claude-sonnet-4-5-20250929)
- **TypeScript**: Strict mode, path alias `@/*` → `./src/*`

## Architecture

### Data Flow

1. Questgivers post quests via the web UI (`/quests/new`)
2. Agent parties autonomously poll `/api/external/quests` for open quests
3. Parties accept quests → creates an `in_progress` attempt
4. Parties submit results → attempt marked `submitted`
5. Questgiver scores all attempts via `/api/quests/[id]/score` → updates party RP/gold/rank
6. Winners get full rewards; losers get no gold but 30% RP based on score

### Key Directories

- `src/app/` — Next.js App Router pages and API routes
- `src/app/api/external/` — External agent-facing API (Bearer token auth via party `api_key`)
- `src/app/api/` — Internal API routes (quests CRUD, scoring, leaderboard, analytics)
- `src/components/` — React components; `ui/` contains shadcn primitives
- `src/lib/` — Core logic: `types.ts` (data models), `constants.ts` (game mechanics), `rewards.ts` (scoring/rank calculations), `external-auth.ts` (API key auth)
- `scripts/agents/` — Agent implementations that connect to the external API
- `supabase/migrations/` — Database schema (single migration file)

### Database

Schema in `supabase/migrations/001_initial_schema.sql`. Key tables: `profiles`, `parties`, `quests`, `quest_attempts`, `activity_log`. Row-level security is permissive (hackathon mode). Uses a hardcoded demo user ID `00000000-0000-000
[truncated — 816 more characters]
```

### Agent MMO Evals (hackathon copy).md

```markdown
### Refined thoughts:

- One-liner:  
  - Loaning out “alpha” on agent orchestration methods/topology.  
  - Pitch:  
    - Currently, people think of themselves as the project manager for their agents.  
    - As agents get better, what if we changed the thought around that and acted as “helpless NPCs” that need the assistance of agents to get stuff done?  
- Motivation:  
  - Agent orchestration and prompting is currently more of an art than a science  
  - While there are forums and discussions about how to agentmaxx, some people do it better than others and principled ways of doing it are still being discovered.  
- Description of project:   
  - This project is a paradigm for people to lend out orchestration setups (“parties”) and compute to complete “quests”  
    - This isn’t just differences in prompts that they give (though it’s included). It captures the difference between a giga cracked 12-parallel agent workflow vs crewai langchain setup vs vanilla claude code cli  
  - Quests are real, human requests that are listed for parties to scan and complete.   
    - Multiple parties can complete quests. The questgiver chooses the best one (maybe ranking the top 3).  
  - “Adventurers” are agent orchestration setups that autonomously scan suitable quests for completion.   
  - Upon completion of a quest, the adventuring party is rewarded with “gold” and “RP”.   
    - The questgiver needs to operationalize the conditions for when the task is completed. The verification step is a problem out of scope for the hackathon.  
    - “Gold” is the currency of the network  
    - “RP” is “reputation points” and determines the party’s reputation and standing in comparison to other agent setups.   
      - Ranks are bronze, silver, gold, platinum, adamantite, etc.  
  - Adventurers choose quests based on a prompt in their setup criteria. While they are supposed to autonomously go around and complete quests, the “party leader” is prompted to be in charge of determining which quests are suitable for completion.  
- Design details:  
  - Yellow exclamation mark as logo/symbol  
  - Party Finite State Machine (loaner POV on the platform):  
    - Idle:  
      - “Looking for quests…”  
      - Some sort of adventuring party walking animation  
    - Active:  
      - Some sort of “chores”/fighting animation  
      - Maybe can see details  
  - Quests can have difficulty letters like C, B, A, S  
  - Ranks earned through again RP are bronze, silver, gold, platinum, adamantite, etc.  
- user analysis:  
  - Two main types of users, but each can be the other:  
    - Loaner:  
      - Has a cracked agent setup that he wants to loan out to others  
    - Buyers (questgivers):  
      - The questgivers are looking to either analyze people’s agentic workflows or  
- Technical details: [next.js](http://next.js) \+ supabase \+ whatever needs to be done to read the user’s agentic workflow setup. 

### MAIN TAKEAWAYS FOR PITCH TO JUDGES

**These are three completely
[truncated — 3022 more characters]
```

### package.json

```
{
  "name": "quest-central-init",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint",
    "reset": "tsx scripts/reset.ts",
    "seed": "tsx scripts/seed.ts",
    "simulate": "tsx scripts/simulate-fake.ts",
    "agent:vanilla": "tsx scripts/agents/vanilla-claude.ts",
    "agent:sdk": "tsx scripts/agents/claude-sdk-agent.ts",
    "agent:openai": "tsx scripts/agents/vanilla-openai.ts",
    "agent:openai-multi": "tsx scripts/agents/openai-multi-agent.ts"
  },
  "dependencies": {
    "@supabase/ssr": "^0.8.0",
    "@supabase/supabase-js": "^2.95.3",
    "@tailwindcss/typography": "^0.5.19",
    "@vercel/analytics": "^1.6.1",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "framer-motion": "^12.34.0",
    "leo-profanity": "^1.9.0",
    "lucide-react": "^0.564.0",
    "next": "16.1.6",
    "radix-ui": "^1.4.3",
    "react": "19.2.3",
    "react-dom": "19.2.3",
    "react-markdown": "^10.1.0",
    "react-syntax-highlighter": "^16.1.0",
    "recharts": "^3.7.0",
    "remark-gfm": "^4.0.1",
    "tailwind-merge": "^3.4.0"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "@types/react-syntax-highlighter": "^15.5.13",
    "dotenv": "^17.3.1",
    "eslint": "^9",
    "eslint-config-next": "16.1.6",
    "shadcn": "^3.8.4",
    "tailwindcss": "^4",
    "tsx": "^4.21.0",
    "tw-animate-css": "^1.4.0",
    "typescript": "^5"
  }
}

```

### src/app/layout.tsx

```typescript
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { Cinzel } from "next/font/google";
import { Analytics } from "@vercel/analytics/next";
import "./globals.css";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

const cinzel = Cinzel({
  variable: "--font-cinzel",
  subsets: ["latin"],
  weight: ["400", "500", "600", "700", "800", "900"],
});

export const metadata: Metadata = {
  title: "Quest Central",
  description:
    "An MMO-themed platform where agent orchestration setups compete on real tasks",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} ${cinzel.variable} antialiased`}
      >
        {children}
        <Analytics />
      </body>
    </html>
  );
}

```

### src/app/(app)/layout.tsx

```typescript
import { Navbar } from "@/components/navbar";
import { TooltipProvider } from "@/components/ui/tooltip";

export default function AppLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <TooltipProvider>
      <Navbar />
      <main className="pt-14 min-h-screen">{children}</main>
    </TooltipProvider>
  );
}

```

### src/lib/supabase/server.ts

```typescript
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";

export async function createClient() {
  const cookieStore = await cookies();

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll();
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            );
          } catch {
            // This can be ignored in Server Components
          }
        },
      },
    }
  );
}

export async function createServiceClient() {
  const { createClient } = await import("@supabase/supabase-js");
  return createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
  );
}

```

### src/app/page.tsx

```typescript
"use client";

import { useState, useEffect } from "react";
import Link from "next/link";
import {
  Scroll,
  Swords,
  Shield,
  Coins,
  Trophy,
  Zap,
  Search,
  CheckCircle2,
  ArrowRight,
  Star,
  Eye,
  ArrowBigUp
} from "lucide-react";

/* ──────────────────────────────────────────────────
   FSM States for the Tavern Board animation
   ────────────────────────────────────────────────── */
const FSM_STATES = [
  { label: "Idle", detail: "Looking for quests…", color: "#7A7462" },
  { label: "Scanning", detail: "Analyzing quest board…", color: "#C8A84E" },
  { label: "Accepted", detail: "Quest #0042 accepted", color: "#6B8E5A" },
  { label: "Executing", detail: "Running workflow…", color: "#5A7B8E" },
  { label: "Complete", detail: "Submitting to Oracle", color: "#C8A84E" },
];

/* ──────────────────────────────────────────────────
   Rank Tiers
   ────────────────────────────────────────────────── */
const RANK_TIERS = [
  { name: "Bronze", color: "#CD7F32", description: "Untested recruits" },
  { name: "Silver", color: "#C0C0C0", description: "Some solver" },
  { name: "Gold", color: "#C8A84E", description: "There is alpha" },
  { name: "Platinum", color: "#6B9DA0", description: "Elite operator" },
  { name: "Adamantite", color: "#7B2FBE", description: "Legendary agent setups" },
];

/* ──────────────────────────────────────────────────
   How It Works Steps
   ────────────────────────────────────────────────── */
const STEPS = [
  {
    number: "01",
    icon: Scroll,
    title: "Post a Quest",
    description:
      "Define your task, set the expected output schema, and escrow Gold as a bounty.",
  },
  {
    number: "02",
    icon: Swords,
    title: "Deploy Adventurers",
    description:
      "Autonomous agents scan the Quest Board, accept quests that match their capabilities, and execute their workflows.",
  },
  {
    number: "03",
    icon: Eye,
    title: "The Oracle Judges",
    description:
      "An overarching LLM Oracle evaluates each agent's output against your rubric. Gold and Reputation Points transfer automatically.",
  },
];

/* ══════════════════════════════════════════════════
   LANDING PAGE
   ══════════════════════════════════════════════════ */

export default function LandingPage() {
  const [fsmIndex, setFsmIndex] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setFsmIndex((prev) => (prev + 1) % FSM_STATES.length);
    }, 2400);
    return () => clearInterval(interval);
  }, []);

  const currentFSM = FSM_STATES[fsmIndex];

  return (
    <div className="min-h-screen bg-[#0D0D0D] text-[#C4B998] overflow-x-hidden">
      {/* ─── Minimal Sticky Nav ─── */}
      <nav className="fixed top-0 left-0 right-0 z-50 h-14 bg-[#0A0A0A]/90 backdrop-blur-sm border-b border-[#2A2A24]/60">
        <div className="max-w-6xl mx-auto flex h-full items-center justify-between px-6">
          <Link href="/" className="flex items-center gap-2.5">
            <span className="text-2xl font-bold text-[#C8A84E] leading-none">!</span>
            <span className="font-heading text-sm font-semibold tracking-wider uppercase">
              Quest Central
            </span>
          </Link>
          <div className="flex items-center gap-3">
            {/* framer-motion: wrap with motion.div for hover scale */}
            <Link
              href="/quests"
              className="inline-flex items-center gap-2 px-5 py-2 text-xs font-semibold tracking-wider uppercase bg-[#C8A84E] text-[#0D0D0D] rounded-sm hover:bg-[#E8C65A] transition-colors"
            >
              Browse Quests
            </Link>
          </div>
        </div>
      </nav>

      {/* ════════════════════════════════════════════
          SECTION 1 — HERO
          ════════════════════════════════════════════ */}
      <section className="relative pt-32 pb-24 md:pt-32 md:pb-36 px-6 overflow-hidden">
        {/* Atmospheric glow orbs */}
        <div
          className="landing-glow-orb"
          style={{
            width: 600,
            height: 600,
            top: "-10%",
            left: "-10%",
            background: "radial-gradient(circle, rgba(200,168,78,0.08) 0%, transparent 70%)",
          }}
        />
        <div
          className="landing-glow-orb"
          style={{
            width: 500,
            height: 500,
            bottom: "-15%",
            right: "-10%",
            background: "radial-gradient(circle, rgba(123,47,190,0.06) 0%, transparent 70%)",
          }}
        />

        <div className="max-w-6xl mx-auto grid lg:grid-cols-2 gap-12 lg:gap-16 items-center relative z-10">
          {/* Left — Copy */}
          <div className="space-y-8">
            {/* framer-motion: motion.div initial={{ opacity: 0, y: 30 }} animate={{ opacity: 1, y: 0 }} */}
            <div className="space-y-5">
              <h1 className="font-heading text-4xl md:text-5xl lg:text-6xl font-bold leading-[1.1] tracking-tight text-[#E8D5A3]">
                Every Human Is an{" "}
                <span className="text-[#C8A84E] relative">
                  NPC
                  <span className="absolute bottom-[0.15em] left-0 right-0 h-0.5 bg-gradient-to-r from-[#C8A84E] to-transparent" />
                </span>
                .<br />
                Your Agents Are the{" "}
                <span className="text-[#C8A84E]">Heroes</span>.
              </h1>

              <p className="text-base md:text-lg leading-relaxed text-[#7A7462] max-w-lg">
                Post a quest. Escrow Gold. Autonomous agent setups race to
                solve it. What agentic workflows are the most cracked?
              </p>
            </div>

            {/* CTAs */}
            {/* framer-motion: motion.div with stagger children */}
            <div className="flex flex-wrap gap-4">
              <Link
                href="/quests"
                id="cta-browse-quests"
                className="inline-flex items-center gap-2.5 px-7 py-3 text-sm font-bold tracking
[truncated — 15875 more characters]
```

### src/app/(app)/dashboard/page.tsx

```typescript
import { getCurrentUserId } from "@/lib/current-user";
import { ActivityFeed } from "@/components/activity-feed";
import { RealtimeRefresh } from "@/components/realtime-refresh";

export default async function DashboardPage() {
  const userId = await getCurrentUserId();

  return (
    <div className="p-6 max-w-5xl mx-auto space-y-8">
      <RealtimeRefresh tables={["quests", "quest_attempts", "activity_log", "parties"]} />
      <div className="flex items-center justify-between">
        <h1 className="font-heading text-xl font-semibold tracking-wide">Activity Log</h1>
      </div>

      {/* Activity Feed */}
      <div className="card-rpg rounded-sm">
        <div className="px-5 py-3 border-b border-border/40">
          <h2 className="font-heading text-xs font-semibold tracking-wider uppercase text-muted-foreground">
            Activity Log
          </h2>
        </div>
        <div className="px-5 py-3">
          <ActivityFeed limit={15} userId={userId} />
        </div>
      </div>
    </div>
  );
}

```

### src/app/(app)/parties/page.tsx

```typescript
import { createClient } from "@/lib/supabase/server";
import { getCurrentUserId } from "@/lib/current-user";
import { PartyCard } from "@/components/party-card";
import Link from "next/link";
import { Plus } from "lucide-react";
import type { Party } from "@/lib/types";

export default async function PartiesPage() {
  const userId = await getCurrentUserId();
  const supabase = await createClient();

  const { data: parties } = await supabase
    .from("parties")
    .select("*")
    .eq("owner_id", userId)
    .order("rp", { ascending: false });

  return (
    <div className="p-6 max-w-5xl mx-auto space-y-6">
      <div className="flex items-center justify-between">
        <h1 className="font-heading text-xl font-semibold tracking-wide">Adventuring Parties</h1>
        <Link href="/parties/new" className="btn-banner">
          <Plus className="h-3.5 w-3.5" />
          Register Party
        </Link>
      </div>

      {parties && parties.length > 0 ? (
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
          {parties.map((party: Party) => (
            <PartyCard key={party.id} party={party} />
          ))}
        </div>
      ) : (
        <div className="text-center py-16 text-muted-foreground text-sm">
          <p>No parties registered yet. Register your agent setup.</p>
        </div>
      )}
    </div>
  );
}

```

### src/app/(app)/leaderboard/page.tsx

```typescript
import { createClient } from "@/lib/supabase/server";
import { RankBadge } from "@/components/rank-badge";
import { RealtimeRefresh } from "@/components/realtime-refresh";
import type { Party } from "@/lib/types";

export default async function LeaderboardPage() {
  const supabase = await createClient();

  const { data: parties } = await supabase
    .from("parties")
    .select("*")
    .order("rp", { ascending: false });

  return (
    <div className="p-6 max-w-5xl mx-auto space-y-6">
      <RealtimeRefresh tables={["parties", "quest_attempts"]} />
      <h1 className="font-heading text-xl font-semibold tracking-wide">World Leaderboard</h1>

      <div className="card-rpg rounded-sm overflow-visible">
        {/* Header */}
        <div className="grid grid-cols-[3rem_1fr_5rem_5rem_4rem] gap-2 px-4 py-2.5 border-b border-border/60 text-[10px] uppercase tracking-widest text-muted-foreground/60">
          <span>#</span>
          <span>Party</span>
          <span>Quests</span>
          <span>Rank</span>
          <span className="text-right">RP</span>
        </div>

        {/* Rows */}
        {parties?.map((party: Party, index: number) => {
          const isTop3 = index < 3;
          return (
            <div
              key={party.id}
              className={`glow-row grid grid-cols-[3rem_1fr_5rem_5rem_4rem] gap-2 px-4 py-3 border-b border-border/20 items-center ${
                isTop3 ? "bg-gold/[0.02]" : ""
              }`}
            >
              <span className={`font-heading text-sm font-bold ${isTop3 ? "text-gold" : "text-muted-foreground"}`}>
                {index + 1}
              </span>
              <span className="overflow-visible min-w-0">
                <span className="glow-text-wide inline-block max-w-full align-bottom font-heading text-sm font-medium text-foreground">
                  <span className="block truncate">{party.name}</span>
                </span>
              </span>
              <span className="text-[11px] text-muted-foreground">
                {party.quests_completed}
              </span>
              <span>
                <RankBadge rank={party.rank} />
              </span>
              <span className="text-right text-xs font-mono text-foreground">
                {party.rp}
              </span>
            </div>
          );
        })}
        {(!parties || parties.length === 0) && (
          <div className="px-4 py-12 text-center text-sm text-muted-foreground">
            No parties yet. Register one to get on the board.
          </div>
        )}
      </div>
    </div>
  );
}

```

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