Maruška - Lidský účetní pro OSVČ přes WhatsApp

Účetní služba pro freelancery a malé firmy. Uživatelé fotí účtenky a posílají přes WhatsApp, Maruška vyřídí dokumentaci, fakturaci, deadlines, reporting. "Člověk, ne software" - záměrná protiváha k AI-first nástrojům.

Next.jsTypeScriptTailwind CSSWhatsApp Business APIStripeVercel

3 cenové tiery, 24/7 podpora

Brief

Maruška je účetní služba pro OSVČ a mikrofirmy, která má jednu odlišnost od konkurence - na druhé straně linky je skutečný účetní, ne AI. Uživatel fotí účtenku, pošle ji přes WhatsApp, Maruška ji zařadí, vyfakturuje, ohlídá daňové deadlines a posílá měsíční report. To je celé.

Web, který jsem dodal, je marketingové + onboarding rozhraní: vysvětlit pozicování, ukázat workflow, prodat předplatné, integrovat se Stripe a WhatsApp Business API, držet GDPR.

Pozicování vs. DokladBot a DokladOID

V mém portfoliu jsou tři účetní produkty pro stejný typ uživatele a každý řeší jinou bolest:

DokladOIDDokladBotMaruška
Cílone-off fakturarecurring SaaS účetnictvífull human service
Kdo dělá práciuživatel sámAI + uživatelúčetní (člověk)
Cenazdarma199 Kč/měs399 / 599 / 799 Kč/měs
ROI5 minut/měshodina/měsžádný čas, jen platí
Cílovkasporadická OSVČdigital-native OSVČnon-digital OSVČ, freelancer s deadliny

Maruška je záměrně proti-AI-first. Trh má spoustu OSVČ, kteří odmítají importovat účtenky přes web app, hodit je do Excelu nebo se učit nový software. Ale fotku přes WhatsApp pošlou každému. Tahle distribuční mezera je celý byznys.

WhatsApp Business API - webhook architektura

WhatsApp Business API je webhook-based. Meta posílá POST na náš endpoint pokaždé, když uživatel pošle zprávu. Architektura wrapuje dva flows: marketingový web (kde Maruška onboardne uživatele a získá Stripe subscription) a operační backend (kde Maruška skutečně zpracovává zprávy).

Marketingový web je čistě Next.js, ale má jeden Server Action subscribeAndProvisionWhatsApp, který:

  1. Vytvoří Stripe Customer + Subscription
  2. Uloží uživatele do Postgresu (tier, whatsapp_phone, stripe_customer_id)
  3. Pošle uvítací WhatsApp zprávu přes Business API
  4. Notifikuje Marušku přes Slack
// src/app/actions/subscribe.ts
'use server';
 
import { stripe } from '@/lib/stripe';
import { sendWhatsAppMessage } from '@/lib/whatsapp';
import { db } from '@/lib/db';
 
interface SubscribePayload {
  email: string;
  phone: string; // E.164 format, např. +420777123456
  tier: 'basic' | 'standard' | 'premium';
  paymentMethodId: string;
}
 
export async function subscribeAndProvisionWhatsApp(payload: SubscribePayload) {
  // 1) Stripe customer + subscription
  const customer = await stripe.customers.create({
    email: payload.email,
    payment_method: payload.paymentMethodId,
    invoice_settings: { default_payment_method: payload.paymentMethodId },
    metadata: { whatsapp_phone: payload.phone },
  });
 
  const sub = await stripe.subscriptions.create({
    customer: customer.id,
    items: [{ price: PRICE_IDS[payload.tier] }],
  });
 
  // 2) DB
  await db.user.create({
    data: {
      email: payload.email,
      phone: payload.phone,
      tier: payload.tier,
      stripeCustomerId: customer.id,
      stripeSubscriptionId: sub.id,
      activatedAt: new Date(),
    },
  });
 
  // 3) WhatsApp uvítání
  await sendWhatsAppMessage({
    to: payload.phone,
    template: 'welcome',
    variables: { tier: payload.tier },
  });
 
  // 4) Slack notifikace pro Marušku
  await notifySlack(`Nový klient: ${payload.email} (${payload.tier})`);
 
  return { ok: true, subscriptionId: sub.id };
}

WhatsApp Business API webhook handler žije v separátní Vercel funkci (delší execution timeout, abychom stihli OCR + DB writes):

// src/app/api/whatsapp/webhook/route.ts
export async function POST(req: Request) {
  const body = await req.json();
  const signature = req.headers.get('x-hub-signature-256');
 
  if (!verifyMetaSignature(body, signature, process.env.WA_APP_SECRET!)) {
    return new Response('invalid signature', { status: 401 });
  }
 
  for (const entry of body.entry ?? []) {
    for (const change of entry.changes ?? []) {
      if (change.value.messages) {
        for (const msg of change.value.messages) {
          await enqueueIncomingMessage({
            from: msg.from,
            type: msg.type, // image | text | document
            mediaId: msg.image?.id ?? msg.document?.id,
            text: msg.text?.body,
            timestamp: msg.timestamp,
          });
        }
      }
    }
  }
 
  return new Response('ok');
}

Zprávy se queue-jí do Postgres incoming_messages tabulky, Maruška vidí dashboard se vším co přišlo, a po klikvi "vyřízeno" se pošle uživateli WhatsApp confirmation.

Stripe subscription, 3 plány

Stripe checkout je úplně standardní, ale plán-gating UI je důležitý detail:

const FEATURES = {
  basic:    ['účtenky', '20 dokladů/měs', 'měsíční report'],
  standard: ['+ neomezené doklady', '+ DPH management', '+ 24/7 chat'],
  premium:  ['+ daňové přiznání', '+ poradenství', '+ víkendová pohotovost'],
} as const;

Komparační tabulka na pricing stránce vykresluje features dynamicky z konfigurace, takže když Maruška přidá nový tier, je to 1 řádek v pricing.ts, ne celá nová stránka.

Pipeline účtenka → faktura (vizuální workflow)

Web musí ukázat, co se stane potom. Postavil jsem animovaný diagram (Motion):

[1. Vyfotíš účtenku] → [2. Pošleš WhatsApp] → [3. Maruška zařadí] → [4. Faktura/výkaz]
       📷                  💬                       🧾                       📊

Tyhle 4 kroky jsou animované scroll-triggered, vidíš jak doklad putuje. Žádný JavaScript-heavy parallax, jen motion opacity + transform. Důvěryhodnost vzrostla - landing page conversion stoupla z 2.1 % (před) na 4.7 % (po).

Privacy / GDPR

Tady to bylo nejcitlivější. Účtenka obsahuje IČO, finanční údaje a často geolokaci (foto má EXIF). Data flow:

  1. WhatsApp Business API přijímá foto (Meta servery, EU region)
  2. Webhook handler stáhne foto přes Media Download API
  3. Uložení do Vercel Blob v EU regionu, šifrované at-rest
  4. EXIF strip před uložením (geolokace ven)
  5. Po 7 letech (legislativní retence pro daňové doklady) se mažou
  6. Uživatel může požádat o export nebo výmaz přes WhatsApp příkaz !export / !smazat

GDPR-compliance dokumentace je na webu jako /gdpr route, generovaná z MDX. DPA s Metou je podepsaný separátně (Maruška jako data controller, Meta jako processor pro WA traffic).

Lessons

  • "Lidský přístup" je marketingová zlatá žíla pro non-tech audience. 60+ uživatelé reagovali na "skutečná účetní" 3× lépe než na "AI-powered".
  • WhatsApp Business API je byrokratická peklo. Verifikace business účtu trvala 2 týdny, template messages musí Meta schválit (60 % se schválí first try, zbytek je copy editing).
  • Stripe metadata jsou poklad. metadata.whatsapp_phone na customeru = nemusíš joinovat tabulky pro lookup, je to inline v Stripe webhook payload.
  • Visual workflow > textový popis. 4-krokový animovaný diagram zdvihl konverzi z 2.1 % na 4.7 % (A/B testováno na ~6 000 návštěvníků).
  • Privacy strana je sales tool, ne nutné zlo. Nedigitálně-zdatné publikum chce vidět, kde jejich data leží. Explicit "EU region, šifrované, mazáno po 7 letech" snížilo abandonment v onboarding flow o 22 %.