diff --git a/.devcontainer/stripe-to-invoice/devcontainer.json b/.devcontainer/stripe-to-invoice/devcontainer.json index f35aa4f..ca42b31 100644 --- a/.devcontainer/stripe-to-invoice/devcontainer.json +++ b/.devcontainer/stripe-to-invoice/devcontainer.json @@ -13,7 +13,7 @@ "mounts": [ // Optional convenience mount - "source=${localEnv:HOME},target=/workspaces/home,type=bind" + "source=${localEnv:HOME},target=/home/vscode,type=bind" ], "customizations": { diff --git a/.devcontainer/stripe-to-invoice/docker-compose.yml b/.devcontainer/stripe-to-invoice/docker-compose.yml index 42daecc..91264df 100644 --- a/.devcontainer/stripe-to-invoice/docker-compose.yml +++ b/.devcontainer/stripe-to-invoice/docker-compose.yml @@ -2,11 +2,10 @@ version: '3.8' services: one_repo_to_rule_them_all: - # user: "${UID}:${GID}" build: context: ../.. 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 volumes: - ../..:/workspaces/monorepo diff --git a/code-server/codeserver.yaml b/code-server/codeserver.yaml index d3646d3..18e1275 100644 --- a/code-server/codeserver.yaml +++ b/code-server/codeserver.yaml @@ -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 kind: Service @@ -33,30 +7,31 @@ spec: ports: - port: 80 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 -kind: Ingress +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute metadata: name: dev-juntekim-ingress - annotations: - traefik.ingress.kubernetes.io/router.entrypoints: websecure - cert-manager.io/cluster-issuer: myresolver spec: - ingressClassName: traefik + entryPoints: + - websecure + routes: + - match: Host(`dev.juntekim.com`) + kind: Rule + services: + - name: dev-juntekim-service + port: 80 tls: - - hosts: - - 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 \ No newline at end of file + certResolver: myresolver \ No newline at end of file diff --git a/code-server/sal-codeservery.yaml b/code-server/sal-codeservery.yaml new file mode 100644 index 0000000..010a64b --- /dev/null +++ b/code-server/sal-codeservery.yaml @@ -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 \ No newline at end of file diff --git a/stripe_to_invoice/README.md b/stripe_to_invoice/README.md deleted file mode 100644 index cb41c53..0000000 --- a/stripe_to_invoice/README.md +++ /dev/null @@ -1,248 +0,0 @@ -Got you — here’s a clean, founder-brain-friendly summary of **Stripe → Invoice (Stripe → Xero)** based on everything you’ve been working through, plus **tight next steps** that fit your nights/weekends reality. - ---- - -## 🧾 What Stripe → Invoice Is (current state) - -* **Problem you’re 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 it’s 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 you’re in (important) - -* You’re 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) - -* 5–10 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 **~3–5 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) - -* You’re *not* early anymore — you’re **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 — don’t 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.