This site uses Netlify Identity for authentication. Users are invited by email, assigned a role, and can only access pages permitted by their role.

Access Levels

There are four access levels, from lowest to highest privilege:

Level Description
Public No login required — anyone can view
Client Requires login with client role or higher
Team Requires login with team role or higher (default)
Admin Requires login with admin role only

Higher roles inherit access from lower roles. An admin can see everything a team member can see, and a team member can see everything a client can see.

Single Source of Truth

All access rules live in markdown frontmatter. This is the only place access is configured — not in JavaScript, not in theme config files.

The doc generator reads frontmatter and outputs data-access attributes on the HTML. The auth script reads those attributes at runtime and enforces them.

frontmatter (cms/*.md) → generator → data-access (HTML) → auth.js (runtime)

Page Access Configuration

Standard roles

access: "public"    # No login required
access: "client"    # Any client or higher
access: "team"      # Team members and admins (default)
access: "admin"     # Admins only

Pages without an access value inherit from _defaults.md in their folder (see below). If no defaults file exists, the fallback is team.

Per-client access

To restrict a page to specific clients, use the client: prefix with a comma-separated list of client folder names:

access: "client:dianomi"              # Only the "dianomi" client
access: "client:dianomi,acme"         # "dianomi" or "acme" clients
access: "client:dianomi,acme,globex"  # Any of these three clients

Team and admin users always have access regardless of the client list. The client folder names must match the clientFolder value in the user's Netlify Identity app_metadata.

On standalone HTML pages

Set the attribute directly on <body>:

<body class="auth-loading" data-access="client:dianomi,acme">

Folder Defaults (_defaults.md)

Any directory in cms/ can contain a _defaults.md file that sets default frontmatter values for all sibling markdown files in that directory. This works like Notion's inherited permissions — set it once at the folder level, override per-page when needed.

How it works

  1. The generator checks for _defaults.md in the same directory as the page being processed
  2. Default values are merged — page frontmatter always wins over folder defaults
  3. _defaults.md files are never generated into HTML pages (skipped during generation)

Current defaults

# cms/_defaults.md
---
access: "team"
---

# cms/clients/dianomi/_defaults.md
---
access: "client:dianomi"
---

# cms/clients/client-template/_defaults.md
---
access: "client:client-template"
---

This means:

  • All main docs default to team access
  • All dianomi pages default to client:dianomi access
  • All client-template pages default to client:client-template access
  • Any page can override its folder default with an explicit access: in its own frontmatter

Tool Access

Tools have two access levels — one for the documentation page and one for the tool app itself:

# cms/calculator-docs.md
---
access: "admin"                              # doc page: admin only
toolUrl: "../tools/cpm-calculator.html"
toolAccess: "public"                         # tool app: anyone
---
  • access controls who can see the documentation page
  • toolAccess controls who sees the tool card in section overviews and who can access the tool app page

The standalone tool HTML pages (tools/*.html) must have a matching data-access attribute on their <body>:

<!-- tools/cpm-calculator.html -->
<body class="auth-loading" data-access="public">

<!-- tools/display-ad-preview.html -->
<body class="auth-loading" data-access="client:dianomi,client-template">

When adding a new client that should see a tool, update the toolAccess field in the markdown file and the data-access attribute on the tool HTML page.

Managing Users

Users are managed in the Netlify Dashboard:

  1. Go to your site in the Netlify Dashboard
  2. Navigate to IntegrationsIdentity
  3. Click Invite users to send email invitations

Assigning Roles

After a user accepts their invitation, edit their profile in the Identity panel to set their role:

  1. Click on the user in the Identity list
  2. Under Metadata, edit the app_metadata field
  3. Set the role:
{
  "roles": ["admin"]
}

Available roles: admin, team, client.

Client Folder Access

Client users need a role that identifies which client folder they belong to. The simplest way is to add the client folder name as a role tag in the Netlify UI:

Option A — Single tag (recommended)

Add just the client name as a role tag (e.g. dianomi). The system automatically treats any non-hierarchy role as a client folder name and assigns the client access level.

Option B — Two tags (explicit)

Add both client and the client name as tags (e.g. client + dianomi). This is more explicit but functionally identical.

Option C — API (app_metadata)

If using the Netlify API, you can set clientFolder explicitly:

{
  "roles": ["client"],
  "clientFolder": "dianomi"
}

All three options produce the same result: the user can access pages with data-access="client:dianomi" (or public). They cannot see pages scoped to other clients.

Team and admin users can access all client folders.

Adding a New Client

  1. Create cms/clients/acme/_defaults.md:
    ---
    access: "client:acme"
    ---
    
  2. Create cms/clients/acme/welcome.md (copy from client-template)
  3. Add theme entry in assets/js/theme-config.js (css, fonts, label, pages — no access config)
  4. Update shared pages the client should see: add acme to toolAccess comma lists in the relevant cms/*.md files
  5. Update the matching tool HTML pages: add acme to data-access on <body>
  6. Run npm run docgen

Adding a New Page

  1. Create the page as usual
  2. Set the access frontmatter (for docs) or data-access attribute (for standalone HTML)
  3. If the page is in a folder with _defaults.md, you can omit access: to inherit the default
  4. Run npm run docgen if it's a docs page
  5. Deploy — the auth script handles the rest

Element-Level Visibility

Individual elements on a page can be shown or hidden based on the user's role. Add a data-auth-role attribute to any HTML element:

<!-- Only visible to admin -->
<div data-auth-role="admin">
  This content is only visible to administrators.
</div>

<!-- Visible to team and above -->
<div data-auth-role="team">
  This content is visible to team members and admins.
</div>

<!-- Visible to everyone (no login needed) -->
<div data-auth-role="public">
  This content is always visible.
</div>

Role inheritance applies: an admin can see elements marked team or client.

Login and Logout

  • Login: The Netlify Identity widget opens automatically on protected pages when no user is logged in. A login button is also available in the sidebar.
  • Logout: A logout button appears in the sidebar when logged in. Clicking it clears the session and redirects to the homepage.

Future Enhancements

Server-Side Enforcement

The frontmatter schema maps directly to Netlify redirect rules for server-side enforcement:

Frontmatter Netlify Role Condition
access: "public" No rule needed
access: "team" Role = ["team", "admin"]
access: "admin" Role = ["admin"]
access: "client:dianomi" Role = ["client-dianomi", "team", "admin"]

A build script could auto-generate netlify.toml redirect rules from frontmatter.

Per-User Access

When needed, extend the frontmatter syntax:

access: "user:erlen@bydefault.studio,jane@dianomi.com"

This would require storing allowed emails in Netlify Identity metadata and checking against them in auth.js.

Security Notes

  • On the free Netlify tier, authentication is enforced client-side. The HTML is still served to all visitors, but the JavaScript hides content from unauthenticated or unauthorised users.
  • This is appropriate for internal documentation. It is not suitable for highly sensitive data.
  • For true server-side protection, upgrade to Netlify Pro and add role-based redirect rules in netlify.toml.

Troubleshooting

User can't log in

  • Ensure Identity is enabled in the Netlify Dashboard
  • Check that the user has been invited and has accepted their invitation
  • Verify the user's app_metadata contains a valid roles array

User sees "Access Denied" unexpectedly

  • Check the user's role tags in the Netlify Identity dashboard
  • Verify the page's data-access attribute matches the user's role
  • For client users, ensure one of their role tags matches the client name in data-access="client:name" (e.g. a user with the dianomi tag can access data-access="client:dianomi")

Auth not working locally

  • Netlify Identity requires a deployed Netlify site. Use netlify dev for local testing with Identity support.

Was this page helpful?

We use this feedback to improve our documentation.

Thanks for your feedback