Skip to main content

Portal pages import

Generates the documents imported on the portal pages screen: Configuration → Interview portal (named Career page on a career portal) or Configuration → Consumer portal, then Import. A portal site is a set of pages. Each page has an address (its slug), an optional place in the menu, and per language a title, an SEO description and an ordered list of blocks: the same blocks the visual page editor builds. A site can also carry theme CSS that restyles the whole portal. One import can create a single page or rebuild a complete careers site, for example a copy of an existing corporate careers website with its sub-pages.
The import dialog checks the documents first (a dry run) and lists what will change. Apply then writes the pages and the theme at once, as drafts. Nothing reaches candidates until it is published: either with the Publish after import switch in the import dialog, or page by page afterwards. The same documents can also be sent through the API or MCP.

Documents

Two document shapes. A file may hold one document or a JSON array of them; the dialog also takes several files at once.

A whole site

One page

What an import does

  • Matched by slug. A page whose slug already exists is replaced: all its languages, and its menu flag and sort order when given (see Page). Any other page is created. Pages that are not in the document are left alone: an import never deletes a page.
  • Only real changes are written. A page whose content, menu flag and order match what is stored is left as it is, so importing the same document twice writes nothing the second time (different block ids alone are not a change).
  • Same slug twice. The last one in the document (or the last file) wins, with a warning.
  • Draft or live. Everything is saved as a draft. With Publish after import switched on, pages and the theme are published in the same step.
  • Theme. When the document has theme.css, it replaces the portal’s theme draft (and is published with the switch on).
  • Checked before writing. The dialog lists every page it will create (+) or replace (↻), with its languages and block count, and any errors and warnings. An error anywhere blocks the whole import: nothing is written until every document passes. Warnings drop only the part named (a block, a language).
  • Lenient about extra keys. Unknown fields are ignored and unknown block types skipped with a warning, so a document written for a newer editor still imports what this one understands.
  • Values are not checked. Only a block’s type and id are validated. The values in the tables below (a layout, columns, a limit range) are what the renderer understands; anything else imports as written and renders with a fallback or not at all.

Page

Language entry

Slugs

A custom slug is refused when:
  • it is not lower-case words joined by dashes, with / between levels (^[a-z0-9]+(-[a-z0-9]+)*(/[a-z0-9]+(-[a-z0-9]+)*)*$), or longer than 200 characters;
  • its first segment is an address the portal already uses: jobs, blog, support, interview, position, login, profile, calendar, application-tracking, privacy_policy, terms_of_service, cookie_policy, home, catalogue, sessions, resume, pricing, faq and about forty more (both portals share one list);
  • its first segment is a language code (de/… is the German version of a page, not a page called “de”);
  • it starts with _ but is not a built-in slug of the portal being imported into (interview portal: _jobs, _blog, _support, _tracking, _completion, _privacy, _cookie_policy, _footer; coaching portal: _signed_in_home, _blog, _support, _footer).
Built-in slugs (starting with _) and the home page cannot be moved or renamed. Importing them replaces their content (every language), and their menu flag and sort order only when the document gives them.
  • A top-level page with show_in_menu: true gets a link in the portal header, labelled with its title in the visitor’s language.
  • Its direct sub-pages with show_in_menu: true form that link’s dropdown. Deeper levels never appear in the menu: link to them from blocks.
  • sort_order orders both levels.
  • Built-in pages that can be in the menu follow their own show_in_menu once published: _jobs, _blog and _tracking on the interview portal, _signed_in_home on the coaching portal, _support on both. Leave show_in_menu out when importing them to keep the current setting.

Blocks

Every block is an object with a type and a stable id (unique within its language; generated when missing or duplicated). All blocks also accept: Fields marked markdown use the restricted renderer described in Format content with Markdown. Images and videos must be public https URLs; the importer uploads nothing. Next to an imageUrl, a block may carry imageAlt (the image’s text for screen readers in that language; "" marks it decorative) and imageFocal ({ x, y }, 0 to 1 from the top left: the part that stays visible when the image is cropped); the media library fills both when a file is picked. Get the list of block types with what each is for and its fields from get_portal_configuration (block_types, returned with the page documents).

Content blocks

Live blocks

These render data from the portal itself. Links (href, ctaHref) are portal paths (/jobs, /about/our-history, /about#values) or full https URLs.

Theme CSS

theme.css restyles the portal on top of the platform styles. It is saved per portal (Theme CSS on the pages screen, as a draft, then published) and reaches:
  • Interview portal: every page, the header and the footer. On the interview screens only the header and footer, so the interview itself keeps its own look. An interview embedded in an iframe gets no theme.
  • Coaching portal: the public pages only (home, custom pages, support, sign-in, legal pages). The signed-in learner area (/home, catalogue, sessions, the coaching session itself) keeps the platform look.
Write every rule under .jm-site, the wrapper of the portal and of the editor canvas: Use var(--accent) for the brand colour instead of a hard-coded value, so Branding stays the source of truth; the other brand-colour variables are listed there. The tone variables --jm-tone-muted-bg, --jm-tone-dark-bg, --jm-tone-dark-fg, --jm-tone-accent-bg and --jm-tone-accent-fg recolour the sections without touching the blocks, and --jm-footer-gap sets the space above the footer (default 4rem). @import of Google Fonts and @font-face are allowed. Any < character is removed before the CSS is served, so keep it out of strings and comments. On the interview portal, if the header is dark, upload a light logo under Branding → Logo on dark backgrounds and show it from the theme (the coaching portal does not render the dark logo):

Style settings and CSS files

With style settings switched on for the company (JobMojito does that), the theme CSS above gives way to a stylesheet built per brand from two parts, both drafts until published:
  • style_settings: colours (text, button, buttonText, soft, page, panel), fonts (heading and body, each { family, url, weight }; url is a WOFF2 file of the company’s media library), the spacing steps xs to xl ({ desktop, phone } in px, 0 to 400), pageWidth (600 to 2400), corners (radius.card, radius.button, 0 to 64) and headings (heading.h1, heading.h2 in px, transform, weight). Only what is set changes the page. The main brand’s are in the site document; a sub-brand’s in the brands document.
  • css_files: the company’s own CSS files, { path, brand, content, sort_order, version }. brand is a sub-brand’s tag, or null for the main brand. Files are matched by brand and path and never removed by an import; send back the version you read, and a file changed since is refused.
A page of a sub-brand loads the main brand’s stylesheet, then its own. publish: true on the import builds and publishes the stylesheet of every brand whose settings or files the documents carry; publish_portal_stylesheet (POST /portal-css-publish) publishes one brand’s.

Looks of a block

A look is a named style for one kind of block, offered on every block of that kind in the editor (Design → Style) and applied with the block’s styleName. A look is defined by a comment in a CSS file, followed by its rules:
  • Every selector starts from .jm-site .jm-block--<type>.jm-style-<slug>, so a look changes only the blocks that chose it.
  • The editor and agents save each look in its own file, components/<type>/<slug>.css. A company’s own files may define looks too; those are changed only by the company.
  • get_component_style_guide (GET /portal-component-styles) gives, per block type, the parts a look can aim at, its layout variants, the brand’s CSS variables, the looks it already has and the pages that use each. generate_component_styles proposes a few looks for a block; save_component_style (POST /portal-component-styles) saves one as a draft, or deletes it with remove: true.
  • A deleted look’s blocks keep their styleName and show the block’s standard look once the stylesheet is published.

Import through the API or MCP

Send the documents in documents of POST /portal-configuration-update with "kind": "portal-site" (it accepts both formats), "portal": "interview" or "consumer" for where the pages and theme go, and "publish": true to publish in the same step. Send "dry_run": true first to see the pages that would be created or replaced. GET /portal-configuration-get?sections=interview-pages (or coaching-pages) returns the portal’s pages and theme as a jobmojito.portal-site document, ready to edit and send back: each page’s draft content, sort order and menu setting (plus a read-only published_at, ignored on import), the built-in pages included, and the theme CSS draft. If some page writes fail, the others are still written and the response (500) lists failures and what was applied. The MCP tools are get_portal_configuration and update_portal_configuration. The request fields and a curl example are on the Branding page.

Rules

  • One language entry per portal language, with the same blocks in each (translated).
  • Keep block ids stable between imports of the same page; they are how the editor tracks blocks.
  • Never invent ids (avatarId, discoverId) or links to pages the document does not create.
  • A page shown in the menu needs a short title: it is the menu label.
  • Put the site footer on _footer, not at the bottom of every page.
  • Import unpublished first, check the pages in the editor, then publish.