Skip to content
mdlake

Site configuration

Every environment variable, config file and generated record of a site built with the kit, with defaults and who may edit each one. For developers.

On this page

A site is configured by a small set of files and environment variables. This page lists all of them. Some you edit, some tools write, and some you must never commit. For the ownership rules behind that, see Ownership zones.

Where settings come from

SourceUsed for
Environment variablesEverything below. A variable that is already set in the environment wins over the file.
.env in the site folderThe same variables for local work. It is read by the kit and by the commands. It is in .gitignore: never commit it.
.env.exampleThe documented list of names, without values. Commit it.
Pipeline variables and secretsThe same variables in CI. See Deploying a site.
App Service settings and Key VaultRun-time settings of the server or the API. See Azure and Bicep.

Astro only gives .env to import.meta.env. The kit also loads it into process.env before it runs, so the build, lake.config.ts and the commands see the same values.

Environment variables

The lake

VariableDefaultMeaning
LAKE_PATHnoneA lake clone you keep by hand. It overrides the managed clone. Without it, a site whose lake.lock has a remote builds from .mdlake/lake, and a site without one builds from ./example-lake. Do not set it in CI.
MDLAKE_LAKE_TOKENnoneA read-only token for fetching the lake in CI (fine-grained, Contents: read on the lake repository). Never commit it. See The lake in CI, and caches.
LAKE_LOCK_CANDIDATEnoneBuild and check against this lake commit instead of the locked one. The refresh flow uses it.
LAKE_LOCK_IGNOREnone1 builds even though the lake is not at the locked commit, with a warning. Emergencies only. Never deploy that build.

The site and its assets

VariableDefaultMeaning
SITE_URLhttps://www.example.comThe public origin. Used for canonical links, the sitemap and social tags. Set it in every environment.
PUBLIC_ASSET_BASE_URLnoneWhere assets are fetched from, as <base>/<asset id>, for example a CDN in front of storage. Without it each asset uses the public url in its sidecar.
PUBLIC_ASSET_RESIZEfalsetrue when the asset host resizes with ?w=<width>. Only the dev server and previews use it. A build copies assets and serves them from its own /files/ path.
ASSET_OPTIMIZEtruefalse copies the original images to /files instead of converting them (faster builds, larger pages). It applies only to assets from a remote host.
SITE_INDEXABLEtruefalse adds noindex to every page and Disallow: / to robots.txt. Use it on staging.
INCLUDE_DRAFTSfalsetrue includes drafts. Only for preview builds.

The CMS connection and previews

VariableDefaultMeaning
MDLAKE_API_URLnoneThe read API of the workspace: https://<cms>/api/lake/<workspace>.
MDLAKE_TOKENnoneA workspace token. A token with the preview scope is needed for npx mdlake preview; the published scope is enough for Claude Code’s lake tools. See Workspace tokens.
MDLAKE_MCP_URLthe origin of MDLAKE_API_URL plus /mcpSet it only when the MCP address is different.
MDLAKE_USAGE_REPORTon0 stops the plugin’s hook from reporting AI token counts to the CMS.
MDLAKE_PREVIEWnone1 or true makes the site read drafts through the API and ignore lake.lock. Set by npx mdlake preview. A production build (astro build) refuses it.
MDLAKE_PREVIEW_POLL5000How often, in milliseconds, a preview asks the CMS for changes.
MDLAKE_PREVIEW_DEPLOYnone1 allows a static build of a preview for a host that only editors can reach (the same as astro build --preview-deploy). Signed asset links in such a build expire after 15 minutes.
MDLAKE_PLUGIN_ROOTnoneThe plugin folder for check-ruleset, when it cannot find it.

Server code: forms, mail and Turnstile

These apply to the server model and to the backend of a split site.

VariableSecretMeaning
MAIL_PROVIDERnoresend or log. See Mail.
RESEND_API_KEYyesThe Resend API key.
MAIL_FROMnoThe sender, on a domain verified in Resend.
<RECIPIENT> (for example CONTACT_FORM_TO)noThe recipient of one form. The name is set in src/forms/<name>.ts as recipientEnv.
PUBLIC_TURNSTILE_SITE_KEYnoThe Turnstile site key. Read at build time and put in the page.
TURNSTILE_SECRET_KEYyesThe Turnstile secret key. See Turnstile.
TRUSTED_PROXY_HOPSnoHow many proxies to trust in X-Forwarded-For, counted from the right. Default 1; the generated Bicep sets 2 for the API of a split site.
HOST, PORTnoWhere the Node server listens. The generated App Service sets HOST=0.0.0.0.
API_PORTnoThe local port of a separate backend and the dev proxy. Default 3001 (Node) or 5088 (.NET).

Build and checks

VariableDefaultMeaning
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATHPlaywright’s own ChromiumA Chromium for check-a11y, for machines where Playwright’s download is not possible.

Files

FileEdit it?What it is
astro.config.mjsYesCalls defineMdlakeConfig() from @mdlake/site-kit/integration. The kit supplies static output, trailing slashes, SITE_URL, redirects.json, React, the sitemap, Tailwind and the page routes. Your Astro options win over its defaults. On the server model the kit adds the Node adapter, standalone.
lake.config.tsThrough plan.mdGenerated. defineLake({ workspace, site, documents, collections, slots }) says what the site binds to: documents by id, collections by folder and tags (with sort), slots for the site type. site is { name, cta? }: cta: { label, href } is the site’s default call to action, the brief’s primaryCta, which the end of a detail page uses when its own end.cta is not set (Site types). Hand edits need npx mdlake adopt lake.config.ts.
lake.lockThrough the refresh flowThe locked lake commit, its remote, the time and the mode (snapshot or live). A kit file: tools write it. See Lake format.
src/pages.config.tsThrough plan.mdGenerated. The routes, their modules, the navigation (nav) and the end-of-page block (end). Headings, button labels and links are site chrome and live here.
src/content/generated/<key>.mdNever by handGenerated copy with provenance.
src/forms/<name>.tsYesA form definition. See Forms.
site.config.tsYesReplaces kit components. See below.
design.mdYesThe design: tone, colours, fonts, radius, container. apply-design.mjs writes the tokens into src/styles/global.css.
plan.mdYesThe brief and the plan. Generated files follow from it.
redirects.jsonYesA map from an old path to a new one, for slugs that changed. Edit this, not astro.config.mjs. Default {}.
builder.jsonNoThe ruleset and template version the site was made from.
provenance.jsonNoThe ownership record: the zone and hash of each kit and generated file, and which files are locked or adopted.
site-snapshot.jsonThrough npx mdlake snapshotThe route snapshot that the refresh flow compares against. Commit it.
.mdlake/ruleset.jsonNorulesetVersion, pluginVersion, lakeLoaderVersion, siteKitVersion, mode.
.mdlake/hosting.jsonNoThe hosting model, adapter, on-demand routes and backend. Commit it. See Choose a hosting model.
.mdlake/types/lake.d.tsNoTyped keys, written from lake.config.ts by mdlake prepare. Gitignored.
.mdlake/lake/NoThe managed lake clone. Gitignored.
CLAUDE.mdAdd your own rulesThe ruleset for Claude Code, written by scaffold-site and replaced by upgrade-ruleset. Keep your own rules in a separate section.
infra/, .github/workflows/deploy.yml, azure-pipelines.ymlSee belowWritten by hosting init.
api/, src/api/generated/api/ yes, generated noThe separate backend and its typed client.

site.config.ts

The file is optional and site-owned. It replaces kit components; it does not change what they show.

TypeScript
import { defineSiteConfig } from '@mdlake/site-kit'

export default defineSiteConfig({
  modules: { hero: './src/components/MyHero.astro' },
  layout: './src/components/MyLayout.astro',
  parts: { Prose: './src/components/MyProse.astro' },
})

Unknown keys are an error. Paths are relative to the site root, or a package name. A path that does not exist is an error that lists every missing file. Restart astro dev after a change.

KeyAccepted names
moduleshero, featureGrid, steps, testimonial, stats, faq, cta, richText, caseHeader, docsPage, form, endOfPage
partsCardGrid, CodeCopy, DocsSearch, DocsSidebar, FormFields, LakeImage, MobileNav, Prose, SEO
layoutA path. It can wrap the kit’s layout (@mdlake/site-kit/layouts/Layout.astro), which has the slots head, banner, header and footer.

A replacement module gets the same props as the kit’s own: data, index and back. See Custom components.

The generated files of hosting

hosting init writes these files, each marked on its first line. Edit the parameter files freely; for anything else, adopt the file first.

FileZone
infra/main.bicep, infra/modules/*.bicepgenerated
.github/workflows/deploy.yml, azure-pipelines.ymlgenerated
infra/parameters/staging.bicepparam, production.bicepparamyours

package.json

Scripts, engines and dependencies of a template site:

ItemValue
engines.node>=22.23.4 in the template’s package.json. npm warns when the Node version is lower.
Dependenciesastro, @astrojs/react, react, react-dom, @mdlake/site-kit, @mdlake/lake-loader
Dev dependencies@astrojs/check, typescript, playwright, axe-core and the React types
Scriptsdev, build, preview, preview:cms, check and the check:* scripts. See CLI reference.

The site’s own .gitignore covers node_modules/, dist/, .astro/, .env, .mdlake/lake/, .mdlake/types/, the preview and candidate files, and the usage state (.mdlake/usage-*).

What’s next