The Next.js starter is a finished site for your project's content: the blog, the changelog, the help center with search, your pages, a read-only roadmap and the site widget. It renders on the server with the Next.js App Router, caches every page, and refreshes a page when you publish. The code is on GitHub at kookee-dot-dev/starter-nextjs, under the MIT license, so you can change anything in it. To see it first, open the live demo, which shows the content of a made-up invoicing app.
Deploy it
In your project, open API keys under Connect and click Create Key. Copy the key.
On the starter's GitHub page, click Deploy with Vercel. Vercel copies the repository to your GitHub account and asks for
KOOKEE_API_KEY: paste the key.Once the deployment is live, open Settings → Project in Kookee and add the site's address to the Allowed Origins card, such as
https://help.example.com. While the list is empty any site can use the key; once it holds an address, browsers on other sites are refused. Only owners and admins can change it.
The site now shows your project's name in the header and your published content on every page. Without a key, every page shows a short setup guide instead.
To work on it on your own machine, clone the repository Vercel created in your GitHub account, run npm install, copy .env.example to .env.local with the key in it, add http://localhost to Allowed Origins (it covers every port), and run npm run dev. Without Vercel, npx create-next-app@latest --example https://github.com/kookee-dot-dev/starter-nextjs my-site gives you a copy to start from.
What the site shows
Address | What it shows |
|---|---|
| The newest posts and changelog entries, and your help categories |
| Posts, 12 per page; a post with its table of contents and reactions |
| Changelog entries; an entry with reactions |
| Categories and search as you type; a category's articles; an article with its table of contents and the "Was this article helpful?" vote |
| Up to 100 open feedback posts, most voted first, by column, read-only |
| Your status page, once you turn it on: incidents, maintenance and each component's uptime over 90 days; an incident with its updates |
| Your pages, such as |
It also serves sitemap.xml, robots.txt, llms.txt and an RSS feed for the blog and one for the changelog. Each post, changelog entry, help article and page takes its title, description, canonical address, Open Graph tags and JSON-LD from the entry and its SEO fields.
The header has a "What's new" badge for your latest changelog entries, and a link to your hosted portal when it is on. Under the header, a pill shows the title of the newest announcement the visitor hasn't dismissed, however old. It opens a dialog that lists the ten newest, without the ones the visitor dismissed; a click on one shows it in full. Dismissals stay in the visitor's browser; to take an announcement down for everyone, unpublish it.
The site widget appears once you have saved its settings under Site widget → Customize and the pages have refreshed: within six hours, or right after a redeploy. Reset to the plain chat takes it off the same way. Once the widget shows, it loads its tabs and texts in the browser, so later changes to them reach the site within about a minute. Set KOOKEE_ROADMAP to false to hide the roadmap. To show your status page at /status, with a "Status" link in the header, set KOOKEE_STATUS to true in Vercel and redeploy, once you have set the page up as Set up a status page describes. The site reads the status with your key, so it shows whether or not your portal's Status page module is on.
The site uses your project's default language only. A help article without a category has no address on this site and is left out, and so is a page whose slug is blog, changelog, help, roadmap, status or api, or a post or changelog entry whose slug is page. A page with the slug status is left out even while the status page is off.
Refresh pages when you publish
A page is served from the cache for six hours, then rebuilt in the background on the next visit. KOOKEE_REVALIDATE_SECONDS changes the window, from the next deploy on. To see a change as soon as you publish it:
Open Webhooks under Connect, click Add endpoint, enter
https://<your-site>/api/kookee-webhook, select the four entry events, and the four incident and monitor events if you show the status page, and click Add endpoint. Then copy the signing secret: Reveal signing secret in the endpoint's menu shows it.In Vercel, add the environment variable
KOOKEE_WEBHOOK_SECRETwith that secret, and redeploy.In the endpoint's menu, click Send test. Kookee shows Test event delivered.
From then on, the next visit after a publish or an edit starts a refresh of the pages that show the entry, and an unpublished or deleted entry is gone from the next page served. The pill is on every page, so publishing, editing, unpublishing or deleting an announcement refreshes every page the same way. Some changes send no event and wait for the cache window: renaming the project, a category or a tag, roadmap changes, a changed slug of an entry that another type links to, and the first save or a reset of the widget settings.
The status page is refreshed every minute, since visitors read it during an incident; after a quiet spell, a visit can get a copy up to five minutes old while it refreshes. With Incident published or maintenance scheduled, Incident updated, Monitor down and Monitor up again selected on the endpoint, the next visit after one of them shows the current status. A status you set by hand, an incident you change with Edit or delete, and a maintenance window that starts or ends send no event and wait for the next refresh.
What it costs
Each time a page is built, the server reads from Kookee with your key: the project, the latest changelog entries, the ten newest announcements (one request for the list and one for each), the pages for the footer, and what the page itself shows. In your visitors' browsers, help search, the widget's Help tab and article reader, reactions and helpful votes are requests too. All of them count toward the monthly API requests of the project owner's account, which all its projects share; Rate limits, plans and error handling lists each plan's allowance. Status page reads are the exception: they do not count toward the monthly requests, and have a rate limit of their own, ten times the project's limit per minute. The widget's AI chat is not an API request: each answer uses one of the account's monthly AI answers.
Each time the server fetches a blog post, page or help article, Kookee counts one view, so view counts here follow page rebuilds rather than readers. A help article opened in the widget's reader counts a view each time, and changelog entries count none. Help article views decide the popular articles in the widget and on your portal.
The key is in your pages' code, so anyone can copy it and spend your requests and AI answers with it. It reads what is published, adds reactions and votes, searches help, asks the assistant and sends widget feedback, and cannot touch drafts or change content. Allowed origins stop other sites' browsers from using it, but not scripts; API keys and security explains how to replace one.
Continue reading
Using the React components with Next.js, TanStack Start or Vite: the patterns the starter is built from.
Send events to your site with webhooks: the events, the payload, signatures and retries.
Next.js integration guide: read Kookee content in a Next.js app of your own.