A newer version of the Gradio SDK is available: 6.22.0
DEPLOY.md — Etsy Listing Optimizer
This walks through getting every free-tier account, wiring the keys, and deploying to a Hugging Face Space. Follow it top to bottom the first time.
Total cost to get running: 0 Kč upfront. Stripe only takes a cut once you actually charge someone.
0. What you'll end up with
- A live app at
https://<your-hf-username>-etsy-listing-optimizer.hf.space - Real auth + database (Supabase)
- Real AI generation (Groq, with Gemini as fallback)
- Real subscription billing (Stripe)
Until you add the keys below, the app runs in demo mode (in-memory storage, a mock AI provider) so you can click around and see it work first.
1. Get every account + API key
1.1 Supabase (database + auth) — free, no credit card
- Go to https://supabase.com → sign up → "New Project".
- Pick an EU region (Frankfurt) — this matters for GDPR data residency, set it now, it can't be changed later without migrating.
- Set a strong database password (you won't need it day-to-day; Supabase manages connections for you).
- Once the project finishes provisioning, go to Project Settings → API:
Project URL→ this is yourSUPABASE_URLanonpublickey → this is yourSUPABASE_ANON_KEYservice_rolesecretkey → this is yourSUPABASE_SERVICE_ROLE_KEY(⚠️ never expose this one client-side or commit it — it bypasses every Row Level Security rule)
- Go to Authentication → Providers → Email and make sure Email auth is enabled (it is by default).
- Go to Authentication → Policies (or Auth → Settings depending on your dashboard version) and turn on "Leaked password protection". This is a checkbox, not code — do it now so you don't forget.
- Go to the SQL Editor, paste the entire contents of
supabase_schema.sqlfrom this project, and run it. This creates all tables and Row Level Security policies.
1.2 Groq (primary AI provider) — free tier, no credit card
- Go to https://console.groq.com/keys, sign up, click "Create API Key".
- Copy it → this is your
GROQ_API_KEY. - Free tier has generous rate limits for Llama 3.3 70B; if you ever hit them, the app automatically falls back to Gemini (see below) — no code changes needed, just add both keys.
1.3 Gemini (fallback AI provider) — free tier, no credit card
- Go to https://aistudio.google.com/app/apikey, sign in with a Google account, click "Create API key".
- Copy it → this is your
GEMINI_API_KEY. - This is optional for v1 (Groq alone works), but recommended — it's what
keeps
/generateworking if Groq ever rate-limits you.
1.4 Stripe (payments) — free to set up, per-transaction fee only
- Go to https://dashboard.stripe.com/register, sign up.
- Stay in Test mode first (toggle top-right of the dashboard) — you can test the entire flow with fake card numbers before going live.
- Go to Developers → API keys → copy the Secret key
(
sk_test_...) → this is yourSTRIPE_SECRET_KEY. - Go to Product catalog → Add product, create three recurring products:
- "Starter" — 149 CZK / month
- "Pro" — 349 CZK / month
- "Business" — 799 CZK / month
For each, copy the Price ID (looks like
price_1AbCdE...) → these becomeSTRIPE_PRICE_STARTER,STRIPE_PRICE_PRO,STRIPE_PRICE_BUSINESS.
- Webhook: you'll finish this step after deploying (step 3 below), because Stripe needs your live URL first.
- When you're ready for real money, flip to Live mode in the dashboard and repeat steps 3–4 to get live keys/price IDs (test and live keys are different).
1.5 Resend (transactional email) — optional for v1, free tier
- Go to https://resend.com, sign up, verify a sending domain (or use their test domain while developing).
- API Keys → create one → this is your
RESEND_API_KEY. - Not wired into the app yet in v1 (password reset emails currently go through Supabase's own email delivery, which works out of the box on the free tier with Supabase's default templates/limits). Add this later if you want branded emails.
1.6 Hugging Face (hosting) — free CPU tier, no credit card
- Go to https://huggingface.co/join if you don't have an account.
- You'll create the Space in step 2 below.
2. Create the Hugging Face Space
- Go to https://huggingface.co/new-space.
- Name:
etsy-listing-optimizer(or whatever you like). - SDK: choose "Gradio" and version 5.12.0. This project's root
README.mdalready contains the metadata block HF Spaces reads (sdk: gradio,app_file: server.py) — as long as you keep that file at the repo root, the Space will runserver.py, which starts the full FastAPI app (auth, billing, webhooks, GDPR routes, etc.) with the Gradio UI mounted on top of it, all on port 7860. No Dockerfile needed. - Hardware: CPU basic (free).
- Visibility: your choice (Public is fine and free; Private also works on the free tier).
- Click "Create Space".
2.1 Push the code
From this project's folder:
git init
git remote add space https://huggingface.co/spaces/<your-username>/etsy-listing-optimizer
git add .
git commit -m "Initial deploy"
git push space main
(Use your HF username/token when prompted for credentials — Hugging Face will show you a personal access token to use as the password under Settings → Access Tokens if you don't have one yet.)
Once pushed, check the Space's Logs tab — you should see uvicorn start
up and, in demo mode, a line noting no LLM provider is configured yet. If
you instead see a build error about app_file, double-check README.md
is present at the repo root with its metadata block intact (git sometimes
excludes dotfiles/READMEs if you cherry-picked what to push — push the
whole folder).
2.2 Add your secrets
In the Space, go to Settings → Variables and secrets → New secret for each of these (values from section 1 above):
SUPABASE_URL
SUPABASE_ANON_KEY
SUPABASE_SERVICE_ROLE_KEY
GROQ_API_KEY
GEMINI_API_KEY
STRIPE_SECRET_KEY
STRIPE_WEBHOOK_SECRET (added in step 3 below, after this first deploy)
STRIPE_PRICE_STARTER
STRIPE_PRICE_PRO
STRIPE_PRICE_BUSINESS
APP_BASE_URL (e.g. https://your-username-etsy-listing-optimizer.hf.space)
Adding a secret automatically restarts the Space. Leave
STRIPE_WEBHOOK_SECRET empty for now — you'll get that value in step 3.
Once SUPABASE_URL, a Supabase service role key, at least one of
GROQ_API_KEY/GEMINI_API_KEY, and STRIPE_SECRET_KEY are all set, the
app automatically leaves demo mode and starts using real services — no code
changes required.
3. Wire up the Stripe webhook
- Once your Space is live, note its URL, e.g.
https://your-username-etsy-listing-optimizer.hf.space. - In Stripe, go to Developers → Webhooks → Add endpoint.
- Endpoint URL:
https://your-username-etsy-listing-optimizer.hf.space/billing/webhook - Select these events to listen for:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deleted
- Save, then copy the Signing secret (
whsec_...) shown on the endpoint's page → set this asSTRIPE_WEBHOOK_SECRETin your HF Space secrets (section 2.2). This restarts the Space again. - Test it: in Stripe's webhook page, click "Send test webhook" and confirm
your Space logs show
200 received: true— check the Space's Logs tab.
4. Verify everything end-to-end
- Open your Space URL. You should no longer see the "Demo mode" banner.
- Sign up with a real email in the Account tab.
- Generate a listing in the Generate listing tab — this now calls Groq for real.
- In the Account tab, click "Get checkout link" for a paid tier, use a
Stripe test card (
4242 4242 4242 4242, any future expiry, any CVC) to complete checkout. - Confirm your tier updated (try generating more than 5 times — the Free cap should no longer apply).
- Test Export my data and Delete my account — confirm the exported JSON looks right and that deletion removes the Supabase Auth user (check Authentication → Users in Supabase — the row should be gone).
5. Going to production (real payments)
- Flip Stripe to Live mode, repeat section 1.4 steps 3–4 for live keys and live Price IDs, update the HF secrets, and set up a second webhook endpoint pointed at the same URL but using your live webhook signing secret.
- Have a lawyer (or a reputable EU-focused generator) review the draft
Privacy Policy / Terms / Refund Policy at
/legal/privacy,/legal/terms,/legal/refundsbefore taking real customers — the current text is a placeholder, not legal advice (see the banner on each page). - Run
pip-auditperiodically againstrequirements.txtto catch known vulnerabilities in dependencies (see note inrequirements.txt). - Consider setting up log monitoring/alerting on your HF Space (or moving to a platform with better observability) once you have real users — the free CPU tier is fine for launch but has no built-in alerting.
Design decisions driven by the "zero upfront cost" constraint
- Groq over a paid API (OpenAI/Anthropic): Groq's free tier is generous and fast (LPU inference); the tradeoff is Llama 3.3 70B is a notch below GPT-4-class models on nuanced copywriting, which is why the code layers heavy programmatic validation + a critic pass on top rather than trusting raw model output.
- Gemini as fallback, not primary: Gemini's free tier has stricter per-minute limits than Groq's, so it's used only when Groq is unavailable.
- Supabase over a self-hosted Postgres: free managed Postgres + auth + RLS in one product, with an EU-region option for GDPR, without paying for a VPS or a database host.
- Hugging Face Spaces (Gradio SDK, CPU basic) over a paid PaaS (Fly.io/Render paid tier): free forever for a single small instance; the tradeoff is you're on a single instance with no autoscaling — fine for a v1 micro-SaaS, but you'll want to move off it if traffic grows (the in-memory rate limiter and demo-mode fallback both assume single-instance too).
- slowapi (in-memory) rate limiting over Redis-backed: free, zero extra
infra; the tradeoff is limits reset if the Space restarts, and won't work
correctly if you ever scale to multiple instances — swap in a Redis
storage_uriat that point. - Resend stubbed rather than wired up: Supabase's built-in auth emails (confirmation, password reset) work out of the box for free, so Resend was left as a v2 nice-to-have rather than a v1 requirement, keeping the initial integration surface smaller.