Support drag-and-drop

Now we will:

  • add a page instance to the New Panel,

  • accept sub-pages and contents under the page app,

  • define a content placeholder to drop contents on the page,

  • render the actual contents on pages.

Add to the New Panel

Let's add a page instance to the New Panel so that you will be able to create new pages via drag-and-drop.

Create the file /sys/new/page, set its type to /apps/page and its title to Page.

Accept sub-pages, contents

We must configure our page app to accept pages and contents in certain buckets.

A page is a file that implements the .Page interface, a content file is one that implements the .Inline interface.

We will use bucket 1 for pages, bucket 2 for contents.

(What is a bucket? Children of a file are stored in one of 256 buckets that are used for grouping files. You can ignore buckets if you don't need them. Bucket 0 is a hidden bucket for system files, all the files we created so far are in bucket 0. The IDE shows bucketIds.)

Create an .Accept file and set its type to:

/apps/page/.Accept           [accept-2]

Configure its attributes as follows:

    "link": "",
    "type": "accept-2",
    "title": "",
    "statusCode": 0,
    "attr": {
        "bucket-1 string": ".Page",
        "bucket-2 string": ".Inline"

You can visit the /apps/page/.Accept file in your browser to verify it is valid.

To use our page app as a sub-page, we need to implement the .Page interface. Let's create the following file:


We don't need to set its type, the only requirement is that it exists.

At this point, you can create a sub-page by dragging the Page instance from the New Panel and dropping it on the center of the Root file's entry in the menu.

Define a content placeholder

A placeholder is a drop zone on the user interface that is routing dropped files to a specific bucket on the filesystem.

Let's define the content holding <div> on our page template to be a placeholder by adding the o1-placeholder class to it, and route it to bucket 2 on the filesystem by setting the data-o1-placeholder attribute as follows:

<div class="<?== css.contents ?> o1-placeholder" data-o1-placeholder="2">

Then we can render the contents in bucket 2 via the following snippet:

<div class="<?== css.contents ?> o1-placeholder" data-o1-placeholder="2">
    <?== f.query(':2').inline() ?>
  • f points to the current file, which is the visited page instance in case of our theme app.

  • f.query(':2') selects all children of the file f that are in bucket 2.

At this point, we can drop contents onto our pages, but first, we will need to install some contents apps on our website. We'll do that in the next section.

Subscribe to our newsletter!