尚未偵測到更新。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.