Integrate in-app help in about an hour
The integration is one request and one component. Everything else on this page is about what you get for it and where the line runs.
GET https://www.helpccms.com/api/deploy/{collection}/{key}That returns the current published text for a key, as HTML and as plain text. There is no package to install, no token to issue, and nothing to keep out of your front-end bundle.
What a developer does once
Get the collection id. Open your collection in the editor and copy it from the register. It is a UUID, it belongs in your configuration, and it is an address rather than a secret.
Write the fetch. Once, somewhere central:
const BASE = "https://www.helpccms.com/api/deploy";
const COLLECTION = process.env.HELP_COLLECTION;
export async function getHelp(key) {
const response = await fetch(`${BASE}/${COLLECTION}/${encodeURIComponent(key)}`);
if (!response.ok) return null;
return response.json();
}Render it where you want it. A tooltip, a panel, an inline paragraph. The response carries html for a rich surface and text for a plain one:
export function Help({ helpKey }) {
const help = use(getHelp(helpKey));
if (!help) return null; // no text is no question mark
return <div dangerouslySetInnerHTML={{ __html: help.html }} />;
}Decide what missing means. A key that has no published content answers with a 404. Your component should show nothing rather than an empty box, and your product should keep working. Help that is unavailable is not an error state.
That is the integration. An afternoon at most, and usually less, because the hard part was never the request.
What replaces your hardcoded strings
Point a coding agent at your codebase and let it collect every explanatory string: tooltips, error messages, onboarding text, empty states. It produces one row per string with three things: the address your app will ask for later, the text as it reads today, and where it sat in your code.
Import that file and every row becomes a topic. Nothing is rewritten on the way in, so your users keep reading exactly what they read before. The import format has the full shape, and it is written to be handed to an agent.
Then the replacement in your code is mechanical: the string becomes a key.
What your developers never do again
Change a sentence. Review a pull request whose entire diff is text. Explain to someone that the fix will ship on Thursday. Carry a support ticket about wording into a sprint.
After the integration, help content changes because someone published it. Your application asks for the current version and gets it within five minutes.
Where the line runs
HelpCCMS holds what the text says. Your application decides when it appears, where it sits, and what it looks like. Nothing renders itself inside your interface.
That is a limit and it is the reason the rest works. Nothing of ours runs in your page, so nothing of ours can slow it down, break your layout or count your users. The security page covers what that means for what is public and what is not.
What to check before you start
Caching. Responses carry an ETag and may be cached for five minutes. If your framework caches fetches, let it: the answer is the same for everyone.
Where the request happens. Server side keeps the collection id out of the browser, which is tidy rather than necessary. Client side works too, because delivery is public and CORS is open.
One key, one topic. An address belongs to exactly one piece of content, and a second claim on it is refused at publish time. Your application never has to deal with two answers.
A first hour that proves it
- Publish one topic with the key
test.hello. - Fetch it from your app and render it on one screen.
- Change the text in the editor and publish again.
- Reload your app.
If step four shows the new text and your deploy pipeline never ran, the integration works and the rest is content.
The full endpoint reference, with status codes, error codes and the version policy, is on the developers page.