# Add a blog to your React (Vite) site

> Add a blog to a React + Vite app: a small serverless proxy keeps your key private, and two components render /blog from the mentionwell Reader SDK.

To add a blog to a React app built with Vite, put a small serverless function in front of the Mentionwell Reader API so your key stays off the browser, then add a /blog index and a /blog/:slug component. Styling comes from the mentionwell package; articles come from your Mentionwell account.

## Setup

1. **Create your site in Mentionwell.** Sign up in the dashboard, or from the terminal: login opens your browser and stores a token, and onboard reads your site, plans articles and starts the first one. New accounts get a 14-day trial with one real article, no card.

   ```
   npx mentionwell-cli login
   npx mentionwell-cli onboard yoursite.com
   ```

2. **Install the SDK and set server-side env vars.** Install the package for its styles and HTML helpers. Add the env vars in your host's dashboard (Vercel, Netlify, Cloudflare), not in a VITE_ variable: anything prefixed VITE_ ships to every visitor.

   `host env vars`

   ```
   # npm install mentionwell
   MENTIONWELL_API_URL=https://app.mentionwell.com
   MENTIONWELL_SITE_SLUG=your-site-slug
   MENTIONWELL_API_KEY=your-reader-key
   ```

3. **Add a proxy function for the key.** This Vercel function forwards /api/blog to the Reader API with your key attached. The docs have the same proxy for Netlify and Cloudflare Workers.

   `api/blog/[...path].ts`

   ```
   export default async function handler(req: any, res: any) {
     const tail = Array.isArray(req.query.path) ? req.query.path : [];
     const suffix = tail.length ? "/" + encodeURIComponent(tail[0]) : "?limit=24";
     const upstream = await fetch(
       process.env.MENTIONWELL_API_URL + "/api/public/" + process.env.MENTIONWELL_SITE_SLUG + "/posts" + suffix,
       { headers: { Authorization: "Bearer " + process.env.MENTIONWELL_API_KEY } }
     );
     res.status(upstream.status).json(await upstream.json());
   }
   ```

4. **Add the /blog index.** Map this component to /blog in your router.

   `src/pages/blog.tsx`

   ```
   import { useEffect, useState } from "react";
   
   export function BlogIndex() {
     const [posts, setPosts] = useState<any[]>([]);
     useEffect(() => {
       fetch("/api/blog").then((r) => r.json()).then((data) => setPosts(data.posts ?? []));
     }, []);
     return (
       <main>
         <h1>Blog</h1>
         {posts.map((post) => (
           <a key={post.slug} href={"/blog/" + post.slug}>{post.title}</a>
         ))}
       </main>
     );
   }
   ```

5. **Add the article page.** Map this component to /blog/:slug and pass the slug from the URL.

   `src/pages/blog-post.tsx`

   ```
   import { useEffect, useState } from "react";
   import { prepareArticleHtml } from "mentionwell/html-utils";
   import "mentionwell/styles";
   
   export function BlogPost({ slug }: { slug: string }) {
     const [post, setPost] = useState<any>();
     useEffect(() => {
       fetch("/api/blog/" + encodeURIComponent(slug)).then((r) => r.json()).then((data) => setPost(data.post));
     }, [slug]);
     if (!post) return <p>Loading…</p>;
     return (
       <article>
         <h1>{post.title}</h1>
         <div className="wb-article-host" dangerouslySetInnerHTML={{ __html: prepareArticleHtml(post.html) }} />
       </article>
     );
   }
   ```

## Start from a template

[Vite + React blog starter](https://github.com/ziplyne-agency/mentionwell-vite-react-starter): Vite, React and React Router, prerendered to static HTML at build time so AI crawlers read every article. The key stays out of the browser.

## Good to know

- These pages render in the browser. Google runs JavaScript, but many AI crawlers do not. If being cited by ChatGPT or Claude matters, pre-render /blog at build time (the Connect wizard's static site option) or use a server-rendered framework such as Next.js or Astro.
- Never put MENTIONWELL_API_KEY in a VITE_ variable or in src/. It belongs in the proxy function's environment only.
- Lovable and Bolt projects are React + Vite too. If you built there, the chat prompt does all of this for you.

## FAQ

### Why do I need a proxy for a React app?

Vite apps have no server of their own, and the Reader API key must not ship to the browser. A small serverless function on Vercel, Netlify or Cloudflare adds the key on the server and forwards the response.

### Will AI engines see articles on a client-rendered page?

Google renders JavaScript, so it will. Many AI crawlers fetch raw HTML only, so for AI citations pre-render /blog at build time or serve it from a server-rendered framework.

### Do I need a CMS?

No. Mentionwell stores and serves the articles. Your site only needs a /blog page that reads them, and your AI builder writes that page for you from the setup prompt.

### What does it cost to try?

Nothing. Every new account gets a 14-day trial with one real article written for your site (it starts as soon as setup finishes), plus a few AI visibility checks. No card. After 14 days you stay on the Free plan, which still writes 1 article a month. Builder is $24/month ($19/month billed yearly) for 5 articles, a weekly AI search check, and the CLI and MCP for your coding agent. Starter is $79/month for 15 articles.

Start free: https://app.mentionwell.com/sign-up
MCP servers and CLI: https://mentionwell.com/mcp
Canonical URL: https://mentionwell.com/builders/react
