Search Docs
Loading...
Skip to content

Pages

Pages define the format of your designs—every graphic block, text element, and media file lives inside a page. This guide covers how pages fit into the scene hierarchy, their properties like margins and title templates, and how to configure page dimensions for different layout modes.

10 mins
estimated time
Download
StackBlitz
GitHub

Pages provide the canvas and frame for your designs. Whether you’re building a multi-page document, a social media carousel, or a video composition, understanding how pages work will help you with structuring your content correctly.

This guide covers:

  • Understanding the scene hierarchy: Scene → Pages → Blocks
  • Creating and managing multiple pages
  • Setting page dimensions at the scene level
  • Configuring page properties like margins and title templates
  • Navigating between pages programmatically

Pages in the Scene Hierarchy#

In CE.SDK, content follows a strict hierarchy: a scene contains pages, and pages contain content blocks. Only blocks attached to a page are rendered on the canvas.

// Create a scene with VerticalStack layout for multi-page designs
engine.scene.create('VerticalStack');
// Get the stack container to configure spacing
const [stack] = engine.block.findByType('stack');
engine.block.setFloat(stack, 'stack/spacing', 20);
engine.block.setBool(stack, 'stack/spacingInScreenspace', true);

When you create a scene with a layout mode like VerticalStack, pages are automatically arranged according to that mode. Create pages using engine.block.create('page'), set their dimensions with setWidth() and setHeight(), then attach them to the scene (or its stack container) with engine.block.appendChild().

// Create the first page and set its dimensions
const firstPage = engine.block.create('page');
engine.block.setWidth(firstPage, 800);
engine.block.setHeight(firstPage, 600);
engine.block.appendChild(stack, firstPage);
// Create the second page with the same dimensions
const secondPage = engine.block.create('page');
engine.block.setWidth(secondPage, 800);
engine.block.setHeight(secondPage, 600);
engine.block.appendChild(stack, secondPage);

Content blocks must be added as children of a page to render. For graphic blocks, set both a shape and a fill for content to display. Append blocks to the page before configuring their properties.

// Add an image block to the first page
const imageBlock = engine.block.create('graphic');
engine.block.appendChild(firstPage, imageBlock);
// Create a rect shape for the graphic block
const rectShape = engine.block.createShape('rect');
engine.block.setShape(imageBlock, rectShape);
// Configure size and position after appending to the page
engine.block.setWidth(imageBlock, 400);
engine.block.setHeight(imageBlock, 300);
engine.block.setPositionX(imageBlock, 200);
engine.block.setPositionY(imageBlock, 150);
// Create and configure the image fill
const imageFill = engine.block.createFill('image');
engine.block.setString(
imageFill,
'fill/image/imageFileURI',
'https://img.ly/static/ubq_samples/sample_1.jpg'
);
engine.block.setFill(imageBlock, imageFill);
// Add a text block to the second page
const textBlock = engine.block.create('text');
engine.block.appendChild(secondPage, textBlock);
// Configure text properties after appending to the page
engine.block.replaceText(textBlock, 'Page 2');
engine.block.setTextFontSize(textBlock, 48);
engine.block.setTextColor(textBlock, { r: 0.2, g: 0.2, b: 0.2, a: 1.0 });
engine.block.setEnum(textBlock, 'text/horizontalAlignment', 'Center');
engine.block.setWidthMode(textBlock, 'Auto');
engine.block.setHeightMode(textBlock, 'Auto');
// Center the text on the page
const textWidth = engine.block.getFrameWidth(textBlock);
const textHeight = engine.block.getFrameHeight(textBlock);
engine.block.setPositionX(textBlock, (800 - textWidth) / 2);
engine.block.setPositionY(textBlock, (600 - textHeight) / 2);

Page Dimensions and Consistency#

The CE.SDK engine supports pages with different dimensions. When using stacked layout modes (VerticalStack, HorizontalStack), the Editor UI expects all pages to share the same size. However, with the Free layout mode, you can set different dimensions for each page in the UI.

// Get the scene to set page dimensions
const scene = engine.scene.get();
if (scene === null) {
throw new Error('No scene available');
}
// Set page dimensions at the scene level (all pages share these dimensions)
engine.block.setFloat(scene, 'scene/pageDimensions/width', 800);
engine.block.setFloat(scene, 'scene/pageDimensions/height', 600);

You can set default page dimensions at the scene level using engine.block.setFloat() with scene/pageDimensions/width and scene/pageDimensions/height. The scene/aspectRatioLock property controls whether changing one dimension automatically adjusts the other. Individual pages can also have their dimensions set directly with setWidth() and setHeight().

Finding and Navigating Pages#

CE.SDK provides several methods to locate and navigate between pages in your scene.

// Demonstrate finding pages
const allPages = engine.scene.getPages();
console.log('All pages:', allPages);
console.log('Number of pages:', allPages.length);
// Alternative: Find pages using block API
const pagesByType = engine.block.findByType('page');
console.log('Pages found by type:', pagesByType);

Use these methods based on your needs:

  • engine.scene.getPages() returns all pages in sorted order
  • engine.block.findByType('page') finds all page blocks in the scene

Page Properties#

Each page has its own properties that control its appearance and behavior. These are set on the page block itself, not on the scene.

Margins#

Page margins define bleed areas useful for print designs. Enable margins and configure each side individually:

// Configure page properties on the first page
// Enable and set margins for print bleed
engine.block.setBool(firstPage, 'page/marginEnabled', true);
engine.block.setFloat(firstPage, 'page/margin/top', 10);
engine.block.setFloat(firstPage, 'page/margin/bottom', 10);
engine.block.setFloat(firstPage, 'page/margin/left', 10);
engine.block.setFloat(firstPage, 'page/margin/right', 10);
// Set a custom title template for the first page
engine.block.setString(firstPage, 'page/titleTemplate', 'Cover');
// Set a custom title template for the second page
engine.block.setString(secondPage, 'page/titleTemplate', 'Content');

Set page/marginEnabled to true to enable margins, then use page/margin/top, page/margin/bottom, page/margin/left, and page/margin/right to configure each side.

Safety Inset#

The safety inset is the inward inset from the page edge that content must stay inside. It is the counterpart of the bleed margin, which extends outward. Print shops cut with a tolerance, so text and logos placed too close to the edge can be trimmed off.

Set page/safetyEnabled to true, then use page/safetyInset/top, page/safetyInset/bottom, page/safetyInset/left, and page/safetyInset/right to configure each side. Every inset defaults to 0, so set a value as well as enabling the area.

The safety inset is authoring state, and nothing it draws reaches an export.

The guide appears while a drag is in the safety inset or comes near the safety line, and goes away when the drag ends. A move or resize with the arrow keys shows it the same way for 1.6 seconds, without snapping. The engine shades the band between the page edge and the line, draws the line itself, and lets the dragged block snap to it. Set page/safetyRevealDuringTransform to false to draw the guide on every page all the time instead.

Set the guide colors with the page/safetyFillColor and page/safetyFrameColor settings; a fully transparent page/safetyFrameColor hides the line and turns its snapping off.

Exclusion Area#

An exclusion area marks a region of a page that content must stay out of: a window on an envelope, a spine on a book cover, a glue flap on a box, an address panel on a mailer. Where the safety inset is one inset per page, a page can carry any number of exclusion areas, each with its own position, size and rotation.

Create one with the //ly.img.ubq/exclusionArea block type and append it to a page. An exclusion area is a graphic, so it takes a shape, a fill, a stroke and the ordinary transform, and you can put the artwork of the obstruction into it. A new exclusion area is a rectangle with no fill and shows a striped pattern, so it is visible at once. Assign a fill to replace the stripes.

An exclusion area is authoring state. The engine washes it in page/exclusionAreaFillColor and frames it in page/exclusionAreaFrameColor, neither of which reaches an export, and a fully transparent page/exclusionAreaFrameColor hides the frame. An exclusion area is left out of an export as well: set includedInExport to true on the exclusion area to put its artwork in the file.

Set exclusionArea/punchOut to true to cut the exclusion area out of an export instead. The page and everything on it get a hole where the exclusion area is, so a die cut window in the design becomes a window in the file. It is off by default, and the canvas keeps showing the content either way.

Title Template#

The page/titleTemplate property defines the display label shown for each page. It supports template variables like {{ubq.page_index}} for dynamic numbering.

The default value is "Page {{ubq.page_index}}". You can customize this to show labels like “Slide 1”, “Cover”, or any custom text.

Fill and Background#

Pages support fills for background colors or images using the standard fill system.

// Set a background fill on the second page
const colorFill = engine.block.createFill('color');
engine.block.setColor(colorFill, 'fill/color/value', {
r: 0.95,
g: 0.95,
b: 1.0,
a: 1.0
});
engine.block.setFill(secondPage, colorFill);

Create a fill using engine.block.createFill('color') or engine.block.createFill('image'), configure its properties, then apply it to the page with engine.block.setFill(page, fill).

Page Layout Modes#

The scene’s layout mode controls how multiple pages are arranged. Set this using engine.block.setEnum() on the scene with the scene/layout property:

  • VerticalStack (default): Pages stack vertically, one below the other
  • HorizontalStack: Pages arrange horizontally, side by side
  • DepthStack: Pages overlay each other, typically used for video editing
  • Free: Pages can be positioned freely without automatic arrangement

Pages for Static Designs vs. Video Editing#

Page behavior varies depending on how the scene is used.

Static Designs#

For static designs, pages act like artboards. Each page is a separate canvas ideal for multi-page documents, social media posts, or print layouts. Pages exist side by side and don’t have time-based properties.

Video Editing#

For video editing, pages represent time-based compositions that transition sequentially during playback. Each page has playback properties:

  • playback/duration controls how long the page appears (in seconds)
  • playback/time tracks the current playback position

Cleanup#

In server environments, always dispose the engine when finished to free resources.

// Always dispose the engine to free resources
engine.dispose();

Troubleshooting#

Content Not Visible#

If content blocks aren’t appearing, check these common causes:

  • Verify the block is attached to a page with engine.block.appendChild(page, block)
  • For graphic blocks, ensure both a shape and fill are set
  • Append blocks to the page before setting their size and position

Dimension Inconsistencies#

If pages appear at unexpected sizes when using stacked layouts, ensure all pages have consistent dimensions. With Free layout mode, pages can have different sizes. Set dimensions on individual pages using setWidth() and setHeight().

Page Not Found#

If engine.scene.getPages() returns an empty array, ensure a scene is loaded first. In headless mode, you must create both the scene and pages manually before querying them.