Papu Studio
← All work
Operations + commerce platformin production with first customers

Workshop and trade platform

One app where there were four separate systems.

A Finnish key, lock and auto-electrics workshop that also supplies parts to the trade. The business ran on four separate systems: a legacy e-commerce platform, a point-of-sale at the till, a payment provider online, and a scheduling tool the workshop floor could not reach. We collapsed it into one Next.js app: public booking calendar, in-shop status board on a TV, till with sequential receipts, trade catalog with credit gates, inventory ledger, performance dashboards, Finnish bank-holiday awareness, and a migration off the old platform on its own schedule.

What it does

  • Public booking calendar with per-location capacity, opening hours, and Finnish bank holidays
  • Seven-step workshop status flow on a TV board, mandatory reasons for stopped jobs
  • Till with sequential receipts, VAT 25.5%, daily totals, accounting CSV export
  • Trade catalog with credit-gated invoice ordering and approval queue
  • Microsoft Entra + Google + Better Auth across staff and customer surfaces
Locksmith working on a car key blank at a workshop bench

The client runs a key, lock and auto-electrics workshop for consumers and a parts catalog for the trade. Four systems sat underneath it: an e-commerce platform for the webshop, a point-of-sale at the till, a separate provider for online payments, and a scheduling tool the workshop floor could not see. Four logins, and the same customer modelled three different ways. The webshop platform was the trigger: its upgrade path had become a rewrite in all but name. They came to us to collapse it into one Next.js app — public bookings, in-shop status board, till, trade catalog, inventory, CRM, performance — and to migrate off the old platform on a schedule they controlled. First production deploy went out the same week we started.

Why it was developed

The client serves two audiences from one workshop: consumers who need a key, a lock or auto-electrics, and trade customers who buy parts. The webshop, the till, the online payments and the scheduling each lived in a different system. Each had its own login, its own customer model, its own idea of what a job was. Keeping them roughly in sync ate the supervisor's day.

The webshop platform was the trigger. Its major-version upgrade path is a rewrite in all but name, and the storefront had accumulated customisations nobody was maintaining any more. Replacing it alone would have been a project. Replacing it and rebuilding the rest onto one set of customer and product tables was a bigger project, but the only one that solved the operator problem instead of moving it.

This is that build: one Next.js app serving both the consumer and the trade side, owning bookings, the workshop status board, the till, the trade catalog, inventory, CRM, performance dashboards, and the migration off the old platform on its own schedule. The supervisor opens one app to see the day, take a payment, approve a trade customer, or check the month's numbers.

What it solves

Roughly in the order the day unfolds, from a customer booking online to the till closing at end of day.

  • Customer booking a key job online
    Before
    Phone the shop. The webshop had no booking surface and the scheduling tool was internal only.
    After
    Public month calendar at /varaa greys out past, closed, and full days using real capacity. Customer picks a time, work order opens in the supervisor's queue with the booking attached.
  • Knowing what is happening on the workshop floor
    Before
    Split between the till, the scheduling tool and the supervisor. No shared view of the day.
    After
    Seven-step status flow (Awaiting, Arrived, In progress, Stopped, Add-on order, Ready, Delivered) on a TV per location. Mechanics drive their own jobs; the supervisor watches the board.
  • A stopped job nobody decides on
    Before
    The mechanic flags an issue verbally or in WhatsApp. Sometimes the supervisor sees it, sometimes not.
    After
    Stopped status requires a reason and a note. Alarms after thirty minutes without a supervisor decision at the kassa. Nothing falls through.
  • Inventory drifting from reality
    Before
    Parts decremented by hand at end of day from a printed report.
    After
    Work-order completion writes to an append-only stock movement ledger. Reorder costs are backfilled so the Tilattavat (to-order) view shows true cost without a fresh supplier feed.
  • Taking payment at the till
    Before
    Separate systems for the till and for cards online, no shared receipt numbering, manual VAT reconciliation against the booking.
    After
    Kassa inside the same app, sequential receipt numbers across both branches, VAT 25.5% applied per line, daily totals on the dashboard, CSV export for the bookkeeper.
  • Bank holidays and staff off
    Before
    Mark each year's holidays by hand. Easter movable holidays got missed at least once.
    After
    Per-location 'Fetch Finnish holidays' button computes Easter-derived dates for any year. Each holiday has an opt-in 'staff off' tickbox that drops billable hours and revenue targets for that day, never assumed.
  • B2B customers ordering parts
    Before
    Email, phone, a Google Sheet of prices for trade buyers. Approval lived in the supervisor's head.
    After
    B2B account signup, approval queue, gated catalog, invoice-only ordering with credit terms. Order history visible to both sides. Approval status is part of the customer record.
  • Knowing whether the month is on track
    Before
    Pull the numbers by hand, month after month.
    After
    Management dashboard shows sales today, sales month vs target, open and ready jobs, inventory value, stock alerts, per-mechanic billable hours and utilization, CSAT averages from public 1-5 review pages.

What the goals were

Set at kick-off with the architecture decisions locked in nine ADRs. The build is held to these.

  • Replace the ageing webshop platform
    Migration-first build sequence (ADR 0002). The new schema landed and the importer ran against the old platform's export before any other surface went live. Cutover is incremental, one product family at a time, no flag-day risk.
  • One source of truth for customer, vehicle, job, inventory, payment
    Relational core plus targeted append-only ledgers (ADR 0003), not full CQRS. Customer 360 page surfaces lifetime spend, receipts, B2B status, and vehicle history from one schema.
  • Workshop runs on the floor, not in the office
    TV-per-location board shows the live status flow. Mechanics drive their own jobs from a phone or a kiosk. The supervisor's view is read-mostly until a stopped job needs a decision.
  • Bilingual, Finnish primary
    Staff and customer surfaces ship in Finnish first, English where it matters. The CONTEXT glossary anchors the domain terms so Työnjohto means the same thing in code, in the UI, and in conversation.
  • First production deploy inside week one
    Hit. The first public booking and the first internal work order both went through the real app within the first week, before any legacy surface was retired.
  • Ship daily, verify in the browser, never block on the customer
    Standing rule: every deploy runs typecheck, lint, tests, and build, then verifies live with Chrome before moving on. The customer reads a changelog page listing what shipped and what needs them, owner-tagged.

How we reached the goals

Short loops with the customer in the room. Daily deploys, often several. Each batch ends with a browser verification pass against the live URL and a one-line changelog entry the supervisor reads in the morning. No requirements document, no Jira, no estimating poker.

The ratio is the same as on every Papu Studio build: Anthropic Claude does most of the typing, an experienced operator does the thinking. The model is fast at scaffolding, schema, server actions, the boring glue. The human stays on the architecture (nine ADRs locked early), the safety calls (B2B credit gates, sequential receipts, staff access control), and the decisions that need taste (when a Stopped job alarms, what shows up on the TV, when to push a feature behind a flag).

Sequence mattered. Migration before flair. Schema before surface. Status flow before notifications. By the time the kassa, the booking calendar, the B2B catalog, and the management dashboard all landed, the schema underneath had been carrying real work for weeks and the shape was stable.

Tech we used

Named so any SME owner can search and verify.

  • Next.js + React
    App framework

    One Next.js app serves both the consumer and the trade domain (ADR 0004). Server actions keep mutations close to the database, no separate API layer.

  • PostgreSQL + Drizzle ORM
    Data layer

    Type-safe schema, migrations as plain SQL files, append-only ledgers for inventory and status history. Chosen over Prisma explicitly (ADR 0001).

  • Railway (EU)
    Hosting and managed Postgres

    Single dashboard for the web service, the managed database and its configuration. EU region keeps customer data inside the bloc.

  • Better Auth
    Sign-in for staff and customers

    Credentials, Google, and Microsoft Entra all linked to the same account by email. Trade-customer sign-in lives on a separate route surface from staff sign-in.

  • Microsoft Entra
    Staff SSO

    Staff sign in with their work Microsoft account. Roles are assigned inside the app, not inferred from the identity provider.

  • Stripe (Payments, Terminal, Tax)
    Payments

    Online card payments via Stripe Checkout, in-shop card payments via Stripe Terminal hardware paired on site, Finnish VAT handled by Stripe Tax.

  • Resend
    Transactional email

    Ready emails, owner notifications, review-request flow, B2B order confirmations. Clean Finnish-domain deliverability without enterprise pricing.

  • Twilio
    SMS (planned)

    Reserved for status-change notifications to customers (job ready, work pausing for parts). Wired but not yet enabled, customer holds the credentials.

  • Cloudflare R2 + CDN
    Media storage and delivery

    Product photos, work-order documents, and brand assets. Egress is free, which matters when the catalog grows.

  • Accounting export
    Accounting integration

    Receipts and invoices export as CSV (semicolon, BOM) on a daily schedule, shaped for the bookkeeper's import flow.

  • Anthropic Claude Sonnet 4.5
    Code generation

    Drafts schema, server actions, page wiring, tests, and Finnish copy from English. The operator stays on architecture and safety calls.

The process

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

  1. Discovery

    A grilling session, one to three hours, structured. We map the actual workflow, name the domain terms, and lock the early architecture decisions as ADRs. You leave with a written project context document, a glossary, and a fixed price and date for the first surface.

  2. Scoped MVP

    First production deploy inside week one. Real schema, real auth, real data. From there every change ships behind your sign-in within hours and you verify it live the same day.

  3. Continuous delivery

    Multiple deploys a day at peak. Every batch ends with a browser verification pass and a changelog entry. The supervisor sees what shipped and what needs them, tagged by owner.

  4. Ownership transfer

    The code lives in your GitHub from day one. Railway and Cloudflare are your accounts. The Stripe keys are yours. If Papu Studio vanishes tomorrow, any competent engineer can take the next ticket from the changelog. No lock-in to us, no per-seat fees, no platform tie.

Run a workshop with a webshop and a B2B side? You can buy this same system.

The platform is in production, used daily by the supervisor and the mechanics, with the old webshop running alongside it during the migration. If you operate a workshop that also sells parts to consumers and to the trade, the shape of what you need is close enough to this build that most of the work is a re-skin and a data migration.

A similar build runs at roughly half the standard Complex tier price because the schema, the status flow, the booking and kassa contracts, the bank-holiday awareness, the B2B credit gates, and the migration tooling are already in place. What remains is the operator-specific work: your locations, your product taxonomy, your accounting export shape, your staff roles. If you want to see the production app running before deciding, that's a thirty-minute call.

Tier reference

Complex

€10,000+

A back-office or commercial product big enough that the integrations and edge cases are the hard part.

What this tier includes →

Want one like this for your workshop?

The hard part, working out the right shape for a mechanic-led workshop that also runs a webshop and a B2B catalog, is solved. A similar build for another key, lock, or auto-electrics shop runs at roughly half the standard Complex tier price, because the schema, the seven-step status flow, the booking calendar, the kassa contract, and the bank-holiday handling are already proven in production.

Start a project

Want one of these for your team?

Start a project