Content Management that can withstand the plundering hoards

Downloads, repeated content and packages

Use downloads, repeated cards and local packages to extend ordinary pages. See the feature reference for package types and behaviour.

Offer a file for download

  1. Create a page and select Raw downloadable object.
  2. Upload the file, add a title and URL such as /downloads/linux, and write a Markdown description. Add related images when useful.
  3. Preview the descriptive page, save the draft and publish.
  4. Visit the public page and test its download link.

The page URL opens the description. The file link uses a generated asset URL and downloads the original bytes as an attachment. Raw uploads accept any file type up to 50 MiB; they are not executed by Viking. Replacing a file uploads a new asset, so previous releases keep their original file. Before deleting a file or related image, remove references to it from raw objects and save.

Repeat cards for pages or downloads

In a visual page, add Site → Repeat files. Its child blocks are the template for one card. Set the URI branch to list, choose all content, pages or raw objects, and choose whether to include descendants. An empty branch uses the current page's path; direct children are the default. URL hierarchy selects items, independently of the menu.

Select the Repeat files container and set Summary length and Summary unit to choose how much text each card shows, for example 50 Words or 2 Paragraphs. The default remains 1 Paragraph. Summaries use the first nonempty paragraphs as plain text; word limits can continue into later paragraphs and stop at a whole word. Shorter descriptions show all available text. These settings also apply to the file gallery layouts below.

To list an imported blog from the homepage, leave the branch empty and select Pages and All descendants. Intermediate URLs do not need their own pages: /poetry/lights-out is included even when there is no /poetry page. A repeater on another page can use / explicitly to list content across the whole site.

Use field properties for title, page URL, summary, download URL, image or filename. The image field uses the featured image when set, falling back to a raw object's first related image. Insert Featured image into the card template when you want only the page cover; it disappears for entries without one. Preview with saved matching content. Items sort by title, then URI; the current page and branch root are excluded. Missing fields remain empty; use one repeater level per template. Publication expands the cards into ordinary static HTML. To refresh them after adding/deleting items, publish again.

Blog posts

Install the Blog plugin ZIP through Plugins and packages. In New page, choose Page type → Blog, then choose Markdown or Visual page. The URL starts as /[date]/[time]/: add a unique name after the tokens, for example /[date]/[time]/our-first-post. Add a prefix to place posts under a URL branch: /journal/[date]/[time]/our-first-post.

Creator comes from the signed-in editor's OAuth identity. It keeps that creator when another editor saves the post. The public author field uses the identity's display name, falling back to its subject identifier when no name is provided. Email, roles and login credentials are not part of the author field.

Publish time defaults to the current UTC time and is editable in the post's properties. Its displayed timezone is explicit; imported timestamps retain their stored offset. It is metadata, not a publication schedule: Publish publishes the current enabled content immediately, including posts with future timestamps. Republishing leaves the saved timestamp unchanged.

The tokens use the saved publish time: [date] becomes YYYY-MM-DD and [time] becomes HH-mm-ss in URLs. A post set to 2026-11-03T12:13:14Z with the example path publishes at /journal/2026-11-03/12-13-14/our-first-post/. Viking checks the resolved URL when saving and publishing, while retaining the editable template. Changing the time or template can change the public URL; arrange redirects for existing links before publishing such changes.

On an existing Markdown or HTML page, use Convert to Blog Post, review the properties and generated URL, then save. Conversion preserves the content format, source, styling, page ID, layout, menu and featured image. It attributes the new Blog post to the editor doing the conversion. The generated URL keeps the old parent prefix and final page name, inserting the date/time tokens between them.

In visual pages and theme templates, Blog Fields supplies [author], [date] and [time] blocks. Markdown posts can use those same tokens in ordinary text; code examples stay literal. Displayed times use HH:mm:ss. Field values become escaped text during preview/publication and update from saved post properties. Inside a repeater, the blocks use each matching post's metadata.

For a blog-only listing, select Blog in the repeater's Content property. Use All descendants when dated URL segments sit beneath the selected branch. Carousel, Cover Flow, Ring Gallery and Masonry share these controls and filters. Listings currently sort by title, then URI. Use the usual summary and featured image fields for post cards. The Blog package cannot be removed while saved posts use it.

Four separate example plugins present the same repeated content in different ways:

Plugin Layout
File carousel A configurable number of visible cards, advancing right to left
Cover flow A larger current card in front of smaller, angled neighbours
Ring gallery Cards arranged around a rotating 3D cylinder
Masonry grid Responsive columns with natural, varying card heights

Install the ZIP for each layout you want, then insert its block from the Blocks panel. Select the gallery in Layers and open Properties to choose its URI path, content kind and descendants. Each example initially lists pages across /; change that branch to list only your blog, portfolio or downloads. Edit the child card to change its title, image, summary and page-link presentation.

For the carousel, set Visible cards to the maximum number shown at once. Narrow screens show fewer cards. The three moving layouts have an Autoplay ms setting: the default is 4000 milliseconds; use 0 to turn automatic rotation off. Positive values below 1000 use a one-second minimum. Cover flow also has a Cards per side setting; both 3D layouts offer a card width in pixels. Masonry has Maximum columns, reduces columns on narrow screens and never rotates or adds navigation buttons.

Preview to see saved matching pages in the layout. The editor itself keeps one editable card template. Save and publish when ready. Previous/Next buttons and Left/Right arrow keys move through the three moving layouts, wrapping from last to first and first to last. Pause/Play controls are available when autoplay is enabled. Rotation pauses while the gallery is hovered, contains keyboard focus, is off screen or the tab is hidden. Reduced-motion preferences disable automatic movement and animated transitions; manual controls still work.

Empty galleries disappear. A single item stays static; a carousel also stays static when all matching cards fit at once. Without JavaScript, the published cards remain a readable list or grid with working links. These plugins require a CMS build with file-gallery support; the ZIPs alone do not upgrade the CMS.

Install and remove packages

Open Plugins and packages, choose a ZIP and wait for installation. A block pack adds blocks to the visual editor; a renderer adds a new source-page format; a page-type package adds a named type and its editing properties; a theme bundle appears under Themes. Installation stores the package in private CMS storage. Apply/select it and publish separately to update the public site.

Install a replacement with a distinct package ID and move content to it before removing the old package. A renderer used by a saved page cannot be removed; migrate/delete those pages first. Blocks already inserted remain ordinary page content after removing their block pack. Theme deletion has its own active/bundled protections in the theme guide.

Renderers run on the CMS in a bounded WebAssembly environment and return sanitized HTML; they are not arbitrary browser JavaScript plugins. A renderer failure blocks preview/publication of its content: correct the source/package and retry.

For custom packages, see the separate package authoring instructions.