Vibecode a polymarket feed

What you'll build: A Next.js app that uses the Algorithms DSL (algo-dsl) to display personalized Polymarket prediction markets with filtering, sorting, and live price charts.

Stack: Next.js App Router, TypeScript, Tailwind CSS, TanStack Query, Framer Motion, algo-dsl, liveline

Resources:


Copy the prompt below into your AI coding assistant along with the llms.txt. The SDK reference covers all builder methods; this prompt adds the Polymarket-specific context the LLM needs.

# Build a Personalized Polymarket Feed

**Stack:** Next.js 15 App Router, TypeScript, Tailwind 4, TanStack Query v5, Framer Motion, lucide-react, `algo-dsl@^4.1` (read its `llms.txt` for full API). API key in `.env.local` as `MBD_API_KEY`.

> Before writing code, inspect a sample item from the index and log features/scores after `features("v1")` to confirm field names.

---

## Index Fields

Index: `polymarket-items` — all snake_case.

| Field | Type |
|---|---|
| `outcome_prices` | `number[]` `[yes, no]` |
| `one_week_price_change`, `one_day_price_change` | `number` |
| `volume_24hr`, `volume_1wk`, `liquidity`, `spread` | `number` |
| `end_date` | ISO string |
| `question`, `slug`, `image`, `icon`, `item_id` | `string` |
| `tags`, `ai_labels_med` | `string[]` |
| `active`, `closed`, `price_0_or_1` | `boolean` |
| `text_vector` | embedding |

`item_id` is the cross-ref key to the Gamma API — MBD truncates slugs, never use them for lookups.

---

## Pipeline — `POST /api/pipeline`

### Shared Filters (all paths)

```ts
.include()
  .term("active", true)
  .term("closed", false)
  .numeric("volume_24hr", ">=", 1000)   // Operator is ">=" not "gte"
.exclude()
  .term("price_0_or_1", true)
```

- **Tag filters:** `.include().term("tags", tag)` (not `.match()`)
- **Search:** `.match("question", query)`, omit `sortBy`, pad queries < 5 chars with `" markets predictions"`
- Search, tags, and wallet all combine.

### Path 1 — No wallet

`filter_and_sort`, size 150. Without a query: `.sortBy(sort, "desc")`.

### Path 2 — Wallet, no query

Full personalization pipeline:

1. `forUser("polymarket-wallets", wallet)` → **boost search** (size 300, `includeVectors(true)`) with:

   > **Note:** The first argument to `forUser` is the **user profile index** (`polymarket-wallets`), not the items index. This tells the Features service where to look up the user's preferences. See the [Algorithms DSL quickstart](../Getting Started/quickstart-studio-sdk) for details.
   ```ts
   .groupBoost("polymarket-wallets", "ai_labels_med", wallet, "label", 1, 10, 10)
   .groupBoost("polymarket-wallets", "tags", wallet, "tag", 1, 10, 10)
   ```
2. `addCandidates`
3. `features("v1")`
4. **Strip `text_vector` and `item_sem_embed2`** from `studio._candidates` and `_source` — ranking API returns 413 with vectors included.
5. `scoring("/scoring/ranking_model/polymarket-rerank-v1")`
6. Ranking:
   ```ts
   ranking()
     .sortingMethod("mix")
     .mix("topic_score", "desc", 30)
     .mix("usr_primary_tags", "desc", 30)
     .mix("rerank_polymkt1", "desc", 40)
     .diversity("fields")          // Not "semantic" — semantic requires vectors → 413
     .fields(["cluster_1"])
     .limitByField()
     .every(5)
     .limit("cluster_1", 2)
   ```

### Path 3 — Wallet + query

Same pipeline as Path 2 but use `.match()` instead of boost, size 150.

### Fallbacks

- Fall back to search order on enrichment failure.
- `normalizeHits` should also strip vectors from output.

> **Note:** Ranking field names (`topic_score`, `usr_primary_tags`, `rerank_polymkt1`) are discovered at runtime from `_scores`/`_features` on hits — confirm these after calling `features("v1")`.

---

## Tags — `GET /api/tags`

```ts
studio.search().index("polymarket-items").frequentValues("tags", 50)
```

- Filter out internal tags: `"Hide From New"`, `"China"`, `"France"`, `"Parent For Derivative"`, `"Recurring"`, `"Up or Down"`, `"5M"`, `"15M"`
- Return top 15. Cache 5 min.

> **Type bug:** Return type is actually `{ id: string; count: number }[]` despite SDK types saying `{ [key: string]: unknown }`.

---

## Price Charts

1. Fetch `gamma-api.polymarket.com/markets/{item_id}`
2. Parse `JSON.parse(clobTokenIds)[0]` → `tokenId`
3. Fetch `clob.polymarket.com/prices-history?market={tokenId}&interval=1w&fidelity=60`

Use **SVG sparklines** (not canvas libs — rendering issues in card grids). Fall back to synthetic data from price change fields.

---

## Deep Links

No `event_slug` in the index. Build a redirect at `/api/market-link`:

- Map `item_id` → `event_slug` via `gamma-api.polymarket.com/events?limit=500&active=true&closed=false`
- In-memory cache
- Fall back to search URL

---

## UI

### Theme

| Token | Value |
|---|---|
| Background | `#06080d` |
| Card | `#0d1117` |
| Yes accent | `#00d4aa` |
| No accent | `#ff4d6a` |
| Font | IBM Plex Sans / Mono |

### Cards

Market image (top-left), question, YES/NO cents, sparkline, stats grid, tag pills.

### Layout & Interaction

- Responsive grid, infinite scroll (25/page)
- Wallet input with ETH address validation
- Search bar with dynamic tag pills from `/api/tags`
- Sort dropdown hidden when personalized or searching
- Disconnecting wallet resets query + tags; connecting preserves them
- Sync `SearchBar` local input state when parent resets

Alternative: Deploy via Feed Config

This tutorial runs the full pipeline on every request via Next.js API routes. For production apps with higher traffic, you can instead:

  1. Save your pipeline as an algorithm in the Console
  2. Create a feed config with caching, fallbacks, and pagination — see Feed Configs
  3. Serve via /deploy/serve — the platform runs your algo, caches results, and handles pagination for you — see Serving

This gives you built-in caching (no re-running the pipeline on every request), pagination via served_id, and new-item detection.


What's Next

  • [Search](../Building Algorithms/search) — Deep dive into filters, boost, semantic search
  • [Features](../Building Algorithms/algo-features) — ML enrichment and personalization signals
  • [Scoring & Ranking](../Building Algorithms/algo-scoring-ranking) — Reranking models, sort methods, diversity
  • Feed Configs — Bundle algorithms for production deployment
  • Serving — Production feed serving with pagination