Configure site settings and inherit them from the app

Clarification By design
A site's settings (images, security, headers, cache, minify, hashjs and login) are grouped in sections. Each section can be its own file in the # folder, such as #/security.json, or a key in #/site.json; if it is in both, they are merged and the file wins. A site built on an app inherits the app's settings key by key: four layers are merged, the most specific last: the app's site.json, the app's section file, the site's site.json and the site's section file. Write only what differs. null removes a value, a list replaces the app's list as a whole, and "$inherit": false turns inheritance off for one section. Docly writes its own settings to the site's #/images.json, never to site.json and never to the app.
Applies to: site.jsonheaders.jsonimages.jsonsecurity.jsonAppsSecurity headersImagesSecurity

What you'll see

You are configuring a site (image sizes, a security level, a CSP, caching or minification) and need to know which file the setting goes in. Or the site is built on an app, and you want to change one setting without losing the rest of the app's settings, or you wonder why the site does not use a value the app sets.

What's actually happening

The sections

SectionFileControls
images#/images.jsonImage sizes, format and quality
security#/security.jsonSecurity level and exceptions
headers#/headers.jsonHTTP headers, such as the CSP
cache#/cache.jsonCaching of pages
minify#/minify.jsonMinification of HTML, CSS and JS
hashjs#/hashjs.jsonCompilation of .hash pages
login#/login.jsonName and logo on the sign-in page

Where a section lives

Each section can live in its own file in the # folder, for example #/security.json. The file contains only the section:

{ "level": "elevated" }

If you prefer everything in one place, write the section into #/site.json instead:

{ "security": { "level": "elevated" },
  "cache":    { "enabled": true } }

If a section is in both places, they are merged. The file is laid on top of site.json, so the file wins for a setting that is in both, and the rest of site.json still applies. If the same setting has different values in the two places, the site console shows a warning, because it is often an old copy.

The order

The settings are laid on top of each other, and the most specific wins:

  1. the app's site.json
  2. the app's section file, e.g. headers.json
  3. the site's #/site.json
  4. the site's section file, e.g. #/headers.json

In an app, the template's root is the # folder, so the app's files are ./site.json and ./headers.json, not ./#/…. See Do not create a # folder inside an app.

Inheritance from the app

A site built on an app inherits the app's settings. You only write what should be different:

App: security.json

{ "level": "elevated",
  "exclude": ["/hook/"] }

Site: #/security.json

{ "level": "normal" }

What applies to the site

{ "level": "normal",
  "exclude": ["/hook/"] }
You want to…Write
change one settingonly that setting
remove a setting the app has set"exclude": null
change a listthe whole list. A list in the site replaces the app's list as a whole.
use your own section and inherit nothing"$inherit": false in the section, in the site's file or in the site's site.json

Objects inside a section are merged key by key in the same way. Keys are compared without regard to case.

Headers

headers follows the same rule. A site that sets one header keeps the rest of the app's headers, including a CSP. "X-Frame-Options": null removes a header completely, also when Docly would otherwise send it by default.

What Docly writes itself

Some settings are written by Docly. The image sizes you save under Image sizes, and the sizes Docly discovers when pages are shown, go to the site's #/images.json. The name and logo for sign-in go to #/login.json. Docly never puts settings in site.json, never writes to the app, and does not copy the app's site.json into the site.

If images is in the site's site.json the first time Docly saves image settings, Docly moves the section to #/images.json. The content is the same, and it is still in only one place.

When something is wrong

A file that is not valid JSON is skipped, and the error is shown in the site console. The other layers still apply, so the site keeps working, but without the settings in that file. If the same setting has different values in the file and in site.json, the console shows that too.

What to do

  • Put settings every site should share in the app, and only what differs in each site. A later change in the app then reaches every site that does not set that key itself.
  • Keep each section in one place per site: the section file or site.json, not both. Then there is no copy to drift out of step; the console warning tells you when the two disagree.
  • Write the whole list when a site changes a list such as security.exclude or images.allowedSizes. The app's list no longer applies for that key, so repeat the entries the site still needs.
  • Use "$inherit": false sparingly. The site then gets none of the app's settings for that section, including later changes to them, such as a tightened CSP.
  • Do not use the section file names for data. #/images.json, #/security.json, #/hashjs.json, #/minify.json and #/cache.json are read as configuration. A data file that happens to have one of these names becomes settings; rename it.
  • Validate the JSON before you save, and check the site console afterwards. An invalid file is skipped rather than taking the site down, but its settings, such as a CSP, are missing until it is fixed.