UGC campaign platform for brand marketing
A Golang and Svelte platform letting brands run user-generated-content competitions across Discord and hosted campaign sites — submission, moderation, judging and winner announcement in one pipeline.
Overview
Built for PlayerState — the third of three engagements for them across four years. A marketing platform where brands run creative competitions: a brand sets a theme, gets a customised campaign site hosted on the platform, and embeds a Discord bot into their own server. The bot runs the competition where the community already is — inviting entries, managing submissions, and pushing results back — while the backend handles moderation, ranking and winner selection.
Problem
Brands wanted to run creative competitions in the communities they already had, which meant Discord, not another destination site nobody visits. But a competition open to the public produces two problems at once: a large volume of user-submitted images and video that has to be stored and served, and an unfiltered stream of content that someone at the brand has to actually look at. The second problem turned out to be the harder one.
Constraints
- Greenfield build under time pressure — sole engineer
- Submissions are arbitrary public UGC: images and video, unmoderated at source
- Brand reviewers are marketing staff, not moderators — their attention is the scarce resource
- Campaign sites had to be brand-customisable but hosted and operated by the platform
- Discord is the primary surface; the web app supports it rather than replacing it
Approach
Treat Discord as the campaign runtime and the web platform as the control plane. The bot handles invitation, submission capture and announcement inside the brand's own server; the backend handles ingest, storage, abuse controls, and the judging workflow. Campaign microsites are generated per brand from the same backend, so a campaign has one source of truth across both surfaces.
Key Decisions
Run the campaign inside the brand's own Discord server rather than on a destination site
The audience for a brand's creative competition is already in that brand's community. An embeddable bot meets entrants where they are, which matters far more for entry volume than any amount of polish on a standalone site.
- Web-only campaign sites with social sharing
- Native integrations per social platform
Multi-tenant campaign sites generated by the platform, not handed over as templates
Brands wanted a campaign-specific look without wanting to host or operate anything. Generating and hosting the sites kept one source of truth for entries and judging, and meant a campaign could not drift out of sync between Discord and the web.
- Static templates handed to the brand's own web team
- Embeddable widget dropped into the brand's existing site
Design the judging workflow around reviewer attention, not just throughput
Automated abuse controls stop the worst of it reaching a human, but a large campaign still leaves far more entries than any marketing team wants to read. The ranking and shortlisting tools existed to make the pile tractable, which is a different problem from making the pipeline fast.
- Raw submission list with manual filtering
- Purely automated scoring with no human judging
Tech Stack
- Golang
- Svelte
- Discord API
Result & Impact
Brands could launch a themed competition, run it inside their own Discord community, review and rank entries through the platform, and push winners back to Discord — without operating any infrastructure themselves. The submission, moderation and judging path worked as one pipeline rather than a set of disconnected tools.
Learnings
- Open UGC is two capacity problems, not one — storage and bandwidth are the easy half, and reviewer attention is the half that actually limits campaign size
- Meeting an audience on the platform they already use beats building a better destination, almost regardless of how good the destination is
- Built today, the triage layer would be an LLM pass ahead of the human reviewer — the tooling then could only rank and shortlist, not summarise or pre-filter on content