The text users read inside a product is usually stored in the code: a tooltip in a component, an error message in a constant, an onboarding line in a template. That works until the text changes. A wording correction then follows the release cycle of the code it sits in.
HelpCCMS stores that text separately. You write it in HelpCCMS, give it a key, and the product requests it by that key.
How it works
Each topic has a help key, for example billing.payment-status. The product requests the key and receives the current text, as HTML and as plain text. After you publish a change, the next request returns the new version. No release is required on the code side.
Delivery
There are two delivery modes:
The content is identical in both modes. They differ in which side initiates the request.
Partial adoption
Keys are migrated one at a time. You can move ten strings and leave the other four hundred in the code. Keys that HelpCCMS does not hold stay where they are.
Before reading further, run the loop once. It takes a few minutes and it makes every other chapter concrete.
On your dashboard, click + New collection and give it a name. A collection is a set of topics that belong together.
You land in the editor with one starter topic.
Write your help text.
In the companion on the right, fill in Help key with something you would recognise in your own code, for example settings.api-keys.
Open the Publish tab and publish.
The help text is published to https://www.helpccms.com/api/deploy/<collection-id>/<your.help-key>.
Integrate this address into your code:
Before:
// The sentence lives in your code
tooltip.textContent = "Create and manage API keys for your account.";After:
// The code names the sentence; HelpCCMS holds it
const help = await getHelp("settings.api-keys");
if (help) tooltip.textContent = help.text;This handbook is written from the source code rather than from a plan. What it describes is what the product does, including the parts that behave differently than you would hope.
So when something is not there, it says so. A chapter that tells you a field does not exist yet is more useful than one that quietly leaves it out, because then you stop looking.
How it is organised
You can read it in order, but it is built to be entered anywhere. Every topic stands on its own, which is the same thing this product asks of you when you write.
A collection is a set of topics that belong together. It is the thing you publish, and it is the thing that has an address.
A topic is one subject: how to reset a password, what a webhook is, why a sync failed. Each topic stands on its own. It has its own identity, and on a paid plan it can be published by itself.
That separation is the whole idea. The topic holds the knowledge; the collection decides where it appears and in what order.
delivery.help-keys.A topic is one subject, written once. It has a title, a short description, and a body made of blocks.
Every topic has a type, and the type is not decoration. It decides which building blocks the editor offers you:
| Type | For | What you get |
|---|---|---|
| Task | A procedure someone follows | Numbered steps, plus before and after sections |
| Concept | Explanation or background | Prose, lists, images. No steps |
| Reference | Material to look things up in | Tables and structured lists |
| Troubleshooting | Problem, cause, solution | A cause and fix structure |
Steps only belong in a task. If you find yourself wanting numbered steps in a concept, the topic is probably two topics.
You can change the type later. Content that no longer fits is not thrown away: it stays in the body, and the editor stops offering the blocks that do not belong.
Some words in a procedure are not ordinary words. Save is a button. Email address is a field. Ctrl-S is a key combination.
A role marks a word as one of those things. You give it a role once, and from then on it is that thing everywhere it appears.
Two reasons this matters, and neither is about styling:
< anywhere in a line. See writing.roles.Everything you make lives in a workspace: your collections, the reusable blocks in your library, and the settings that decide how a publication looks.
You get one workspace when you create your account. It is created for you the moment you confirm your email address, so there is nothing to set up.
Deleting your account deletes the workspace and everything in it. That is irreversible and it happens immediately. Invoices are kept, because the tax authorities require it.
The dashboard lists your collections, newest first, with the date you created each one. Clicking a row opens it in the editor.
Click + New collection at the top right.
Type a name for the collection and confirm.
You land in the editor of the new collection straight away. It is not empty: it arrives with one starter topic so there is something on screen.
Bring in a document under Import, or write your first topic yourself.
Dit is context.
Deleting a collection removes the topics in it as well. Reusable blocks and roles live in your workspace rather than in a collection, so those stay.
You almost never start from nothing. The Import tab takes what you already have.
| Format | Good for |
|---|---|
| .docx | A Word document with heading styles |
| .md and .markdown | Anything already written in Markdown |
| .html and .htm | A page exported from another tool |
| .txt | Plain text |
| .png .jpg .jpeg .webp | Screenshots |
You can also paste. The paste area takes up to 500,000 characters and shows a counter, with a switch between plain and formatted text.
Started an import and walked away? It stays under Imports in progress on the Import tab. Resume picks the triage up where you left it, and Discard closes it without adding anything. Discarded imports stay visible under Recent history, so nothing disappears behind your back.
Two ways to read a Word file
With Word structure you choose what happens next: review everything first, which is what we recommend, add it directly, or bring in only the structure and write the content yourself.
After an import you land in triage. Your document has been cut into pieces, and you say what each piece is. It is built for the keyboard: you go through it once, quickly, without touching the mouse.
| Key | What it does |
|---|---|
| ↓ or j | Next piece still waiting for a decision |
| ↑ or k | Previous one |
| D | Throw this piece away |
| T | A topic starts here. This piece is the title |
| Z | Undo the last decision. Ctrl-Z works too |
| Enter | Put everything into the collection |
Notice what the arrows skip: they jump to the next piece that still needs a decision, not to the next row. Once you have handled something it drops out of your path, so the list gets shorter as you work rather than longer.
On a paid plan you also get S for a section, B for a block type, and C to send a piece to a different collection. S does nothing on a piece you marked as a topic title, because a title is not part of a section.
Editing as you go
A line of text can be edited right there in the row. Ctrl-Enter saves it, Escape cancels. While your cursor sits in that box the single-letter keys stop working, so you can type a d without throwing the piece away.
If your document has a table of contents
You may be asked whether the text contains one. Point it out and the structure that follows is read against it, which usually saves you most of the T presses.
When you start an import you choose between two ways of working.
Both end in the same place, and the result is the same kind of content. The difference is how much sorting you do yourself.
The editor has three panels. You can drag the dividers, and double-clicking a divider resets it. Your widths are remembered per workspace.
| Panel | What it is for |
|---|---|
| Left | The list of topics in this collection, and their order |
| Middle | The topic you are writing |
| Right | The companion: properties of this topic, and publishing |
Above the panels sit two rows. The top one takes you back to your dashboard and holds search and your account. The second one has the Back button and three tabs: Topics, Library and Import.
The middle panel is also a drop zone. Drag a screenshot onto it and it becomes an image in your text, wherever you are in the topic.
The left panel shows every topic in this collection as a tree. The header tells you how many there are, and lets you set how deep the table of contents goes.
Creating a topic
Click + Add at the top of the list.
Give the topic a title and pick its type. Task is preselected; press Enter to confirm.
Ordering and nesting
The buttons at the bottom of the list work on the topic you have open:
Choosing what gets published
Every row has a globe. Switch it off and that topic stays in your collection but is left out of the publication. Use it for drafts, or for material meant only for your own team.
Deleting
The bin on the row deletes the topic after a confirmation. This removes the topic itself, not just its place in the list.
The toolbar sits above your text and stays in view while you scroll.
Left: structure
Right: formatting
Bold, italic, underline and inline code, then a table, a code block and a bulleted list.
The second row
Put your cursor in a table and a row of table actions appears: add or remove rows and columns, or delete the whole table. In a code block you get one button to step back out of it.
What is not there
There is no button for an image, a numbered list, a section, a reusable block, or undo. Images arrive by dropping them. Sections and reusable blocks have their own keys, which the next chapter covers.
+ Step instead. That way the numbering survives publishing and keeps counting across blocks.The right panel has two tabs, Companion and Publish, and it remembers which one you had open. That memory sits in your browser, so it follows you between collections but not between devices.
Selection sits at the top and answers one question: what is under my cursor. It is always filled, even when the answer is nothing in particular.
Containers never appear as the thing itself. A step and a section are where you are standing, not what you are holding, and they have no properties to show.
Topic properties sit below that:
delivery.help-keys.Below that sits a short reminder of the keys you can type while writing, and how to give a word a role.
Publish is the other tab. That is where you publish the collection, copy its address, and take it offline again. It has its own chapter.
Most of what you need while writing sits on four keys. You never have to leave the keyboard to add structure.
| Key | Gives you | Where it works |
|---|---|---|
| / | Blocks: warning, note, tip, table, list, code, image, section title | At the start of a line |
| { | Sections: Before you start, Context, Result, Next steps, or your own | At the start of a line |
| + | A numbered step | At the start of a line |
| < | A role for a word | Anywhere in a line |
Three of the four only listen at the start of a line, so you can type a slash or a plus halfway through a sentence and nothing happens. That is the whole escape hatch: position, not a special character.
Inside a code block none of them fire either. There you are writing code, so Tab inserts two spaces and Enter just makes a new line.
Also worth knowing
A section groups part of a topic under a heading. Four of them have a fixed meaning, which is what lets a published page show them consistently.
Start a new line and type {.
Pick one of the four, or type your own title and choose Create section.
The four presets are Before you start, Context, Result and Next steps. A reader recognises them across topics, and a translation can rename them once for the whole workspace instead of per topic.
Steps only exist in a task. Type + at the start of a line, or use the + Step button.
If there is no procedure yet, one starts. If there is, your step is added to it.
Two procedures in one topic
Start a step on an empty line while a procedure already exists and you get a choice:
Getting out
Press Enter twice on an empty line to leave a step and continue in the body of the topic. The same works inside a section or a list.
A role says what a word is. Save is a button, Preferences is a window, Ctrl-S is a shortcut.
Two ways in
Why bother
You manage your roles under Library, in the Roles tab. That is also where you can create a batch of them up front, before you start writing.
Drag a file into the topic and it lands where your cursor is. You can also type / and choose Image, which opens a file picker.
Three formats are accepted: JPEG, PNG and WebP. The limit is 5 MB per file. Anything else is refused with a message rather than silently ignored.
What happens next is worth knowing, because it explains the rest of this chapter. The file goes into your workspace storage and becomes an item in your library, named after the file without its extension. The topic itself only holds a reference to that item.
Your draft images are not on a public address. Each one is served through a signed link that expires after fifteen minutes, so a link that leaks is worthless within the hour.
You never notice this while writing, because the editor asks for fresh links whenever it opens a topic. It matters in one place: copying an image address out of the editor and pasting it somewhere else will not keep working.
Publishing is what makes an image permanent. At that moment the file is copied to the published side, and there the address is stable for as long as the publication exists.
Alt text is the sentence a screen reader speaks and the text that appears when the image cannot be shown. The image block carries it, and publishing puts it on the page.
What you cannot do yet: there is no field for it in the editor. The value comes from the library item, and per-image editing is on the list. Until then an image you add carries whatever the library item says, which for an uploaded file is empty.
Writing a topic rarely starts with an empty head. There is a paragraph from a chat, a screenshot somebody sent you, the old manual as a PDF, a passage from a specification. Diff Stage is where that material waits.
Waits, not sits. Everything here is on its way somewhere: into this topic, or into the bin. That is why you always see it next to what the topic already holds before anything moves.
It belongs to one topic. Open another topic and you see that topic's Diff Stage.
Two things it is not
Click Diff Stage above the editor. The middle of the screen splits: you keep writing on the left, Diff Stage sits on the right.
Want more room, collapse the topic list with the « in its header. It leaves a narrow strip with a » to bring it back, so you can always find your way out.
The button only appears when a topic is open, because Diff Stage belongs to a topic and without one there is nothing to belong to.
Four ways in, and they behave differently on purpose.
Anything else is refused with a reason. We would rather tell you than accept something we cannot show you.
Click a parked document and it opens beside your topic. What you see depends on what it is, and the difference is real rather than cosmetic.
A Word file is shown as text, because it was read when you parked it. So you can select a passage and click Put the selected text in Diff Stage. That selection becomes an ordinary text item and then follows exactly the same path as anything you pasted.
A PDF is shown by your browser's own viewer. We cannot reach what you select inside it, so there copying and pasting is the way. Annoying, and it is the honest answer rather than a button that does nothing.
Click an item and you see what it will become, next to what your topic holds now. That comparison is the point of the whole thing: you are bringing in something you did not just type, so you should see it before it lands. An image is shown as an image, not as the word image.
The help key
Above the comparison sits the help key of the topic you are pulling into. It starts at whatever the topic already has, so usually you glance at it and move on. But if this is a topic your product will ask for by name, set it here. Afterwards you have to go and find the properties, and that is the step people forget. A topic without a key delivers nothing, and nobody notices until a tooltip stays empty.
Leave the field as you found it and nothing changes. An empty field does not wipe a key you already had.
Then you choose
If somebody else, or your own second tab, saved this topic while you were looking, you get a warning instead of a silent overwrite. Reload and decide again.
An item you have pulled in stays visible, marked as used. Nothing disappears behind your back, and later you can still see what came from where.
Some things appear in many topics: a safety warning, a set-up step, an explanation of a term. Copying them means that one day they will disagree with each other.
Put your cursor in the block you want to reuse.
Press Ctrl-S. Checkboxes appear next to your blocks.
Use the arrow keys and the space bar to extend the selection, then press Enter.
Give it a name, and optionally a search key so you can find it back.
Your selection has to be one continuous run within the same parent. Gaps are filled in automatically, and selecting a block somewhere else starts a new selection.
Editing something reused
Put your cursor in reused content and a green banner tells you what it is and in how many places it appears. Any edit asks first, because you are about to change every one of those places:
Cleaning up
Reusable blocks live under Library. You can only delete one when it is used nowhere, which is the same rule as for roles.
Publishing takes a frozen copy of your collection and puts it at a public address. Whatever you edit afterwards stays private until you publish again.
Open the Publish tab in the right-hand panel.
Click Publish.
The status turns to published and an address appears. Copy puts the full address on your clipboard.
The page stays there. There is no expiry date, and publishing again overwrites the same address, so a link you share once keeps working.
Choosing what goes in
The globe on each row in the topic list decides whether that topic is part of the publication. Switch it off for drafts.
Taking it offline
Unpublish removes the publication and the address stops working straight away. Your content is untouched, so you can publish again whenever you want.
A topic can also be published on its own. That is what makes it usable as help inside another product: one subject, one address.
You do it from the topic properties in the companion, not from the Publish tab. Publishing a topic is about that topic, so it lives with the rest of its properties.
A published topic is embeddable: you can put it in an iframe, and it does not refuse to be framed. It is public, read-only, and has no buttons.
A help key is a name you give a topic in the External reference field. Something you would recognise in your own code:
Your product asks for that name and gets the current text back. Change the text, publish, and every place that asks for that key shows the new version. No release on your side.
Only published topics can be fetched. If it is not published, it does not exist as far as delivery is concerned, so a draft can never leak into somebody's product.
What a key cannot do yet
A key names a whole topic, not a paragraph inside it. So a tooltip gets the entire topic, and if you want one sentence somewhere and three paragraphs elsewhere, those are two topics today. Keys on individual blocks are on the list, not in the product.
There are two ways to get your text into a product, and they deliver exactly the same thing.
| Fetching | Sending | |
|---|---|---|
| Who starts | Their application asks | We send it to them |
| Where the text lives | With us | In their own systems |
| Depends on our uptime | Yes | No |
| Setup | One request | An endpoint and a signature check |
Start with fetching. It is one request and there is nothing to install. Move to sending when someone tells you they cannot depend on an outside service at runtime, which is a normal thing for a larger customer to say.
For sending you set up a target under Delivery: where to send it, and whether it should go automatically whenever you publish a topic.
| Free | Pro | |
|---|---|---|
| Bring in and structure | Yes | Yes |
| AI sorting during import | No | Yes |
| Publish a collection as a page | Yes | Yes |
| Publish a single topic, with its own address | No | Yes |
| Deliver by help key | No | Yes |
| Price | Free | EUR 100 per seat per month |
Genesis is the same product as Pro at a permanent 40% discount, limited to the first 500 subscriptions. The discount lasts as long as your subscription runs without interruption. Cancel and it is gone for good, and the place does not come back.
Republishing is unlimited on every plan. There is no cap on how often you publish.
You can delete your account from your account page. There is no form to fill in and nobody to ask.
What happens, in this order:
Invoices are kept, because tax rules require it. They hold billing details rather than anything you wrote.
Two other things stay, on purpose. If you signed up for the newsletter, that is a separate permission with its own unsubscribe link, so closing your account does not silently cancel it. And any error report you sent us stays, with your name taken off it: the report keeps its value, you are no longer in it.
The interface language is a setting on your account. It changes labels and buttons, not a word of what you wrote.
Your content has its own language, set when you publish. That separation is what lets one person work in a Dutch interface on an English collection.
Your product asks for a help key and gets nothing back. Before you go looking at the connection, check these three, in this order. Together they cover almost every case.
1. The topic is not published
Delivery only ever hands out published topics. A draft does not exist as far as your product is concerned, and that is deliberate: it means work in progress can never leak into somebody else's screen. It also means that writing the text is not enough. You have to publish it.
2. Two topics carry the same key
Within one collection a key must point at exactly one topic. If two of them carry it, nothing is delivered at all. That is a choice: showing the wrong explanation is worse than showing none. Search your collection for the key and take it off the one that should not have it.
3. The key does not match
It is compared exactly, including capitals and dots. billing.payment-status and Billing.Payment-Status are two different keys.
Publishing takes a frozen copy. Everything you type afterwards stays private until you publish again, and that is the whole point: your readers never see half-finished work.
So the first answer is usually the simple one. Publish again.
But there is a second case, and it is easier to miss
Shared things are frozen into that copy as well: reusable blocks, roles, and images. Replace a screenshot or rename a role, and every already published topic that uses it keeps showing the old version until you publish that topic again.
So after changing something shared, ask yourself where else it is used. The library tells you: open the item and it lists the topics it appears in.
Numbering is a property of where a topic sits, not of the topic itself. A topic higher up the tree can have it switched off, and then everything underneath follows.
You can see it in the topic properties: it will say numbering is on but suppressed, because a parent has it off. That is not a bug report, it is the answer.
Fix it at the parent, or accept it. What you cannot do is force one topic to be numbered inside an unnumbered branch, because then the numbers would not run in order anymore.
Put your cursor anywhere in the word. The Selection panel at the top of the companion tells you which role is on it, and offers Change role and Remove role.
Pressing < again with your cursor in the word works too: the picker then applies to the whole word, and No role at the top takes it off.
Your work is already saved. The editor writes as you type, so there is no save button and no moment where you can lose the last paragraph.
That frees up Ctrl-S, and it starts selecting blocks to turn into reusable content, with the block your cursor is in already ticked. Press Escape to back out.
If not one item in a chapter matches anything else, that chapter is usually the table of contents. The sections it lists live in other chapters, and each of those becomes a topic of its own on import.
So you can nearly always throw this page away. Nothing is lost: the content it points at is elsewhere in the same document.
Pointing out the table of contents when you are asked has a real payoff, by the way. The structure that follows is read against it, which saves you most of the T presses.
Two rules, and both are refusals rather than warnings.
So testing against your laptop does not work. Put something reachable in front of it, or build your check against Test first: that sends a signed message with no content in it, so you can get your signature check right before anything real arrives.
Deleting a collection deletes the topics in it. There is no undo and no bin.
What survives is everything that lives in your workspace rather than in the collection: reusable blocks, roles, and images stay where they are, because other collections may be using them.
That asymmetry is worth remembering the other way around too. A topic belongs to a collection; a role belongs to you.
Delivery puts your published topics where your product can use them.
A target is somewhere to send them: your endpoint, and whether we should send automatically whenever you publish a topic. If you would rather have your application fetch the text itself, you do not need a target at all.
Either way the content is identical. The difference is who starts, and where the text ends up living.
The address we send published help to.
It has to use https, and it cannot point at an address inside a private network. Every request carries a signature so you can check it really came from us.
Not sure it works? Use Test first. That sends a signed message with no content in it, so you can try out your signature check before anything real arrives.
Sends a signed message with no content, to check the connection.
Useful before you have published anything, and useful while the receiving side is still being built.
Replaces the secret. The old one stops working immediately.
You see the new secret once, so store it before you close the panel. There is no way to look it up afterwards, which is what makes it a secret rather than a password.
Do this if the secret may have been seen by someone who should not have it, or when someone with access to it leaves.
A role marks what a word IS, not how it looks. A button name stays a button name when your styling changes, and a reader recognises it as one.
Here you see every role you made, what it renders as, and in how many topics it is used. Renaming one changes it everywhere it stands, which is the reason to make it a managed role rather than typing the word again.
Deleting is only possible when it is used nowhere. If the button is still standing in a topic, remove it there first.
You do not have to be writing to make a role. Sit down once, add the twenty controls your product has, and afterwards you insert them without breaking your sentence.
You give it a name, a role from the list, and how it should appear: as text or as a standard symbol. The fallback text is what a screen reader says and what shows up if the symbol cannot be drawn, so it is never optional.
Counted across every topic in your workspace, not just this collection. That is the point of a library: an piece you share is shared everywhere.
Zero means it is safe to delete. Anything else means the delete button stays off until you remove it from those topics, because deleting it out from under them would leave holes in text you never opened.
A safety warning, a set-up step, an explanation of a term. Written once, standing in as many topics as you like, and changed in one go.
Expand one to see where it stands. Editing it there changes every one of those places, so the editor asks first.
Same rule as for roles: it can only be deleted when it is used nowhere.
> **Status: ROUGH DRAFT (2026-06-16, EN).** Grounded in the current import code; > still to refine + verify against the live UI. The user-facing flow is stable; > import *accuracy* keeps improving under the hood (a structured parser is > planned) without changing these steps.
**Import** turns existing content into a topic without retyping. ManualCraft reads your source, splits it into chapters, and sorts the content into blocks. You stay in control: you review the proposal before anything lands in your manual.
> ⚠️ Only import content you have the rights to. Bulk-importing third-party > material is not allowed.
Open the **Import** tab in the editor.
Choose your **import mode**:
Provide your content: **paste** text, **upload** a file, or pick a **screenshot**.
ManualCraft splits your source into **chapters** by heading (each `# H1` becomes its own chapter → its own topic).
The content is sorted into **blocks** (paragraph, list, step, table, …) — by the AI if you chose that, otherwise deterministically from the structure.
You land in the **review screen (triage)**. Here you see the proposal:
Click **Place / Confirm** to commit the chapter as a **topic** in your manual.