An AI-powered blog generation platform that produces SEO-optimized, publication-ready articles in seconds. Users provide a keyword, select up to two writing tones, choose an article length, and receive a fully formatted blog streamed in real time.
Live: autoblog.wendiblac.com
Portfolio: wendiblac.com
- Features
- Tech Stack
- Architecture
- Project Structure
- Getting Started
- Environment Variables
- Usage
- Testing
- Deployment
- License
| Feature | Description |
|---|---|
| AI Blog Generation | Streams long-form articles from an LLM via a serverless edge function |
| Multi-Tone Selection | Select up to two tones (Professional, Casual, SEO Optimized, Persuasive) per article |
| Configurable Length | Short (~400 words), Medium (~800 words), or Long (~1 500 words) |
| Real-Time Streaming | Content renders progressively as the model generates tokens |
| Markdown Rendering | Headings, lists, code blocks, and blockquotes display with full typographic styling |
| Local Persistence | Generated blogs are saved to localStorage for offline access |
| Edit & Export | Switch between rendered preview and raw Markdown editor; copy to clipboard |
| Responsive UI | Fully responsive layout optimised for desktop and mobile viewports |
| Layer | Technology |
|---|---|
| Framework | React 18 with TypeScript 5 |
| Build Tool | Vite 5 |
| Styling | Tailwind CSS 3 + shadcn/ui component library |
| Markdown | react-markdown + remark-gfm |
| State Management | React hooks (useState, useCallback, useEffect) |
| Routing | React Router v6 |
| Backend | Supabase Edge Functions (Deno runtime) |
| AI Model | Google Gemini 2.5 Flash (via OpenAI-compatible endpoint) |
| Testing | Vitest + Playwright |
| Linting | ESLint 9 with TypeScript and React plugins |
┌─────────────────────────────────────────────────┐
│ Client (React SPA) │
│ │
│ LoginScreen ──▶ BlogForm ──▶ BlogEditor │
│ │ │ │ │
│ useAuth generateBlog() useBlogs │
│ (localStorage) (fetch + SSE) (localStorage) │
└───────────────────────┬─────────────────────────┘
│ HTTPS POST (streaming)
▼
┌─────────────────────────────────────────────────┐
│ Supabase Edge Function │
│ /generate-blog │
│ │
│ • Validates request body │
│ • Constructs system + user prompt │
│ • Streams response from Gemini API │
│ • Returns chunked text/event-stream │
└─────────────────────────────────────────────────┘
- Authentication — User enters name and email; credentials are stored in
localStorageand used to personalise the session. - Blog Generation — The client sends keyword, tone, and length to the
/generate-blogedge function. The function streams Markdown tokens back via Server-Sent Events. - Rendering —
BlogEditorconsumes the stream incrementally, parsing Markdown into styled HTML withreact-markdown. - Persistence — On stream completion, the finished blog is serialised to
localStorageunder a UUID key.
├── public/ # Static assets (robots.txt, placeholder SVG)
├── src/
│ ├── components/
│ │ ├── ui/ # shadcn/ui primitives (button, input, card, etc.)
│ │ ├── BlogEditor.tsx # Markdown preview + raw editor with streaming support
│ │ ├── BlogForm.tsx # Keyword, tone selector, length picker
│ │ ├── BlogList.tsx # Saved blog cards with delete action
│ │ ├── LoginScreen.tsx # Name + email authentication screen
│ │ └── NavLink.tsx # Reusable navigation link
│ ├── hooks/
│ │ ├── useAuth.ts # Authentication state (localStorage)
│ │ ├── useBlogs.ts # CRUD operations for saved blogs
│ │ └── use-mobile.tsx # Responsive breakpoint hook
│ ├── lib/
│ │ ├── generateBlog.ts # Edge function client with SSE streaming
│ │ └── utils.ts # Tailwind merge utility
│ ├── pages/
│ │ ├── Index.tsx # Main application page
│ │ └── NotFound.tsx # 404 fallback
│ ├── types/
│ │ └── blog.ts # Blog, Tone, ArticleLength type definitions
│ ├── App.tsx # Route definitions
│ ├── index.css # Design tokens + Tailwind base layers
│ └── main.tsx # Application entry point
├── supabase/
│ └── functions/
│ └── generate-blog/
│ └── index.ts # Edge function: prompt construction + LLM streaming
├── index.html # HTML shell with SEO meta + JSON-LD
├── tailwind.config.ts # Theme tokens + custom fonts
├── vite.config.ts # Build configuration
└── vitest.config.ts # Test runner configuration
- Node.js ≥ 18
- Bun (recommended) or npm
- A Supabase project with Edge Functions enabled
# Clone the repository
git clone https://github.com/wendiblac/autoblog-ai.git
cd autoblog-ai
# Install dependencies
bun install
# Start the development server
bun run devThe application will be available at http://localhost:5173.
Create a .env file in the project root:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=your-anon-keyThe edge function requires an AI API key configured as a Supabase secret:
supabase secrets set AI_API_KEY=your-api-key- Sign in — Enter your name and email on the landing page.
- Configure — Type a focus keyword, select one or two tones, and pick an article length.
- Generate — Click "Generate Blog" and watch the article stream in real time.
- Edit — Toggle between the formatted preview and the raw Markdown editor to refine content.
- Manage — View, reopen, or delete saved blogs from the blog list.
# Unit tests
bun run test
# End-to-end tests
bunx playwright testThe application is deployed as a static SPA. Any static hosting provider works:
bun run build # Output: dist/Point your DNS to the hosting provider and configure the custom domain autoblog.wendiblac.com.
This project is part of the wendiblac portfolio. All rights reserved.