Skip to content

View and Edit Modes

Mehrdad Pajuhaan edited this page Oct 23, 2026 · 1 revision

View and Edit Modes

The Page Builder runs in one of two modes. View mode renders saved pages for visitors (storefronts). Edit mode installs everything needed for the visual editor (dashboards). This page explains how to set up each mode, how lazy loading works, and which props and events the main components expose.

SetupPageBuilder(app, options)

SetupPageBuilder (exported from @selldone/page-builder and @selldone/page-builder/page-builder.ts) installs the builder as a Vue plugin:

options.mode Behavior
"view" Installs the builder. No server options are needed.
"edit" Requires options.server. Throws an error if server is missing. Logs an error if server.uploadImageUrl is not a function or returns an empty value for a test call.
anything else Logs Invalid page builder initial mode! Use 'edit' or 'view'! and installs nothing.

Calling it without options throws Options are not set in the setup page builder!.

When installed, the builder:

  • registers all page elements (XSection, XContainer, XRow, XColumn, XText, XButton, XUploader, XProducts, XCode, …) as global Vue components,
  • registers UFadeScroll, UPrice and UCountDown from Components, because Vue code sections can use them,
  • installs the SVG filters used by CSS filter effects,
  • imports the builder stylesheet (styles/page-builder.scss).

Options

The options object follows builder.IOptions in Builder.types.ts:

Option Type Notes
mode "edit" | "view" Required.
server { uploadImageUrl, uploadVideoUrl } Required in edit mode. See Upload Handlers.
customFonts Shop.CustomFont[] Shop-managed fonts. Kept separate from style.fonts, which is reserved for Google Fonts.
columnsPrefix { mobile, tablet, desktop, widescreen, ultrawide } CSS class prefixes for responsive columns. Defaults: v-col-, v-col-sm-, v-col-md-, v-col-lg-, v-col-xl-.
title, sections, style, css — Initial content. Usually left empty and loaded per page.
type, model "page" | "popup" | "menu", model Edit mode only. Normally set per page with $builder.setModel().

Lazy loading with PageHyper

PageHyper(app, options) (from @selldone/page-builder/PageHyperService.ts) is the recommended entry point. It:

  1. saves your options as app.config.globalProperties.$PageHyperOptions,
  2. creates a service and provides it to the app as $PageHyper,
  3. returns the service, which has an isInitialized ref and an initialize() method.

LPageViewer and LPageEditor inject $PageHyper, call initialize() on creation, and render only after isInitialized becomes true. initialize() imports @selldone/page-builder dynamically and calls SetupPageBuilder(app, options) once. If $PageHyper was never provided, the components log Page Builder initialization failed: $PageHyper not found!.

import { PageHyper } from "@selldone/page-builder/PageHyperService.ts";

// Storefront (view mode)
const $PageHyper = PageHyper(app, { mode: "view" });
// Dashboard (edit mode)
PageHyper(app, {
  mode: "edit",
  server: {
    uploadImageUrl: (type, model) => window.API.POST_UPLOAD_PAGE_IMAGE(model.shop_id, model.id),
    uploadVideoUrl: (type, model) => window.API.POST_UPLOAD_PAGE_VIDEO(model.shop_id, model.id),
  },
});

Eager loading

When you know a page will be shown immediately (for example, the shop home page is a landing page), load the builder up front and mark the service as ready. The Storefront does exactly this:

import { PageHyper } from "@selldone/page-builder/PageHyperService.ts";
import { SetupPageBuilder } from "@selldone/page-builder/page-builder.ts";

const $PageHyper = PageHyper(app, { mode: "view" });

SetupPageBuilder(app, { mode: "view" });
$PageHyper.isInitialized.value = true;

View mode components

LandingRender

@selldone/page-builder/LandingRender.vue (also exported as LandingRender from the package) fetches a page and renders it with LPageViewer.

Item Details
Prop forceFetchUrl Full URL to fetch the page from. When set, route-based detection is skipped.
Slot header Content above the page (your shop menu). Positioned over the page when the page style sets menu_transparent.
Event onFetch:data Emitted with the server response ({ page, augment, asset, ... }). Use it for SEO.
Event update:page Emitted with the loaded page model.

Without forceFetchUrl, the endpoint depends on the current route: the custom home page, a landing page by $route.params.page_name, an include page, or a vendor landing page (all through window.XAPI from the Storefront SDK). If the server pre-loaded the page in window.PRE_LOADED_DATA.PAGE, it is used without a network request.

LandingRender also records anonymous mouse-move, click and scroll positions and sends them with the page statistics, which powers the page heatmap in the Selldone dashboard. On the dashboard preview route (ShopPageRender) it shows the heatmap instead of recording.

LPageViewer

@selldone/page-builder/page/viewer/LPageViewer.vue renders page JSON you already have:

Prop Description
initialPageData Page content: { title, sections, style }.
initialPageCss Page CSS: { classes: [{ selector, value }], raw }.
customFonts Optional shop fonts. Falls back to $shop.custom_fonts, then to customFonts passed to PageHyper.
augment Optional dynamic values (key/value items) used to fill dynamic text and images.

The viewer hides sections according to each section's data.hide flags: sm, md, lg, xl (per breakpoint), guest (hidden from visitors who are not logged in) and user (hidden from logged-in customers).

Edit mode: LPageEditor

@selldone/page-builder/page/editor/LPageEditor.vue is the full editor: artboard, top menu, left menu (hierarchy, sections, elements, CSS, SEO, statistics, versions, assets), settings dialogs and the uploader toolbar. It injects $shop and $PageHyper.

Props

Prop Type Description
modelValue Object The page, popup or menu model. Use v-model to keep it in sync.
histories Array Required. Saved versions shown in the Versions panel. Pass [] if you have none.
backTo route location Required. Target of the back button in the editor header.
saveFunction Function Called with $builder.export() ({ title, sections, style }) on save and Ctrl/Cmd + S.
busySave / busyFetch Boolean Show progress while saving or loading.
fetchPageData Function Lets the left menu reload the page from your server.
isPopup / isMenu Boolean Edit a popup or a menu page instead of a landing page. Controls the model type passed to upload handlers.
customFonts Array Shop fonts available in the editor.
device String desktop (default), tablet or mobile.
hasSettingButton, demo Boolean UI options.
aiAutoFillFunction Function Optional. Shows an AI button on sections. See AI-Friendly JSON.
aiPageGenerateFunction Function Optional. Shows a "generate page" action. See AI-Friendly JSON.

Events

Event Payload
changeMode true when the editor enters edit mode.
scale 0.5 when the artboard is scaled down (side menu or sorting), 1 otherwise.
load:template { content, image } or a page object, when the user starts from a template.

Example

<template>
  <LPageEditor
    v-model="page"
    :histories="page?.histories || []"
    :back-to="{ name: 'ShopPages' }"
    :save-function="save"
    :busy-save="busySave"
  />
</template>

<script lang="ts">
import LPageEditor from "@selldone/page-builder/page/editor/LPageEditor.vue";

export default {
  components: { LPageEditor },
  data: () => ({ page: null, busySave: false }),
  methods: {
    async save(content) {
      this.busySave = true;
      try {
        // Persist content (and page.css) with your API
      } finally {
        this.busySave = false;
      }
    },
  },
};
</script>

When modelValue changes, the editor calls $builder.setModel(type, model) and $builder.loadPage(model), then saves an initial history entry.

Keyboard shortcuts

Shortcut Action
Ctrl/Cmd + S Save
Ctrl/Cmd + Z Undo
Ctrl/Cmd + Y Redo
Ctrl/Cmd + E Toggle the copy-style pipette (click a source element, then a target)
Esc Leave copy-style mode
Tab Toggle the side menu and the scaled-down overview
Ctrl/Cmd + B, I, U, L, R Bold, italic, underline, strike-through, remove formatting (inside editable text)
Ctrl/Cmd + 1 / 2 Make selected text smaller / bigger (inside editable text)

Set window.PAGE_BUILDER_BLOCK_LISTEN_KEYS = true to temporarily stop the editor from handling keys, for example while your own dialog is open.

The $builder instance

Both components create a reactive Builder instance and provide it to children as $builder. Useful methods:

Method Description
loadPage({ content, css, direction }) Load page content, CSS and text direction (ltr, rtl, auto). Migrates old content.
export() Return { title, sections, style } and write it to model.content when a model is set.
setModel(type, model) Link the builder to a page, popup or menu model (used for upload URLs).
setAssets(images, videos) / getAssets() Media library shown in the editor.
setCustomFonts(fonts) Replace the shop font catalog.
add(section, position), remove(section), sort(old, new), find(uid), clear() Manage sections.
history.undo(), history.redo(), history.save() Local history (up to 50 entries, saves are throttled to one every 2 seconds).
importer.loadFile(file) Load a .landing file into the current page.

Next steps