Front Page Layout (sphynx)

DrEdition's front page layout engine is called Sphynx. Whenever you publish an update to your front in DrEdition, Sphynx generates markup and CSS for embedding directly on your own web site, and makes sure you at all times accomplish the best available representation of your design intention for the front page.

While we strongly recommend considering Sphynx for Front Pages, you may also use the API directly to fetch Front Page data from DrEdition.

Sphynx provides a real-time preview while editing

Design

Feel free to draw the whole front page in a graphical design tool of your choosing as a specification for the below.

  • Font type and colors

  • Minimum, default and maximum font sizes

  • Paddings and margins

  • Background colors

  • List all placeholders needed (i.e. fixed or flexible advertisement positions, or any fixed or flexible widgets on the front page, i.e. videos or "most read"-list.)

  • Provide all icons and graphics, preferably as SVGs

  • Provide all fonts ready for use on web (reusing your public urls is preferable)

Animated icons are best delivered as SVGs with embedded animations, or as clearly defined CSS pseudo elements.

Get in touch with support@aptoma.com to have a front page setup based on your design.

Layout

We support four layout breakpoints:

  • Small/mobile (<767px width)

  • Medium/tablet

  • Large/medium desktop

  • X-Large/wide desktop

There's an underlying 12 column grid, where you define the column gap and total width for each size. All columns in the grid have the same width.

Within each size, the layout will be either responsive or adaptive. We generally recommend using responsive design for Small, and an adaptive design for each of the other breakpoints. An adaptive design is strongly recommended if you have any content that is not responsive, such as ads or 3rd party embeds.

The small breakpoint will always be at <767px. The switch from medium to large should be no higher than 1024px, but can be less. You also have the option of only having a small and large design, skipping the medium and X-Large versions. We recommend specifying the mobile design at 375px width, as that tends to scale well for all common mobile devices.

Also note that the same markup will be served for all sizes, so any reordering of content is limited to what can be predictably achieved with CSS. Placeholders can be shown/hidden at certain sizes, but this is limited within each group (see below).

Item Sizes

For Medium, Large and X-Large:

  • One third, four grid columns

  • Half, six grid columns

  • Two thirds, eight grid columns

  • Full, twelve grid columns

For Small:

  • Half, six grid columns

  • Full, twelve grid columns

For full and two thirds item sizes, the image can be horizontally aligned.

Item contents

Each item can have a number of components, which can be combined to support a wide variety of designs. The basic building blocks are:

  • Header

  • Image

  • Pretitle

  • Title

  • Summary

  • Footer

  • Chasers (ie. related articles)

There are a few more as well, so reach out to us if you have something special in mind.

Grouping

The layout engine will optimize the visual presentation of your front page according to the journalistic priority of your content. We also apply touch ups for a tight and effective design. Items are first grouped into rows or more complex compositions, and then the content of each group is optimized with font size and image crop adjustments.

Items can be assigned to groups either manually or automatically. For manual groups, you still have the option of leaving the group layout selection to the layout engine.

Front editors assign priority to items, either A+, A or B:

  • A+ and left aligned image will always be 100%

  • A-priority will be at least 50%

  • B-priority will be at most 50% (unless left-aligned image)

With these constraints in place, items are assigned to groups:

  • Manually created groups are left untouched

  • Items that need to be fullwidth (A+/placeholder/left-aligned image) will always be fullwidth

  • Items are not pulled up across groups/fullwidth items

  • Items may be reordered within an auto-group/row to accommodate priority/size restrictions

  • The layout engine is greedy, ie BBB will be a triple row, not BB plus B.

  • Items without image will have additional restrictions, to prevent size mismatch when placed next to items with image

Grouping is targeting desktop, as that's where the most complex layouts are supported. Group layouts have mostly deterministic tablet and mobile translations, but priority and placeholder grid restrictions may trigger alternate layouts. Get in touch with us for information about available layouts and how they behave.

Placeholders

Placeholders are what you will use to insert ads and any kind of dynamic editorial content on your front. For an item to be identified as a placeholder, it needs to have a property "placeholder". The actual value is up to you, but we recommend using this value to signify the placeholder type, ie. "ad" or "latest-news-widget".

Planning Placeholder Setup

When designing your front page, you should make a list of all placeholders that will be needed, including both ads and editorial widgets. For each placeholder, specify its rendered dimensions (including any "Advertisment" labels etc), and what restrictions apply regarding placement in the grid. Are any placeholders responsive or variably sized?

Once you have this list, we can help you configure the schemas in DrEdition optimally. We also recommend creating a feed of all placeholders, so that your editorial staff can easily place them on the front page without having to know all the technical details.

Placeholder Schema

Sphynx will optimize the editorial content around placeholders, by picking layouts and adjusting image crops. In order to help Sphynx make optimal choices, you should configure your placeholders with some device specific properties:

{
"placeholder": {
"title": "Placeholder type",
"format": "enumTitle",
"default": "ad",
"type": "string",
"oneOf": [
{
"title": "Ad",
"enum": [
"ad"
]
},
{
"title": "Latest news",
"enum": [
"latest-news"
]
}
]
},
"showOnMobile": {
"type": "boolean",
"title": "Show on mobile?",
"default": true
},
"mobileSize": {
"type": "string",
"format": "enumTitle",
"default": "300x250",
"x-schema-form": {
"condition": "vm.model.data.showOnMobile",
"destroyStrategy": "retain"
},
"enum": [
"300x250",
"320x160",
"160x160"
]
},
"mobileGrid": {
"type": "string",
"format": "enumTitle",
"default": "full",
"x-schema-form": {
"condition": "vm.model.data.showOnMobile",
"type": "radios",
"destroyStrategy": "retain"
},
"enum": [
"full",
"half"
]
},
"showOnTablet": {
"type": "boolean",
"title": "Show on tablet?",
"default": true
},
"tabletSize": {
"type": "string",
"format": "enumTitle",
"default": "300x250",
"x-schema-form": {
"condition": "vm.model.data.showOnTablet",
"destroyStrategy": "retain"
},
"enum": [
"740x60",
"300x250"
]
},
"tabletGrid": {
"type": "string",
"format": "enumTitle",
"default": "full",
"x-schema-form": {
"condition": "vm.model.data.showOnTablet",
"type": "radios",
"destroyStrategy": "retain"
},
"enum": [
"full",
"two-cols",
"half",
"third"
]
},
"showOnDesktop": {
"type": "boolean",
"title": "Show on desktop?",
"default": true
},
"desktopSize": {
"type": "string",
"format": "enumTitle",
"default": "300x250",
"x-schema-form": {
"condition": "vm.model.data.showOnDesktop",
"destroyStrategy": "retain"
},
"enum": [
"930x180",
"580x400",
"468x60",
"300x250"
]
},
"desktopGrid": {
"type": "string",
"format": "enumTitle",
"default": "full",
"x-schema-form": {
"condition": "vm.model.data.showOnDesktop",
"type": "radios",
"destroyStrategy": "retain"
},
"enum": [
"full",
"two-cols",
"half",
"third"
]
}
}

The grid settings while take precedence when creating layouts, while the size settings will affect the image crops of the other items in the same composition. Size should include any additional padding or labels of your placeholder content.

Placeholders with grid settings will at least get their required size, but may in certain cases be given more space (ie. due to next/previous item having fullwidth requirement)

Fetching Content

You can fetch urls to the latest published version of your front at https://sphynx.aptoma.no/burned/{editionId}.

You should download the content from the HTML url, and serve from your local cache. The CSS url can be hot-linked, but you may want to download this as well, or proxy through your own CDN.

The urls will be updated whenever their contents change. Ie. the CSS url will be same until the CSS has been updated.

Production images will be served from https://smooth-storage.aptoma.no/. If you do not want to incur extra traffic costs from Aptoma, we recommend that you set up your own image proxy and replace the image urls accordingly.

The front content will be wrapped in a single div.front-element.

Processing Placeholders

Any placeholders you add to your front will be rendered as dre-item--placeholder, with some additional data, including an attribute data-id, referencing the item in the edition. The Sphynx output is valid HTML, which can be loaded into a DOM parser for manipulation:

const dom = new JSDOM(html);
const doc = dom.window.document;
const edition = await getEditionFromDrEditionApi(editionId);
Array.from(doc.querySelectorAll('[data-placeholder]')).map((node) => {
const item = edition.items.find((item) => item.data.id === node.dataset.id);
const div = doc.createElement('div');
div.classList.add('dre-replaced');
div.innerHTML = myPlaceholderRenderer(item);
const parentNode = node.parentNode;
parentNode.replaceChild(div, node);
});

Placeholders rendered by Sphynx will get attributes data-lg, data-md and data-sm, as well as a style attribute that sets CSS variables --lg-width, --lg-height, --md-width, --md-height, --sm-width and --sm-height. These are used during measuring of items to optimize the layout. You should not rely on their presence to control item size after you have run your placeholder replacement logic, as hese are not supported by older browsers.

We recommend replacing the entire placeholder element with your own markup, making sure that you replace it with a single root element (as some layouts depend on the number of direct children). This will prevent placeholder styles that are only used for layout to bleed through to your production site.

Lazy Load Images

To enable lazy load of images on the published front, add the following properties to the edition schema:

{
"lazyLoad": {
"title": "Enable lazy load of images?",
"type": "boolean",
"default": false
},
"lazyLoadStartRow": {
"title": "First row to start lazy loading images",
"type": "number",
"default": 0,
"x-schema-form": {
"condition": "model.lazyLoad",
"destroyStrategy": "remove"
}
}
}

This will replace the src attribute of images starting at the specified row with data-src. The image will also get an additional lazy class.

Provided the browser supports IntersectionObserver (or has a polyfill), this should work:

document.addEventListener('DOMContentLoaded', () => {
const lazyImages = [].slice.call(document.querySelectorAll('img.lazy'));
if ('IntersectionObserver' in window) {
const lazyImageObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove('lazy');
lazyImage.parentNode.querySelectorAll('source').forEach((source) => {
source.srcset = source.dataset.srcset;
});
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach((lazyImage) => {
lazyImageObserver.observe(lazyImage);
});
}
});

This example is based on https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/, which also contains code for fallback options using event handlers without a polyfill.