尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
One feed for New York nightlife. NOCT pulls club nights, raves and day parties from every platform that
lists them — Resident Advisor, DICE, venue calendars, Ticketmaster (and EDMTrain if licensed) — dedupes
them into one event per night per room, shows every ticket price side by side, and tags each night with a
genre and a vibe.
NOCT is a working name. Nothing is attached to it yet.查看完整 README ↗One feed for New York nightlife. NOCT pulls club nights, raves and day parties from every platform that lists them — Resident Advisor, DICE, venue calendars, Ticketmaster (and EDMTrain if licensed) — dedupes them into one event per night per room, shows every ticket price side by side, and tags each night with a genre and a vibe.
NOCT is a working name. Nothing is attached to it yet.
index.html the app (mobile-first, 440px). Loads /api/feed; falls back to the sample weekend
studio/ the Instagram review page, served gated by api/studio.ts (never as a static file)
api/ Vercel Functions
feed.ts GET /api/feed?from&to → events/venues/days in the shape the UI expects
(&counts=1 → per-night counts only, what the month calendar draws)
recommend.ts GET /api/recommend → nights picked from the caller's own going/saved history
ingest/[source].ts GET|POST /api/ingest/ra|dice|elsewhere|…|all (Bearer CRON_SECRET)
enrich.ts POST /api/enrich — genre/vibe pass over new/changed events
health.ts GET /api/health — last run per source
studio.ts GET /studio — the Instagram review page, behind a studio session
session.ts POST|DELETE /api/session — sign in to the studio, or out
posts.ts the queue's data API: draft a weekend, edit a caption, approve or pass
img.ts GET /api/img — one promoter flyer, treated, as JPEG (host allowlist)
render.ts GET composes one 1080x1350 slide from a signed URL; POST signs a deck
publish.ts POST /api/publish — puts one approved deck on Instagram. Manual, never cron
GET — preflight: does the credential work, how many posts left today
src/
sources/ one adapter per source (RA, DICE, Elsewhere, Good Room, Public Records, SILO, Ticketmaster, EDMTrain): fetch + normalise, no DB
ingest/ runner: adapter → upsert_listing() → resolve_pending() → tombstone_sweep()
enrich/ taxonomy, crosswalk, rules engine, Claude reconciler
feed/ read model → UI shape, and the recommendation scorer's caller
post/ Instagram: slide templates (satori), tones/veil/grain (sharp), flyer treatments,
weekend drafting, caption house rules, the queue store, the Instagram API
client, and the 60-day token refresh that keeps a weekly post unattended
lib/ http (polite fetch, block detection), time (NY ⇄ UTC), normalize, db
supabase/migrations/ Postgres schema: listings, events, venues/aliases, resolution SQL, enrichment,
app tables, views + RLS, pg_cron schedules
tests/ vitest — unit tests on real captured payloads; DB tests; opt-in live tests
docs/ DATA_SOURCES.md (terms + decisions), OPERATIONS.md, GENRE_VIBE.md,
RECOMMENDATIONS.md, FRONTEND.md, INSTAGRAM.md, sources/*.md
NormalizedListing
rows. The runner upserts them (upsert_listing, keyed by (source, source_id)), tracks first/last
seen, content changes and disappearances (tombstones), and stores every price tier.resolve_listing() links each listing to a canonical event: hard cross-references
first (a venue page linking a DICE id), then venue family + nightlife date + trigram title + lineup
overlap. Grey-zone matches land in match_candidate for review; canonical fields are recomputed from
the highest-priority live listing (refresh_event).event_tag)./api/feed reads event_feed (RLS-guarded view) and returns the weekend in the UI's
shape, cached at the edge for five minutes.npm install
cp .env.example .env # fill DATABASE_URL (local Postgres is fine) and optional keys
bash scripts/db-local.sh noct # creates the DB and applies every migration
npm run fetch -- ra --limit 5 # dry-run one adapter (no DB)
DATABASE_URL=postgresql://localhost:5432/noct npm run ingest -- ra elsewhere publicrecords goodroom
DATABASE_URL=postgresql://localhost:5432/noct npm run enrich -- --limit 20 # rules-only unless an LLM key is set (docs/GENRE_VIBE.md → Provider options)
npm test # unit + DB tests (DB tests skip without DATABASE_URL); NOCT_LIVE=1 adds live tests
npx vercel dev # serves index.html + /api/*
supabase link --project-ref <ref>, supabase db push. Copy the
Supavisor transaction pooler URL (IPv4, port 6543) into DATABASE_URL.vercel link, set env vars from .env.example (DATABASE_URL, CRON_SECRET, keys),
vercel deploy --prod. vercel.json registers the daily fallback crons (Hobby limit).vercel_base_url and cron_secret into app_setting so pg_cron can call
/api/ingest/* every few hours (docs/OPERATIONS.md)./api/ingest/ra?limit=5 once and read /api/health. If a source shows BLOCKED:, that host
rejects datacenter traffic — see docs/DATA_SOURCES.md; NOCT does not work around blocks.Read docs/DATA_SOURCES.md. Short version: RA's GraphQL endpoint is the canonical record (their terms
restrict automated commercial extraction — ask for written permission), DICE runs only with a key DICE
issues to you, EDMTrain is off unless licensed, venue feeds are on, Ticketmaster is on with a free key.
NOCT never solves bot challenges, proxies, or borrows credentials found on other sites.
Verified locally end to end on PostgreSQL 14: one fresh apply of all eight migrations, 250 tests
(npm test, DB-backed ones included), a real ingest of RA + Elsewhere + Public Records + Good Room for
the next 7 nights (≈230 listings → ≈210 events, 15 cross-source merges, 12 grey-zone matches queued for
review), a rules-only enrichment pass, and /api/feed JSON for a Friday–Sunday range. Not yet exercised:
a real Vercel deployment, pg_cron on Supabase, the live Claude call (needs ANTHROPIC_API_KEY), DICE /
Ticketmaster / EDMTrain with real keys.
0005_app.sql) but the
UI is not wired to Supabase Auth (Instagram is not a Supabase provider — see docs/FRONTEND.md).not_electronic flag are what fix that.docs/GENRE_VIBE.md) but not implemented.venue.needs_review)./studio. Venue slides still need photographs. Using promoter flyers in NOCT's own marketing posts (rather
than to display listings) is a rights question both RA and DICE restrict — see docs/INSTAGRAM.md.NOCT_CITIES); San Francisco, Chicago, Miami, DC, Detroit, Toronto, London, Berlin are registered (src/lib/cities.ts) and switch on by adding them to NOCT_CITIES. Venue-direct feeds and the venue seed are New York only, so other cities rely on RA (+ 19hz where it has a list).Open an issue, or leave comments on the relevant line.