Open-Source Cold Email & Warmup Platform
Warmbly는 메일함을 예열하고 캠페인 전송·답변 triage를 지원하는 오픈소스 콜드 이메일 플랫폼입니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Route your next tour to where your fans already are.
GigRoute is a taste-grounded tour planner for independent musicians, built on the Qloo Taste AI Insights API. Enter your artist (or a better-known artist you sound like) and a region. An agent then:
Every city and venue has a “Why this city / venue?” panel built from Qloo's query.affinity and query.explainability: the affinity score, the tags that match your sound, and the artists whose fans drove the result.
Try it in one click: the landing page has a “See a sample tour” button (Radiohead · UK). It always runs on built-in sample data, so it works instantly with no keys.
Requires Node 20 or 22 (see .nvmrc).
nvm use # optional, picks Node 22
npm ci
npm run dev # http://localhost:3000
With no environment variables, the app runs in mock mode: a deterministic mock LLM drives the agent against hand-written fixture data. No network calls are made to Qloo or to any LLM.
| Command | What it does |
|---|---|
npm run dev | Development server |
npm run build / npm start | Production build and server |
npm test | Vitest unit tests (all mocked, no network) |
npm run lint | ESLint |
npm run contract-check | Optional live contract check against Qloo (see below). |
The key lives only in your shell for the length of one command. It is never written to a file or committed:
QLOO_API_KEY=... npm run contract-check
The script (scripts/qloo-contract-check.ts) makes one real request per endpoint GigRoute uses (search, similar artists, fan hotspots, venues with explainability, brand and movie cross-domain, tags) and checks that the response has the fields the app reads. It prints one line per check, with counts and field names only. It never prints response data or the key (anything it prints is scrubbed of the key as a safeguard).
PASS GET /search (artist): 10 artists; fields: id, name, type, popularity, tags, explainability
PASS /v2/insights filter.type=urn:entity:place (venues in London) + explainability: 5 places; ...; explainability on 5/5
FAIL /v2/insights filter.type=urn:entity:movie (cross-domain): Qloo 403: entity type or endpoint not enabled for this key
/search failed, so the checks that need an artist ID didn't run.0 means everything passed; 1 means at least one check failed or was skipped. With no key set it calls nothing, prints a skip message and exits 0.Set these in .env.local for local development (it is gitignored) or in Vercel → Project → Settings → Environment Variables. Never commit real values.
| Variable | Required | Example (empty means unset) | Purpose |
|---|---|---|---|
QLOO_API_KEY | For live Qloo | QLOO_API_KEY= | Sent as the X-Api-Key header. If empty, mock mode is used. |
QLOO_BASE_URL | No | QLOO_BASE_URL= | Defaults to https://hackathon.api.qloo.com. |
QLOO_MOCK | No | QLOO_MOCK= | Set to 1 to force mock Qloo data even when a key is present. |
LLM_BASE_URL | No | LLM_BASE_URL= | Any OpenAI-compatible chat completions endpoint. Defaults to OpenAI. |
LLM_API_KEY | For a live LLM | LLM_API_KEY= | If empty, the deterministic MockLLM plans the tour. |
LLM_MODEL | With LLM_API_KEY | LLM_MODEL= | Model name for the endpoint above. Must support tool calling. |
NEBIUS_API_KEY | No | NEBIUS_API_KEY= | Enables Nebius Token Factory summary rewrite when non-empty. |
NEBIUS_BASE_URL | No | NEBIUS_BASE_URL= | Defaults to https://api.tokenfactory.nebius.com/v1/. |
NEBIUS_MODEL | No | NEBIUS_MODEL= | Defaults to nvidia/nemotron-3-super-120b-a12b. |
NEBIUS_TIMEOUT_MS | No | NEBIUS_TIMEOUT_MS= | Defaults to 20000. |
NEBIUS_REASONING | No | NEBIUS_REASONING= | Empty = reasoning off (reasoning_effort: none + chat_template_kwargs.enable_thinking: false). Set default to omit both fields. |
Going live: set QLOO_API_KEY (and leave QLOO_MOCK unset). That is the only change. The real client already sends the documented requests (see below). The LLM is independent: with no LLM key, the mock LLM drives the real Qloo client.
GigRoute includes an optional, non-blocking final step that passes the deterministic tour summary and the Qloo facts it was built from to NVIDIA Nemotron on the Nebius Token Factory for rewriting. Set NEBIUS_API_KEY to enable it. If it times out, throws an error, or the key is not set, GigRoute seamlessly falls back to the deterministic summary without failing the plan.
"engines": { "node": ">=20 <23" } from package.json and uses Node 22./api/plan is a streaming (SSE) route function; / and /plan are static.A build with QLOO_MOCK=1 and no LLM key is tested as part of CI-style verification (npm ci && npm run build && npm test && npm run lint).
All requests are GET with the X-Api-Key header. The parameters are built in lib/qloo/requests.ts, the same builders feed the mock, and the URLs are asserted in tests/params.test.ts.
| Purpose | Request |
|---|---|
| Resolve artist | GET /search?query=<name>&types=urn:entity:artist&take=10 |
| Tag lookup | GET /v2/tags?filter.query=<q>&filter.parents.types=urn:entity:artist&take=20 |
| Similar artists (co-bills) | GET /v2/insights?filter.type=urn:entity:artist&signal.interests.entities=<id>&take=6 |
| Fan hotspots | GET /v2/insights?filter.type=urn:entity:destination&signal.interests.entities=<ids>&feature.explainability=true&take=10[&filter.location.query=<region>] |
| Venues per city | GET /v2/insights?filter.type=urn:entity:place&signal.interests.entities=<ids>&filter.location.query=<city>&feature.explainability=true&take=5 |
| Merch cues | GET /v2/insights?filter.type=urn:entity:brand or urn:entity:movie &signal.interests.entities=<id>&take=5 |
take is clamped to the documented maximum of 50.results.entities[] (insights), results[] (search) and results.tags[] (tags). Each entity contributes entity_id, name, subtype, properties, location, tags, popularity, query.affinity and query.explainability["signal.interests.entities"].lib/qloo/fixtures/mock-data.json are hand-written fake data, not real API responses. They copy the documented response shapes. Entity IDs are prefixed mock-, and addresses are placeholders.filter.location.query filters them by name (for example UK or USA; United Kingdom, England, US and United States work too). Other regions (for example India or Germany) end with a message explaining the sample data's coverage, with links to try the UK, the USA or everywhere.QLOO_MOCK=1 or QLOO_API_KEY is empty. The demo preset (demo=1) always uses mock mode.lib/qloo: RealQlooClient and MockQlooClient behind one QlooClient interface, with shared request builders and normalizers.lib/agent: a tool-calling agent over any OpenAI-compatible LLM (or MockLLM). Tool results are folded into a typed Plan (lib/agent/plan.ts), and a snapshot of that plan streams to the browser over SSE after every step.app/plan: renders the streamed plan, with progress, skeletons, empty and error states, the explainability panels, and a Leaflet/OpenStreetMap route map.narrateTour, pitchEmail in lib/agent/plan.ts) are pure and deterministic. The MockLLM's closing summary, the per-stop “why” text, the per-venue pitch drafts and the exports all come from the same Qloo evidence (affinity, tags, explainability, similar artists). Pitch drafts are shown with a copy button only; GigRoute never sends email./plan?artist=…®ion=…&cities=…&stops=… encodes every input, so a shared link re-runs the same plan (deterministic in mock mode). The plan page can copy that link, download Markdown or JSON (gigroute-plan@1), or print a clean light-on-paper view. Nothing is stored on a server.next/og (app/opengraph-image.tsx, app/twitter-image.tsx); the icon is app/icon.svg. Set NEXT_PUBLIC_SITE_URL to change the absolute URL used in the meta tags (defaults to https://gigroute.vercel.app).filter.location.query locality matching is fuzzy on Qloo's side. Very broad or unusual regions may return no destinations.query.explainability keyed by signal, with per-entity scores normalized 0–1). If the live API differs, the panels fall back to affinity and tags.