Feature 4 — Deep Dive

Admin Vertical Tagging

How internal tagging of buyer projects feeds UpStage’s AI category match-scoring engine — and connects talent to the right projects.

1. Vertical Tagging — The Foundation

Every buyer project on UpStage has a content vertical. The operator-managed buyer_projects.vertical value is the singular, human-curated taxonomy field that records the primary category. Vertical tagging is the operator-side queue at /admin/tags, backed by a Postgres project_vertical enum.

Beyond semantic matching, the explicit category signal is separate: the computeMatchScore() path applies its explicit verticalBoost only when the project’s verticals array overlaps the talent’s project_types array — separate from the singular admin taxonomy field.

2. The Four Vertical Buckets

The project_vertical enum is a single-valued, “primary-axis” column on buyer_projects. Legacy rows default to short-film; new projects default the same way unless the creator explicitly picks another value via POST /projects/new.

Vertical • default
Short-Film
Indie Film — shorts, festival bound, narrative statement pieces.
short-film
Vertical • branded
Commercial
Branded Content — paid ads, brand spots, agency work.
commercial
Vertical • live
Theater
Stage — live performance, run-of-show, on-stage credits.
theater
Vertical • emerging
New-Media
Vertical Drama — episodic streaming-first, mobile-first formats.
new-media

Each value maps to a market category the talent operator cares about — and each is its own “axis of relevance” in the matching engine. Pick one per project.

3. Tagging → Scoring → Matching

The end-to-end workflow that takes a project from “just posted” to “ranked on a talent card” flows through three stages:

Stage 1
Admin Tags
Operator hits /admin/tags, chooses a vertical, hits Save.
→
Stage 2
Vertical Write
Taxonomy metadata is updated via setProjectVertical(id, vertical) in db/buyer-projects.js.
→
Stage 3
Match Score
On a later scheduled match check, computeMatchScore() applies a 5% verticalBoost inside the 40% skills weight only when the project’s verticals overlap talent project_types.

Admin hits /admin/tags → selects the vertical enum → on POST /admin/tags/vertical/:id the row gets vertical written via setProjectVertical as taxonomy metadata → on a later scheduled match check, the matching engine re-reads the project verticals array and talent project_types array; only an overlap adds the bounded verticalBoost and surfaces as the category sub-score on the talent card.

4. What the Admin Sees

The tagger UI at /admin/tags is a deliberately thin admin surface — it lists every buyer_projects row and exposes a dropdown + Save pair per row, backed by the project_vertical enum.

upstageplatform.com/admin/tags
Project #1284 current: short-film sarah.k · posted Jun 28
vertical: Save
Project #1291 current: new-media mateo.r · posted Jun 30
vertical: Save
Project #1303 current: short-film nina.w · posted Jul 03
vertical: Save

The dropdown submits via POST /admin/tags/vertical/:id — gated by requireAdminSecret at routes/admin.js:1663 so only the operator (with the secret in the URL or the Authorization header) can alter a project’s vertical.

5. Buyer Brief Tags vs. Talent Profile Tags

UpStage carries a singular operator-managed taxonomy field on the brief, plus matching arrays on the brief and talent profile. The operator touches the brief-side taxonomy; computeMatchScore() uses the two arrays for the explicit category signal.

Buyer sets
Buyer brief tags
Single, enum-valued vertical on buyer_projects (Postgres enum, default short-film), plus a multi-select verticals TEXT[] array the buyer can fill at POST /projects/new. Talent matching reads verticals for the explicit overlap cue.
Talent sets
Talent profile tags
Multi-select project_types TEXT[] array on seller_profiles the talent fills when editing their profile. The match boost fires when at least one of the project’s verticals labels overlaps a talent project_types label (case-insensitive).

The two arrays meet inside computeMatchScore() at services/matching.js:69–86 — and the overlap yields the 5% explicit verticalBoost that sharpens the existing 40% skills weight without changing its headroom.

6. Closing the Loop — Cron & Category Score

Saving the singular admin vertical field persists taxonomy metadata; it does not itself rescore a project. On a later scheduled match check, the AI matching path re-reads the project’s verticals array and the talent’s project_types array. The daily ai-talent-match-check cron (referenced in the CLAUDE.md changelog for 2026-08-12) re-runs the matching every cron run, while the 3-day cadence ensures notifications fire on the match_run_counter % 3 == 0 rhythm (corrected in the 2026-07-15 fix).

In practice: an operator hits Save on the tagger screen, and a later cron cycle can apply the bounded verticalBoost when those matching arrays overlap. The category score may then surface on the talent card; Save itself does not guarantee a notification or delivery.