new-term-radar
신규 AI 용어를 매일 추적, X·Hugging Face·GitHub 등에서 모델·제품·레포 이름을 빠르게 수집
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
SociaFlux is an AI-powered creator-brand matchmaking platform for onboarding brands, building product personas, analyzing creators, posting campaigns, and running a two-sided application marketplace between brands and creators.README 전문 보기 ↗SociaFlux is an AI-powered creator-brand matchmaking platform for onboarding brands, building product personas, analyzing creators, posting campaigns, and running a two-sided application marketplace between brands and creators.
@libsql/clientnpm install
cp .env.example .env.local # then fill in the SOCIAFLUX_TURSO_* values
npm run db:migrate
npm run db:seed
npm run dev
Open http://localhost:3000.
SOCIAFLUX_AI_PROVIDER="mock" uses the built-in heuristic analysis engine; set
SOCIAFLUX_OPENAI_API_KEY and SOCIAFLUX_AI_PROVIDER="openai" to use real model
calls. Without Turso credentials the app falls back to a local SQLite file, so it
still runs.
All variables are prefixed with SOCIAFLUX_ so they do not collide with other
projects sharing Vercel team-level environment variables.
Campaigns, applications and creator profiles are stored in the database, so the two workspaces share one marketplace across browsers and devices.
/creator/login with a handle (for example @mayaskinnotes), pick niches during onboarding, and add published work under My portfolio.Sign in under a different handle to add a second applicant to the same campaign.
Both workspaces are behind a real login. An account is an email, a password and a role; creators also own one Instagram handle, which is what ties the account to its profile.
| Route | Purpose |
|---|---|
POST /api/auth/signup | create an account, claim the handle, start a session |
POST /api/auth/login | email and password only — the handle comes back from the account |
POST /api/auth/logout | expire the cookie |
GET /api/auth/session | who is signed in, or null |
POST /api/auth/forgot | email a single-use reset link (always the same reply) |
POST /api/auth/reset | set a new password from a valid reset token |
Passwords are hashed with scrypt from node:crypto — memory-hard, no
dependency to keep patched. Cost parameters live inside each hash, so raising
them later only affects new passwords and needsRehash re-hashes the rest at
next login.
Sessions are signed cookies rather than database rows, so verifying one
costs no query and src/middleware.ts can check every request. The trade is
that a session cannot be revoked before it expires; rotating
SOCIAFLUX_SESSION_SECRET invalidates all of them at once. Signing uses Web
Crypto, not node:crypto, so the same code runs in edge middleware.
Middleware is navigation, not a security boundary — it only redirects. Anything
that changes data or reveals private fields checks again server-side via
src/lib/auth/guard.ts, because an API route can be called directly.
Login failures return one message for both "no such account" and "wrong password", so the response cannot be used to discover which emails are registered.
A Forgot password? link on each login page emails a single-use reset link
to the address on file. Only a SHA-256 of the token is stored, so a leaked
password_resets table cannot reset anyone: the raw token lives only in the
link. Tokens expire in an hour, requesting a new one retires the old, and
consumeResetToken marks a token used atomically so it cannot be replayed.
With no SOCIAFLUX_RESEND_API_KEY set, the link is written to the server log
rather than sent — enough to test locally, and to recover an account from
Vercel function logs before a provider is wired up. For a locked-out account
with no inbox access, npm run auth:password <email> sets one directly.
A creator profile may predate accounts, or have been created by an Instagram connection. Signing up with that handle claims it, unless another account already has — then sign-up is refused rather than silently taking over somebody's profile.
Campaigns, applications, creator profiles and brands live in Turso (libSQL), so a brand and a creator in different browsers see the same marketplace.
Storage is hybrid: the fields the app filters, sorts and joins on are real
columns, while the full domain object is kept as JSON in a data/profile
column. That keeps the nested shapes the app already uses — campaign targets,
brief assets, creator analytics — without flattening them into dozens of columns.
npm run db:migrate # applies src/lib/db/schema.sql (safe to re-run)
npm run db:seed # demo brand, creators, campaign and applications
Both read SOCIAFLUX_TURSO_DATABASE_URL and SOCIAFLUX_TURSO_AUTH_TOKEN from
.env.local. With neither set, the app falls back to a local SQLite file at .data/sociaflux.db,
so it still runs without credentials.
| Table | Holds |
|---|---|
brands | business profile JSON, keyed by a slug of the brand name |
creators | handle, niches, location, barter flag, follower count as columns; full CreatorProfile as JSON |
campaigns | objective, budget, barter policy, region rule as columns; full Campaign as JSON |
applications | one row per (campaign, creator), enforced by a unique constraint |
What is still per-browser in localStorage: the signed-in creator handle, draft
onboarding answers, and UI preferences like sort order and filters.
| Route | Purpose |
|---|---|
GET/POST /api/creators | list the directory, upsert a profile |
GET /api/creators/search | filter by niche, tag, language, country/state/city, price, barter |
GET/POST /api/campaigns | list campaigns, post one |
GET/POST /api/applications | list (by campaign or creator), apply |
PATCH/DELETE /api/applications/:id | brand decision, creator withdrawal |
POST /api/match/campaign | rank creators against a campaign |
Writes from the UI are optimistic: local state updates immediately and the server's version replaces it when it lands. Creator edits are debounced so typing through onboarding does not write on every keystroke.
Instagram serves a stripped page to datacenter IP addresses, so a hosted server cannot read follower counts from a public profile. Scraping works on a laptop and returns nothing on Vercel. The app handles this three ways, in this order:
POST /api/analyze/creator tries Business Discovery first and silently falls
back to scraping, reporting which one answered as source in the response.
Two accounts are involved and confusing them is the usual setup mistake:
| Account | |
|---|---|
| The lens | An Instagram professional account you control, linked to a Facebook Page. Its id is SOCIAFLUX_INSTAGRAM_DISCOVERY_USER_ID. |
| The target | Whoever is being looked up. Needs no relationship to the app, but must be public and professional. |
The token is a Facebook token (EAA…), not an Instagram Login token
(IGAA…), and the two are not interchangeable — graph.facebook.com rejects
the latter outright. It needs instagram_basic, pages_show_list and
pages_read_engagement.
npm run ig:setup # verify the token, print the lens account id
npm run ig:setup cristiano # ...and prove a lookup works
Because the lens account belongs to the app's own admin, this works while the Meta app is still in Development mode. App Review and Business Verification are only needed to run it publicly in production.
A long-lived Page token does not expire, so prefer one over a user token and the 60-day refresh problem disappears.
Unlike scraping, Business Discovery returns recent posts, so average likes and comments are measured rather than inferred from follower count. The UI drops the "est." suffix when that is the case.
What it will never return: email, phone, audience demographics, or anything at all for a private or personal account.
Requires a Meta app with the "Manage messaging & content on Instagram" use
case and the instagram_business_basic permission, set up through API setup
with Instagram login. Only Business and Creator accounts return metrics.
In development mode only accounts added as Instagram testers can authorise; App Review lifts that for public use.
Access tokens are stored in their own database column, never inside the profile
JSON, so they are not serialised into any API response. Long-lived tokens last
about 60 days and refreshLongLivedToken renews them.
A campaign carries everything a creator needs to make the ad, and everything a brand needs to judge whether it worked:
awareness, engagement, traffic, conversions or ugc.
This changes how click-through and conversion are projected.src/lib/campaign-metrics.ts turns a roster of creators into projected reach,
impressions, engagements, clicks, conversions, spend and CPM, and compares that
against the targets. Reach rate and engagement rate fall as follower count rises,
and repeat deliverables add impressions faster than they add new people.
These are planning heuristics derived from follower counts, not measured results — the rates are named constants at the top of the module, ready to be replaced with real platform data.
The brand's Applicants page screens like a hiring pipeline:
The Campaign plan panel on the same page projects what the shortlisted and approved roster will deliver, against the campaign's targets and budget.
src/lib/ai/taxonomy.ts classifies a scraped site into one of 15 categories. It
scores every category rather than taking the first keyword hit, weights the page
by section (title > description > headings > body > links), matches terms on word
boundaries, and discounts a category supported by only one distinct term.
That combination is what stops a consumer brand being classified by its footer: an "Investor Relations" link no longer makes a phone maker a venture studio, and "AI" no longer matches inside "available".
src/lib/campaign-matching.ts scores every creator against a campaign on three
weighted criteria, and reports hard eligibility separately so a brand can rank
everyone while still seeing who its own rules exclude.
| Criterion | Weight | How it scores |
|---|---|---|
| Tag match | 0.5 | Share of the campaign's tags (targetNiches + tags) covered by the creator's niches and content tags, plus 0.15 when a tag hits their primary niche. Untagged campaigns fall back to keyword affinity against the brief. |
| Region match | 0.3 | 1.0 when the creator satisfies a target at the specificity the campaign asked for (country, state or city); 0.5 for the right country but wrong state/city; 0.5 for an unstated location; 0 otherwise. No targets means open worldwide. |
| Barter compatibility | 0.2 | paid ignores barter (1.0 for everyone); flexible gives 1.0 to barter-friendly creators and 0.5 to the rest; barter_only gives 1.0 or 0. |
Tag matching is tolerant of phrasing: a campaign tag counts when it equals,
contains, or is contained by one of the creator's tags, so Skincare matches a
creator tagged Skincare education.
Hard filters set eligible: false with a reason, and are the only rules that
exclude rather than rank:
minFollowers floor,barter_only and the creator is not open to barter,regionRequirement is "required" and the creator is outside the targets, or has no stated location.POST /api/match/campaign exposes the engine. Pass a campaign (and optionally
creators, requireRegionMatch, eligibleOnly) and it returns ranked matches
with a per-criterion breakdown:
curl -X POST http://localhost:3000/api/match/campaign \
-H "content-type: application/json" \
-d '{"campaign":{"name":"Barter push","targetNiches":["Skincare"],"barterPolicy":"barter_only","budget":0}}'
GET /api/creators/search filters the directory on niche, tag (repeatable),
language, country, state, city, maxPrice and openForBarter.
Country codes are ISO 3166-1 alpha-2. Inputs are canonicalised on the way in, so
IN, in and India are equivalent, as are common aliases like UK for GB.
npm test
Runs tests/*.test.ts on the Node test runner via tsx — 244 cases covering tag
intersection, barter policy, region specificity, the hard filters, score
weighting and ranking order, the reach/conversion projection model, and the
business classifier including the Samsung and Apple regressions, and the
database repositories, the Instagram Business Discovery parser, and password hashing session
signing, and the single-use password-reset tokens, the brand/creator marketplace flow and
per-brand campaign scoping, brand-profile persistence and brand-initiated
outreach. The
database tests run against a throwaway local SQLite file, never against Turso.
This project is ready to deploy on Vercel as a Next.js app.
.env.example.Set SOCIAFLUX_TURSO_DATABASE_URL and SOCIAFLUX_TURSO_AUTH_TOKEN in the Vercel
project so the deployed instance talks to the same database.
Copy .env.example to .env.local for local development and fill in the required keys.