{"id":50743313,"url":"https://github.com/cloud-gov/eleventy-preset","last_synced_at":"2026-06-10T18:32:32.289Z","repository":{"id":359407145,"uuid":"1245118677","full_name":"cloud-gov/eleventy-preset","owner":"cloud-gov","description":"Shared Eleventy v3 preset for Studio-managed USWDS 11ty sites","archived":false,"fork":false,"pushed_at":"2026-06-09T16:54:22.000Z","size":665,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T18:22:38.974Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloud-gov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-20T23:42:51.000Z","updated_at":"2026-06-09T17:02:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cloud-gov/eleventy-preset","commit_stats":null,"previous_names":["cloud-gov/eleventy-preset"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/cloud-gov/eleventy-preset","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Feleventy-preset","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Feleventy-preset/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Feleventy-preset/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Feleventy-preset/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloud-gov","download_url":"https://codeload.github.com/cloud-gov/eleventy-preset/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Feleventy-preset/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34165482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-10T18:32:32.083Z","updated_at":"2026-06-10T18:32:32.276Z","avatar_url":"https://github.com/cloud-gov.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @studio/eleventy-preset\n\nShared Eleventy v3 preset for Studio-managed USWDS 11ty sites. Helps centralizes\nthe reusable build and configuration layer while site repos keep site metadata,\ncontent, CMS schemas, search indexing, deployment settings, and one-off\ncollections local.\n\n## Features\n\n- 🧱 Common dependency ownership for USWDS, Decap CMS, and shared Eleventy utilities.\n- 🔌 Eleventy plugins for navigation, image transforms, RSS, HTML base URL handling,\n  and USWDS sprites.\n- 🎨 Asset pipeline for Sass, JavaScript bundling, USWDS font/image copying,\n  production minification, autoprefixing, and watch-mode rebuilds.\n- 🧩 Shared shortcodes for USWDS icons, YouTube embeds, and optional responsive\n  image helpers.\n- 📚 Built-in YAML data support and a reusable `postsByYear` collection helper.\n- 🚀 Single `studio-eleventy` CLI for build and dev server.\n\n## Creating a New Site\n\n\u003cdetails\u003e\n\u003csummary\u003eShow setup instructions\u003c/summary\u003e\n\nThese steps create a small Eleventy site that uses the preset for Eleventy\nconfiguration, USWDS assets, Sass and JavaScript builds, shared shortcodes, and\nDecap CMS runtime ownership.\n\n### 1. Create the Site Folder\n\n```sh\nmkdir new-site\ncd new-site\nnpm init -y\n```\n\n### 2. Install the Site Dependencies\n\nInstall the preset from the tagged GitHub release:\n\n```sh\nnpm install --save @studio/eleventy-preset@github:cloud-gov/eleventy-preset#v0.3.0\nnpm install --save-dev @11ty/eleventy\n```\n\nThe site should not install `@uswds/uswds` or `decap-cms`\ndirectly unless it has a proven site-specific direct import. The preset owns\nthose runtime packages.\n\n### 3. Add Package Scripts\n\nAdd scripts like these to the site's `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"build\": \"studio-eleventy build\",\n    \"dev\": \"studio-eleventy dev\",\n    \"pages\": \"studio-eleventy build\"\n  }\n}\n```\n\n`npm run dev` is the local development command. The deployed Pages build should\nrun `npm run pages`, which runs the same preset-owned production build.\nBoth `build` and `dev` clear Eleventy's output directory before the initial\ngeneration, removing stale files from the default `_site` directory.\n\n### 4. Add Eleventy Configuration\n\nCreate `.eleventy.js`:\n\n```js\nmodule.exports = async function (config) {\n  const { default: studioPreset } = await import(\"@studio/eleventy-preset\");\n\n  await studioPreset(config, {\n    // Example: enable optional Eleventy RSS support.\n    // features: { rss: true },\n    // Example: override the default passthrough copy list.\n    // passthroughCopy: [\"admin\", \"favicon.ico\", \"img\"],\n    // Example: disable the default posts-by-year collection helper.\n    // collections: { postsByYear: { enabled: false } },\n  });\n};\n```\n\n### 5. Add the Minimum File Structure\n\nCreate these folders and files:\n\n```text\n_data/site.yaml\n_includes/layouts/base.html\nadmin/index.html\nindex.md\njs/admin.js\njs/app.js\njs/uswds-init.js\nstyles/styles.scss\n```\n\n### 6. Add Site Data\n\nCreate `_data/site.yaml`:\n\n```yaml\ntitle: New Site\ndescription: A new Eleventy and USWDS site.\n```\n\nSite metadata stays local to the site. Add navigation, contact data, CMS\nsettings, and content-specific data here or in other local `_data` files.\n\n### 7. Add a Base Layout\n\nCreate `_includes/layouts/base.html`:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\" /\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /\u003e\n    \u003ctitle\u003e{{ title | default: site.title }}\u003c/title\u003e\n    \u003clink rel=\"stylesheet\" href=\"{{ '/assets/styles/styles.css' | url }}\" /\u003e\n    \u003cscript src=\"{{ '/assets/js/uswds-init.js' | url }}\"\u003e\u003c/script\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ca class=\"usa-skipnav\" href=\"#main-content\"\u003eSkip to main content\u003c/a\u003e\n    \u003cmain id=\"main-content\" class=\"grid-container usa-section\"\u003e\n      {{ content }}\n    \u003c/main\u003e\n    \u003cdiv style=\"display: none\"\u003e\n      {% usa_icons_sprite %} {% uswds_icons_sprite %}\n    \u003c/div\u003e\n    \u003cscript src=\"{{ '/assets/js/app.js' | url }}\"\u003e\u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n### 8. Add a Home Page\n\nCreate `index.md`:\n\n```md\n---\nlayout: layouts/base.html\ntitle: New Site\n---\n\n# New Site\n\nThis site is using Eleventy, USWDS, and `@studio/eleventy-preset`.\n```\n\n### 9. Add JavaScript Entry Points\n\nCreate `js/app.js`:\n\n```js\nrequire(\"@studio/eleventy-preset/uswds\");\n```\n\nCreate `js/uswds-init.js`:\n\n```js\nrequire(\"@studio/eleventy-preset/uswds-init\");\n```\n\nCreate `js/admin.js`:\n\n```js\nimport CMS from \"@studio/eleventy-preset/admin\";\n\nCMS.init();\n```\n\n### 10. Add Admin HTML\n\nCreate `admin/index.html` if the site will use Decap CMS:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\" /\u003e\n    \u003ctitle\u003eContent Manager\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cscript src=\"/assets/js/admin.js\"\u003e\u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nKeep `admin/config.yml`, collections, media folders, editorial workflow\nsettings, and custom CMS registrations local to the site.\n\nThe preset admin entry automatically registers the shared USWDS Accordion and\nUSWDS Card Group editor components before `CMS.init()`. Sites using\n`@studio/eleventy-preset/admin` do not need custom registration code or\n`admin/config.yml` changes for these components.\n\n### 11. Add Sass\n\nCreate `styles/styles.scss`:\n\n```scss\n@use \"uswds-core\" as * with (\n  $theme-show-compile-warnings: false,\n  $theme-show-notifications: false,\n  $theme-font-path: \"../uswds/fonts\",\n  $theme-image-path: \"../uswds/img\"\n);\n\n@forward \"uswds\";\n```\n\nThe preset automatically adds the preset-owned USWDS Sass load paths and copies\nUSWDS fonts and images to `/assets/uswds/...`.\n\n### 12. Build the Site\n\nRun:\n\n```sh\nnpm run build\n```\n\nExpected output includes:\n\n```text\n_site/assets/js/app.js\n_site/assets/js/admin.js\n_site/assets/js/uswds-init.js\n_site/assets/styles/styles.css\n_site/assets/uswds/fonts/\n_site/assets/uswds/img/\n```\n\nUse `npm run dev` for local development.\n\n\u003c/details\u003e\n\n## Eleventy Preset Options\n\nMost sites can call `await studioPreset(config);` without passing options. When\na site needs to override preset behavior, pass a second argument. This example\nshows the public options with their default values.\n\n```js\nmodule.exports = async function (config) {\n  const { default: studioPreset } = await import(\"@studio/eleventy-preset\");\n\n  await studioPreset(config, {\n    features: {\n      htmlBase: true, // false skips Eleventy's HTML base plugin.\n      imageShortcodes: false, // true enables image, image_with_class, and image_with_caption.\n      imageTransform: true, // false skips @11ty/eleventy-img transforms.\n      navigation: true, // false skips @11ty/eleventy-navigation.\n      rss: false, // true enables @11ty/eleventy-plugin-rss.\n    },\n\n    passthroughCopy: [\n      \"admin\",\n      \"uploads\",\n      \"favicon.ico\",\n      \"site.webmanifest\",\n      \"img\",\n    ], // Replace for a different static-file layout.\n    watchTargets: [\"styles\", \"js\"], // Replace when extra Eleventy watch paths are needed.\n\n    markdown: {\n      html: true, // false escapes HTML in Markdown content.\n      breaks: false, // true converts single line breaks to \u003cbr\u003e tags.\n      linkify: true, // false disables automatic links for plain URLs.\n      typographer: false, // true enables Markdown It's typographic replacements.\n      namedHeadings: true, // false disables markdown-it-named-headings.\n      pdfLinksNewWindow: false, // true opens Markdown PDF links in a new window.\n      markdownFilterName: \"markdownify\", // Change to rename the Markdown rendering filter.\n    },\n\n    imageTransform: {\n      failOnError: false, // true fails the build when image transforms fail.\n      widths: [\"auto\", 600], // Change to generate a different responsive image set.\n      htmlOptions: {\n        imgAttributes: {\n          loading: \"lazy\", // Change for eager images.\n          decoding: \"async\", // Change when synchronous decoding is required.\n        },\n        pictureAttributes: {}, // Add attributes for generated \u003cpicture\u003e elements.\n        fallback: \"largest\", // Change to use a different transform plugin fallback.\n      },\n    },\n\n    collections: {\n      postsByYear: {\n        enabled: true, // false disables this grouped archive collection.\n        tag: \"press-release\", // Change to group a different tagged collection.\n        name: \"postsByYear\", // Change to expose the collection under a different name.\n      },\n    },\n\n    imageShortcodes: {\n      outputDir: \"./_site/img/\", // Change where shortcode-generated images are written.\n      includeCaption: false, // true also enables image_with_caption.\n    },\n  });\n};\n```\n\n## Runtime Entry Points\n\nThe preset also exposes browser entry modules for USWDS and Decap CMS JavaScript bundles:\n\n- `@studio/eleventy-preset/uswds`\n- `@studio/eleventy-preset/uswds-init`\n- `@studio/eleventy-preset/admin`\n\n## USWDS Accordion Editor Component\n\nSites on `@studio/eleventy-preset` v0.3.0 or later get a Decap CMS Markdown\neditor component labeled `USWDS Accordion` automatically through:\n\n```js\nimport CMS from \"@studio/eleventy-preset/admin\";\n\nCMS.init();\n```\n\nAfter updating to v0.3.0, rebuild the site admin bundle so the preset admin\nentry includes the component registration.\n\nSupported fields:\n\n- `bordered`: boolean, default `false`\n- `allow_multiple`: boolean, default `false`\n- `items`: list of accordion items\n- item `title`: string\n- item `content`: Markdown\n- item `open`: boolean, default `false`\n\nThe editor saves a re-editable Liquid paired shortcode block with YAML instead\nof generated HTML:\n\n```liquid\n{% uswds_accordion bordered=false allow_multiple=false %}\nitems:\n  - title: \"First item\"\n    open: false\n    content: |-\n      Markdown body.\n{% enduswds_accordion %}\n```\n\nItem content is rendered as Markdown only. Embedded Liquid tags, Liquid output,\nand shortcodes inside item content are preserved as text and are not executed.\n\n## USWDS Card Group Editor Component\n\nSites using `@studio/eleventy-preset/admin` get a Decap CMS Markdown editor\ncomponent labeled `USWDS Card Group` automatically:\n\n```js\nimport CMS from \"@studio/eleventy-preset/admin\";\n\nCMS.init();\n```\n\nRebuild the site admin bundle after updating the preset so the preset admin\nentry includes the component registration. No site-specific registration code\nor `admin/config.yml` change is required.\n\nSupported fields:\n\n- `cards`: list of cards\n- card `heading`: optional string\n- card `content`: optional Markdown\n- card `image.src`: optional image URL or path\n- card `image.alt`: optional alt text\n- card `button.label`: optional primary button label\n- card `button.href`: optional primary button URL or path\n- card `link.label`: optional secondary link label\n- card `link.href`: optional secondary link URL or path\n\nThe editor saves a re-editable Liquid paired shortcode block with readable YAML\ninstead of generated HTML:\n\n```liquid\n{% uswds_card_group %}\ncards:\n  - heading: \"Card heading\"\n    content: |-\n      Markdown body.\n    image:\n      src: \"/uploads/example.jpg\"\n      alt: \"Descriptive alt text\"\n    button:\n      label: \"Primary action\"\n      href: \"/example/\"\n    link:\n      label: \"Secondary link\"\n      href: \"/example/details/\"\n{% enduswds_card_group %}\n```\n\nNew cards start with empty optional fields. Empty fields are omitted from the\nsaved YAML; an entirely empty card is saved as `{}` and does not add placeholder\nheading, body, image, button, or link text.\n\nCard body content is rendered as Markdown only. Embedded Liquid tags, Liquid\noutput, shortcodes, and raw HTML inside card content are preserved as text and\nare not executed.\n\nDuring Eleventy rendering, missing optional fields omit their USWDS wrappers:\nheaders render only when a heading exists, media renders only when an image\nsource exists, body renders only when content exists, and footer renders only\nwhen a button or secondary link exists. Card class controls are not exposed to\neditors; every rendered card uses\n`class=\"usa-card tablet:grid-col-6 desktop:grid-col-4\"`.\n\n## Releasing\n\nReleases are created from `main` after a release-prep PR is merged.\n\nDo not manually create or push release tags from the command line for normal\nreleases. Use the `Release` GitHub Actions workflow.\n\nThe release workflow does not bump versions or commit changes to `main`.\nVersion bumps must happen through a normal release-prep branch and PR before\nthe release workflow is run.\n\n### 1. Create a release branch\n\n```sh\ngit switch main\ngit pull\ngit switch -c release/v0.3.0\n```\n\n### 2. Bump the package version\n\n```sh\nnpm version 0.3.0 --no-git-tag-version\n```\n\nThis updates both:\n\n- `package.json`\n- `package-lock.json`\n\nConfirm both files contain the exact version being released.\n\n### 3. Run tests\n\n```sh\nnpm test\n```\n\n### 4. Update docs if needed\n\nUpdate README examples, install instructions, or release-related documentation\nif they reference the previous version.\n\n### 5. Commit and open a PR\n\n```sh\ngit add package.json package-lock.json README.md\ngit commit -m \"Prepare release v0.3.0\"\ngit push -u origin release/v0.3.0\n```\n\nOpen a PR into `main`.\n\n### 6. Merge the PR\n\nAfter review and passing tests, merge the PR.\n\n### 7. Run the release workflow\n\nIn GitHub:\n\n1. Go to **Actions**.\n2. Select **Release**.\n3. Click **Run workflow**.\n4. Select the `main` branch.\n5. Enter the version without the `v` prefix, for example `0.3.0`.\n6. Choose whether this is a prerelease.\n7. Run the workflow.\n\nThe workflow will:\n\n- Install dependencies.\n- Run `npm test`.\n- Confirm it is running from `main`.\n- Confirm `package.json` and `package-lock.json` match the requested version.\n- Confirm the release tag does not already exist.\n- Create an annotated tag named `v\u003cversion\u003e`.\n- Push the tag.\n- Create a GitHub Release with generated notes.\n\n### Troubleshooting\n\nIf the workflow fails because the package versions do not match, create a\nrelease-prep PR that updates both `package.json` and `package-lock.json`.\n\nIf the workflow fails because the tag already exists, do not overwrite the tag.\nInvestigate whether the release already happened or whether the tag was created\nmanually by mistake.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-gov%2Feleventy-preset","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloud-gov%2Feleventy-preset","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-gov%2Feleventy-preset/lists"}