Search
Loading...
Skip to content

Lock the Template

Set up a two-surface integration where template creators have full editing access while template adopters can only modify designated areas.

Lock the Template

10 mins
estimated time
Download
StackBlitz
GitHub

Many integrations need two different editing experiences: one for designers who build templates, and one for end users who customize them. The Creator and Adopter roles make this possible—same CE.SDK, different permissions based on who’s using it. For detailed scope configuration patterns, see Lock Content .

In the live example, the headline text is pre-selected and the Placeholder panel is open, showing the scope settings that control what Adopters can edit. Toggle the role to Adopter and try selecting the logo to see the restrictions in action.

This guide covers how to understand the two-surface pattern, configure roles for different user groups, and set up scope restrictions that control what Adopters can edit.

Understanding the Two-Surface Pattern#

Template-based workflows typically involve two distinct user groups with different needs:

SurfaceUsersRoleWhat they can do
Creator SurfaceDesigners, adminsCreatorFull editing—build templates, set locks
Adopter SurfaceEnd users, marketersAdopterRestricted editing—only modify unlocked areas

This separation protects design intent while enabling customization. The Creator role ignores all locks, giving full access. The Adopter role respects locks, restricting users to what’s explicitly allowed.

Setting Up the Creator Surface#

The Creator surface is where templates are built. We use engine.editor.setRole('Creator') to give designers unrestricted access.

// The Creator role ignores all scope restrictions
engine.editor.setRole('Creator');

In Creator mode, all operations are permitted regardless of scope settings. This is where designers build the template layout, configure which elements should be editable, set scope restrictions using engine.block.setScopeEnabled(), and save the template for distribution.

Setting Up the Adopter Surface#

The Adopter surface is where templates are used. Call engine.editor.setRole('Adopter') to enforce the restrictions configured by creators. In Adopter mode, users can only interact with blocks that have the appropriate scopes enabled. The Adopter role respects all lock configurations, ensuring brand consistency and design intent are maintained.

When to Use This Pattern#

This two-surface approach works well for:

  • Brand template systems: Marketing teams customize approved templates
  • Design approval workflows: Creators build, reviewers can’t accidentally modify
  • Self-service customization: End users personalize within guardrails
  • White-label products: Customers can only edit designated areas

For simpler use cases where all users have the same permissions, you may not need separate surfaces.

Configuring What Users Can Edit#

The scope system controls what Adopters can modify. In Creator mode, we enable specific scopes on blocks that should be editable.

// Configure which elements Adopters can edit
// Enable selection and text editing on the headline
engine.block.setScopeEnabled(headlineBlock, 'editor/select', true);
engine.block.setScopeEnabled(headlineBlock, 'text/edit', true);
// Leave all scopes disabled on the logo (default state)
// This prevents Adopters from selecting or modifying the logo

When Adopters load this template, they can edit the headline text but nothing else. The editor/select scope must be enabled for users to interact with a block at all. For comprehensive scope configuration patterns, see Lock Content .

Configuring Scopes in the Editor UI#

Designers can also configure scopes visually without writing code. In Creator mode, select any block and open the Placeholder panel in the inspector. This panel provides toggles for each scope:

  • Allow selecting (editor/select): Users can click to select the block
  • Allow editing text (text/edit): Users can modify text content
  • Allow changing fill (fill/change): Users can swap images or change colors
  • Allow moving (layer/move): Users can reposition the block
  • Allow deleting (lifecycle/destroy): Users can remove the block

Changes made in the Placeholder panel are equivalent to calling engine.block.setScopeEnabled() programmatically. When the template is saved, these settings persist and apply when Adopters load the template.

Adding a Role Toggle#

Add a segmented control to the navigation bar that switches between Creator and Adopter modes. Engine calls inside the builder are automatically reactive—the component re-renders when the role changes.

// Add a role toggle to the navigation bar (engine calls are reactive)
cesdk.ui.registerComponent(
'ly.img.roleToggle.navigationBar',
({ builder }) => {
const role = engine.editor.getRole();
builder.ButtonGroup('role-toggle', {
children: () => {
builder.Button('creator', {
label: 'Creator',
isActive: role === 'Creator',
onClick: () => engine.editor.setRole('Creator')
});
builder.Button('adopter', {
label: 'Adopter',
isActive: role === 'Adopter',
onClick: () => {
// Close the placeholder panel since Adopters can't configure scopes
cesdk.ui.closePanel(
'//ly.img.panel/inspector/placeholderSettings'
);
engine.editor.setRole('Adopter');
}
});
}
});
}
);
cesdk.ui.setNavigationBarOrder([
'ly.img.undoRedo.navigationBar',
'ly.img.spacer',
'ly.img.roleToggle.navigationBar',
'ly.img.spacer'
]);

Troubleshooting#

IssueCauseSolution
Adopter can edit everythingWrong role or scopes not configuredVerify role is Adopter and scopes are set in Creator mode
Adopter can’t edit anythingeditor/select scope not enabledEnable editor/select on blocks users should interact with
Creator can’t set locksWrong roleSwitch to Creator role before configuring scopes
Changes not persistingTemplate not saved after scope changesSave template after configuring scopes in Creator mode

API Reference#

MethodDescription
engine.editor.setRole(role)Set the editing role ('Creator', 'Adopter', or 'Viewer')
engine.editor.getRole()Get the current editing role
engine.block.setScopeEnabled(block, scope, enabled)Enable or disable a scope on a block
engine.block.isScopeEnabled(block, scope)Check if a scope is enabled on a block
cesdk.ui.registerComponent(id, renderFn)Register a custom UI component
builder.ButtonGroup(id, { children })Create a segmented control
builder.Button(id, { label, isActive, onClick })Create a button

Common Scopes#

ScopeDescription
'editor/select'Allow selecting the block (required for any interaction)
'fill/change'Allow changing the block’s fill (images, colors)
'text/edit'Allow editing text content
'text/character'Allow changing text formatting (font, size, color)
'layer/move'Allow moving the block
'layer/resize'Allow resizing the block
'layer/rotate'Allow rotating the block
'layer/crop'Allow cropping the block
'lifecycle/destroy'Allow deleting the block