Frontend Development 37 min read

Unlocking No‑Code Platform Power: Inside the Frontend Canvas Architecture

This article explores how No‑Code & Low‑Code (NCLC) platforms transform frontend development by introducing a canvas‑editor and generator architecture, UIDL communication, IOC modular design, layered rendering, event systems, drag‑and‑drop mechanics, smart snapping, and component insertion techniques.

Watermelon Frontend Tech Team
Watermelon Frontend Tech Team
Watermelon Frontend Tech Team
Unlocking No‑Code Platform Power: Inside the Frontend Canvas Architecture

What Is a Building Platform

Before discussing building platforms, the concept of NCLC (No Code & Low Code) must be introduced, as it drives many recent technology waves. Products such as Meego, Retool, and Notion exemplify NCLC, and the most rapidly growing form is website‑building platforms like Dreamweaver, Webflow, and various domestic solutions.

Development efficiency: Building platforms replace traditional coding with component drag‑and‑drop and configuration, dramatically reducing the time to create activity pages, promotional sites, or back‑office tools.

Staff transformation: They enable non‑technical staff, especially operations personnel, to build pages without developer involvement, lowering resource waste and improving workflow efficiency.

Derived Concepts

The platform can be summarized as Editor (canvas + settings) + Generator , where the data source is “materials” and communication follows the UIDL protocol.

Editor renders front‑end material on the canvas and produces a UIDL specification.

Generator consumes UIDL and, based on predefined templates, produces the final page.

This layered design decouples the page type from the used materials.

Architecture Design

IOC Architecture

All functional modules are coupled via an IOC container. Each module declares its usage contract, and the container injects dependencies at runtime, allowing independent iteration and easy adaptation to new terminals such as TV or mobile.

Edit‑Render Layering

The canvas is split into a render layer and an edit layer, communicating through a protocol. The edit layer hosts the real DOM elements; the render layer is a mask of virtual elements that enables instant preview and clean interaction.

When a user selects a component, anchor points appear on the render layer, while actual edits occur on the edit layer.

<code>interface ComponentAddAction {}
interface ComponentDragAction {}
// ... other action interfaces
</code>
<code>interface ComponentFocusRenderer {}
interface ComponentMirrorRenderer {}
// ... other renderer interfaces
</code>

To keep the edit and render layers synchronized, the

resize

and

scroll

events trigger re‑rendering of the render layer.

Event System

The platform defines a comprehensive event system that maps each editor action (init, dragEnd, etc.) to lifecycle callbacks, allowing modules to consume events for loading materials, rendering schemas, or handling drag‑and‑drop.

Specification Design

UIDL Specification

UIDL: a structured description of all UI‑related information needed to build a page.

UIDL consists of four parts:

UIDL meta information (version, etc.)

Project meta information (id, title, author, etc.)

Page Schema – a tree of component instances

Materials and their configuration

<code>interface ComponentProps {
  id: string;
  [key: string]: any;
}

interface Schema {
  id: string;
  type: MaterialId;
  name: string;
  children: Schema[];
  props: ComponentProps;
}

interface UIDL {
  meta: { version: string };
  project: { id: string; title: string; version: string; author: User; url: string };
  schema: Schema;
  materials: { components: Component[] };
}
</code>

Material Specification

Materials describe the reusable building blocks. They are categorized by terminal (mobile web, mini‑program, TV), shape (component, plugin, action), and function (basic, container, interactive).

Canvas Design

The canvas addresses three core challenges: adding components, dragging components, and selecting components.

Adding Components

When a component is added, a Schema node is generated and later inserted into the UIDL. The generation parses the component’s settings and produces a node like:

<code>genSchema(component: ComponentMaterial): Schema {
  const children: Schema[] = [];
  const props = {};
  const styles: React.CSSProperties = SchemaService.defaultStyles;
  return {
    id: this.genComponentId(),
    type: component.id,
    name: component.name,
    props,
    children,
    styles,
  };
}
</code>

Materials are loaded lazily; only the needed material bundle is fetched, reducing initial load time.

Packaging Standards

Four module formats are compared (AMD, CJS, ESM, UMD). Modern frontend development favors ESM for its standardization and bundler support.

Material Loading

SystemJS is recommended for loading modules because it supports AMD, ESM, and CJS, and integrates well with modern bundlers.

Dependency Analysis

Materials may depend on base frameworks (e.g., React), specific libraries (e.g., xg‑player), or other components. Common frameworks are treated as shared dependencies and are not bundled with each material.

Sandboxing

Each material runs in a sandbox to avoid interference. Logical isolation can use

eval

or

Function

with a proxy window; style isolation can use CSS modules, styled‑components, or Shadow DOM.

<code>const varBox = {};
const fakeWindow = new Proxy(window, {
  get(target, key) { return varBox[key] || window[key]; },
  set(target, key, value) { varBox[key] = value; return true; }
});
const fn = new Function('window', code);
fn(fakeWindow);
</code>

Dragging Components

A drag library must emit three phases: mouse down (start), mouse move (drag), mouse up (end). It provides position, direction, distance, and boundary scrolling information.

During dragging, a mirror component is rendered to give immediate visual feedback.

<code>let componentMap = {};
let mirror = { move: xxx, destroy: xxx };

onMouseDown = (e) => {
  const schema = genSchema(e);
  loadComponent(schema);
  mirror = renderMirror(schema);
};

onMouseMove = (e) => { mirror.move(e); };

onMouseUp = (e) => { mirror.destroy(); };
</code>

Anchor points (8 per component) allow resizing; each anchor manipulates a subset of the component’s rect (width, height, left, top).

<code>const pointList = ['t','r','b','l','lt','rt','lb','rb'];
const genPointStyle = (point) => {
  // calculate style based on point and component geometry
};
</code>

Smart Snapping

Three snapping types improve placement precision:

Position snapping: aligns edges when the distance is within a small threshold (≈3 px).

Distance snapping: matches existing margins between components.

Size snapping: aligns width/height when the size difference is within tolerance.

Reference lines are drawn on the canvas to visualize the snap.

Selecting Components

After a component is selected, an event provider dispatches actions without modifying the component itself. Quick operations include delete, copy‑paste, cut, inline text editing, and rotation.

<code>function withEventProvider<P>(Component: React.ComponentType<P>) {
  const Wrapped: React.ComponentType<P> = (props) => (
    <div style={{display:'contents'}} onClick={e => console.log(e, props)}>
      <Component {...props} />
    </div>
  );
  const name = Component.displayName ?? Component.name ?? 'Unknown';
  Wrapped.displayName = `withEventProvider(${name})`;
  return Wrapped;
}
</code>

Multi‑select allows users to drag a rectangular area, automatically computing the minimal bounding box of all fully contained components and enabling batch move or resize.

<code>let startPoint = null;
const area = { width:0, height:0, x:0, y:0 };

onMouseDown = e => { startPoint = new Point(e); };
onMouseMove = e => {
  area.width = Math.abs(e.x - startPoint.x);
  area.height = Math.abs(e.y - startPoint.y);
  area.x = Math.min(e.x, startPoint.x);
  area.y = Math.min(e.y, startPoint.y);
};
</code>

Conclusion

The canvas is the core of a building platform, handling component addition, drag‑and‑drop, smart snapping, insertion, and selection. Future articles will cover the settings panel and generator.

No‑Code/Low‑Code ecosystem diagram
No‑Code/Low‑Code ecosystem diagram
Edit‑render layering illustration
Edit‑render layering illustration
Event system diagram
Event system diagram
Component anchor points example
Component anchor points example
Eight anchor points around a component
Eight anchor points around a component
Smart snapping reference lines
Smart snapping reference lines
Distance snapping illustration
Distance snapping illustration
Size snapping illustration
Size snapping illustration
Canvasfrontend architectureno-codedrag and dropUIDL
Watermelon Frontend Tech Team
Written by

Watermelon Frontend Tech Team

We are from ByteDance, the frontend division of Watermelon Video, responsible for its product development. We share business practices from the product to provide valuable experience to the industry, covering areas such as marketing setups, interactive features, engineering capabilities, stability, Node.js, and middle‑back office development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.