Skip to content

The publishing pipeline

When you publish a target, Topicary processes every topic through a 4-stage pipeline. Understanding these stages helps you predict how your authored content becomes the published output.

Pipeline stages at a glance

Stage

Input

Output

What happens

1. Resolve

Raw topic content with component references

Content with all components expanded inline

Every ComponentRef and InlineComponentRef is replaced with the referenced component's content, recursively

2. Filter

Resolved content with conditional blocks

Content with non-matching conditions removed

Each conditional block is evaluated against the target's condition profile; non-matching blocks are stripped

3. Replace

Filtered content with variable tokens

Content with all tokens substituted

Each VariableToken is looked up in the target's variable set (and overrides) and replaced with its value

4. Render

Fully resolved plain content

Final HTML (web) or PDF

Content is converted to semantic HTML with heading IDs, sanitized output, and structured metadata

Stage 1: Resolve

The pipeline starts by resolving component references. Every ComponentRef and InlineComponentRef node in the content is replaced with the actual content of the referenced component.

This happens recursively. If a component references another component, that reference is resolved too. The output of this stage is content with no component references remaining, only their expanded content.

Stage 2: Filter

Next, the pipeline evaluates conditional blocks against the target's condition profile. Each conditional block specifies a filter group and one or more values, for example "Audience: Admin". The project defines those groups under Configure > Filters; the target's selection is its condition profile, set in the target's Conditions subsection.

The target's condition profile records which values are active. If a block's values overlap with the profile, the block's content is kept. If not, the entire block is removed.

A filter group the profile does not mention is not filtered at all: every block tagged with that group is kept. So an empty condition profile includes all conditional blocks regardless of their values.

You build the profile by selecting values in the target's Conditions subsection, not by writing it out. Stored, it refers to filter groups and values by their internal identifiers rather than by the names you see, so it is not something you can hand-write or copy between projects.

Stage 3: Replace

The pipeline then processes variable tokens. Each VariableToken node contains a variable key (for example, product_name). The pipeline looks up the key in the target's variable set and replaces the token with the value.

If the target has variable overrides, those take precedence over the set's values for the specified keys.

If a key is not found in the variable set or overrides, the token renders as the raw key name. The content health system flags it as an undefined variable.

Stage 4: Render

Finally, the resolved, filtered, variable-substituted content is rendered to HTML. For web targets, this produces semantic HTML with heading IDs (for the table of contents), sanitized output (for security), and structured metadata (for search indexing).

For PDF targets, the HTML is rendered into a print-ready template with page breaks, cover pages, and branded headers and footers.

How web publishing runs

For web targets, this content pipeline runs inside a background job when you publish. Two checks run before the job starts, in this order:

  1. The release gate. Draft paragraphs and unresolved track-changes suggestions block the publish, named one by one with the topic and the block number. This check also runs on the page before you click, so the Publish button is already disabled with a count when something is unfinished.

  2. Content validation. If any topic has a blocking validation error, publishing is refused with a count and you fix them in the Validation panel.

Once both pass, the background job reports progress as it works: it rebuilds the site, records the page addresses, then generates social preview (Open Graph) images, embeddings, AI-readiness (GEO) scores, and the external search index. You can watch the progress and see a clear failure if a step goes wrong, rather than a silent hang. The external search index step does nothing when the target uses the built-in search backend, which needs no separate index.

After the first publish, the live site is served from a cache that refreshes when you publish the target again, and on its own within 24 hours. Publishing again regenerates the site and refreshes the cache immediately. On the dashboard, the Publishing overview, the map toolbar, and the editor's Publishing panel, the button reads Publish before the first publish, Update when the content has changed since, and Published when the live site is current. Published stays clickable: click it to re-publish and refresh the live site.

What this means in practice

A published site is served from a cache, so edits to topics, components, variables, or the map structure are not reflected instantly. Cached pages refresh within 24 hours, or you can click Update on the target to publish the latest content immediately.

The site is rebuilt from your current content each time the cache refreshes. Publishing is what makes that happen on demand: it is not a frozen copy that holds the old wording until you say otherwise.

Processing order matters

The 4 stages run in a fixed order: resolve → filter → replace → render. This means:

  • Components are resolved before conditions are filtered. If a component contains conditional blocks, those blocks are correctly filtered in stage 2.

  • Conditions are filtered before variables are replaced. If a conditional block contains variable tokens, those tokens are only replaced if the block passes the filter.

  • Variables are replaced before rendering. The rendered HTML contains final values, not tokens.

This ordering ensures that all authoring features compose correctly: components can contain conditions, conditions can contain variables, and the output is always consistent.

To try out condition profiles and variable sets without touching a live site, create a second target with the settings you want and publish that one. Each target resolves the pipeline against its own profile and variable set, so the two outputs are independent. Changing the settings on a live target, by contrast, refreshes its cache and can put the change in front of readers.


See also

Was this page helpful?