Wedge StudioStart

Wedge Studio, websites, web apps and internal tools

Case studies

Image model companyInternal tool

Growth team HQ

The internal tool an image model company's growth team ran its week from. Outreach, listening, events and brand protection in one place, with an assistant that answers from the team's own data.

Client
An image model company
Scope
Internal tool, data pipelines, AI
Launched
July 2026
Link
Private to their team

We started working with an image model company in the summer of 2026, alongside their growth team. That team ran a lot at once. Student programs, creator partnerships and press outreach lived in their CRM, talk about the product was spread across more than a dozen sites, and events had a platform and guest lists of their own.

It started as one screen. We sketched an outreach dashboard with no backend at all, and gave its sample data the same shape as their CRM, so the real data could slide in later without the screens changing. The sidebar already listed what might come next, a content calendar, events and a story library, all greyed out.

Over the next weeks those grey items became real views, and more arrived behind them. By late July the team had one place for the whole week, fourteen views behind one sign in, fed by its own collectors and a careful AI layer.

14
views in one tool
13
sources listened to
30 min
between background refreshes
1
sign in for the team

What we built

  • An outreach pipeline kept in step with their CRM
  • A drafting desk with templates, voices and AI rewrites
  • A content calendar that shares its grid with events
  • Social listening with digests that cite their sources
  • A mentions archive covering the last twelve months
  • Brand watch for copycat sites and fake API sellers
  • Events with synced guest lists and sorted attendees
  • A search bar that also answers questions
  • AI spend tracked by task, every call sized to the job
  • A live photo wall for their events
The overview, shown with invented demo data
The overview, shown with invented demo data

One place for the week

The overview opens on what needs attention. Overdue next steps, new brand findings, a listening source that failed or a scan that went stale, each one a row that jumps straight to where it gets fixed. Below that sit the pipeline, the content month and the last week of listening.

Drafts that are ready to send are left off that list on purpose. They are steady work, and the list is kept for exceptions.

Outreach and drafts

Every partner group has its own flow, from the first email to an active partner, and changes made here are written back to the CRM. When the CRM is slow, the tool answers from its last copy straight away and refreshes in the background.

The partner pipeline, every name and address invented
The partner pipeline, every name and address invented

Drafts is where the emails get written. Each group and stage has a starting template, there are four voices to write in, from warm and personal to press formal, and one line of instructions asks the AI to make a draft shorter, warmer or closer to the person's latest work. Edits save as you type.

Writing an email from the queue, sample data
Writing an email from the queue, sample data

The content calendar

Ideas, drafts, scheduled pieces and published posts sit on one month grid, with the team's hosted events on the same days, so a launch week reads as one picture. The overview counts come from the same model as the calendar, so the two numbers always agree.

A month of content and events, sample data
A month of content and events, sample data

Listening across the open web

Collectors read thirteen sources, from Reddit, Hacker News, Bluesky and YouTube to news sites and the open web, every thirty minutes in the background. Each mention is tagged for tone and topic, and a digest sums up any time window, with the posts behind every point one click away.

Light, Listening in light and dark, sample dataDark, Listening in light and dark, sample data
Listening in light and dark, sample data

Some platforms cannot be read without signing in, so we left them out rather than show half a picture. A number a site does not publish stays blank instead of showing as zero.

A year of mentions

The mentions archive keeps a year of conversation and uses the same chart as Listening, so the two views always line up. Every mention lands in positive, neutral, negative or unclassified, and the unclassified count is expected to reach zero.

Twelve months of mentions by tone, sample data
Twelve months of mentions by tone, sample data

Keeping it clean took work, because plenty of what the searches returned was about something else entirely. An AI pass reviews new mentions for relevance, and anything ruled out goes on a list the next refresh respects, so it never comes back.

Brand watch

Scans search the web for sites using the company's name. An AI reads each one against a written list of what the company actually runs, then marks copycats and sites selling fake API access with a risk level and a takedown flag. New findings wait on the overview until someone triages them.

Brand watch, with invented domains
Brand watch, with invented domains

Events and the people who come

Events pulls in every hosted event and its guest list from their events platform. Each attendee is sorted into a group, such as student, creator, engineer or press, from what they wrote when they registered, and people who come to several events are merged into one record.

None of that is written into the CRM. Anything that does reach outward, an invite, a guest status or a new event, asks for a second click first.

An upcoming event and its guests, all invented
An upcoming event and its guests, all invented

Search that also answers

Command K opens one search over every view, partner, contact, event, post and template. Type a question instead, and the last row hands it to the assistant.

One search across the whole workspace, sample data
One search across the whole workspace, sample data

The assistant answers only from the team's own data, which it reads in full, and it cites what it used. A cited post, contact or calendar entry is a link that opens the exact thing. When someone pushes back, it checks the data again and stands by the numbers the data supports.

AI that watches its own cost

Every AI task goes to a model sized for it. Small, fast models sort and tag, larger ones write the digests, and the largest is kept for a single job. Each call is fingerprinted so the same input is never paid for twice, and Settings breaks the cost down by task and by day, so a mistake shows up as a spike.

AI cost by task, with invented numbers
AI cost by task, with invented numbers

Built to keep running

The server is plain Python with no outside packages, and everything lives in one SQLite database. Large collections are stored one row per item, so saving a big archive after one new post writes a single row. A snapshot is taken every day and the last seven are kept.

Bugs that cost the team time became tests, one per regression, so each one stays fixed.

Design

The look went through three passes in one day. We tried a bolder editorial redesign and set it aside. The final version is the calm one, white panels on an off-white canvas, with every fact stated once, one status signal per row and empty spaces hidden until there is something to show.

On a phone the sidebar folds into an icon rail, sample data

A photo wall for their events

One more piece shares the same server. Guests at the team's events upload photos from their phones, and the photos appear live on a big screen. Every upload is checked by its real file type, rebuilt to strip location and camera data, and rate limited, and the wall is run from a small control panel behind the team sign in.

Where it ended up

By the end of the summer the growth team had one tool for outreach, listening, events, brand protection and the content calendar, with an assistant that answered from their own data. Every screen on this page is the real interface, run locally with invented data, with names and details changed to keep the company private.