Everything a developer changes on a Core dna site lives in its theme repository. This guide covers the repository and its build, printing records in templates, stylesheets and client-side code, and the parts of a site around the main content.
L1–L2
Unit 01 · Anatomy of a theme repo
The CSP nonce
Anatomy of a theme repoPage 7 of 35Updated
Every page is sent with a Content Security Policy built from a site setting, and every script tag, inline or external, carries the request's nonce. The policy and its default, the syntax in both engines, what a refused script looks like, and what a nonce cannot fix.
Who this is for. Anyone who writes a <script> tag in a template, adds a third-party script, or pastes markup from a vendor's instructions. Afterwards you will write script tags that run under the site's policy, recognise a refused script in seconds, and know when the policy itself has to change.
The policy
The platform sends a Content-Security-Policy header with every page it renders. Its value is the site setting System › Global Settings › Security › CSP policy (Globals.security.cspPolicy), whose default is:
For each response the platform replaces %nonce% with a fresh random value and hands the same value to the templates as _inlineScriptNonce. Scripts may therefore come from the site itself, from cdnjs, or carry that nonce. A page served from the page cache is served with the header it was cached with, so its nonce still matches the markup. A switch beside the setting, Disable CSP, removes the header altogether; leave it off.
Every script tag carries the nonce
Put the nonce on every <script> tag, inline or external:
Under the default policy an external script from the site's own host would run without the nonce, because 'self' allows it. Give it the nonce anyway. A site whose policy adds 'strict-dynamic' is enforced with nonces alone: browsers that support it ignore 'self' and host lists, so a same-origin /dist/app.js without a nonce stops running the day the policy changes. Under 'strict-dynamic', scripts that a nonced script loads, webpack chunks and a payment provider's SDK among them, are trusted in turn and need no nonce of their own.
A <script type="application/ld+json"> block is data, not code: the browser never executes it, and it needs no nonce.
What a refused script looks like
Nothing on the page. The script does not run, the feature it drives is dead, and the only trace is in the browser's developer tools. Chrome's console reports an inline script as:
HTMLChrome console
Refused to execute inline script because it violates the following Content Security Policy
directive: "script-src 'self' https://cdnjs.cloudflare.com 'nonce-…'". Either the
'unsafe-inline' keyword, a hash ('sha256-…'), or a nonce ('nonce-…') is required to enable
inline execution.
and an external script from a host the policy does not list as Refused to load the script '…' because it violates the following Content Security Policy directive, with the request shown as (blocked:csp) in the Network panel. Open the console on every page type after any change to scripts or to the policy, on every environment: a refused script raises no error a visitor or a monitor would notice.
What a nonce cannot fix
Inline event handlers and javascript: URLs.onclick="…", onload="…" and href="javascript:…" cannot carry a nonce, so a nonce-based policy refuses them. Attach handlers from your bundle with addEventListener. This catches vendor snippets and the popular <link rel="preload" onload="this.rel='stylesheet'"> pattern: Critical and deferred CSS.
Scripts from other hosts. Analytics, tag managers, chat widgets and payment SDKs are refused unless their hosts are in the policy. Add each host the provider documents to the setting, keeping 'nonce-%nonce%', and test the page that uses it. A script you can serve from your own build needs no change.
Scripts injected by a script without the nonce. A tag manager's container loaded with the nonce can add tags; one loaded without it cannot even start.
The default policy has only a script-src directive, so styles, fonts, images and frames are not restricted: a <style> block needs no nonce. A site that adds style-src or img-src takes on the same discipline for those.
Changing the policy changes it for every page
The setting is site-wide and only a super admin can edit it. Copy the current value before you change it, change one thing at a time, and check the console on the home page, a content page, a form and the checkout before you call it done.