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:
- Blog post - How the pipeline works and what each prompt does
- Example repo - Full source code for the finished app
- SDK docs (llms.txt) - Full
algo-dslAPI reference — feed this to your LLM - Embed Console - Sign up and grab your API key (starts with
mbd-)
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 resetsAlternative: 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:
- Save your pipeline as an algorithm in the Console
- Create a feed config with caching, fallbacks, and pagination — see Feed Configs
- 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
Updated 10 days ago
