stripe to invoice

This commit is contained in:
Jun-te Kim 2026-03-01 17:18:30 +00:00
parent 5b188f0b32
commit 71ea3e4da4
5 changed files with 58 additions and 298 deletions

View file

@ -13,7 +13,7 @@
"mounts": [ "mounts": [
// Optional convenience mount // Optional convenience mount
"source=${localEnv:HOME},target=/workspaces/home,type=bind" "source=${localEnv:HOME},target=/home/vscode,type=bind"
], ],
"customizations": { "customizations": {

View file

@ -2,11 +2,10 @@ version: '3.8'
services: services:
one_repo_to_rule_them_all: one_repo_to_rule_them_all:
# user: "${UID}:${GID}"
build: build:
context: ../.. context: ../..
dockerfile: .devcontainer/stripe-to-invoice/Dockerfile dockerfile: .devcontainer/stripe-to-invoice/Dockerfile
command: code-server --bind-addr 0.0.0.0:8080 --auth password command: su - vscode -c "code-server --bind-addr 0.0.0.0:8080"
# command: sleep infinity # command: sleep infinity
volumes: volumes:
- ../..:/workspaces/monorepo - ../..:/workspaces/monorepo

View file

@ -1,29 +1,3 @@
# ======================================================
# DEV.JUNTEKIM.COM → LOCALHOST:8080
# ======================================================
---
apiVersion: v1
kind: Service
metadata:
name: dev-juntekim-external
spec:
type: ExternalName
externalName: host.docker.internal # change if needed
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: dev-juntekim-external
subsets:
- addresses:
- ip: 192.168.0.181
ports:
- port: 8080
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
@ -33,30 +7,31 @@ spec:
ports: ports:
- port: 80 - port: 80
targetPort: 8080 targetPort: 8080
selector: {} # no selector — used with external endpoints ---
apiVersion: v1
kind: Endpoints
metadata:
name: dev-juntekim-service
subsets:
- addresses:
- ip: 192.168.0.181 # mist node
ports:
- port: 8080
--- ---
apiVersion: networking.k8s.io/v1 apiVersion: traefik.io/v1alpha1
kind: Ingress kind: IngressRoute
metadata: metadata:
name: dev-juntekim-ingress name: dev-juntekim-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
cert-manager.io/cluster-issuer: myresolver
spec: spec:
ingressClassName: traefik entryPoints:
- websecure
routes:
- match: Host(`dev.juntekim.com`)
kind: Rule
services:
- name: dev-juntekim-service
port: 80
tls: tls:
- hosts: certResolver: myresolver
- dev.juntekim.com
secretName: dev-juntekim-tls
rules:
- host: dev.juntekim.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dev-juntekim-service
port:
number: 80

View file

@ -0,0 +1,34 @@
apiVersion: v1
kind: Service
metadata:
name: sal-juntekim-service
spec:
ports:
- port: 80
targetPort: 8081
---
apiVersion: v1
kind: Endpoints
metadata:
name: sal-juntekim-service
subsets:
- addresses:
- ip: 192.168.0.181 # mist node
ports:
- port: 8081
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: sal-juntekim-ingress
spec:
entryPoints:
- websecure
routes:
- match: Host(`sal.juntekim.com`)
kind: Rule
services:
- name: sal-juntekim-service
port: 80
tls:
certResolver: myresolver

View file

@ -1,248 +0,0 @@
Got you — heres a clean, founder-brain-friendly summary of **Stripe → Invoice (Stripe → Xero)** based on everything youve been working through, plus **tight next steps** that fit your nights/weekends reality.
---
## 🧾 What Stripe → Invoice Is (current state)
* **Problem youre solving**
* UK VAT-registered small businesses using Stripe struggle with **audit-safe, VAT-correct invoices** in Xero
* Existing tools are overbuilt, accountant-first, or break down on VAT, clearing accounts, or reconciliation
* This is fundamentally a **VAT + audit correctness problem**, not just “sync data”
* **Who its for**
* UK solo founders / one-person companies / tiny teams
* Using **Stripe only** (Payment Links + Subscriptions)
* Using **Xero**
* Not accountants, not agencies, not complex multi-channel setups
* **What the MVP does today**
* Stripe OAuth + Xero OAuth both working
* Webhooks flow end-to-end (validated against real finance manager)
* Automatically:
* Creates **clean Xero invoices** from Stripe payments
* Applies VAT correctly
* Posts payments via a **Stripe Clearing account**
* Validated by a finance manager → *very happy* (huge signal)
* **Key MVP constraints (intentional)**
* UK + GBP only
* Stripe Payment Links + Subscriptions only
* Xero contacts matched/created by **email only**
* Willing to:
* Run one-off scripts
* Do manual fixes early
* Goal: **first ~5 paying customers**, not scale yet
---
## ✅ Recently fixed
* **Xero contact creation** — Now checks for existing contacts by email first, reuses if found, only creates if missing
* **Stripe OAuth app reuse** — Added unique constraints on `userId` and `stripeAccountId` to prevent duplicate connections
* **Smart redirect flow** — Users are automatically routed based on connection state:
* Both connected → `/dashboard`
* Only Stripe → `/connect/xero`
* No connections → `/connect/stripe`
* **Connection visibility** — Dashboard now displays connected Stripe account ID and Xero tenant ID
### Frontend Improvements Details
**Smart Onboarding Flow**
* Automatic routing based on connection state
* Users never see unnecessary steps
* Seamless progression: Login → Stripe → Xero → Dashboard
**Dashboard Enhancements**
* Connected account visibility (Stripe account ID + Xero tenant)
* Account code configuration (sales + clearing accounts)
* Real-time save confirmation
* Clean, minimal UI
**Development Experience**
* Development mode fallback for webhook testing
* Comprehensive logging at each webhook stage
* Environment-aware configuration
---
## ⚠️ Known issues & TODO
* **CRITICAL: Stripe payment integration**
* Need to implement Stripe Billing API to accept payments
* Currently not accepting any money from users (test mode only)
* Must add subscription checkout flow before going live
* Reference: [Stripe Billing API docs](https://stripe.com/docs/billing)
* **Missing UX guardrails:**
* No clear **pre-payment checklist** before enabling sync
---
## 🧪 Current mode youre in (important)
* Youre correctly running this in **“design partner / friend test” mode**
* Payments disabled
* Banner: *“Internal test not a commercial product”*
* Clear paper trail of non-commercial intent
* CFO + finance manager already acting as **design partners**
* This massively de-risks VAT/audit assumptions before charging anyone
---
## ✅ What you should do next (ordered, ruthless, realistic)
### 1⃣ Finish the last **correctness blockers** (highest ROI)
These unlock charging real money.
* [x] ~~Fix Xero contact creation~~ ✅ DONE
* ~~Check by email → reuse if exists → only create if missing~~
* [x] ~~Fix Stripe OAuth app reuse (stop creating new apps)~~ ✅ DONE
* [x] ~~Re-enable "mark invoice as paid" via Stripe Clearing once accounts are valid~~ ✅ DONE
> Outcome: rock-solid, boring, accountant-approved flow
---
### 2⃣ Add a tiny **pre-flight checklist UI** (not a full settings page)
* [x] ~~Dashboard shows connected accounts~~ ✅ DONE
* ~~Stripe account ID displayed~~
* ~~Xero tenant ID displayed~~
* [x] ~~Smart redirect flow based on connection state~~ ✅ DONE
* [ ] VAT status detection
* [ ] Sales account code shown (editable)
* [ ] Stripe clearing account shown (editable)
> Even basic connection visibility prevents 80% of future support pain
---
### 3⃣ Implement subscription billing (enables first paid customer)
* Integrate Stripe Billing for subscription management
* Add usage tracking (invoice count per month)
* Create pricing page and checkout flow
* Implement subscription status checks in webhook handler
* Remove "internal test" banner once billing is live
---
### 4⃣ Switch from "design partner" → **first paid customer mode**
* Pick **one**:
* A founder you already know **OR**
* A cold UK Stripe + Xero business with obvious VAT needs
* Offer:
* £15/month Starter plan
* "Early access / founder pricing" (50% off for life)
* Manual support included
* Goal is **money changing hands**, not scale
> You've said it yourself: getting paid energises you — lean into that.
---
### 5⃣ Do *targeted* cold outreach (low volume, high signal)
* 510 emails max, not a campaign
* Target:
* UK SaaS / indie founders
* Stripe Payment Links or Subscriptions
* Clearly VAT-registered
* Lead with:
* "I built this because my accountant hated existing tools"
* Emphasise **audit-safe, VAT-correct invoices**
* Not "automation", not "syncing"
---
### 6⃣ Future UX polish + automation (after first paying customers)
* Auto-detect or create Stripe Clearing account in Xero
* Bulk historical invoice sync
* Invoice preview before creation
* Reduce manual fixes you find yourself repeating
* Nothing else until:
* You have **~35 paying users**
* And they're still using it after month 1
---
## 💳 SaaS Subscription Model (proposed)
### Pricing Tiers
**All Plans — £50/month**
* Unlimited invoices/month
* Stripe Payment Links + Subscriptions support
* Full VAT handling and audit compliance
* Email support
* Perfect for: UK businesses using Stripe + Xero, any size
**Future tiers** (if needed):
* Starter — £30/month (up to 50 invoices)
* Professional — £50/month (up to 200 invoices)
* Business — £100/month (unlimited)
### Implementation Notes
* **Billing via Stripe Checkout** (dogfooding our own product)
* **Monthly recurring subscriptions** with automatic renewal
* **14-day free trial** — no credit card required
* **Founder pricing lock-in** — First 50 customers get lifetime 50% off
* **Usage tracking** — Invoice count displayed in dashboard, soft warnings at 80% of limit
* **Graceful degradation** — Over-limit users get notified but sync continues (no hard cutoff)
### Revenue Model
* **Target: 100 paying customers in 6 months**
* 60% Starter (£900/mo)
* 30% Professional (£1,050/mo)
* 10% Business (£750/mo)
* Total: ~£2,700/mo MRR
* **Conservative burn**
* Hosting: £50/mo (Vercel + DB)
* Email: £10/mo (AWS SES)
* Support: Founder time only
* Net: ~£2,640/mo profit margin
### Next Steps for Monetization
1. Add Stripe Billing integration to the app
2. Implement usage tracking in webhook handler
3. Create pricing page on landing site
4. Add subscription management in dashboard
5. Enable payments and remove "internal test" banner
---
## 🧠 The big picture (sanity check)
* Youre *not* early anymore — youre **post-validation, pre-pricing**
* The hard bit (VAT correctness + finance approval) is already done
* The remaining work is boring plumbing + selling
* This is exactly where most side projects die — dont overbuild now
If you want, next we can:
* Draft the **first cold email**
* Write the **“Why this exists” landing page copy**
* Or map a **2-week nights/weekends execution plan**
Just say the word.