{"_id":"@eleventy-plugin-themer/theme-base","_rev":"7-3be8bb156563419fbae52c6783cf81f3","name":"@eleventy-plugin-themer/theme-base","dist-tags":{"latest":"0.5.2"},"versions":{"0.1.0":{"name":"@eleventy-plugin-themer/theme-base","version":"0.1.0","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"author":{"name":"Artis Lismanis"},"license":"MIT","_id":"@eleventy-plugin-themer/theme-base@0.1.0","maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"dist":{"shasum":"c8f2d465e5ea05ab874f18ed872123861cd915b5","tarball":"https://registry.npmjs.org/@eleventy-plugin-themer/theme-base/-/theme-base-0.1.0.tgz","fileCount":35,"integrity":"sha512-EPMgPWqJ4Ough/CFTuFDjYmwbgO4LDfS8R7k6osImUIRx90IUPS0zpXrM3dwsDN1iJmLk7wGAOlLgbvRxJQlSQ==","signatures":[{"sig":"MEUCIEeQowsf2L0e3mcm13MnikbwiHyS8NlrmkmrtlLrmHiqAiEAtdzU3zO7Im83Edt57ZU9teeDOLD1219ES6GXj+2yCXo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76045},"main":"lib/index.mjs","type":"module","engines":{"node":">=22"},"exports":{".":"./lib/index.mjs","./styles/*":"./styles/*","./layouts/*":"./layouts/*","./scripts/*":"./scripts/*","./features/*":"./features/*","./theme.json":"./theme.json"},"gitHead":"ca19d933936453a503e5cd1aba78acea7dcb8696","scripts":{"lint":"eslint .","test":"vitest run","test:watch":"vitest"},"_npmUser":{"name":"artislismanis","email":"artis@lismanis.uk"},"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"_npmVersion":"10.9.8","description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","directories":{},"_nodeVersion":"22.22.3","dependencies":{"luxon":"^3.7.0","markdown-it":"^14.1.0","markdown-it-anchor":"^9.2.0","@eleventy-plugin-themer/core":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@11ty/eleventy":"^3.1.0","@11ty/eleventy-navigation":"^1.0.0","@11ty/eleventy-plugin-syntaxhighlight":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/theme-base_0.1.0_1781953227664_0.7203948033430636","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@eleventy-plugin-themer/theme-base","version":"0.2.0","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"author":{"name":"Artis Lismanis"},"license":"MIT","_id":"@eleventy-plugin-themer/theme-base@0.2.0","maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"dist":{"shasum":"78a273a1d6f679d3dc1d71919f96cc6815bd4ae3","tarball":"https://registry.npmjs.org/@eleventy-plugin-themer/theme-base/-/theme-base-0.2.0.tgz","fileCount":38,"integrity":"sha512-JY7SVO5D/a1iOj9j2TSFNoxPGHjJ4T7aQrr4oG6xlZLagvi3qdH54iz6NAakXm7ONef1gdPlG7a1je8t1Zzp+g==","signatures":[{"sig":"MEUCIBFf+RHgTXloTkC1XAtioebZo3Adi/4/KT7tQa4lp1+1AiEAqv3Pt+dR/sH2vxqhAKl4pv7HY9lWBoHKDqMkmTL2n5s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":83329},"main":"lib/index.mjs","type":"module","engines":{"node":">=22"},"exports":{".":"./lib/index.mjs","./styles/*":"./styles/*","./layouts/*":"./layouts/*","./scripts/*":"./scripts/*","./features/*":"./features/*","./theme.json":"./theme.json"},"gitHead":"61211c56052643adac5ad0c66afd501fc85a0d4a","scripts":{"lint":"eslint .","test":"vitest run","test:watch":"vitest"},"_npmUser":{"name":"artislismanis","email":"artis@lismanis.uk"},"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"_npmVersion":"10.9.8","description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","directories":{},"_nodeVersion":"22.22.3","dependencies":{"luxon":"^3.7.0","markdown-it":"^14.1.0","markdown-it-anchor":"^9.2.0","@eleventy-plugin-themer/core":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@11ty/eleventy":"^3.1.0","@11ty/eleventy-navigation":"^1.0.0","@11ty/eleventy-plugin-syntaxhighlight":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/theme-base_0.2.0_1781970810579_0.4035061393583821","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@eleventy-plugin-themer/theme-base","version":"0.3.0","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"author":{"name":"Artis Lismanis"},"license":"MIT","_id":"@eleventy-plugin-themer/theme-base@0.3.0","maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"dist":{"shasum":"af5c79bc9066c919a07f1e9f52076f1693ff6ea5","tarball":"https://registry.npmjs.org/@eleventy-plugin-themer/theme-base/-/theme-base-0.3.0.tgz","fileCount":40,"integrity":"sha512-L2HMBBQzMpCgsxxCazsFFVizsxBrpObeKu6gZ2sKsrsbLTGvxf8qYGInje3kzjLKoK0BTu69+EFUcoEAtcyO+A==","signatures":[{"sig":"MEUCIAZMRDaEHDSeVE/YLTkjoFzH4CZfhbhkKK1YJdulya8OAiEA6aja8ktihCEBJn3Y8DtFj0OR1cJQkiuA++LD2NwCZr4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98391},"main":"lib/index.mjs","type":"module","engines":{"node":">=22"},"exports":{".":"./lib/index.mjs","./styles/*":"./styles/*","./layouts/*":"./layouts/*","./scripts/*":"./scripts/*","./features/*":"./features/*","./theme.json":"./theme.json"},"gitHead":"6553b8cbbbed9302d10dce8a2710153d7a77e3f2","scripts":{"lint":"eslint .","test":"vitest run","test:watch":"vitest"},"_npmUser":{"name":"artislismanis","email":"artis@lismanis.uk"},"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"_npmVersion":"10.9.8","description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","directories":{},"_nodeVersion":"22.22.3","dependencies":{"luxon":"^3.7.0","markdown-it":"^14.1.0","simple-icons":"^16.23.0","markdown-it-anchor":"^9.2.0","@eleventy-plugin-themer/core":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@11ty/eleventy":"^3.1.0","@11ty/eleventy-navigation":"^1.0.0","@11ty/eleventy-plugin-syntaxhighlight":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/theme-base_0.3.0_1782036257263_0.6233110006442901","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@eleventy-plugin-themer/theme-base","version":"0.4.0","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"author":{"name":"Artis Lismanis"},"license":"MIT","_id":"@eleventy-plugin-themer/theme-base@0.4.0","maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"dist":{"shasum":"dda08dee9d7fe7b7465e2245aeefd03bebf8661f","tarball":"https://registry.npmjs.org/@eleventy-plugin-themer/theme-base/-/theme-base-0.4.0.tgz","fileCount":40,"integrity":"sha512-icRrEJwaIAdt2LB3LHcxjiwgPZGSrx7IWcF7tVPLzBnresxEvg99b11cogt96lZZhbeTgUKpgspA01yQZnakyw==","signatures":[{"sig":"MEUCIFeFfFbd5e/jrs8sW3XYRN4pXeA0hWeo9sXh2bfeXM0AAiEAobNLGkQoocpaAmxxOMShw27oeog2sK6KYffCkssE650=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96973},"main":"lib/index.mjs","type":"module","engines":{"node":">=22"},"exports":{".":"./lib/index.mjs","./styles/*":"./styles/*","./layouts/*":"./layouts/*","./scripts/*":"./scripts/*","./features/*":"./features/*","./theme.json":"./theme.json"},"gitHead":"bcc252ea28916abc6fb22670b6de7463adf42673","scripts":{"lint":"eslint .","test":"vitest run","test:watch":"vitest"},"_npmUser":{"name":"artislismanis","email":"artis@lismanis.uk"},"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"_npmVersion":"10.9.8","description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","directories":{},"_nodeVersion":"22.22.3","dependencies":{"luxon":"^3.7.0","markdown-it":"^14.1.0","simple-icons":"^16.23.0","markdown-it-anchor":"^9.2.0","@eleventy-plugin-themer/core":"^0.4.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@11ty/eleventy":"^3.1.0","@11ty/eleventy-navigation":"^1.0.0","@11ty/eleventy-plugin-syntaxhighlight":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/theme-base_0.4.0_1782058955393_0.9234581755631976","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@eleventy-plugin-themer/theme-base","version":"0.4.2","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"author":{"name":"Artis Lismanis"},"license":"MIT","_id":"@eleventy-plugin-themer/theme-base@0.4.2","maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"dist":{"shasum":"58975283ede79615e5afee7b3dad1acebd5bce4b","tarball":"https://registry.npmjs.org/@eleventy-plugin-themer/theme-base/-/theme-base-0.4.2.tgz","fileCount":40,"integrity":"sha512-znZbSpo5wPIyQtcJplyZPeRLK3jKEOBCmbrJgtMJD5eSpVNQbVgDiHSo5sPKfNe9Kl+aRtTqIpxLuYXmZf+5PQ==","signatures":[{"sig":"MEUCIEzePyPXtwVkXb1CIYocsYqGiMXpT5i9eYwcmh3DXk+eAiEAjWTiyY/iI4P4HCVVLawEfkplpZNewLJMIjhIO/S/Vy0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97135},"main":"lib/index.mjs","type":"module","engines":{"node":">=22"},"exports":{".":"./lib/index.mjs","./styles/*":"./styles/*","./layouts/*":"./layouts/*","./scripts/*":"./scripts/*","./features/*":"./features/*","./theme.json":"./theme.json"},"gitHead":"880addbec4bb4b2e9c3853327794b4623f299943","scripts":{"lint":"eslint .","test":"vitest run","test:watch":"vitest"},"_npmUser":{"name":"artislismanis","email":"artis@lismanis.uk"},"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"_npmVersion":"10.9.8","description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","directories":{},"_nodeVersion":"22.22.3","dependencies":{"luxon":"^3.7.0","markdown-it":"^14.1.0","simple-icons":"^16.23.0","markdown-it-anchor":"^9.2.0","@eleventy-plugin-themer/core":"^0.4.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@11ty/eleventy":"^3.1.0","@11ty/eleventy-navigation":"^1.0.0","@11ty/eleventy-plugin-syntaxhighlight":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/theme-base_0.4.2_1782063303565_0.5912868100343958","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@eleventy-plugin-themer/theme-base","version":"0.5.1","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"author":{"name":"Artis Lismanis"},"license":"MIT","_id":"@eleventy-plugin-themer/theme-base@0.5.1","maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"dist":{"shasum":"afcb99553a14fb82c31cca8b694feeeb40ce8508","tarball":"https://registry.npmjs.org/@eleventy-plugin-themer/theme-base/-/theme-base-0.5.1.tgz","fileCount":40,"integrity":"sha512-kjLGhE1asoRJYa5KfDsiUpHnATmJWgPjaQCkLeJWKhrQPC/4Tz09B9/M9ZmRXpXq7AI5sa3S2f4YZdcfTs/h8w==","signatures":[{"sig":"MEYCIQCAkJUKu6XEmGlKQKwYyxrp+ICU/uww/fjDpP3X4RfOWwIhAJZQvyl0MXB/LANzhDkJdFIH2zqTJmSB8cTK2VusbZeM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCe2ccJlRi/HNvOViH5+YaVGX2YcqshXrN8nipfh0biHwIgHzsIM7qqCc/kFJrOE9qBjig2cfPcbtXrl+kaRZDYBCw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@eleventy-plugin-themer%2ftheme-base@0.5.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":97160},"main":"lib/index.mjs","type":"module","engines":{"node":">=22"},"exports":{".":"./lib/index.mjs","./styles/*":"./styles/*","./layouts/*":"./layouts/*","./scripts/*":"./scripts/*","./features/*":"./features/*","./theme.json":"./theme.json"},"gitHead":"ebacf6fe6076746447f82cf3ddefea56c9947acb","scripts":{"lint":"eslint .","test":"vitest run","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b5c4f276-dfa8-40a0-a196-2445646b9e63"}},"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"_npmVersion":"11.19.0","description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","directories":{},"_nodeVersion":"24.20.0","dependencies":{"luxon":"^3.7.0","markdown-it":"^15.0.2","simple-icons":"^16.31.0","markdown-it-anchor":"^10.0.0","@eleventy-plugin-themer/core":"^0.5.1"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"peerDependencies":{"@11ty/eleventy":"^3.1.0","@11ty/eleventy-navigation":"^1.0.0","@11ty/eleventy-plugin-syntaxhighlight":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/theme-base_0.5.1_1789850841129_0.06485042371015881","host":"s3://npm-registry-packages-npm-production"}},"0.5.2":{"_id":"@eleventy-plugin-themer/theme-base@0.5.2","bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"dist":{"shasum":"8ff8b73e481e12119eac993ef74addda75139311","tarball":"https://registry.npmjs.org/@eleventy-plugin-themer/theme-base/-/theme-base-0.5.2.tgz","fileCount":40,"integrity":"sha512-bGp5hpC1JJMXfqab2P7l4k9/GEkn1rAVphkF8AeS7V/Nqfcig/yB+Sg5dSz0Tp1wjCK4WfhOpfeWl3bCOd6NVg==","signatures":[{"sig":"MEQCIDYkjyRfI6nzXg7vpsOu+daaEU+jFQNq65wyzsYtOnlaAiAzxmDLuDXiKJmn+lj+XL45V48WlXmOXO8JMUP4PNMf9g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGBVCeaUqjyjUvX78Zi/tfyzhrhZFz4suXp7hls//0u8AiEA7DSjdo2rNZX27tJzXiTPtRVUfYQ9JhAkfUONOMoLQ08="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@eleventy-plugin-themer%2ftheme-base@0.5.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":97160},"main":"lib/index.mjs","name":"@eleventy-plugin-themer/theme-base","type":"module","author":{"name":"Artis Lismanis"},"engines":{"node":">=22"},"exports":{".":"./lib/index.mjs","./styles/*":"./styles/*","./layouts/*":"./layouts/*","./scripts/*":"./scripts/*","./features/*":"./features/*","./theme.json":"./theme.json"},"gitHead":"407523d3b790a042462c013ff6556543eca00402","license":"MIT","scripts":{"lint":"eslint .","test":"vitest run","test:watch":"vitest"},"version":"0.5.2","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b5c4f276-dfa8-40a0-a196-2445646b9e63"}},"homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"_npmVersion":"11.19.0","description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","directories":{},"maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"_nodeVersion":"24.21.0","dependencies":{"luxon":"^3.7.0","markdown-it":"^15.0.2","simple-icons":"^16.32.0","markdown-it-anchor":"^10.0.0","@eleventy-plugin-themer/core":"^0.5.1"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"peerDependencies":{"@11ty/eleventy":"^3.1.0","@11ty/eleventy-navigation":"^1.0.0","@11ty/eleventy-plugin-syntaxhighlight":"^5.0.2"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/theme-base_0.5.2_1790423322313_0.39348420772938386"}}},"time":{"created":"2026-06-20T11:00:27.537Z","modified":"2026-09-26T11:48:42.740Z","0.1.0":"2026-06-20T11:00:27.797Z","0.2.0":"2026-06-20T15:53:30.739Z","0.3.0":"2026-06-21T10:04:17.394Z","0.4.0":"2026-06-21T16:22:35.539Z","0.4.2":"2026-06-21T17:35:03.710Z","0.5.1":"2026-09-19T20:47:21.217Z","0.5.2":"2026-09-26T11:48:42.417Z"},"bugs":{"url":"https://github.com/artislismanis/eleventy-plugin-themer/issues"},"author":{"name":"Artis Lismanis"},"license":"MIT","homepage":"https://github.com/artislismanis/eleventy-plugin-themer/tree/main/packages/themes/base#readme","keywords":["eleventy","eleventy-theme","11ty","blog-theme","blog-template","feature-system"],"repository":{"url":"git+https://github.com/artislismanis/eleventy-plugin-themer.git","type":"git","directory":"packages/themes/base"},"description":"A minimal convention-based Eleventy theme with self-describing metadata and extensible features","maintainers":[{"name":"artislismanis","email":"artis@lismanis.uk"}],"readme":"# @eleventy-plugin-themer/theme-base\n\nA blog theme for Eleventy built on `@eleventy-plugin-themer/core`. A port of [eleventy-base-blog](https://github.com/11ty/eleventy-base-blog) with dark mode, configurable styling, and extensible features.\n\n## Features\n\n- **Cascade System** - User files override theme files (layouts, data, assets, features)\n- **@theme Alias** - Clean imports in Nunjucks templates: `{% extends \"@theme/layouts/base.njk\" %}`\n- **Dark Mode** - Configurable light/dark toggle with system preference support\n- **Extensible Features** - Self-contained feature modules loaded per-page via front matter\n- **CSS Custom Properties** - Easy theming via variables for colors, typography, spacing\n- **Configurable** - Override theme defaults via `theme.config.mjs`\n\n## Installation\n\n```bash\nnpm install @eleventy-plugin-themer/core @eleventy-plugin-themer/theme-base @11ty/eleventy-plugin-syntaxhighlight\n```\n\nWith Vite build optimizations:\n\n```bash\nnpm install -D @eleventy-plugin-themer/build-vite @11ty/eleventy-plugin-vite\n```\n\n## Quick Start\n\n```js\n// eleventy.config.mjs\nimport { eleventyPluginThemer } from '@eleventy-plugin-themer/core';\n\nconst THEME_NAME = '@eleventy-plugin-themer/theme-base';\n\nexport default async function (eleventyConfig) {\n  const __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n  const { dir } = await eleventyPluginThemer(eleventyConfig, {\n    theme: THEME_NAME,\n    projectRoot: __dirname,\n    input: 'content',\n    output: '_site',\n  });\n\n  return { dir };\n}\n```\n\nSee the [eleventy-starter](https://github.com/artislismanis/eleventy-starter) repository for a complete working example.\n\n## Project Structure\n\n```\nyour-project/\n├── eleventy.config.mjs   # Theme + plugin configuration\n├── content/              # Your content\n│   ├── index.md\n│   ├── posts/\n│   └── _data/\n│       ├── site.js       # Site metadata\n│       └── theme.js      # Theme config overrides\n├── overrides/            # Customizations\n│   ├── layouts/          # Override/extend theme layouts\n│   ├── features/         # Custom or overridden features\n│   ├── scripts/\n│   │   └── main.js       # Your JavaScript entry point\n│   └── styles/           # Your styles\n└── public/               # Static assets (favicon, etc.)\n```\n\n## Theme Configuration\n\nOverride theme defaults by creating `theme.config.mjs`:\n\n```js\nexport default {\n  themeToggle: {\n    defaultTheme: 'auto', // 'auto', 'light', or 'dark'\n    showToggle: true,\n  },\n  colors: {\n    // Grayscale theme with a single reddish-plum accent. Links are grayscale and\n    // light up to the accent on hover (linkHover defaults to the accent).\n    light: {\n      background: '#ffffff',\n      primary: '#1a1a1a',\n      accent: '#9b3b54',\n      text: '#262626',\n      link: '#1a1a1a',\n      linkHover: '#9b3b54',\n      linkVisited: '#595959',\n    },\n    dark: {\n      background: '#171717',\n      primary: '#f5f5f5',\n      accent: '#9b3b54',\n      text: '#e5e5e5',\n      link: '#fafafa',\n      linkHover: '#9b3b54',\n      linkVisited: '#a3a3a3',\n    },\n  },\n  typography: {\n    fontFamily: '-apple-system, system-ui, sans-serif',\n    fontFamilyHeading: 'inherit',\n    fontFamilyMono: \"'Consolas', 'Monaco', monospace\",\n  },\n  logos: {\n    default: '',\n    dark: '',\n    favicon: '/favicon.svg',\n  },\n  social: [],\n  footer: {\n    copyright: '{year} {site.title}', // supports {year} and {site.title}\n    startYear: null, // e.g. 2024 -> renders a \"2024–<current>\" range\n    alignment: 'center', // footer-bottom row: 'left' | 'center' | 'right'\n    showPoweredBy: true, // \"Built with Eleventy\" line\n    showGitSha: true, // short commit hash (see Build metadata below)\n    gitHubRepo: '', // e.g. 'https://github.com/you/repo' -> links the commit\n  },\n};\n```\n\nAll config values are deeply merged with the theme's defaults from `theme.json`. Use `null` to explicitly clear a value.\n\n`footer.alignment` controls only the bottom row (copyright / \"Built with\" / commit hash); the footer navigation (menu + social links) layout is unaffected.\n\n## Customization\n\n### Override Layouts\n\nReplace a theme layout:\n\n```nunjucks\n{# overrides/layouts/post.njk - completely replaces theme's post.njk #}\n<article>\n  <h1>{{ title }}</h1>\n  {{ content | safe }}\n</article>\n```\n\nExtend a theme layout:\n\n```nunjucks\n{# overrides/layouts/custom.njk #}\n{% extends \"@theme/layouts/base.njk\" %}\n\n{% block content %}\n  <div class=\"custom\">{{ content | safe }}</div>\n{% endblock %}\n```\n\n### Override Data\n\nCreate `content/_data/site.mjs` to replace theme's site data:\n\n```js\nexport default defineSiteData({\n  title: 'My Blog',\n  url: 'https://myblog.com',\n  language: 'en',\n  author: { name: 'Your Name', email: 'you@example.com' },\n  social: [{ platform: 'github', account: 'your-handle' }],\n});\n```\n\n### Override Static Assets\n\nPlace files in `public/` to override theme assets:\n\n```\npublic/\n├── favicon.svg       # Overrides theme's favicon\n└── logo.png          # Your custom asset\n```\n\n## Features\n\nFeatures are optional functionality modules loaded per-page via front matter.\n\n### Using Features\n\nAdd to any page's front matter:\n\n```yaml\n---\ntitle: My Post\nfeature: code-highlighting\n---\n```\n\n### Available Theme Features\n\n#### code-highlighting\n\nSyntax highlighting powered by PrismJS (via `@11ty/eleventy-plugin-syntaxhighlight`). Includes copy button, optional line numbers, diff highlighting, and custom scrollbar.\n\n**Usage** — add to any page's front matter:\n\n```yaml\n---\nfeature: code-highlighting\n---\n```\n\n**Configuration** — override in `theme.config.mjs`:\n\n```js\nexport default {\n  codeHighlighting: {\n    prismTheme: 'prism-tomorrow', // PrismJS theme name (default)\n    diffHighlight: true, // Include diff-highlight plugin (default)\n  },\n};\n```\n\n**Available PrismJS themes:**\n\n| Theme                  | Style                                   |\n| ---------------------- | --------------------------------------- |\n| `prism`                | Light, minimal (Lea Verou's default)    |\n| `prism-coy`            | Light with subtle left border           |\n| `prism-solarizedlight` | Light, Solarized palette                |\n| `prism-dark`           | Dark, muted tones                       |\n| `prism-funky`          | Dark with coloured line backgrounds     |\n| `prism-okaidia`        | Dark, Monokai-inspired                  |\n| `prism-tomorrow`       | Dark, Tomorrow Night Eighties (default) |\n| `prism-twilight`       | Dark, warm greys                        |\n\n**Diff highlighting** — use the `diff-` language prefix with `+`/`-` line markers:\n\n````markdown\n```diff-js\n+const added = true;\n-const removed = false;\n const unchanged = null;\n```\n````\n\n**CSS custom properties** — enhancements on top of PrismJS (override in your own CSS):\n\n| Property                    | Default                  | Description                   |\n| --------------------------- | ------------------------ | ----------------------------- |\n| `--code-border-radius`      | `0.5rem`                 | Border radius for code blocks |\n| `--code-copy-button-bg`     | `var(--color-surface)`   | Copy button background        |\n| `--code-copy-button-fg`     | `var(--color-text)`      | Copy button text colour       |\n| `--code-line-number-fg`     | `rgb(255 255 255 / 30%)` | Line number colour            |\n| `--code-line-number-width`  | `3rem`                   | Line number column width      |\n| `--code-scrollbar-thumb-bg` | `rgb(255 255 255 / 20%)` | Scrollbar thumb colour        |\n\n#### back-to-top\n\nA floating button that appears once the page is scrolled past a threshold and\nsmooth-scrolls back to the top. Fully self-contained (no template or data\ndependencies).\n\n**Usage** — add to any page's front matter:\n\n```yaml\n---\nfeature: back-to-top\n---\n```\n\n**Customization** — import and call `init()` manually instead of using the\nauto-init variant:\n\n```js\nimport { init, defaultConfig } from '@theme/features/back-to-top/index.js';\ninit({ ...defaultConfig, threshold: 800 });\n```\n\n**CSS custom properties** (override in your own CSS):\n\n| Property               | Default                   | Description          |\n| ---------------------- | ------------------------- | -------------------- |\n| `--back-to-top-bg`     | `var(--color-primary)`    | Button background    |\n| `--back-to-top-fg`     | `var(--color-background)` | Glyph colour         |\n| `--back-to-top-size`   | `2.75rem`                 | Button width/height  |\n| `--back-to-top-offset` | `1.5rem`                  | Distance from corner |\n\n### Creating Custom Features\n\nCreate `overrides/features/my-feature/index.js` (or `index.auto.js` for auto-initialization):\n\n```js\n// index.auto.js - auto-initializes when loaded\nconsole.log('My custom feature loaded');\n```\n\nIf both `index.auto.js` and `index.js` exist in the same directory, the\nplugin picks `index.auto.js` first. Use `index.auto.js` for self-running\nfeatures and `index.js` for ones the consumer imports and initializes\nexplicitly.\n\nThen reference in front matter: `feature: my-feature`\n\n### Overriding Theme Features\n\nCreate `overrides/features/code-highlighting/index.auto.js` to replace the theme's version.\n\n## Shortcodes\n\n### Hero Section\n\n```nunjucks\n{% hero title=\"Welcome\", subtitle=\"Build beautiful websites\", align=\"center\", height=\"400px\" %}\n  {% heroButton url=\"/start\", variant=\"primary\" %}Get Started{% endheroButton %}\n  {% heroButton url=\"/learn\", variant=\"secondary\" %}Learn More{% endheroButton %}\n{% endhero %}\n```\n\n| Parameter         | Description                               | Default    |\n| ----------------- | ----------------------------------------- | ---------- |\n| `title`           | Main heading                              | -          |\n| `subtitle`        | Secondary text                            | -          |\n| `background`      | Background image URL                      | -          |\n| `backgroundColor` | Background color (fallback)               | -          |\n| `align`           | Text alignment: `left`, `center`, `right` | `'center'` |\n| `height`          | Minimum height                            | `'auto'`   |\n| `overlay`         | Dark overlay on background image          | `true`     |\n\n### Content Grid\n\n```nunjucks\n{% contentGrid cols=3, gap=\"1.5rem\" %}\n  {% box title=\"Feature 1\", link=\"/about\", linkText=\"Learn More\" %}\n    Description of feature 1.\n  {% endbox %}\n{% endcontentGrid %}\n```\n\n## Navigation\n\nUses `@11ty/eleventy-navigation` for menus. Add pages via front matter:\n\n```yaml\n---\neleventyNavigation:\n  key: About\n  order: 2\n---\n```\n\nFooter navigation uses `parent: footer`. Hierarchical pages get automatic breadcrumbs.\n\n## Build metadata\n\nThe theme provides a `build` global with the current git commit and a build timestamp,\nso the footer commit hash works without any setup on your side:\n\n| Field               | Example          |\n| ------------------- | ---------------- |\n| `build.gitSha`      | full commit SHA  |\n| `build.gitShaShort` | 7-char short SHA |\n| `build.timestamp`   | ISO build time   |\n\nIt runs `git rev-parse HEAD` in your project at build time (falling back to\n`unknown`/`dev` outside a git repo). The footer shows `build.gitShaShort` when\n`footer.showGitSha` is enabled, linking to the commit if `site.repository` is set.\n\nTo override (e.g. inject a CI build number), provide your own\n`content/_data/build.js` — Eleventy's directory data takes precedence over the\ntheme's global data.\n\n## Social links\n\nConfigure social links via the `social` array in `content/_data/site.mjs` (social is\nsite data, not theme config). Each entry needs a `platform` plus **either** an `account`\n(expanded through a URL template) **or** a full `url`:\n\n```js\nexport default defineSiteData({\n  social: [\n    { platform: 'github', account: 'artislismanis' },\n    { platform: 'mastodon', url: 'https://fosstodon.org/@you' },\n    { platform: 'linkedin', account: 'your-handle', label: 'LinkedIn' },\n  ],\n});\n```\n\n- `account` is expanded by core's `socialUrl` filter using the framework's\n  `SOCIAL_PLATFORMS` table (`github`, `x`, `linkedin`, `youtube`, `instagram`, `facebook`,\n  `tiktok`, `discord`, `twitch`, `reddit`, `bluesky`, `mastodon`). Themes may extend it via\n  `theme.json#socialPlatforms`. Mastodon also accepts an `@user@instance` account.\n- `url` takes precedence over `account` and is validated by `safeUrl` (see Security\n  helpers).\n- `label` is optional (used for the `aria-label`); it defaults to the capitalized\n  platform name.\n\n### Icons\n\nIcons are inline brand SVGs from [`simple-icons`](https://www.npmjs.com/package/simple-icons),\nrendered with `fill=\"currentColor\"` so they inherit the link colour (grey, plum on hover).\n**The `platform` value must match a simple-icons _slug_.** Browse and search slugs at\n**[simpleicons.org](https://simpleicons.org/)** — e.g. the \"GitHub\" tile has the slug\n`github`, \"X\" has `x`. The resolution order per link is:\n\n1. `social.icon` — a custom image path you provide (per-link override, wins over everything)\n2. the `simple-icons` brand SVG matched by slug\n3. a plain **text** label fallback when no icon is found\n\nSpecial cases handled in `lib/filters.mjs`:\n\n- **`twitter` is aliased to the `x` slug** (the Twitter glyph was retired upstream), so\n  legacy config keeps working.\n- A few brands have been **removed from simple-icons** at the owner's request (notably\n  **LinkedIn**). The theme ships fallback glyphs for those in the `SUPPLEMENTAL_ICON_PATHS`\n  map in `lib/filters.mjs` — add an entry there (keyed by slug, 24×24 path data) to cover\n  any other removed brand, or override `overrides/layouts/partials/social/icon.njk` to\n  fully customise rendering.\n\n## Security helpers\n\nNunjucks runs with `autoescape: false` in this framework, so the theme exports a set of escape filters that **must** be applied explicitly to any dynamic value:\n\n| Filter           | Use for                                                                 |\n| ---------------- | ----------------------------------------------------------------------- |\n| `escapeHtml`     | Text in HTML body context                                               |\n| `escapeAttr`     | Values inside `=\"…\"` attributes                                         |\n| `escapeCssValue` | CSS custom-property values (strips quotes, brackets, `;`, `\\`, `/* */`) |\n| `escapeJsString` | Values inside JS string literals (escapes `</script>`, U+2028/9, etc.)  |\n| `safeUrl`        | Values used as `href` / `src`                                           |\n\n`safeUrl()` and the related `socialUrl()` filter use a strict scheme **allowlist** (`http`, `https`, `mailto`, `tel`, plus relative URLs). Everything else returns `#`. The filter also strips control / zero-width / bidi-override chars, rejects `https:\\/\\/` backslash-authority forms, and blocks percent-encoded CR/LF in `mailto:` / `tel:` (header smuggling).\n\n## Related Packages\n\n- [@eleventy-plugin-themer/core](../../core/README.md) - Build-agnostic cascade system\n- [@eleventy-plugin-themer/build-vite](../../build/vite/README.md) - Vite production optimizations\n\n## License\n\nMIT\n","readmeFilename":"README.md"}