Groselia

Social media that runs itself

My role

Co-founder
Engineering
Product and brand design

Description

Groselia runs social media for small businesses: strategy, design, publishing, comment replies and reporting, on every channel, from one platform.

Team

Danilo ParmegianiCo-founder
Pedro CritchiCo-founder

Context

I started Groselia with Pedro as a team of two. He runs marketing, sales and operations; I designed the brand and the product and built the platform it runs on, from the database to the last animation. It runs our customers' content and social media today.

Tools

Codex
Claude Code
Figma
Adobe tools

Stack

  • React
  • Next.js
  • TypeScript
  • Tailwind
  • Supabase
  • Anthropic LLMs
  • Trigger.dev
  • Stripe
  • Vercel

Timeline

2025–now

By the numbers

9,700+
commits
520+
pull requests
426
database migrations
47
edge functions
8
social networks
17
languages

Challenge

Building stopped being the bottleneck. Being seen became it.

AI collapsed the cost of making software. A founder with no engineering background can ship a product in a weekend now, and so can everybody else. What didn't get cheaper was getting anyone to notice it. Distribution is a continuous operation, not a task: posting every day, on eight networks that each want a different format, answering every comment, and reading numbers that each app reports differently.

Small businesses pay for that in one of three ways. They hire a team they can't afford, they stitch together a dozen tools that each solve one slice, or they post nothing and pay with growth. Groselia exists to be the fourth option.

How it got here

Groselia changed shape four times before it found what it is. Every turn kept what worked and dropped the rest.

  1. Now

    Service as a software

    We sell the work, not the tool. Our team runs each customer's social media on the platform, which makes one person able to run what used to take an agency.

  2. Sep 2026

    A social media manager

    Customers didn't want AI to make their content. They wanted their own photos posted well and their comments answered. We cut generation and went deep on running the channels.

  3. Aug 2026

    Lovable for marketing

    One conversation instead of a form: describe the campaign and Groselia plans, writes and publishes it. A chat agent with tools, not a roster of bots.

  4. Apr 2026

    Motion video

    Groselia started as Apple-style launch videos made from After Effects templates. I validated the whole pipeline by hand, and then saw it couldn't scale to the quality bar.

  5. 2025

    Argibee

    An AI brand-design platform. It didn't find its market, but its brand-kit engine became the spine of everything after it.

Brand

I wanted Groselia to look like a friendly consumer app, not marketing software: something a café owner would smile at, sitting on a phone next to the apps they love. I designed the brand myself in Figma, and every decision went on one board, measured, so it could be compared and argued with.

The symbol

The symbol came first and stayed. Three soft petals turning around a centre, it carried over from the very first version of the company, and the new logo was built around it rather than over it: its geometry was copied and scaled, never redrawn.

The wordmark

The wordmark is TT Commons Pro Bold, lowercase, outlined into vectors so it renders the same everywhere. At its natural spacing it felt loose next to the symbol, so I tightened it to −4% tracking by moving each letter left by an extra 6.4 units at 160px. It sounds tiny; it took the word from 564 to 520 units wide and made it read as one shape.

A grid of H

Everything is measured in H, the wordmark's visible height, on a grid of H/10. That way the logo scales without anyone having to eyeball it again.

For the stacked logo I drew six options, three symbol sizes (1.50H, 1.75H, 2.00H) against two gaps (0.15H, 0.25H), and we picked B: a 1.75H symbol, 0.15H above the word. For the horizontal one I compared gaps from 0.20H to 0.35H and settled on a 1.10H symbol with a 0.35H gap.

1.75H0.15HH

The stacked logo on its construction grid. H is the wordmark's height; the grid is H/10.

Groselia horizontal logo

Horizontal

Symbol 1.10H · gap 0.35H

Groselia stacked logo

Stacked

Symbol 1.75H · gap 0.15H

Groselia symbol logo

Symbol

Original ratio, 0.93 : 1

Colour

The palette is fifteen colours, loud on purpose. But the logo only ever comes in four treatments: blue symbol with black text, blue with white, all black and all white. The other colours are grounds, never the symbol.

To prove that, I put the symbol and both lockups on twelve backgrounds, 24 studies each, and kept the ones where its silhouette survives. On blue grounds the symbol goes monochrome. Click a colour to copy it.

Typography

TT Commons Pro does every job: six weights from Light to ExtraBold, an eleven-step scale from 12 to 96px, and true italics. I migrated all 688 text layers in the file to it, so the brand book, the app and the website now speak in one voice.

Primary font

TT Commons
Pro

TT Commons ProDisplay · 01
→Groselia@
Reels → Posts
Nº 128⅝ e

App icon

The app icon is the one place the brand goes 3D: the symbol in porcelain, layered, lit from above and a little glossy. In a later refresh I shrank the symbol inside it by 10% so it breathes in its tile. It also gets its own lockup with the wordmark, the tile at 1.5H.

Groselia app icon

A world of 3D objects

Around the logo lives a cast of 3D objects: a heart with googly eyes, chat bubbles, a hashtag, sparkles. They're the brand's voice on the website and in our posts, and they're never still: they float, and on the site they react to the cursor. These do too: shove them, or pull one back and let it go.

Neo doodles

For everything flat there's Neo, our icon set: thick black outlines, fills from the palette and one white shine. On the website each one starts as a plain line icon in a white chip, and turns into its doodle when you hover it, its parts arriving one at a time: the disc pops, the bars drop, the shine draws. These are the website's own doodles and animation, copied as-is. Hover one.

Official connections
Hands off
Pause any time
Everything recorded
Data stays private
Leave whenever
Replies in your voice
Human review
Leads flagged
Paid ads
Landing page
Product redesign
Rebranding
Spark
Heart
Trophy

Product

Everything in Groselia is done by talking. You say what should go out and when, and it schedules it, publishes it, answers the comments and tells you what worked. The work arrives as one plan the owner approves, instead of a dozen screens to operate.

A conversation, not a dashboard

How did last week go?

Best week since June.

  • Reach is up 38%, driven by the latte-art reel (41K views on Instagram, 64K on TikTok).
  • Saves doubled on the espresso carousel. People keep recipes.
  • Comments are waiting. 14 questions about delivery and grind size, most unanswered.

The pattern is clear: video between 5 and 7pm, photos in the morning. I'd follow that for the next two weeks.

2 days ago

Morning! Two things need you this week:

  • The Carmo de Minas harvest hits the shelf Friday, and nothing is planned for it yet.
  • 14 questions are waiting on your posts, mostly about delivery.

Where do you want to start?

Select one
8 minutes ago

Groselia started as a form: pick a goal, fill in the fields, get a campaign. Nobody wants to fill in forms about their own business, so now every brand has one conversation instead.

You open your brand and talk. Ask what you should post this week, drop in photos from your phone, or say “answer yesterday's comments”. The agent looks before it answers: your calendar, what has performed, the brand's memory.

When it needs something from you, it asks one short round of questions you answer with a tap. Then it proposes one plan: the posts with their dates and times, the replies, any changes. You edit what you want, approve it, and watch the calendar fill in.

The card here is the real chat, rebuilt in the browser from the app's own tokens. Go ahead and use it.

Designed twice: for owners, then for us

The first audience was small business owners who run their own social media. They don't think in campaigns, funnels or posting cadences; they think “what do I post this week?”. So the hard part was hiding the machinery: onboarding in four questions, a brand kit filled in from a link, a calendar you can drag, every screen in seventeen languages and usable on a phone.

Then we learned customers didn't want to operate any tool, however simple. They wanted the work done. So we became the main users. One person on our team runs many brands, and the same app had to grow multi-brand workspaces, cycles that open with a meeting and close with a report, an approval step on every post and one inbox for every network. Customers still log in, but now the app is where they watch the work, not where they do it.

November 2026

Mon
103
Tue
113
Wed
123
Thu
133
Fri
143
Sat
152
Sun
162
8:00

Why we pay 40% over market

Imported
6
New harvest
49:00

New harvest: Carmo de Minas

Published
5
Behind the scenes
17:30

POV: first shift at the roastery

Published
Recipes
9:00

How we dial in the espresso

Published
12:00

Unpopular opinion on dark roast

Published
Failed
Behind the scenes
1218:00

Rating our regulars' orders

Published
8:30

Croissant o'clock

Scheduled
3
Hiring
11:00

Meet Ana, our head barista

By hand
RecipesNew harvest+1
17:00

Latte art in slow motion

Scheduled
9:00

What 1 kg of green coffee becomes

Scheduled
7
Behind the scenes
11:00

Inside the roastery, start to finish

Scheduled
Recipes
18:30

Cold brew in 60 seconds

Draft
Needs video
New harvestPromo
9:00

The new harvest is on the shelf

Scheduled
Draft
Hiring
10:00

We're hiring a head roaster

Scheduled
17:00

Iced latte, start to finish

Draft
Promo
10:00

Your Saturday table

Scheduled
15:00

Espresso tonic season is here

Draft
Recipes
11:00

The 4-minute pour-over guide

Scheduled
Promo
18:00

Meet the Oakline bag

Draft
4

Built to be read by agents

More and more, the first reader of a brand or a web page is an AI. So everything in Groselia is written for agents as much as for people. A brand's memory is a set of plain Markdown documents, preferences, do's and don'ts, brand facts, that the agent reads before every reply and edits itself with four tools, the way AI assistants keep their own memory. People open and edit the very same documents in the brand kit.

Insights run through one shared core that both the dashboard and the agent read, so when you ask “what's working?”, the answer comes from the numbers you see. And the website does the same for the assistants people ask about us: groselia.com serves an llms.txt, a longer llms-full.txt and a comparison file, all generated from one source of facts in the code, so what an AI says about our prices or security can't drift from the site.

Engagement over time

Per week, last 30 days, by publish date

Eng. rate7.69%

Key features

  • A brand kit from a link

    Paste a website and connect your accounts. Groselia scrapes the site, reads your past posts and fills in logo, colours, fonts, voice and audience on its own.

  • One conversation

    An AI agent with 41 tools captions your media, picks times from your own engagement data, reads metrics and drafts replies, then bundles it all into a plan.

  • A calendar for eight networks

    Instagram, LinkedIn, TikTok, YouTube, X, Facebook, Threads and Reddit, each in its native format, with past posts imported so the calendar is never empty.

  • Every comment answered

    Comments and DMs from every network in one inbox, with replies drafted in the brand's voice and anything sensitive held for a person.

  • Insights in plain language

    Reach, views and engagement across every account, honest about what each platform does and doesn't report, and an answer to “what's working?”.

  • Cycles and approvals

    Work runs in cycles. Each opens with a meeting, closes with a report the AI writes from the numbers, and every post can wait for the customer's approval.

Website

The website is where the brand gets loud. I designed and built it in Next.js. It's in seventeen languages, and it hands each visitor's language over to the app when they sign up.

A hero you can play with

The logo turns in while the page loads, then the hero: 3D props that float, lean with the mouse and get shoved around by the cursor, and a scroll scene that ends in “Made for you”.

groselia.com
The groselia.com hero: “We run your socials. You run your business.”, with the 3D props around the heart

The real app, rebuilt

“Inside your Groselia” shows the platform as it is, rebuilt in code from the app's own screens with a demo brand.

groselia.com
“Inside your Groselia”: the platform's channel connections screen

A blog

Notes on running social media. Posts are plain MDX files, one per language, with no CMS, and each gets its own feed and structured data so search engines and AI assistants read it right.

groselia.com
The groselia.com blog, the first post lit up under the cursor and more posts below

A form that qualifies leads

Every “Book a call” opens a short form before the calendar: who you are, where you post, what you need and your budget. Each step is saved to our database as you go, so we see even half-finished answers, and a finished form pings our team on Slack.

groselia.com
The booking page: “Let's talk about your social media.”, with the form beside the three steps

Responsive, always

Every page is designed for phones too, not just shrunk to fit. Where there's no hover, the sections wake as they reach the middle of the screen.

The homepage on a phone
“Always in sync with your team” on a phone, its first card awake
The booking form on a phone, at the step that asks what you need and your monthly budget

Engineering

Architecture

I built the platform myself, with AI as my pair. The app is React and Vite, the landing is Next.js, and both sit on one Supabase project: Postgres with row-level security, auth, realtime and storage, and 47 edge functions. Anything slow or scheduled runs on Trigger.dev, the social networks come through one publishing API, and Stripe handles plans, cards and Brazilian boleto.

There's also an MCP server and a Codex plugin, so Groselia can be used from inside an AI agent: the same brands, posts and drafts, as tools.

Where it's used

The core

Supabase

Behind it

The app, the website and the MCP server are hosted on Vercel.

Hover or tap a box to see what it does and what it talks to.

How a post travels

The best way to see how the parts fit is to follow one post, from a sentence in the chat to its numbers on Insights. Click through the steps, or let them play.

Web app

The owner asks

“Post the harvest photos on Friday, Instagram and LinkedIn.” The message goes to the agent's edge function, which streams its answer back.

ReactSSE stream

The agent

The agent runs on Anthropic's LLMs, as one streaming edge function with a tool loop. The model gets 41 tools of its own plus web search and web fetch, up to eight hops per turn. The hard part was never the model. It was making sure the agent always knows what's true right now.

So every turn, before the model sees the message, the function rebuilds the context from the database: the date and time in the owner's timezone, the brand's memory documents, the live calendar, the open plans, uploaded documents and a rolling summary of older messages. The stable part of the prompt is cached for an hour; this part is never cached, so it can't go stale.

Two rules shaped the rest. Anything public or irreversible goes into a plan the owner approves, never straight out. And a post only exists if a tool created it this turn, which ended the days when the agent described work it hadn't done. When Anthropic's mid-size model got good enough, I moved the chat to it from their largest one, to cut the cost per conversation.

Context, rebuilt every turn

Instructions and toolscached for an hour
Date and timethe owner's timezone
Memory documentspreferences, do's and don'ts
Live calendarevery post and its status
Open plansproposed and approved
Story so fara rolling summary
→The LLMAnthropic · up to 8 hops→

Tool calls

✓get_posting_times
✓get_insights
✓propose_plan

Plan, waiting for approval

Harvest week: 3 posts, 4 replies

The agent, building its context
// Volatile block: time + memory + live calendar + active plans + rolling summary.
// Rebuilt each turn (never cached) so the agent always sees current state.
const volatileSystem = () => {
  const parts = [
    nowBlock,
    renderMemories(memories),
    renderCalendar(calendar, todayISO),
    renderPlans(plans),
  ]
  if (documents.length) parts.push(renderDocuments(documents))
  if (rollingSummary) parts.push(`STORY SO FAR (summary of earlier messages in THIS conversation):\n${rollingSummary}`)
  // … then a line for each of the brand's other conversations
  return parts.join('\n\n')
}

Data model

Around 55 tables, in a few clear groups. A workspace has members and brands; everything else hangs off the brand, so row-level security can answer one question everywhere: is this person a member of this brand?

Who

  • Workspaces
  • Members
  • Brand roles
  • Profiles

The brand

  • Brands
  • Colours, fonts, logos
  • Products and people
  • Memory documents
  • Brand documents

Talking

  • Conversations
  • Messages
  • Plans
  • Plan items

The calendar

  • Posts
  • One per network
  • Post metrics
  • Post comments

Channels

  • Connected accounts
  • Daily account metrics
  • Channel settings

Inbox and cycles

  • Inbox threads
  • Inbox messages
  • Reply drafts
  • Cycles
  • Cycle reports

Everything below “Who” carries a brand id; row-level security checks it on every read and write.

Reliability and security

Groselia publishes to real accounts, so the costly failures are a post going out twice, or a post that silently never goes out. Most of the engineering is there.

1Approving twice runs once

The plan runner claims the plan, then each item, with a conditional update, and every idempotency key comes from the item's own id. A double click or a retry replays instead of posting again.

2Webhooks are signed and replayed

Every delivery from the publishing API must carry a valid HMAC signature. Handlers are idempotent because deliveries can arrive more than once, and a job replays any missed event every ten minutes.

3Refuse before queueing

One shared rule file says what each network accepts (Instagram needs media, YouTube needs video, no mixing on Facebook). The scheduler checks it before anything is queued, and a refused post comes back as Failed, with the reason, instead of sitting on the calendar as Scheduled.

4Access checked on every call

Row-level security in Postgres, a role check in every edge function, and MCP access through OAuth with PKCE, scoped per brand and per action, revocable from one page.

For a while my local app and the live one shared a single production database, and a migration that ran ahead of a deploy once emptied the live Brand Kits page. Since then backend work happens on a Supabase branch first and merges into production with the code that needs it.

Quality and workflow

About 1,000 test cases across 140 test files cover the app, the MCP server and the edge functions. Some checks are there because something broke once: a parity test fails the build if any of the 17 languages misses a key, and the database suites for the MCP run on synthetic data and roll back at the end.

The agent has evals of its own. One asks the live agent a fixed set of questions about a brand's performance, each in a fresh conversation, and checks that it read Insights with the right period and that its answer carries the same numbers the Insights page shows.

One person shipped 520+ pull requests by treating AI agents like a team. Every change gets its own branch in its own git worktree, so Claude Code and Codex can work on several things at once without stepping on each other. Each one runs its tests and type checks, opens a small pull request, and nothing merges before I've read it.

A change→Its own worktree→Claude Code or Codex→Tests and types→A small PR→My review→Merge and deploy

Technical challenges

Each one looked like a bug in the interface and turned out to be something deeper: the shape of a stream, a timestamp, what a network really reports, a clock.

Making generation feel live · Realtime

Generating a month of posts took a spinner and then twelve posts popping in at once. It felt slow, but the model wasn't the problem. The granularity was.

I switched the model's output to JSON Lines and streamed it, inserting each post the moment its line closed. The calendar subscribes to Postgres changes over Supabase Realtime and paints placeholders first, so posts type themselves in one by one.

The same wait now feels like watching someone work.

Two timestamps that never matched · Data

Supabase warned the database was about to run out of disk IO. Reads were fine. Something was rewriting the same rows: 344k inserts to store 83k messages.

The inbox sync compared the timestamp it saved with the one it read back. Postgres returned it as +00:00 and we wrote it as Z, so every conversation looked changed and every sweep re-downloaded it. Comparing instants instead of strings fixed it.

Comparing two timestamps
export function sameInstant(a: string | null | undefined, b: string | null | undefined): boolean {
  if (a == null && b == null) return true;
  if (a == null || b == null) return false;
  if (a === b) return true;
  const ta = Date.parse(a);
  const tb = Date.parse(b);
  return Number.isFinite(ta) && Number.isFinite(tb) && ta === tb;
}

Inserts to store 83k messages

344k→one per new message

Conversations re-read each sweep

all→the changed ones

Write churn stopped, and inbox histories that never finished synced for the first time.

A zero isn't always a zero · Analytics

Our analytics provider returns one shape for every network and fills whatever a network doesn't report with 0. Instagram “had” zero clicks on every post. Charts lied politely.

A per-platform metric registry that records what each network really reports, nulls the rest at ingest, and lets every chart show, degrade or hide a metric honestly.

Insights across eight networks that never show a number nobody measured.

Logged out by a fast clock · Auth

My co-founder was logged out the instant he signed in: fifteen token refreshes a second, then a rate limit. Nobody else could reproduce it.

His computer's clock was over an hour fast, so every fresh token looked expired. I wrapped the session storage to re-anchor expiry to the local clock when a session is written.

Token refreshes per second

15→0

Sign-in works on any device clock, and the console says when one is off.

Takeaways

Taste is the moat

When AI makes building cheap, everyone can ship, and most of it looks the same. What's still scarce is judgment: knowing what to leave out, how a screen should feel, when an animation is one too many. For a team of two that can't outspend anyone, taste is what makes Groselia look and work like something much bigger, and it's the one part I'd never hand to a model.

Sell the outcome, not the tool

Nobody wanted to operate marketing software, however good. They wanted to be seen. Selling the work instead of the app made the product matter more, not less: it became the engine we run every day, so every rough edge got fixed.

Context beats cleverness

The agent got better when it knew more, not when the prompt got smarter. Giving it the live calendar, the memory and the open plans every turn, and making it ask before it acts, did more than any model upgrade.

AI changes the size of the team

With agents writing most of the code in parallel, my job moved to deciding what to build, reviewing every change and keeping the bar high. One person can now run what used to take a team, as long as the person stays the editor.