Train a personalized AI model on your photos and generate stunning portraits in any style.
- Frontend: SvelteKit 2.x with Svelte 5
- Styling: Tailwind CSS v4
- Platform: Cloudflare Pages with D1 (SQLite) and R2 storage
- Auth: Supabase Auth (email/password, Google OAuth)
- AI: Replicate API (Flux LoRA training and generation)
- Billing: Stripe Checkout
npm install
npm run devFor Cloudflare bindings locally:
npx wrangler pages dev .svelte-kit/cloudflareDeployed to Cloudflare Pages via GitHub Actions on push to master.
Managed in wrangler.toml (public) and Cloudflare dashboard (secrets):
Public (in wrangler.toml):
SUPABASE_URLSUPABASE_ANON_KEYPUBLIC_SUPABASE_URLPUBLIC_SUPABASE_ANON_KEYPUBLIC_R2_URL—⚠️ DEV ONLY — Change before production
Secrets (Cloudflare dashboard):
REPLICATE_API_TOKEN— Replicate API keySTRIPE_SECRET_KEY— Stripe secret keySTRIPE_WEBHOOK_SECRET— Stripe webhook signing secret
npx wrangler d1 execute selfiepr-db --remote --file=migrations/001_init.sqlCreate bucket:
npx wrangler r2 bucket create selfie-bucketEnable public access in Cloudflare dashboard and update PUBLIC_R2_URL accordingly.
⚠️ Note: The currentPUBLIC_R2_URLinwrangler.tomlis for development only. Before production, replace with your production R2 public URL.
TODO: Configure Google OAuth in Supabase:
- Enable Google provider in Supabase → Authentication → Providers
- Create Google OAuth credentials at console.cloud.google.com
- Add redirect URI:
https://ybrxeupsthtbzqmpwivq.supabase.co/auth/v1/callback - Add production URL to allowed origins:
https://selfiepr.pages.dev - Configure Site URL and Redirect URLs in Supabase
npm run test
npm run test:coveragesrc/
├── lib/
│ ├── db/ — Database queries
│ ├── images/ — Image resize utilities
│ ├── replicate/ — Replicate API client and pricing
│ ├── storage/ — R2 upload helpers
│ ├── stripe/ — Stripe utilities
│ └── supabase/ — Supabase client setup
├── routes/
│ ├── api/ — API endpoints
│ ├── app/ — Authenticated app pages
│ └── auth/ — Login, signup, OAuth callback
└── migrations/ — D1 migration files
- User signs up/logs in (Supabase Auth)
- User adds balance via Stripe Checkout
- User uploads 5-10 photos for training
- Photos uploaded to R2, training started on Replicate
- Webhook received when training completes
- User generates portraits using style presets or custom prompts
- Generated images stored in R2, displayed in gallery