Frontage generates production-ready starter sites - local businesses, personal portfolios, and product dashboards - complete with AI-written copy, a curated color system, SEO basics, and a one-click ZIP export.
Quick Start β’ Features β’ Architecture β’ Contributing
| Kind | For | Types included |
|---|---|---|
| Business | Local storefronts | Restaurant, pharmacy, dentist, salon, retail, real estate, education, general services |
| Portfolio | Personal sites | Developer, designer, freelancer / consultant |
| Dashboard | Product / demo UIs | SaaS analytics, admin panel, e-commerce |
Bring your own key for Claude (Anthropic), GPT (OpenAI), or Gemini (Google).
Frontage auto-detects whichever is configured, or force one via AI_PROVIDER. No key
at all still works - every type ships with solid placeholder copy.
8 curated palettes, or drop into custom mode with native color pickers for every CSS variable. Logo/avatar upload with automatic resizing, embedded directly into the export as a data URI. Auto-generated monogram favicon when no logo is provided.
Address, hours, and an embedded Google Map. Meta description, Open Graph tags, and schema.org JSON-LD structured data, mapped per type for better search visibility. WhatsApp deep links that correctly normalize local Pakistani number formats.
Sidebar nav, stat cards, a weekly trend chart, and a recent-activity feed - all static, all clearly labeled as sample data, built from your own nav items and metric labels.
Every generation auto-saves to a local SQLite database. Regenerating copy updates the same draft instead of piling up duplicates. Browse, reload, or delete past work from the Drafts panel.
Skip-to-content links, visible focus states, alt text, and semantic landmarks baked into every export.
Two independent services over a local HTTP API:
frontend/- React + Vite. The form, the live preview (sandboxed iframe), the drafts drawer, the download.backend/- Flask. Owns type/palette config, calls whichever AI provider is configured, renders via Jinja2, persists drafts to SQLite, builds the export ZIP in memory.
Nothing leaves your machine except the AI call for copywriting, which is entirely optional.
- Python 3.10+
- Node.js 18+
- An API key from Anthropic, OpenAI, or Google AI Studio - optional, the tool falls back to placeholder copy without one
git clone https://github.com/LwkMoon/frontage.git
cd frontagecd backend
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .envOpen .env and add any one of these: (Adding API Key is optional)
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
GEMINI_API_KEY=...Set more than one and Frontage picks Anthropic > OpenAI > Gemini automatically, or force a specific provider:
AI_PROVIDER=openaiThen run it:
python app.pyBackend is live at http://localhost:5000. A drafts.db SQLite file is created
automatically on first run (gitignored, stays local to you).
Run
python selftest.pyfirst for a fast sanity check - it exercises every type across all three site kinds and works with or without an API key.
cd frontend
npm install
copy .env.example .env # only needed if the backend isn't on localhost:5000
npm run devFrontend is live at http://localhost:5173.
- Pick a kind - Business, Portfolio, or Dashboard.
- Fill in identity, appearance (palette or custom colors), and the kind-specific details.
- Claude/GPT/Gemini writes the headline, tagline, and supporting copy.
- Preview live, regenerate copy as many times as you like, then download a ready-to-edit ZIP.
- Everything auto-saves along the way - reopen any past draft from Drafts.
frontage/
βββ backend/
β βββ app.py Flask app: routes, rendering, JSON-LD, SEO
β βββ site_kinds.py Registry: kind β types + template
β βββ business_types.py Business type configs
β βββ portfolio_types.py Portfolio type configs
β βββ dashboard_types.py Dashboard type configs
β βββ palettes.py Curated palettes + custom color resolution
β βββ db.py SQLite draft persistence
β βββ selftest.py End-to-end sanity check, no server required
β βββ services/
β β βββ ai_provider.py Multi-provider AI calling (Claude/GPT/Gemini)
β β βββ prompts.py Prompt construction per kind
β β βββ demo_data.py Deterministic sample data for dashboards
β β βββ images.py Logo processing + favicon generation
β βββ templates_data/
β βββ business.html.jinja Business template
β βββ portfolio.html.jinja Portfolio template
β βββ dashboard.html.jinja Dashboard template
β βββ base.css.jinja Shared CSS (business + portfolio)
β βββ dashboard.css.jinja Dashboard-specific layout CSS
βββ frontend/
βββ src/
βββ App.jsx Top-level state, draft lifecycle
βββ api.js Backend API client
βββ components/
βββ KindSelector.jsx Business / Portfolio / Dashboard switcher
βββ BusinessForm.jsx
βββ PortfolioForm.jsx
βββ DashboardForm.jsx
βββ PreviewPane.jsx Live preview + export
βββ HistoryDrawer.jsx Draft browser
New business/portfolio/dashboard type - add an entry to the relevant
*_types.py file: label, layout, icon, fallback copy. No template changes needed.
New palette - add an entry to PALETTES in backend/palettes.py with six
CSS variables.
New AI provider - add a caller function to services/ai_provider.py
following the existing pattern.
See CONTRIBUTING.md for the full guide.
- Multi-page export (Home / About / Contact) as an alternative to single-page
- Direct deploy to Vercel/Netlify from the UI
- Image gallery section for uploaded photos beyond the logo
- Bilingual export (English + Urdu) with RTL support
- Docker Compose for one-command local start
Have an idea that's not listed? Open an issue.
New types and palettes are the easiest way to add real value in a single PR. See CONTRIBUTING.md for setup, guidelines, and what a good PR looks like here.
- Per-provider model overrides live in
.env:ANTHROPIC_MODEL,OPENAI_MODEL,GEMINI_MODEL. - The Google Maps embed uses the no-API-key
output=embedURL pattern. - Uploaded logos are capped at 3MB and resized to 480px max before embedding.
- Dashboard numbers are deterministic sample data, always labeled as such - never presented as real analytics.
- Built as a local, single-user tool: no auth, no rate limiting. Put it behind auth before deploying anywhere reachable over a network.
MIT - see LICENSE. Use it, fork it, ship it for clients, whatever's useful.