Builder Flow v9 — Osobne hostingu per persona, backend jako API, brak współdzielonego systemu plików
Czym jest Builder Flow v9?
Builder Flow v9 to proces, w którym każda persona ma własny, niezależny hosting — osobny serwer, osobna domena, osobny nginx, osobny SSL. Komunikacja między landing page a wspólnym silnikiem odbywa się wyłącznie przez backend API. Żadnego współdzielonego systemu plików, żadnych symlinków, żadnego bezpośredniego dostępu do "cudzego" kodu.
Kluczowe różnice względem v8:
| Aspekt | v8 | v9 ✅ |
|---|---|---|
| Hosting | Wszystko na jednym serwerze | Każda persona na osobnym hoście / VPS |
| Współdzielenie kodu | Symlink do _app/ | Brak — każdy hosting ma własny frontend |
| Komunikacja frontend ↔ backend | Bezpośredni dostęp do plików | Wyłącznie przez API (REST/GraphQL) |
| Backend | Współdzielony plikowo | Osobny serwer backendu, dostępny tylko przez API |
| Izolacja | Logiczna (symlinki) | Fizyczna (osobne procesy, osobne porty, osobne VPS) |
| Cięcie | W razie awarii jednego hosta — reszta działa | Awaria jednego hosta — tylko ta persona offline |
Architektura — osobne hostingu, backend przez API
INTERNET
=========
prywaciarz.example.com firmowiec.example.com
(Host A) (Host B)
│ │
│ Landing page │ Landing page
│ Checkout │ Checkout
│ Thank you │ Thank you
│ Frontend SPA │ Frontend SPA
│ │
└──────────┬───────────────────┘
│ API (HTTPS)
▼
api.example.com
(Host C — Backend)
│
│ REST API / GraphQL
│ Baza danych
│ Autoryzacja
│ Wspólna logika
│
└── app.10s.pl (opcjonalnie)
(Host D — neutralna app)
Zasady architektury:
- Każdy hosting to osobny VPS / Docker container — osobny nginx, osobny proces, osobne IP
- Frontend na hoście persony — statyczne HTML/CSS (landing, checkout, thank-you)
- Backend na osobnym hoście — API, baza danych, logika biznesowa
- Brak współdzielonego FS — żadnych NFS, symlinków, shared volume
- Komunikacja TYLKO przez API — frontend ↔ backend przez HTTPS
- Aplikacja (dashboard) może być SPA — ładowana z frontendu persony, dane z API backendu
Faza 0: Brainstorming
mkdir -p /root/projects/<projekt>/.superpowers/sdd
cat > /root/projects/<projekt>/.superpowers/sdd/brainstorming-brief.md << 'EOF'
# Brainstorming — produkt
- Jaki problem rozwiązuje ten produkt?
- Jaka jest jedna zdaniowa definicja?
- Jakie są kryteria sukcesu?
- Ilu person spodziewasz się na start? (wpływa na liczbę hostingów)
EOF
opencode run --prompt 'Przeczytaj brainstorming-brief.md. Zadaj pytania, zapisz odpowiedzi do brainstorming-report.md.' --auto
Faza 0.5: Persona Discovery
cat > /root/projects/<projekt>/.superpowers/sdd/persona-discovery-brief.md << 'EOF'
# Persona Discovery
Dla KAŻDEJ persony: tożsamość, motywacje, płatność, prywatność, język, customer journey.
Output: persona-discovery-report.md z 2-5 personami.
EOF
opencode run --prompt 'Przeczytaj brainstorming-report.md i persona-discovery-brief.md. Wykonaj Persona Discovery. Zapisz do persona-discovery-report.md.' --auto
Faza 0.75: Marketing Campaigns
cat > /root/projects/<projekt>/.superpowers/sdd/marketing-campaigns-brief.md << 'EOF'
# Marketing Campaigns per Persona
Dla każdej: kanały, targetowanie, budżet, KPI, keywords.
Output: marketing-campaigns-report.md
EOF
opencode run --prompt 'Przeczytaj persona-discovery-report.md i marketing-campaigns-brief.md. Wygeneruj marketing-campaigns-report.md.' --auto
Faza 0.8: Domain & Hosting Strategy (NOWOŚĆ v9)
CEO definiuje osobny hosting dla każdej persony oraz osobny hosting backendu.
Krok 0.8.1: Brief domain & hosting
cat > /root/projects/<projekt>/.superpowers/sdd/hosting-strategy-brief.md << 'EOF'
# Hosting Strategy — osobne hostingu per persona, backend jako API
## Cel
Dla KAŻDEJ persony: domena, hosting, nginx, SSL. Osobno dla backendu.
## Wymagane — dla każdej persony
### 1. Domena
- Nazwa domeny (np. prywaciarz.example.com)
- Czy domena jest dostępna?
- Czy jest SSL? (Let's Encrypt, Cloudflare)
### 2. Hosting
- Gdzie hostowane? (VPS, Docker, Netlify, Vercel, Cloudflare Pages)
- Jaki system? (Ubuntu, Alpine, Docker)
- Jaki web server? (nginx, Caddy, Apache)
- State files czy SPA? (statyczne HTML czy framework JS)
### 3. Frontend
- Co jest na tym hoście? (landing, checkout, thank-you, app SPA)
- Jakie zasoby? (RAM, CPU, storage)
- Czy potrzebuje build toola? (npm, vite, webpack)
### 4. API Backend (wspólny)
- Oddzielny hosting dla backendu
- REST API czy GraphQL?
- Baza danych (PostgreSQL, SQLite, MySQL)
- Autoryzacja (JWT, API keys, OAuth)
- Rate limiting (ile requestów na minutę z jednej domeny)
### 5. Komunikacja
- Frontend → Backend: fetch('/api/...') przez HTTPS
- Backend → Frontend: JSON responses
- CORS: dozwolone origins tylko z domen person
- Żadnego bezpośredniego dostępu do plików backendu
## Przykład: Persona "Prywaciarz"
- Domena: prywaciarz.example.com
- Hosting: VPS Hetzner CX22 ($5/mies) lub Netlify (free)
- SSL: Let's Encrypt przez Certbot
- Frontend: statyczne HTML w /var/www/html/
- App: SPA pobierająca dane z api.example.com
## Przykład: Persona "Firmowiec"
- Domena: firmowiec.example.com
- Hosting: VPS Hetzner CX22 ($5/mies) lub Cloudflare Pages (free)
- Frontend: statyczne HTML
- App: SPA pobierająca dane z api.example.com
## Przykład: Backend
- Domena: api.example.com
- Hosting: VPS Hetzner CX32 ($10/mies) — więcej RAM dla bazy
- Stack: FastAPI + PostgreSQL + Redis
- CORS: allow origins prywaciarz.example.com, firmowiec.example.com
## Output
Plik hosting-strategy-report.md — hosting per persona + backend.
EOF
opencode run --prompt '
Przeczytaj persona-discovery-report.md, domain-strategy-report.md, marketing-campaigns-report.md i hosting-strategy-brief.md.
Wygeneruj hosting-strategy-report.md. Dla każdej persony: domena, hosting, frontend. Dla backendu: domena, stack, API, CORS, baza danych.
' --auto
Krok 0.8.2: Przykład — Hosting Strategy
Persona: Prywaciarz
| Aspekt | Wartość |
|---|---|
| Domena | prywaciarz.example.com |
| Hosting | Docker container na VPS, port 3001 |
| Nginx | reverse proxy, SSL, statyczne pliki |
| Frontend | HTML/CSS w /srv/prywaciarz/ |
| App | SPA pobierająca dane z api.example.com |
| CORS | origin: prywaciarz.example.com |
| Koszt | $5/mies (VPS) lub $0 (Netlify) |
Persona: Firmowiec
| Aspekt | Wartość |
|---|---|
| Domena | firmowiec.example.com |
| Hosting | Docker container na VPS, port 3002 |
| Frontend | HTML/CSS w /srv/firmowiec/ |
| App | SPA pobierająca dane z api.example.com |
| CORS | origin: firmowiec.example.com |
| Koszt | $5/mies (VPS) lub $0 (Cloudflare Pages) |
Backend (wspólny)
| Aspekt | Wartość |
|---|---|
| Domena | api.example.com |
| Hosting | Docker container, port 3000 |
| Stack | FastAPI (Python) + PostgreSQL |
| API | REST: GET/POST/PUT/DELETE /api/v1/* |
| Autoryzacja | JWT token (Bearer) |
| CORS | allow: prywaciarz.example.com, firmowiec.example.com |
| Rate limit | 100 req/min per origin |
| Koszt | $10/mies (VPS) |
Faza 1: Specyfikacja przez superpowers SDD
cat > .superpowers/sdd/phase-1-brief.md << 'EOF'
# Phase 1: Specyfikacja biznesowa
Persony, user stories, MVP scope, przepływ biznesowy (od reklamy do API calla).
Output: phase-1-report.md
EOF
opencode run --prompt 'Przeczytaj brainstorming-report.md, persona-discovery-report.md, hosting-strategy-report.md i phase-1-brief.md. Wygeneruj phase-1-report.md.' --auto
cat > .superpowers/sdd/phase-2-brief.md << 'EOF'
# Phase 2: Specyfikacja techniczna
## Architektura (v9 — osobne hostingu, API communication)
- prywaciarz.example.com → Host A (frontend: landing, checkout, thank-you, app SPA)
- firmowiec.example.com → Host B (frontend: landing, checkout, thank-you, app SPA)
- api.example.com → Host C (backend: REST API, baza danych, autoryzacja)
## API Endpoints (wszystkie przez HTTPS)
- GET /api/v1/health — health check
- POST /api/v1/auth/login — logowanie (JWT)
- POST /api/v1/auth/verify — weryfikacja tokena
- GET /api/v1/user/profile — profil użytkownika
- GET /api/v1/sessions?limit=10&offset=0 — lista sesji
- GET /api/v1/sessions/{id} — szczegóły sesji
- POST /api/v1/sessions — dodaj sesję
- GET /api/v1/stats/dashboard — statystyki dashboardu
## CORS
- Access-Control-Allow-Origin: https://prywaciarz.example.com, https://firmowiec.example.com
- Access-Control-Allow-Methods: GET, POST, PUT, DELETE
- Access-Control-Allow-Headers: Authorization, Content-Type
## Model danych
- users: id, email, pin_hash, created_at
- sessions: id, user_id, date, duration, pressure, status, notes
- devices: id, user_id, name, last_seen
## Output
Plik phase-2-report.md
EOF
opencode run --prompt 'Przeczytaj phase-1-report.md i phase-2-brief.md. Wygeneruj phase-2-report.md.' --auto
cat > .superpowers/sdd/phase-3-brief.md << 'EOF'
# Phase 3: Specyfikacja wizualna
## Kategoria A: Landing Pages (per hosting, per domena)
Dla każdej: domena, hosting, URL, cel, sekcje, CTA, komponenty DaisyUI
## Kategoria B: Checkout Pages (per hosting)
Dla każdej: URL, kroki, formularze, metody płatności
## Kategoria C: Thank You Pages (per hosting)
Dla każdej: URL, co widzi po zakupie
## Kategoria D: Aplikacja (SPA na froncie, dane z API)
- HTML szkielet z JS pobierającym dane z api.example.com
- Dashboard: fetch('/api/v1/stats/dashboard') → render
- Sesje: fetch('/api/v1/sessions') → render
- Profil: fetch('/api/v1/user/profile') → render
## Output
Plik phase-3-report.md
EOF
opencode run --prompt 'Przeczytaj phase-1-report.md, phase-2-report.md i phase-3-brief.md. Wygeneruj phase-3-report.md.' --auto
Faza 1.5: Hooks & Angles
cat > /root/projects/<projekt>/.superpowers/sdd/hooks-brief.md << 'EOF'
# Hooks & Angles — 10+ powodów
Dla każdego: headline, body, persona, kanał, emocja.
Output: hooks-report.md
EOF
opencode run --prompt 'Przeczytaj persona-discovery-report.md, domain-strategy-report.md, marketing-campaigns-report.md i hooks-brief.md. Wygeneruj hooks-report.md.' --auto
Faza 1.75: Ad Creatives
cat > /root/projects/<projekt>/.superpowers/sdd/ad-creatives-brief.md << 'EOF'
# Ad Creatives
Dla każdej persony × kanał: platforma, nagłówek, opis, CTA, URL docelowy (domena persony na jej hostingu), wariant B.
Output: ad-creatives-report.md
EOF
opencode run --prompt 'Przeczytaj persona-discovery-report.md, domain-strategy-report.md, hooks-report.md i ad-creatives-brief.md. Wygeneruj ad-creatives-report.md.' --auto
Faza 2: Design System — DaisyUI per hosting
Każdy hosting ma własny motyw DaisyUI. Aplikacja (SPA) pobiera dane z API i renderuje neutralny UI.
<!-- prywaciarz.example.com — Host A, port 3001, data-theme="dark" -->
<!DOCTYPE html>
<html lang="pl" data-theme="dark">
<head>
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet">
<script>
tailwind.config = { daisyui: { themes: [{ dark: { "primary": "#22c55e", "base-100": "#0f172a" } }] } }
</script>
<!-- firmowiec.example.com — Host B, port 3002, data-theme="corporate" -->
<!DOCTYPE html>
<html lang="pl" data-theme="corporate">
<head>
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet">
<script>
tailwind.config = { daisyui: { themes: [{ corporate: { "primary": "#1e3a5f", "base-100": "#ffffff" } }] } }
</script>
Faza 3: Landing Pages — każda na swoim hostingu
Krok 3.1: Landing page na Host A (prywaciarz.example.com)
# Na serwerze Host A (prywaciarz.example.com, port 3001)
mkdir -p /srv/prywaciarz/checkout /srv/prywaciarz/thank-you /srv/prywaciarz/app
opencode run --prompt '
Stwórz landing page w /srv/prywaciarz/index.html.
ZASADY:
1. DaisyUI dark (primary: #22c55e, base-100: #0f172a)
2. TYLKO klasy DaisyUI
3. Język: techniczny, konkretny
4. App to SPA pobierające dane z API: https://api.example.com/api/v1/...
5. WSZYSTKIE zapytania do API przez fetch()
SEKCJE: Hero, Problem, Rozwiązanie, Korzyści, Jak działa, Cena (0.05 XMR), FAQ, Footer
CTA: "Kup za Monero →" → /checkout/
' --auto
Krok 3.2: Landing page na Host B (firmowiec.example.com)
# Na serwerze Host B (firmowiec.example.com, port 3002)
mkdir -p /srv/firmowiec/checkout /srv/firmowiec/thank-you /srv/firmowiec/app
opencode run --prompt '
Stwórz landing page w /srv/firmowiec/index.html.
ZASADY:
1. DaisyUI corporate (primary: #1e3a5f, base-100: #ffffff)
2. TYLKO klasy DaisyUI
3. Język: formalny, biznesowy
4. App to SPA pobierające dane z API: https://api.example.com/api/v1/...
SEKCJE: Hero, Problem, Rozwiązanie, Korzyści, Cena, Jak działa, FAQ, Footer
CTA: "Zamów dla firmy →" → /checkout/
' --auto
Faza 3.5: Checkout + Thank You na hostingu persony
Checkout na Host A (prywaciarz.example.com)
opencode run --prompt '
Stwórz /srv/prywaciarz/checkout/index.html.
Kroki: 1. Wybierz krypto (Monero/BTC) → 2. Wyślij → 3. Czekaj → 4. Link
CTA: "Już wysłałem — sprawdź →" → /thank-you/
Link do app: /app/ (SPA na tym samym hostingu, dane z API)
DaisyUI dark.
' --auto
Thank You na Host A
opencode run --prompt '
Stwórz /srv/prywaciarz/thank-you/index.html.
"Gratulacje! Jesteś teraz anonimowy."
"Twój link: https://prywaciarz.example.com/app/?token=abc123"
CTA: "Przejdź do aplikacji →" → /app/ (SPA, dane z API)
DaisyUI dark.
' --auto
Checkout na Host B (firmowiec.example.com)
opencode run --prompt '
Stwórz /srv/firmowiec/checkout/index.html.
Kroki: 1. Dane firmy → 2. Plan → 3. Płatność → 4. Potwierdzenie
CTA: "Zamów i zapłać" → /thank-you/
Link do app: /app/ (SPA na tym samym hostingu, dane z API)
DaisyUI corporate.
' --auto
Thank You na Host B
opencode run --prompt '
Stwórz /srv/firmowiec/thank-you/index.html.
"Dziękujemy za zamówienie!"
"Panel admina: https://firmowiec.example.com/app/?token=xyz789"
CTA: "Przejdź do panelu →" → /app/ (SPA, dane z API)
DaisyUI corporate.
' --auto
Faza 4: Aplikacja SPA na każdym hostingu (dane z API)
Aplikacja to SPA (Single Page Application) — HTML + JS, który pobiera dane z API backendu. Każdy hosting ma swoją kopię SPA, ale wszystkie pobierają dane z tego samego API.
Krok 4.1: SPA dashboard na Host A z API callem
opencode run --prompt '
Stwórz /srv/prywaciarz/app/index.html — SPA dashboard.
ZASADY:
1. DaisyUI light — neutralny, zero brandingu persony
2. Wszystkie dane pobierane z API: https://api.example.com/api/v1/...
3. Fetch API przez JavaScript (async/await)
4. Obsługa błędów: jeśli API nie odpowiada, pokaż alert
STRUKTURA SPA:
- Navbar z linkami do /app/, /app/sessions, /app/profile
- Dashboard: fetch("/api/v1/stats/dashboard") → render statystyk
- Tabela: fetch("/api/v1/sessions?limit=5") → render table table-zebra
- Alert: jeśli fetch fail, alert alert-error
PRZYKŁAD KODU:
<script>
async function loadDashboard() {
try {
const res = await fetch("https://api.example.com/api/v1/stats/dashboard", {
headers: { "Authorization": "Bearer " + getToken() }
});
const data = await res.json();
document.getElementById("stats").innerHTML = renderStats(data);
} catch(e) {
document.getElementById("stats").innerHTML = "<div class=\"alert alert-error\">Nie można załadować danych</div>";
}
}
window.onload = loadDashboard;
</script>
' --auto
Krok 4.2: SPA na Host B (ten sam kod, inne API URL)
SPA na Host B (firmowiec.example.com) ma ten sam kod, ale pobiera dane z tego samego API:
# Ten sam kod SPA, to samo API: https://api.example.com/api/v1/...
# Różni się tylko domeną hostingu (firmowiec.example.com)
# API to to samo — CORS akceptuje obie domeny
cp /srv/prywaciarz/app/index.html /srv/firmowiec/app/index.html
Faza 5: Backend API na osobnym hostingu (Host C)
Krok 5.1: Backend API
# Na serwerze Host C (api.example.com, port 3000)
opencode run --prompt '
Stwórz backend API w /srv/api/.
Stack: FastAPI (Python) + PostgreSQL
Endpointy:
- GET /api/v1/health → {"status": "ok"}
- POST /api/v1/auth/login → {"token": "jwt..."}
- GET /api/v1/user/profile → {"email": "...", "sessions_count": 12}
- GET /api/v1/sessions?limit=10&offset=0 → [{"id":1, "date":"...", ...}]
- GET /api/v1/sessions/{id} → {"id":1, "date":"...", "duration":60, ...}
- POST /api/v1/sessions → {"id": 2, ...}
- GET /api/v1/stats/dashboard → {"completed":12, "total":20, "hours":24, "compliance":85}
CORS:
- allow_origins = ["https://prywaciarz.example.com", "https://firmowiec.example.com"]
- allow_methods = ["GET", "POST", "PUT", "DELETE"]
- allow_headers = ["Authorization", "Content-Type"]
Autoryzacja:
- JWT token w header Authorization: Bearer <token>
- Token ważny 24h
- Rate limiting: 100 req/min per origin
Uruchomienie:
- uvicorn main:app --host 0.0.0.0 --port 3000
- Nginx reverse proxy: api.example.com → localhost:3000
' --auto
Krok 5.2: API — przykładowa odpowiedź
// GET https://api.example.com/api/v1/stats/dashboard
// Authorization: Bearer eyJ...
{
"completed": 12,
"total": 20,
"hours": 24,
"compliance": 85,
"last_session": "2026-07-20",
"next_session": "2026-07-22",
"sessions": [
{"id": 1, "date": "2026-07-20", "duration": 60, "status": "completed"},
{"id": 2, "date": "2026-07-18", "duration": 45, "status": "completed"},
{"id": 3, "date": "2026-07-16", "duration": 60, "status": "interrupted"}
]
}
Faza 6: Nginx — każdy hosting ma własny config
Host A — prywaciarz.example.com
# /etc/nginx/sites-available/prywaciarz.example.com
server {
listen 443 ssl;
server_name prywaciarz.example.com;
ssl_certificate /etc/letsencrypt/live/prywaciarz.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/prywaciarz.example.com/privkey.pem;
root /srv/prywaciarz;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# app SPA — statyczne pliki, dane z API
location /app/ {
alias /srv/prywaciarz/app/;
try_files $uri $uri/ /app/index.html;
}
}
Host B — firmowiec.example.com
# /etc/nginx/sites-available/firmowiec.example.com
server {
listen 443 ssl;
server_name firmowiec.example.com;
ssl_certificate /etc/letsencrypt/live/firmowiec.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/firmowiec.example.com/privkey.pem;
root /srv/firmowiec;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /app/ {
alias /srv/firmowiec/app/;
try_files $uri $uri/ /app/index.html;
}
}
Host C — api.example.com
# /etc/nginx/sites-available/api.example.com
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Faza 7: Symulacja lokalna (prototypowanie)
W fazie prototypu, zanim kupisz osobne VPS, możesz symulować architekturę na jednym serwerze przez osobne porty i osobne katalogi:
# Symulacja 3 hostingów na jednym serwerze:
# Host A: prywaciarz.example.com → localhost:3001 → /srv/prywaciarz/
# Host B: firmowiec.example.com → localhost:3002 → /srv/firmowiec/
# Host C: api.example.com → localhost:3000 → /srv/api/
# 1. Uruchom backend API na porcie 3000
cd /srv/api && uvicorn main:app --host 0.0.0.0 --port 3000 &
# 2. Uruchom serwer statyczny dla Host A na porcie 3001
cd /srv/prywaciarz && python3 -m http.server 3001 --bind 0.0.0.0 &
# 3. Uruchom serwer statyczny dla Host B na porcie 3002
cd /srv/firmowiec && python3 -m http.server 3002 --bind 0.0.0.0 &
# 4. Test — Host A (prywaciarz)
curl -s http://127.0.0.1:3001/ | head -5
# Oczekiwane: HTML landing page z Incognito Browser
# 5. Test — Host B (firmowiec)
curl -s http://127.0.0.1:3002/ | head -5
# Oczekiwane: HTML landing page z EnterpriseShield
# 6. Test — API (backend)
curl -s http://127.0.0.1:3000/api/v1/health
# Oczekiwane: {"status": "ok"}
# 7. Test — SPA na Host A pobiera dane z API
curl -s http://127.0.0.1:3001/app/ | grep -c "api.example.com"
# Oczekiwane: > 0 (SPA ładuje dane z API)
Faza 8: Weryfikacja — izolacja fizyczna
Krok 8.1: Weryfikacja — każdy hosting jest niezależny
# 1. Sprawdź czy każdy hosting działa na swoim porcie
for port in 3001 3002 3000; do
echo "Port $port: $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:$port/ || echo 'DOWN')"
done
# 2. Sprawdź czy Host A nie ma dostępu do plików Host B
curl -s http://127.0.0.1:3001/../firmowiec/index.html | head -3
# Oczekiwane: 404 lub puste (brak dostępu)
# 3. Sprawdź czy Host B nie ma dostępu do plików Host A
curl -s http://127.0.0.1:3002/../prywaciarz/index.html | head -3
# Oczekiwane: 404 lub puste
# 4. Sprawdź czy API dostępne tylko przez swój port
curl -s http://127.0.0.1:3001/api/v1/health
# Oczekiwane: 404 (Host A nie ma API)
Krok 8.2: Weryfikacja — API communication
# 1. SPA na Host A powinno zawierać fetch do API
grep -c 'api.example.com' /srv/prywaciarz/app/index.html || true
# Oczekiwane: > 0 (SPA ładuje dane z API)
# 2. SPA na Host B powinno zawierać fetch do tego samego API
grep -c 'api.example.com' /srv/firmowiec/app/index.html || true
# Oczekiwane: > 0 (ten sam backend)
# 3. Żaden hosting nie powinien mieć bezpośredniego dostępu do plików backendu
ls /srv/prywaciarz/main.py 2>/dev/null && echo "❌ ACCESS" || echo "✅ NO ACCESS"
ls /srv/firmowiec/main.py 2>/dev/null && echo "❌ ACCESS" || echo "✅ NO ACCESS"
# Oczekiwane: NO ACCESS dla obu
Krok 8.3: Raport do zatwierdzenia
hermes kanban --board convertere comment <card-id> \
"[CEO] ✅ Prototyp v9 — osobne hostingu, API communication:
🔒 prywaciarz.example.com (Host A:3001):
- Landing, checkout, thank-you, app SPA
- Dane z API: https://api.example.com/api/v1/*
- DaisyUI dark
🏢 firmowiec.example.com (Host B:3002):
- Landing, checkout, thank-you, app SPA
- Dane z API: https://api.example.com/api/v1/*
- DaisyUI corporate
⚙️ api.example.com (Host C:3000):
- FastAPI + PostgreSQL
- CORS: prywaciarz, firmowiec
- JWT auth, rate limiting
Weryfikacja:
✅ HTTP 200 — każdy hosting na swoim porcie
✅ Żaden hosting nie ma dostępu do plików innego
✅ SPA na obu hostingach ładuje dane z tego samego API
✅ API dostępne tylko na swoim porcie
✅ Zero współdzielonego systemu plików
⏳ Czekam na zatwierdzenie"
Architektura v9 — pełna wizualizacja
PRODUKCJA
=========
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ Host A │ │ Host B │ │ Host C │
│ prywaciarz.example │ │ firmowiec.example │ │ api.example.com │
│ ──────────────── │ │ ──────────────── │ │ ──────────────── │
│ VPS / Docker │ │ VPS / Docker │ │ VPS / Docker │
│ Port 443 (SSL) │ │ Port 443 (SSL) │ │ Port 443 (SSL) │
│ │ │ │ │ │
│ /srv/prywaciarz/ │ │ /srv/firmowiec/ │ │ /srv/api/ │
│ ├── index.html │ │ ├── index.html │ │ ├── main.py │
│ ├── checkout/ │ │ ├── checkout/ │ │ ├── database.py │
│ ├── thank-you/ │ │ ├── thank-you/ │ │ ├── models.py │
│ └── app/ │ │ └── app/ │ │ └── requirements.txt│
│ └── index.html │ │ └── index.html │ │ │
│ (SPA) │ │ (SPA) │ │ API endpoints: │
│ │ │ │ │ /api/v1/health │
│ fetch() ────────────┼───┼── fetch() ───────────┼──→│ /api/v1/auth/* │
│ │ │ │ │ /api/v1/user/* │
│ │ │ │ │ /api/v1/sessions/* │
│ │ │ │ │ /api/v1/stats/* │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
SYMULACJA LOKALNA (prototyp)
============================
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ localhost:3001 │ │ localhost:3002 │ │ localhost:3000 │
│ (prywaciarz) │ │ (firmowiec) │ │ (api) │
│ python3 http.server │ │ python3 http.server │ │ uvicorn main:app │
│ /srv/prywaciarz/ │ │ /srv/firmowiec/ │ │ /srv/api/ │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
Porównanie v8 → v9
| Aspekt | v8 | v9 ✅ |
|---|---|---|
| Hosting | Jeden serwer | Osobne VPS / Docker per persona + backend |
| Współdzielenie kodu | Symlink do _app/ | Brak — każdy hosting ma własny frontend |
| Komunikacja | Bezpośredni dostęp do plików | Tylko przez API (HTTPS) |
| Aplikacja | Statyczne HTML z symlinka | SPA z fetch() do API backendu |
| Backend | Współdzielony plikowo | Osobny serwer: FastAPI + PostgreSQL |
| Izolacja | Logiczna (symlinki) | Fizyczna (osobne procesy, porty, VPS) |
| CORS | Niepotrzebny | Wymagany — allow origins per persona |
| Awaria | Jeden host = wszystko pada | Awaria Host A = tylko Prywaciarz offline |
| Skalowanie | Skaluje się całość | Każdą personę można skalować osobno |
| Koszt produkcji | 1 VPS (np. $5/mies) | 3+ VPS (np. $5+$5+$10 = $20/mies) |
| Koszt prototypu | $0 (jeden serwer) | $0 (symulacja na portach) |
Playbook: 60-minutowy Builder Flow v9 (symulacja lokalna)
Przygotowanie (2 min):
- [ ]
mkdir -p /srv/prywaciarz /srv/firmowiec /srv/api - [ ] Stwórz kanban task
Brainstorming + Persona Discovery (8 min):
- [ ] Pytania o produkt + identyfikacja person
Hosting Strategy (5 min):
- [ ] Dla każdej persony: domena, hosting, port
- [ ] Dla backendu: domena, stack, API endpoints, CORS
Marketing + Hooks + Ads (8 min):
- [ ] Kampanie, hooki, ad creatives
Specyfikacja (5 min):
- [ ] superpowers SDD → phase-1, phase-2, phase-3
Landing Pages per hosting (10 min):
- [ ] Host A (port 3001): landing + checkout + thank-you
- [ ] Host B (port 3002): landing + checkout + thank-you
SPA + API (10 min):
- [ ] Host C (port 3000): FastAPI backend z endpointami
- [ ] Host A: SPA z fetch() do API
- [ ] Host B: SPA z fetch() do API (ten sam kod)
Uruchomienie (5 min):
- [ ]
uvicorn /srv/api/main:app --port 3000 & - [ ]
cd /srv/prywaciarz && python3 -m http.server 3001 & - [ ]
cd /srv/firmowiec && python3 -m http.server 3002 &
Weryfikacja (7 min):
- [ ] HTTP 200 na każdym porcie
- [ ] Brak dostępu do plików innego hosta
- [ ] SPA ładuje dane z API
- [ ] API odpowiada poprawnie
- [ ] CORS działa (symulacja przez curl)
- [ ] Decyzja go/no-go
Mierzenie sukcesu
| Metryka | Target | Jak mierzyć | ||
|---|---|---|---|---|
| Hosty uruchomione | 3+ | curl -s http://127.0.0.1:3001/ && curl -s http://127.0.0.1:3002/ && curl -s http://127.0.0.1:3000/api/v1/health | ||
| HTTP 200 na każdym | 100% | for port in 3001 3002 3000; do curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:$port/; done | ||
| Brak dostępu do plików innego hosta | 404 | `curl -s http://127.0.0.1:3001/../firmowiec/index.html \ | head -1` | |
| API dostępne tylko na swoim porcie | 404 | curl -s http://127.0.0.1:3001/api/v1/health | ||
| SPA ładuje dane z API | > 0 | grep -c 'api.example.com' /srv/prywaciarz/app/index.html | ||
| CORS skonfigurowany | 2 origins | `grep -c 'prywaciarz\ | firmowiec' /srv/api/main.py` | |
| Zero współdzielonego FS | brak | `ls /srv/prywaciarz/main.py 2>/dev/null && echo FAIL \ | \ | echo OK` |
| Czas od pomysłu do prototypu | < 60 min | Stoper |
Źródła (Linki URL)
- DaisyUI — dokumentacja
- FastAPI — Python backend
- PostgreSQL — baza danych
- Let's Encrypt — darmowe SSL
- Nginx — reverse proxy
- superpowers — obra/superpowers GitHub
- opencode — kimi-k27/code
- Builder Flow v1
- Builder Flow v2
- Builder Flow v3
- Builder Flow v4
- Builder Flow v5
- Builder Flow v6
- Builder Flow v7
- Builder Flow v8
- Builder Flow v9 — ta wersja
Źródła (Pliki)
/root/.config/opencode/opencode.json— konfiguracja opencode/root/convertere/reports/builder-flow-v1.md— v1/root/convertere/reports/builder-flow-v2.md— v2/root/convertere/reports/builder-flow-v3.md— v3/root/convertere/reports/builder-flow-v4.md— v4/root/convertere/reports/builder-flow-v5.md— v5/root/convertere/reports/builder-flow-v6.md— v6/root/convertere/reports/builder-flow-v7.md— v7/root/convertere/reports/builder-flow-v8.md— v8/root/convertere/reports/builder-flow-v9.md— ten raport