Papu Studio
← All work
Operator back-officein production with first customers

Korppi Console

The multi-brand back-office behind every brand Joona ships.

A multi-brand operator console that owns the funnel end to end: prospects restaurants from Google Maps, enriches decision-maker contacts, drafts personalised cold openers, runs reply-aware drip sequences, classifies inbound mail, books demos, tracks MRR, and handles support email. First customer is Pisteo. Easy Host, Caravan Helsinki, Umami Catering, and Papu Studio plug in by changing one config value.

What it does

  • AI-driven restaurant prospecting from Google Maps with decision-maker enrichment
  • Personalised cold openers and drip sequences that pause the moment a reply lands
  • Unified inbox with auto-classification of inbound replies
  • MRR + pipeline dashboard wired to Stripe and Cal.com webhooks live
  • Multi-brand from day one — one console, every brand on the same schema
Korppi Console dashboard showing MRR, demo pipeline, and the unified inbox side by side

Pisteo is a Finnish restaurant SaaS: QR ordering, kiosk, takeaway, cashier, reservations, the works. Stripe handled billing, Cal.com handled demo bookings, HubSpot would have handled the CRM, Front would have handled the support inbox. That stack adds up to about €600 a month and three browser tabs, and it still doesn't auto-prospect restaurants from Google Maps, find a venue's decision-maker on their own website, write a personalised cold email opener for each lead, or pause a drip sequence the moment someone replies. Pisteo came to us because the off-the-shelf admin stack covered billing and meetings but left the actual sales motion to spreadsheets. We built the back-office that closes that gap, and the same shell now scales to every brand Joona runs.

Why it was developed

Pisteo had the customer-facing app live and was ready to start signing restaurants. The bottleneck was on Joona's side: every part of running the business lived in a different tool. Stripe for invoices, Cal.com for demo bookings, a Notion doc for prospects, a Gmail folder for replies, Buffer for social, ChatGPT for first-line personalisation copy-pasted by hand.

He could have stitched HubSpot, Intercom, and Retool together. That covers the obvious surfaces but leaves the work he actually spends time on: identifying which Helsinki restaurants are using a switchable POS, finding the owner's email from the restaurant's own website, writing an opener that references that specific venue, and knowing which replies need a human and which can stay in the sequence. None of those are line items in an off-the-shelf CRM.

We built Korppi Console: a back-office shell that owns the funnel end to end and is structured from day one to support every brand Joona runs, not just Pisteo. First customer is Pisteo. Easy Host, Caravan Helsinki, Umami Catering, and Papu Studio itself plug in by changing one config value.

What it solves

Each row is a thing Joona did manually before, and what changed once the console took it over.

  • Finding prospects
    Before
    Searching Google Maps by neighbourhood, copying restaurant names into a Notion doc, pasting URLs.
    After
    One button pulls restaurants in a radius from Google Places, dedupes against existing contacts, and stages them in the CRM.
  • Finding the decision-maker
    Before
    Open the restaurant's website, look for an About page, try to guess the owner's email, give up half the time.
    After
    Claude reads the website and surfaces the decision-maker's name and role. Hunter.io fills in the email when the site doesn't list one.
  • Writing the first email
    Before
    Open ChatGPT, paste in what the restaurant does, ask for a personalised opener, copy back, edit, send.
    After
    Every contact has a one-line opener generated in the background. It merges into the template under {firstLine}.
  • Following up
    Before
    Calendar reminders. Half got skipped.
    After
    Drip sequences in pg-boss run on schedule and pause the moment the contact replies, books a demo, or unsubscribes.
  • Reading replies
    Before
    Gmail, hand-classify intent, decide whether the sequence keeps running.
    After
    Inbound replies land in the console, Claude classifies them (interested / not_interested / question / etc.), the sequence pauses automatically.
  • Booking demos
    Before
    Cal.com email arrives in Gmail. Joona had to remember to update the contact's stage.
    After
    Cal.com webhook flips the contact to demo_booked and stamps the meeting time on the contact card.
  • Knowing where the money is
    Before
    Open Stripe, count active subscriptions, multiply by the right tier price, do it again next week.
    After
    Dashboard shows MRR, plan mix, new MRR this month, and at-risk MRR from past-due subscriptions in real time.
  • Handling a support email
    Before
    Switch to Gmail, write the reply, remember to log it somewhere.
    After
    Reply directly from the inbox, threaded correctly, with a Finnish or English macro one click away. Auto-linked to the customer's workspace if the sender is a known member.

What the goals were

Goals were set at the start of the build, with the launch sprint as the constraint. Numbers below are what we hit, not what we aimed for.

  • Zero-touch outreach loop: prospect → send → reply classification → human only when needed
    Live end to end. Joona reviews replies in the inbox, the sequence handles everything else.
  • All sales and support work in one tab
    Stripe and Buffer are linked out from inside the console. Everything else, including the inbox, lives in /dashboard, /crm, /inbox, /pisteo/workspaces.
  • Multi-brand from day one without scope creep
    brand_id column on every multi-tenant table, routes namespaced under /pisteo/, brand picker can land in a single afternoon when the second brand needs it.
  • Support a customer in 60 seconds, not 5 minutes
    "Sign in as" button on every workspace mints a 15-minute scoped session on the customer app. Audit-logged on both sides.
  • Stay shippable on a shared database without breaking the customer-facing app
    Migrations apply manually against the public DB URL, never on console deploy. Caught the silent-drift Drizzle bug before it broke anything important.

How we reached the goals

Short loops. We worked in two-to-four-hour sessions with the customer in the room. Joona described what he was about to do manually that afternoon, we built it, he used it that evening, we adjusted the next morning. No requirements doc, no Jira, no estimating poker.

AI did the typing, the operator did the thinking. Claude wrote most of the code and most of the prose copy. Joona made every product decision: which integrations matter, what the funnel actually looks like, where the friction was. The work that needed taste, judgement, or knowledge of his own customers stayed with him. The work that was mechanical translation, schema, server actions, page wiring, got handed off.

Ship small, ship often, revert cheaply. Every feature is its own commit. We deployed straight to production because there were no customers yet, so the cost of a bad deploy was a revert and a fresh push. That stopped working the moment the first paying restaurant landed, at which point we added the impersonation contract and tightened the audit log so support could happen without prod access.

Tech we used

Named so any SME owner can search and verify the choices.

  • Next.js 15 + React 19
    App framework and UI

    App Router for clean server actions, React Server Components for cheap dashboards, no separate API layer to maintain.

  • PostgreSQL + Drizzle ORM
    Data layer

    Type-safe queries that read like SQL, migrations as plain .sql files, no Prisma runtime engine to deploy.

  • Better Auth + Google OAuth
    Sign-in

    Email allowlist via a database hook keeps the console operator-only. No invite flow, no password resets to support.

  • Anthropic Claude Sonnet 4.5
    Enrichment, personalisation, reply classification, lead scoring, template translation

    One model, six jobs. Prompt caching keeps the bill low.

  • Google Maps Places API
    Restaurant prospecting

    The source of truth for what restaurants exist in a Helsinki neighbourhood.

  • Hunter.io
    Decision-maker email fallback

    When the restaurant's own website doesn't list the owner's email, Hunter usually does.

  • Resend
    Outbound email + tracking webhooks

    Modern API, proper deliverability, webhooks land cleanly. Replaced needing a separate Mailgun + Postmark setup.

  • Cloudflare Email Worker
    Inbound email pipeline

    Custom code at the edge that POSTs every inbound email to the console with an HMAC-signed body. Replaces Resend Inbound, which Resend doesn't actually offer.

  • Cal.com
    Demo booking

    Webhook fires when a restaurant books, contact stage flips automatically.

  • Buffer
    Social scheduling

    AI composes Instagram, Facebook, and LinkedIn drafts; operator approves; Buffer queues.

  • pg-boss
    Scheduled jobs

    Drip sequences run inside the same Postgres the app already uses. No separate Redis or queue service.

  • Stripe
    Billing source of truth

    Console reads subscription status, never writes. All plan changes happen in Stripe; webhooks flip restaurants.subscriptionStatus.

  • Railway
    Hosting and managed Postgres

    Single dashboard, shared DB across services, env-var management without leaving the project.

  • Sentry + PostHog
    Observability

    Sentry catches the 500s before the operator sees them. PostHog tells us which dashboard cards actually get looked at.

The process

What working with Papu Studio looks like, from first message to the day you own the code.

  1. Discovery

    One conversation, usually under an hour. We map your current tools, where the work actually goes, and the three things that, if automated, would buy you the most time back. You leave with a plain-language brief and a fixed price for the MVP.

  2. Scoped MVP

    Two to four weeks. We pick the smallest version of the system that still earns its keep and ship it to production. You use it on real work from day three or four. We don't write specs, we ship features.

  3. Continuous delivery

    After the MVP lands, we work in short loops based on what you actually do with it. Every change goes to production behind your usual sign-in. You see the change the same day, often the same hour.

  4. Ownership transfer

    The codebase is yours from commit one. It lives in your GitHub, deploys to your Railway, sends from your Resend. When you want to stop working with us, the system keeps running and any developer can pick it up. No platform lock-in, no per-seat fees, no rug-pull.

Running a SaaS? You can buy this same system.

Korppi Console is live and running Pisteo's sales and support today. The architecture, the AI integrations, the inbound email pipeline, the impersonation contract, the multi-brand schema — all of it is solved. The next operator who needs an admin shell for their SaaS gets a version tailored to their funnel without paying for the months we already spent figuring out the shape.

Ballpark: a similar build for another B2B SaaS founder runs roughly half the standard project tier, because the spine is already there. Reach out at hello@papu.studio and we'll start from your three biggest time sinks.

Tier reference

Demanding

€5,000 – €10,000

A real internal product. Multi-user, multi-feature, fits the way your team actually works.

What this tier includes →

Want one like this for your operation?

The hard part, working out the shape of an operator-side console for a multi-brand SaaS, is solved. A similar build for another founder in this space costs roughly half what a from-scratch project would, because the architecture, the migration story, and the AI integration patterns are already proven in production.

Start a project

Want one of these for your team?

Start a project