Gooism Collective × WallSpace.Studio

GPortal

A unified directory, planner, and matchmaking surface for VJs, artists, and event spaces — built by the collective, for the collective. Closes the loops that today happen via DMs and tribal knowledge.

v0.1 Draft · Updated 2026-04-28 · Office hours 2026-04-29 · 17 sections
← Gooism Collective

Contents

  1. Why GPortal
  2. Core entities (VJ / Artist / Space)
  3. Search & directories
  4. Event Planner
  5. Signal Planner (visual node-based)
  6. Calendar & availability
  7. Chat & messaging
  8. Ratings & reviews
  9. Integrations
  10. VJ Outreach & BD
  11. Hiring & Bookings
  12. Grants & Fundraising
  13. AI Assistant
  14. Roadmap
  15. Tech stack
  16. Open questions
01 — Premise

Why GPortal exists

The Gooism collective has three constituencies that today coordinate through DMs, group chats, and the kindness of mutual friends: VJs, Artists, and Event Spaces. Information is lossy at every hop. GPortal is the unified surface that closes those loops.

VJ

Show up under-briefed

Booked by a friend-of-the-artist's-manager; arrives without knowing the rig, the audience, the artist's typical visual cues, or even the room's projector count.

Artist

Conscripted as middleman

Pinged with venue-tech questions they can't answer ("does the booth have a ground-loop hum?"). Ends up forwarding messages between strangers.

Space

Books under-qualified

No way to verify a VJ's experience with a specific rig, headcount, or genre. Gambles each booking; sometimes wins, often regrets.

The unifying frame

One tool, three faces of the same problem. Directory + Planner + Chat in a single surface, owned by the collective, with the data structured so every constituency benefits from the others' contributions. The Signal Planner reuses WallSpace's wall/output/scope data model so technical work flows directly between live shows and the planning surface.

GPortal lives under the Gooism collective umbrella, which is currently in a proposed structural phase (a 501(c)(3) is one of the options on the table, but nothing is decided — the Proposed Org Structure doc is the working draft, pending full collective approval + legal/financial advisor review). The accessibility-first mission is the through-line. Long-term home is gooism.org; short-term home is wallspace.studio/gooism/ while we build out the actual product surface at gportal.wallspace.studio.

02 — Data model

Core entities

Three first-class profile types. Each entity owns its own profile, sets its own discoverability rules, and edits its own fields. Cross-references resolve into hyperlinks (a VJ's "primary venue" jumps to that Space's profile; a Space's "house VJ" jumps to that VJ; etc.).

🎞 VJ profile

The visual artist running live shows. Ownership: the VJ. Edit gating: VJ + collective admins.

FieldTypePurpose
display_nametextHow they appear in directories
biotextShort narrative; AI-assist available (§13)
primary_venue_idFKTheir home base, if any
experience_yearsintCareer length
skillsjson[]e.g. ["controlnet", "midi-mapped", "scope-live", "milkdrop", "ndi-routing"]
tech_knowledgejson[]e.g. ["resolume", "wallspace", "touchdesigner", "scope", "mainstage"]
venue_experiencesFK[]List of spaces they've worked + show counts (drives "venue veterans" filter)
socialsjsonInstagram, YouTube, TikTok handles
media_urlsR2[]Reels + portfolio uploads
references_textjson[]Public artistic references — "I'm influenced by"
rate_min / rate_maxintFloor + typical ceiling, integer minor units
rate_currency / rate_unitenumUSD + event/hour/night/day
rate_negotiableboolWilling to discuss outside the range

Specialized packages (productized services)

VJs can publish 0+ named packages: pre-priced, scoped offerings that artists and spaces can purchase directly without going through the full custom-quote flow. This complements the per-event rate range — packages cover the cases where the offering is well-defined enough to put a price on. Lower buyer friction, faster to book, and lets specialists productize unique offerings.

Flagship example: Fetz's specialized CRT packages (4-unit / 8-unit / custom-cluster) ship as buyable line items, not "let's negotiate" inquiries.

FieldTypePurpose
nametexte.g. "CRT Cluster — 4 unit / 4 hr"
categoryenumcrt / projection / led / ai-live / recorded / audio-reactive / multi-cam / captions / consult / mentor / other
descriptiontextWhat this package is — the elevator pitch
price / currencyint / enumFixed price; minor units; USD default
duration_hours / duration_unitreal / enumHow long the package covers; unit is event / hour / set / license (for recorded)
max_event_sizeint?Sized for headcount up to N; null = any
includes_textjson[]Bullet list — "4× consumer CRT, 1× video wall PC, cabling, setup + teardown, operator on-site"
requires_textjson[]What the venue must provide — "2× 20A circuits, 8'×6' floor footprint, 2 h load-in"
addons_jsonjsonA la carte upsells: [{ name, price_delta, description }] (e.g. "+1 CRT", "Custom mounting", "Dual-operator")
lead_time_daysintMinimum advance booking — physical packages need build/ship time
buyable_directlyboolIf true, artist/space can book without negotiation; if false, package is shown but routes through inquiry
travel_included_radius_kmint?Free travel radius; null = no travel offered
travel_extra_per_kmintSurcharge beyond the included radius
media_urlsR2[]Example reels showing the package in action — matters most for visually-distinctive packages (CRT clusters, LED, projection)
sample_event_idsFK[]Past events_internal rows where this package was deployed — powers "see it live" cross-links
activeboolHide without deleting (seasonal packages, retired offerings)

Package categories are not exhaustive — the other bucket is open. Initial curated list: CRT clusters, projection mapping, LED wall design, live AI / ControlNet restyling, recorded set rentals, audio-reactive performance, multi-camera live mix, caption / accessibility overlay packages, mentoring / training / consults.

Schema-level note: Artist and Event Space "packages" are a logical extension (artists offering set-length tiers, venues offering bundled night-rate-with-bar-split). Out of scope for v0.1; same pattern when added.

🎤 Artist profile

The musician / performer being booked. Two rate fields: their own performance fee, and the typical VJ-side spend when they're the booking party.

FieldTypePurpose
display_nametextStage name
genrejson[]Multi-tag — e.g. ["techno", "ambient", "vocal-house"]
tech_rider_texttextFree-form rider; structured fields planned for v1
primary_vj_user_idFKTheir go-to VJ when one exists
service_rate_min / maxintThe artist's own performance fee floor + ceiling
expected_vj_budget_min / maxintWhat they typically allocate for visuals when booking
spotify_artist_idtextDrives §09 preview embeds
soundcloud_urltextUnderground / pre-Spotify artists
bandcamp_url / apple_music_urltextAdditional embed surfaces
preview_track_urltext"Listen to this first" — falls back via platform priority

🎪 Event Space profile

The venue. Capacity, rig, budget realities. Owned by an authorized account holder per venue.

FieldTypePurpose
display_name / citytextVenue identity
capacity / max_screensintHeadcount + max simultaneous outputs
layout_texttextFree-form room description; structured layout schema in v1
tech_capabilitiesjson[]e.g. ["ndi", "syphon", "4k-projector", "5-crt-cluster", "led-wall-2x4m"]
skill_requirementsjson[]What a VJ needs to know to walk in cold
years_openintTrack record context
house_vj_user_idFKThe resident VJ when one exists
public_eventsboolPublic-ticketed vs. private/corporate
vj_budget_min / maxintTypical VJ-services budget per show
artist_budget_min / maxintTypical artist-fee budget per show
budget_negotiableboolDoor-open signal even when not in range

Why pay-range is in the schema, not just freeform

Pay matching is the single most useful filter for both directions. A venue with a $300–500 VJ budget should not see a VJ whose floor is $800; a VJ should not waste pitches on under-budget venues. Storing min/max + currency + unit lets every search facet, the Event Planner, and the Hiring module reason about budget overlap without parsing free-text. Negotiable flags keep the door open when the situation calls for it without burying genuinely-incompatible matches.

Promoter v0.5 directory shipped

Intermediaries and hiring agents who book talent + run nights at venues. Sit in the middle of the model: they have a "client roster" (talent they hire) AND a "venue partnership" list (where they run shows). Distinct from artists (talent themselves) and spaces (venues themselves). Example: Boof Party in SF runs nights at The Midway, hires Fetz + collective VJs directly.

FieldTypeNotes
idPKnanoid
user_idFK / nullableNullable — promoters often exist as a public handle before signing in. Admin-created entries are unowned until claimed.
display_name + slug + avatar_urlstringSame identity pattern as other directories
city / regionstring"Bay Area, CA"-style region grouping for non-city promoters
primary_contact_namestringWhen the promoter is a brand (Boof Party) but the booking contact is a person
website_url + socialsJSONEspecially Instagram (the canonical promoter channel)
genre_focusJSON arrayWhat kinds of nights they run
typical_event_sizeJSON arrayintimate / medium / festival
partnered_venue_idsJSON arrayFK to event_space_profiles.id — venues they regularly run at. Powers cross-link on both sides.
typical_vj_budget_min / maxintWhat they generally pay VJs — same matching role as venue's vj_budget fields
typical_artist_budget_min / maxintWhat they generally pay artists
verified / booking_count / response_ratetrustCollective-verified flag; derived counters populated as bookings flow through GPortal

Multi-stage venues Shipped

Some venues have multiple bookable rooms with different capacity / rig / vibe. The Midway (SF) has main concert hall (1500), Concourse (350), Patio (250), Annex Studio (150), and an opt-in Pier 80 expansion (5000). Each gig books one stage; the parent venue is the contact + billing surface.

Stored as stages_json on the parent event_space_profiles row — we don't need stages to be queryable as their own rows, just attachable to gigs / bookings. Shape:

[
  { "name": "Main Concert Hall", "capacity": 1500, "screens": 4 },
  { "name": "Concourse",         "capacity":  350, "screens": 1 },
  { "name": "Patio",             "capacity":  250 },
  { "name": "Annex Studio",      "capacity":  150, "screens": 2 },
  { "name": "Pier 80 expansion", "capacity": 5000, "screens": 8,
    "notes": "Opt-in. Requires permit + Midway crew." }
]
04 — Coordination

Event Planner

The matchmaking + staffing + costing surface. Inputs go in (artist + space + date), reconciled requirements come out (tech list, VJ shortlist, cost estimate, rider/cost split). Confirms into a saved event everyone can see.

Inputs → Auto-derived → Manual

// Inputs artist + event_space + date_range + headcount? // Auto-derived from intersection required_tech = artist.tech_rider space.tech_capabilities recommended_vjs = vjs WHERE availability(date_range) AND skills required_tech AND venue_experience(space) > 0 AND rate_overlap(space.vj_budget) != none suggested_rate = median(comparable_shows) budget_estimate = sum(line_items.midpoint) rider_split = collective_default_or_per_event_override // Manual layer + bespoke_gear, + contractors, + hospitality, + custom_line_items

Budget reconciliation panel

The planner's most distinctive surface. Side-by-side: venue VJ budget (min–max), shortlisted VJ rate ranges, artist fee, artist budget. Overlap state per pair shown as green/yellow/grey with a one-tap "negotiate" affordance that opens a thread pre-filled with the gap context. Same panel surfaces artist-fee vs. venue-artist-budget reconciliation.

Output

A saved event record visible to all participants (VJ, artist, space, optional collective admins). Exportable as a one-pager that includes the agreed rate, payment terms, and rider/cost split. Once confirmed and the event date passes, ratings unlock for all parties (§08).

Package suggestions alongside custom shortlist

The planner's recommendations panel shows two parallel rails: Custom-fit VJs (the rate-matched, skill-matched shortlist for a bespoke quote) and Buyable packages (already-priced offerings that fit the event's needs). Spaces and artists who already know what they want can skip the negotiation entirely and book a package; the rest get the traditional shortlist. Same backend, two UX paths.

05 — Topology

Signal Planner Visual node-based App-agnostic

The technical design surface for an event — what's plugged into what, who runs which control, where each output lands. Visual node graph, not a form or spreadsheet. Signal flow is a graph; spreadsheets hide topology. Node graphs are how VJs already think.

Any app or none at all

This is a planning surface for the event, not a control surface for any one product. Resolume, TouchDesigner, OBS, VDMX, MadMapper, Notch, WallSpace, hardware-only rigs — all valid topologies. Apps are first-class nodes; you can mix multiple apps in one event (e.g. Resolume for live mix + ControlNet on a GPU pod + a Roland hardware video mixer for the final composite). WallSpace is one option among many, never assumed.

When an event has a confirmed venue, the planner pulls the venue's tech_capabilities in as the starting Output nodes, you wire your inputs/apps/processors into them, and the saved graph becomes a proposal — visible to the artist + space manager with comment threads, so the rig is locked before load-in instead of reverse-engineered on the night.

INPUTS PROCESSORS OUTPUTS FaceTime HD Camera webcam · 720p · 30fps cinema_loop.mp4 media · 4K · loop Mixer L/R audio · 48 kHz · stereo APC mini mk2 midi · CC + scenes ControlNet · Soft Edge processor · GPU pod Scene Mixer processor · WallSpace Audio FFT → Reactivity processor · local Front Wall · 4× CRT output · 4:3 Left Wall · Projector output · 1080p Right Wall · LED 2×4m output · NDI Web Portal Stream output · WebRTC Recording · MP4 output · file
Sample graph — 4 inputs (camera, MP4, mixer, MIDI) → 3 processors (ControlNet, scene mixer, audio reactivity) → 5 outputs (CRT cluster, projector, LED wall, web portal, recording). Cyan = video signal, pink = output rendering, grey dashed = control. Recording = optional / dashed border.

Node types

Input nodes

Camera, MP4, MIDI source, audio source, capture card, NDI, Syphon, AI input, Spotify-driven metadata.

Processor nodes

Per-pixel effect, ControlNet preprocessor, AI model, scene mixer, audio analyzer, blend stage.

Output nodes

CRT, projector, NDI send, Syphon, WebRTC publish, file record, second-screen confidence monitor.

Operator nodes

A human role — VJ, FOH, lighting tech — assigned to operate one or more processors / outputs. Powers the staffing surface in the Event Planner.

Edge types

WallSpace data-model reuse

WallSpace's Wall / CRT / Projector / LayerState shapes (src/renderer/types/index.ts) translate directly to Output and Input nodes. v1.0+ supports import-from-WallSpace (existing setup JSON seeds the graph) and export-to-WallSpace (graph becomes a scene scaffold). Same compositor mental model on both sides of the surface.

Templates

Pre-built common graphs the collective curates. Each ships as a starting graph + a description of when to reach for it. Examples: 4-CRT cluster + camera + ControlNet, two-screen DJ wall + Spotify + caption layer, 3D scene + remote camera ingest, recorded-only fallback rig.

Implementation: @xyflow/react on the GPortal app. Graph stored as JSON in events_internal.signal_graph_json. v0.1 ships a static demo at /planner; v0.5 ships interactive create + save + load.

06 — Time

Calendar & availability

Three-tier sync: manual entry (always works), iCal feed read-only (lightweight), Google Calendar two-way (v1.0). Availability surfaces in directories with privacy gating: public busy/free, detailed view to confirmed connections only.

Manual entry

Drag-to-create on the calendar grid. Block + describe. Always available, no third-party setup. Lives in v0.5.

iCal feed (read-only)

Drop a public iCal URL; GPortal polls and merges into the availability layer. v0.5 stretch.

Google Calendar two-way

OAuth, full read+write, conflict detection at booking time. Locks confirmed events back to Google as a held block. v1.0.

Privacy

Recurring availability windows ("I'm available Thursday–Saturday nights, never Mondays") express as a separate layer that doesn't have to compete with one-off blocks.

07 — Comms

Chat & messaging

Async-first; per-event group threads + DMs. Real-time presence is a v1.5 stretch goal. No public message walls in v1 — comms is targeted, not broadcast.

DMs

One-to-one threads between any two GPortal members. Emerges from a profile-page "Message" CTA or a Hiring/Outreach context.

Per-event threads

Auto-created when an event confirms. All participants (artist, VJ, space owner, optional co-promoter) get added. The thread is the project-management surface.

Notifications

Email + in-app. Per-event muting; per-thread muting. Quiet hours respected from the user's profile timezone.

08 — Trust

Ratings & reviews

Two-way: VJ ↔ Artist, VJ ↔ Space, Artist ↔ Space. Ratings only unlock for parties tied to a confirmed completed event in events_internal — no drive-by reviews, no review-bomb attack surface.

Aggregate (public)

Star average + count. Optional one-line public "this person/space is solid" pull-quote per reviewer.

Detail (private)

Long-form notes between the rated party and the rater. Visible to collective admins only on dispute.

Edge-case handling and arbitration policies are an open question for the collective — see §16.

09 — External

Integrations

Four external surfaces where GPortal pulls or interoperates: music platforms (Spotify + SoundCloud + Bandcamp + Apple Music), the 19hz event feed, Will's event.tools, and the Fetz intake form schema.

Music platforms Artist preview & embed

Every artist profile gets an embedded preview player so VJs and venues can sample an artist's actual sound before booking, and so artist research surfaces "what music am I designing visuals for?" in one click. Visual-design choices are genre-sensitive; today VJs Google an artist's Spotify after the booking locks. GPortal moves that step to before the conversation starts.

PlatformAuthWhat we getTier
Spotify PKCE OAuth (reuse from WallSpace) Latest album, top tracks, monthly listeners, follower count, official iframe player. TOS-compliant: display-only metadata, audio stays in Spotify domain. v0.5
SoundCloud None — oEmbed Public oEmbed widget (any track or profile URL). Metadata limited to title + thumbnail + artist name. Critical for underground / pre-Spotify artists. v1.0
Bandcamp None — oEmbed Embed widget for tracks + albums. Important for the experimental / DIY tier. v1.5
Apple Music None — embed widget music.apple.com /embed/ works without auth. Artist or album page. v1.5

Profile fields (per-artist, all nullable): spotify_artist_url, soundcloud_url, bandcamp_url, apple_music_url, plus a preview_track_url the artist designates as their "listen to this first" calling card. Player UI: small embed on directory cards (collapsed; click to expand-and-play), full-size embed on the Artist detail page, and an "Open in [platform]" deep-link as the always-available escape hatch.

19hz.info CSV feed confirmed

19hz.info publishes plain CSV feeds at predictable URLs (https://19hz.info/events_<Region>.csv) with no auth and no API key — verified via the public phi-line/19hz.bot Discord bot scraping the same feeds. Available regions: BayArea, LosAngeles, Atlanta, Texas, Miami, Massachusetts. CSV columns: date, name, genre, location, time, price, ages, promoter, url1, url2, datetime.

Event-feed landscape v0.5 expansion

19hz covers underground West Coast electronic well, but a national, multi-genre footprint needs more sources. Below is the landscape we surveyed (per docs/SC5/vj_event_api_landscape.pdf), with the ingestion strategy GPortal will follow as we expand outward from the West Coast electronic feed.

SourceAPI?Best forStrategy
19hz.info CSV feed (no auth) Underground electronic, 6 US regions Live in v0.5 Cron Worker pulls every 30 min; primary feed for early launch.
EDM Train Public REST API Plug-and-play electronic events nationwide Core API. Add as second feed in v0.5; same events_external table with source='edmtrain'.
JamBase API (developer key) US live-music coverage; broad genre Backup feed; fills gaps EDM Train misses (jam, jazz, indie, festivals).
Bandsintown Artist-events API Artist-side enrichment Enrichment, not aggregation. When an artist profile lists a Bandsintown URL, pull their tour dates to seed availability + cross-reference incoming gigs.
Songkick Enterprise API only Strong global dataset Defer until partnership / pricing makes sense. Not a v1 dependency.
Eventbrite Public API Mainstream + mixed-genre events Noisy; ingest with strict filters (city + tags) only when a region requests it. Default off.
Resident Advisor None — scrape Underground / club / techno Scraping layer (post-MVP) Critical dataset; queue-backed scraper, polite cadence, robots.txt-aware. Cache aggressively to minimize traffic.
Shotgun None — scrape Emerging promoter ecosystem Same scraping pattern as RA. Surface promoter contacts into the lookup_cache for outreach.
Facebook Events Restricted API Underground event discovery Leave for later — access barriers + ToS friction. Watch for policy changes.

Ingestion architecture (v0.5+):

event.tools (Will's product) Post-MVP

Future integration target. We want to hear what Will needs from GPortal before designing the interface. Listed here so it's not forgotten; not on the v0.1 critical path.

Fetz intake form

Reference doc: Fetz Artist/Event intake form. Used as a field-list reference when designing the Artist + Event intake schemas. No live integration; just structural inspiration.

10 — Push direction

VJ Outreach & Business Development Flagship growth feature

Live-music bookings outpace visual-element bookings — most events run with simple lighting because no one pitched the artist or venue. GPortal turns 19hz from a passive feed into an active BD engine, handing VJs the right event + the right context + the right template at the right moment.

The VJ growth loop

  1. Browse 19hz events filtered to "no GPortal VJ attached."
  2. Click event → Research panel pops up with artist socials, venue website, booking contact, recent activity, mutual GPortal connections.
  3. Click Pitch → pick template + channel (email / Instagram DM / comment / story reply) → personalize via variable substitution → send (or copy to clipboard for native compose).
  4. Outreach is auto-logged in the VJ's CRM view + soft-claimed in the collective — other Gooism VJs see "already pitched by X on date Y." No duplicate spam.
  5. Status tracked: sent / opened / replied / declined / booked. Booking confirmation feeds the ratings system (only people who actually worked together can rate).

Lookup / Research module

A research-aggregator usable on any artist, venue, or promoter — not just outreach contexts. Cached per target (14-day TTL) so repeated visits don't hammer external services.

Outreach template library

Curated by the collective, customizable per VJ. Faceted by:

Template versioning + anonymized A/B success-rate tracking ("Template Y replied 38% of cold emails to BayArea venues") so the collective improves the library over time.

Outreach log (CRM-lite)

Per-VJ. Per-target row with channel + template + sent_at + status + response_at + notes + follow-up reminder. Filterable by target type / status / date range / event. CSV export for VJs who keep their own pipeline tools.

Collective claim & etiquette layer

Privacy boundaries

Outreach log is private to the sender + collective admins. Recipients (artists, venues) never see GPortal-internal notes or status. Public "X has worked with Y" badges only after a confirmed booking — never from outreach alone. VJs can opt out of leaderboards / aggregate stats while still using the tool.

11 — Pull direction

Hiring & Bookings

The inverse direction: artists and event spaces actively hiring VJ talent. Pairs with §10 to make GPortal a fully bidirectional matching engine.

End-to-end streamlining (the unifying value)

Today, a venue that wants visuals usually has to route the conversation through the artist's manager → artist → "do you know a VJ?" → friend-of-friend → eventually a VJ. Information loses fidelity at every hop — the venue's actual capability spec, the date, the budget, the rig.

GPortal collapses this. A venue (or artist) can directly look up VJs by availability + skill + venue experience + rate compatibility, request a quote, exchange the missing context inline, and move into project management — all in one thread, with no third-party hand-offs. Same path works in reverse for VJs reaching artists. The artist stops being an unwilling middleman; the venue stops getting under-qualified VJs; the VJ stops getting incomplete briefs.

Three entry points

Open gig listing

"Looking for a VJ" — posted by an artist or event space; visible to all VJs; multiple applicants compete; lister picks one.

Direct booking request

Browse VJ directory → click profile → "Request booking" → structured inquiry lands in the VJ's inbox.

Buy a package Fast path

Browse packages directory or a VJ's profile → click "Book this package" → structured purchase with the price, scope, and lead time pre-defined. Skips the multi-message negotiation when the package fits.

Package buy flow

  1. Buyer (artist or space) sees a package card with Buy button on the VJ's profile or in the packages directory.
  2. Click → modal: target date(s), venue (autocomplete from Spaces or freeform), event description, optional add-ons (from addons_json), travel surcharge calculated automatically based on venue location, total price shown.
  3. Buyer confirms. If buyable_directly=true, the package goes straight to the VJ's inbox as booking_requests.status='pending' with a package_id set; the VJ accepts (auto-confirms event) or counters (returns to negotiation flow).
  4. If buyable_directly=false, the package surfaces but routes through standard inquiry — the VJ wants to vet fit before committing.
  5. Confirmation creates events_internal with the package snapshot frozen on the event record (so future package edits don't change historical bookings).

Open gig flow

  1. Artist or space clicks Post a gig → form: event date(s), venue, genre / vibe, required skills, required tech, expected duration, budget range, application deadline, additional notes, contact preferences.
  2. Listing goes live in the Open Gigs feed — public board filterable by region / date / genre / budget overlap with the viewer's rate range.
  3. Eligible VJs (matching rate range + skills + availability) see the gig with a green badge; near-misses see it greyed; out-of-budget hidden by default with a "show all" toggle.
  4. VJ clicks Apply → form pre-filled from their profile (portfolio link, rate, recent work) + a personalized message + 1–3 portfolio reels. One click to submit.
  5. Lister sees ranked applications (sortable by rate / experience / venue history / portfolio match). Shortlist, message any applicant, decline politely with a one-tap template.
  6. Confirmation creates an events_internal record with primary_vj_id set; remaining applicants get a courtesy decline.

Direct booking flow

  1. Visitor on a VJ profile clicks Request booking → modal: target date, venue (autocomplete from Spaces + freeform), event description, budget offer, message, expected response window.
  2. Request lands in the VJ's inbox; status pending.
  3. VJ can: accept (confirms event), counter (proposes adjusted rate / date), decline (with optional template), or refer (forward to another collective VJ if unavailable — strengthens the collective's reliability story).
  4. Confirmation creates events_internal and locks the date in the VJ's calendar.

Trust signals on listings

Collective broker mode v1.5

A venue or artist posts a gig with target=collective instead of choosing a specific VJ. The collective coordinator (or an automated rotation) routes it to the best-fit available VJ. Reduces the search burden on first-time clients.

12 — Funding

Grant Spec'ing & Fundraising Post-MVP / v2.0

Non-profit events — community shows, accessibility-focused performances, educational outreach, benefits — should be able to pursue grant funding and sponsorship without leaving GPortal. Dovetails with Gooism's potential 501(c)(3) status (proposed; pending collective + legal review — see Proposed Org Structure) and the explicit accessibility-for-visual-art mission.

Why this lives in GPortal

VJs and event planners regularly want to fund community-focused work but lack the legal vehicle, the grant-database knowledge, and the time to draft applications. Embedding the workflow next to event planning means a single thread — "this is the event, this is the budget, here are the grants that match, here's the draft application" — instead of three disconnected tools.

Module surface

Grant directory

Curated DB by category: visual + digital arts; music / live performance; accessibility (deaf / hard-of-hearing — direct Gooism mission); community + cultural; local / regional; foundation; corporate sponsorship; crowdfunding. Each entry: eligibility, award range, deadline cadence, applicant-type requirements, past-success notes.

Match engine

For an events_internal flagged non_profit=true, ranks grants by eligibility match, award size relative to budget gap, deadline feasibility (most arts grants want 3–6 months lead time — hard-filter anything that can't make the deadline), past-success rate within the collective.

Application drafting

Templates + AI-assisted (Claude API) drafting: letter of intent, project narrative, budget narrative (auto-populated from Event Planner), outcomes framework, boilerplate for Gooism collective + applicant-entity status (pending Proposed Org Structure review) + accessibility mission, references to past grant-funded events.

Sponsor outreach (parallel rail)

Same workflow as VJ Outreach (§10) but targeting local businesses (cash + in-kind asks: gear loan, venue donation, hospitality), corporate sponsorship programs, crowdfunding kick-off (Kickstarter / GoFundMe / Patreon scaffolding).

Application tracker

Per-event funding pipeline: applied / under review / awarded / declined / withdrawn. Stacking visualization (multiple grants against one event budget). Cash-flow timeline (when each award disburses). Match-funding tracking (some grants require 1:1 match).

Award compliance & reporting

Required reporting cadence (interim + final), documentation requirements (photos, attendance, demographics, accessibility metrics), final report templates pre-populated from event metadata, reminder cadence so reports don't slip.

Accessibility-funded path (Gooism flagship)

Events that include captioning / sign interpretation / hearing-loop accessibility get a dedicated grant filter — accessibility-specific funders (e.g. NEA Accessibility, regional Deaf-arts foundations, ADA-compliance grants) often fund things general-arts grants won't. The collective's existing A.EYE.ECHO + Matt-led accessibility work makes this a credible applicant story.

Trust & legal

13 — AI surface

AI Assistant (Claude-powered)

Modeled on the gifting app's existing "opus generate" pattern. One Claude-API surface inside GPortal, surfaced contextually wherever drafting, personalizing, or triaging is the bottleneck. Every AI-touched output is logged with ai_assisted=true for transparency, and the user always reviews + edits before anything sends.

Surfaces (in priority order)

  1. Targeted outreach drafts (§10) — primary use case. Personalized draft + 2 alternates ("warmer" / "tighter") + tone-confidence note.
  2. Booking-request response suggestions (§11) — 3 reply drafts: accept-with-confirm, counter-offer, polite decline. Pre-filled with calendar conflicts, rate-overlap analysis, referral suggestions.
  3. Profile bio assistance — "Describe my style based on my portfolio + recent events" generates a 60–120 word bio. Same for tech-rider summaries on Artist profiles + space-description blurbs on Venue profiles.
  4. Gig listing description (§11) — draft a compelling listing from the structured fields. Reduces the blank-page intimidation that kills posting rates.
  5. Inbox triage — summarize the VJ's unread messages: "3 booking requests, 1 needs a reply by Thursday, 1 likely a tire-kicker based on budget mismatch."
  6. Grant application drafts (§12) — same Claude pipeline; letter of intent / project narrative / budget narrative / outcomes framework, all pre-populated from event metadata + collective boilerplate.
  7. Lookup-result enrichment — AI summarizes "what to know in 30 seconds" from the Lookup module's findings.

Implementation pattern

Trust + transparency

Every AI-generated draft has a visible "AI assisted — edit before sending" banner. The final stored body is always the edited version the user actually sent, not the raw AI output — this avoids inflating success-rate metrics on AI drafts that humans heavily rewrote. Aggregate analytics ("AI-assisted drafts replied at X% vs. manual at Y%") published to the collective for honest evaluation; per-VJ usage stays private.

Funder-facing surfaces (grant applications) carry an explicit AI-disclosure flag — some funders prohibit AI-generated narratives, and we surface the rule in the directory entry for that grant.

Privacy guardrails

14 — Plan

Roadmap

Four tiers, additive. v0.1 is the spec doc + skeleton. Each tier is shippable on its own; we don't gate on the next one.

v0.1 — this week
Foundation
  • This spec doc
  • GPortal app skeleton
  • One directory (VJs) end-to-end
  • Static Signal Planner mockup
v0.5 — 4–6 weeks
Three directories live
  • All three directories + auth-gated edit
  • Search incl. rate-range filters
  • Calendar manual-entry
  • Event Planner v1
  • Interactive Signal Planner with save/load
  • 19hz Cron Worker ingestion
  • Direct booking requests
  • Spotify artist embed
  • VJ packages — schema + create/edit + browse-by-category directory + buy-flow MVP
v1.0 — matchmaking
Bidirectional matching
  • Calendar sync (Google + iCal)
  • Chat / shared inbox
  • Ratings (gated to confirmed bookings)
  • Event Planner auto-derivation
  • Signal-graph templates
  • gooism.org migration
  • VJ Outreach v1 (Lookup + templates + log)
  • Open gig listings
  • SoundCloud oEmbed
  • AI Assistant v1
v1.5 → v2.0
Collective + non-profit
  • Collective claim system + etiquette
  • Collective broker mode
  • Outreach analytics
  • Bandcamp + Apple Music embeds
  • AI Assistant v2 (gig drafts, triage, enrichment)
  • v2.0: Grant Spec'ing module
  • Accessibility-funded grant path
  • Grant-writer marketplace
15 — Build

Tech stack & infra

Reuse over rebuild. The app sits on Cloudflare's stack (already provisioned for wallspace.studio); auth carries over via cross-subdomain cookies; UI primitives port from the gifting app; the node editor is the one new dependency.

LayerChoiceWhy
FrameworkNext.js 16 (App Router)Mirrors the gifting app; React-first which we need for xyflow; Server Components for DB-backed list views; Server Actions for forms.
HostingCloudflare Pages + OpenNext@opennextjs/cloudflare; same deploy paradigm as gifting; subdomain gportal.wallspace.studio for v0.1.
UI primitivesshadcn/ui + Radix + TailwindPort from gifting src/components/ui/. Battle-tested form / dialog / tabs / dropdown.
Node editor@xyflow/react (MIT)De-facto standard React node-graph library. Beats rete.js (more boilerplate), drawflow (vanilla but ugly), and roll-your-own.
AuthReuse wallspace.studio JWT + Google/GitHub/Apple OAuthAlready wired. Cross-subdomain cookies via Domain=.wallspace.studio. A wallspace account is a GPortal account.
DB — identityExisting AUTH_DB D1 bindingUsers table already lives there. We just FK user_id.
DB — GPortal dataNew GPORTAL_DB D1 bindingVJ / Artist / Space profiles, events, hiring, outreach, grants. Independent schema evolution.
Media storageExisting MEDIA_BUCKET R2Reuse signed-upload pattern from assets/web-functions/api/upload.ts.
AIAnthropic SDK + prompt cachingClaude Opus 4.7 / Sonnet 4.6. Port pattern from gifting's ai-provider.ts.
MusicSpotify Web API + SoundCloud/Bandcamp/Apple oEmbedSpotify port from WallSpace; everything else needs no auth.
19hz feedCloudflare Cron Worker + CSV parsePublic CSV; 30-min schedule; content-hash diff.
EmailResend (port from gifting)For transactional notifications + decline / accept / reminder emails.

Repo layout

// New repo at ~/Downloads/gportal/ gportal/ src/ app/ layout.tsx // auth-aware shell page.tsx // landing vjs/page.tsx // directory list + search vjs/[id]/page.tsx // VJ detail vjs/new/page.tsx // add VJ form (auth-gated) artists/ // stubbed v0.1, fleshed v0.5 spaces/ // stubbed v0.1, fleshed v0.5 planner/page.tsx // xyflow demo (read-only sample graph) api/ vjs/route.ts // GET (list + search) / POST (create) vjs/[id]/route.ts // GET / PATCH / DELETE ai/generate/route.ts // AI Assistant (v1.0+) auth/me/route.ts // reads wallspace JWT cookie lib/ auth.ts // JWT verify (port from wallspace _auth.ts) db.ts // D1 helpers (port from gifting) schema.sql // GPORTAL_DB schema ai-provider.ts // Claude SDK wrapper components/ ui/ // shadcn (port from gifting) directory/ // generic — reused by all 3 entity types planner/ // xyflow wrapper + node-types wrangler.toml // AUTH_DB + GPORTAL_DB + MEDIA_BUCKET open-next.config.ts
16 — For the collective

Open questions

Decisions GPortal can't make alone. These should land at office hours so the schema + UX commit cleanly.

  1. Membership model. Invite-only? Application-based? Open with verification? How does someone become a Gooism VJ vs. a non-collective participant in the directory?
  2. Ratings gating. Confirmed-event-only, or freer? Anonymous, or attributed? How are disputes handled?
  3. Pay-range visibility. Are rate ranges shown publicly, only to authenticated members, or only after a match-request handshake? Trade-off: transparency vs. anchoring / lowballing dynamics.
  4. Pricing recommendations. Should GPortal opine on rates (collective median, tier suggestions) or just show comparables? Tied to whether the platform takes any normative stance on fair pay.
  5. Cost-split defaults (rider/services). Published collective standard, or per-event?
  6. Hiring fees / collective take-rate. Does GPortal charge for confirmed bookings (small flat fee, % of fee, subscription)? Different rates for custom bookings vs. package purchases? Implications for whichever org structure the collective approves (see Proposed Org Structure) and the relationship to commercial WallSpace.
  7. Package economics & quality control. Are packages curated by collective admins (vetted before going live), or self-serve with abuse mitigation? Refund / dispute policy when a package's promised scope doesn't match delivery? Insurance / liability for hardware-heavy packages (CRT clusters, custom mounts)?
  8. Outreach etiquette enforcement. Are cooldowns and max-pitches-per-event hard limits or just visible friction? Who arbitrates disputes ("X poached my pitch")?
  9. Collective broker mode coverage. Who acts as the broker (rotation, volunteer, automated)? What's the SLA on routing a gig to the right VJ?
  10. Outreach data privacy. Is the outreach log fully private to the VJ, or visible to collective admins for safety / dispute review? Privacy vs. accountability.
  11. Grants & fundraising governance. What's the relationship between any future Gooism non-profit entity (pending Proposed Org Structure review), per-event fiscal sponsorship, and individual applicant grants? Who curates the grant directory? Does the collective take any cut of awarded grants for platform sustainability, or does 100% pass through?
  12. AI-assisted application drafts. On-demand opt-in, or always-available? Disclosure language to funders that AI assisted a draft? (Some funders explicitly prohibit AI-generated narratives.)
  13. Data ownership when someone leaves the collective. Their profile data, their outreach log, their event history.