Table of Contents

Deploy under a subpath

Serve a Baseline site from a subpath like /docs/ without breaking links, asset paths, canonical URLs, or the sitemap on the way.


Prerequisites

  • Baseline registered in eleventy.config.js.
  • package.json with "type": "module" and scripts (start, build).
  • settings.url set to the production origin (no trailing slash, no subpath).
  • You deploy to a subpath (e.g. a GitHub Pages project site, a reverse proxy, or a Netlify subdirectory).

Set pathPrefix in Eleventy's config export

Keep settings.url pointed at the origin and put the subpath on pathPrefix:

import baseline, { config as baselineConfig } from '@apleasantview/eleventy-plugin-baseline';
import settings from './src/_data/settings.js';

/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
export default async function (eleventyConfig) {
	await eleventyConfig.addPlugin(baseline(settings));
}

export const config = {
	...baselineConfig,
	pathPrefix: '/docs/' // include leading and trailing slash
};

Eleventy rewrites root-relative URLs with pathPrefix, and the sitemap picks it up through Eleventy's htmlBaseUrl filter.


Keep settings.url clean (origin only)

Deployment checks covers the env shape. Sitemap entries combine settings.url with pathPrefix automatically.

The head does not carry pathPrefix today.

The canonical, og:url, the hreflang alternates and the JSON-LD @id values are built from settings.url plus the page's own URL, and Eleventy's HtmlBasePlugin leaves an already-absolute URL alone. So on a site deployed under /docs/, in-page links and the sitemap read https://www.example.com/docs/about/ while the canonical reads https://www.example.com/about/.

Putting the subpath in settings.url instead is not the fix: it doubles the prefix on the links and the sitemap. Until this is closed, a subpath deployment ships head URLs that are one segment short.


Reference built assets and pages with leading slashes so Eleventy applies pathPrefix:

<link rel="stylesheet" href="/assets/css/index.css">
<script src="/assets/js/index.js" defer></script>
<a href="/getting-started/">Getting started</a>

Avoid hardcoded full URLs with the subpath baked in.


Build and inspect what comes out

  • Dev: npm start
  • Build: npm run build
  • Open dist/sitemap.xml and confirm URLs include /docs/.
  • Inspect a built page for asset and link URLs that include /docs/. The canonical will not, per the warning above.

Preview under the same subpath you'll deploy to

  • Serve dist/ from a subpath-capable server, or use Eleventy's preview with --pathprefix="/docs/" to spot broken links.
  • Click through pages and assets to confirm they resolve under /docs/.

What goes wrong

Nearly everything that breaks a subpath deployment is a URL that pathPrefix could not reach. Eleventy rewrites root-relative URLs and leaves everything else alone, so a hardcoded https://www.example.com/docs/about/ and a slashless assets/js/index.js fail for the same reason from opposite directions: one is already absolute and the other is relative to wherever the page happens to be. Write every link and asset path with a leading slash and the rewrite has something to work with.

The other half is a mismatch between the prefix you build with and the prefix you deploy under. Building without pathPrefix and serving from /docs/ breaks every link, which is why the preview step above uses the same value you plan to ship. Going the other way, back to root hosting, means clearing pathPrefix again or every path gains a segment it no longer has.

And the one that looks like a fix and is not: putting the subpath in settings.url as well as pathPrefix, which doubles it into /docs/docs/ across links and the sitemap. The warning above has the detail.


See also