Zach’s ugly mug (his face) Zach Leat­herman

Copy *and* Paste? …in this Economy?

October 28, 2025 00

Astute visitors to the Eleventy Documentation will notice something new on the code blocks on the site.

A wild copy-to-clipboard component has appeared:

This feature been a long time coming and is our first use of Web Awesome on the docs (via the <wa-copy-button> custom element). Take special note of the unparalleled synergy of the Font Awesome icon used by the Web Awesome component used on the Eleventy docs.

  • Progressive Enhancement behavior: this is a JavaScript-only feature and has no before/without JavaScript experience. You might call this a JavaScript Web Component.
  • Performance-focused:

Usage

Direct from CDN

There are a few ways to use the Copy Button component stock, with the easiest being to load the script directly from the CDN, like so (via jsdelivr):

<script type="module" src="https://cdn.jsdelivr.net/npm/@awesome.me/webawesome@3.0.0/dist-cdn/components/copy-button/copy-button.js"></script>

Or via unpkg:

<script type="module" src="https://unpkg.com/@awesome.me/webawesome@3.0.0/dist-cdn/components/copy-button/copy-button.js"></script>

Bundling

For this implementation we used esbuild to create a focused bundle for the single Web Awesome component (though this esbuild code would work for any JavaScript file).

We went with this method for improved runtime performance and to reduce the number of third-party dependencies on the web site (with a nod to André Jaenisch). You can do the same with the following bit of Eleventy configuration (e.g. in a eleventy.config.js file):

// eleventy.config.js
// don’t forget to `npm install esbuild -D`
import esbuild from "esbuild";
import { fileURLToPath } from "node:url";

async function esbuildToFile(entryPoints, outfile, options = {}) {
	return esbuild.build(Object.assign({
		entryPoints,
		platform: "browser",
		format: "esm",
		bundle: true,
		minify: true,
		banner: {
			js: `/* via ${entryPoints} */`,
		},
		outfile,
	}, options));
}

async function bundleModuleToFile(modulePath, outfile) {
	let sourcefile = fileURLToPath(import.meta.resolve(modulePath));
	return esbuildToFile([ sourcefile ], outfile);
}

export default async function(eleventyConfig) {
	let outfile = path.join(eleventyConfig.directories.output, "js/copy-button.js");

	// This will run once per build/serve/watch
	// (not with subsequent builds, save for config file changes)
	await bundleModuleToFile("@awesome.me/webawesome/dist/components/copy-button/copy-button.js", outfile);
}

Markdown Code Block Wrappers

This task also served as the impetus for fixes related to wrapper elements around code blocks in Markdown, documented in the previous blog post on this very web site.


Older >
Permanent Facepile Credit to Individuals Supporting Eleventy

Zach Leatherman IndieWeb Avatar for https://zachleat.com/is a builder for the web at Font Awesome and the creator/maintainer of IndieWeb Avatar for https://www.11ty.devEleventy (11ty), an award-winning open source site generator. At one point he became entirely too fixated on web fonts. He has given 86 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of CloudCannon, Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »

Shamelessly plug your related post

These are webmentions via the IndieWeb and webmention.io.

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)

Post published and built