Eleventy Quick Tips
All of the official Eleventy Quick Tips, in feed form.
2023-01-24T00:00:00Z
https://www.11ty.dev/
Zach Leatherman
zach@zachleat.com
Quick Tip #011—Draft Posts using Computed Data
2023-01-24T00:00:00Z
https://www.11ty.dev/docs/quicktips/draft-posts/
<p>Here’s a quick snippet that shows how to combine Eleventy’s <a href="https://www.11ty.dev/docs/data-global-custom/">Configuration API Global Data</a> and <a href="https://www.11ty.dev/docs/data-computed/">Computed Data</a> features in your Eleventy Configuration file to implement a simple drafts feature for any piece of content.</p>
<p>Set <code>draft: true</code> anywhere in a file’s <a href="https://www.11ty.dev/docs/data-cascade/">data cascade</a> and that file will be <em>only</em> be built when using Eleventy in <code>--serve</code> or <code>--watch</code> modes. It will be excluded from full Eleventy builds.</p>
<p>You might imagine how this could be extended to add a publishing date feature too: to exclude content from builds before a specific date set in a post’s front matter (or elsewhere in the data cascade).</p>
<div class="codetitle codetitle-left"><b>Filename </b>.eleventy.js</div>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token comment">// When `permalink` is false, the file is not written to disk</span><br> eleventyConfig<span class="token punctuation">.</span><span class="token function">addGlobalData</span><span class="token punctuation">(</span><span class="token string">"eleventyComputed.permalink"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token comment">// Always skip during non-watch/serve builds</span><br> <span class="token keyword">if</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span>draft <span class="token operator">&&</span> <span class="token operator">!</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">BUILD_DRAFTS</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">return</span> data<span class="token punctuation">.</span>permalink<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token comment">// When `eleventyExcludeFromCollections` is true, the file is not included in any collections</span><br> eleventyConfig<span class="token punctuation">.</span><span class="token function">addGlobalData</span><span class="token punctuation">(</span><span class="token string">"eleventyComputed.eleventyExcludeFromCollections"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token comment">// Always exclude from non-watch/serve builds</span><br> <span class="token keyword">if</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span>draft <span class="token operator">&&</span> <span class="token operator">!</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">BUILD_DRAFTS</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">return</span> data<span class="token punctuation">.</span>eleventyExcludeFromCollections<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> eleventyConfig<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"eleventy.before"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>runMode<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token comment">// Set the environment variable</span><br> <span class="token keyword">if</span><span class="token punctuation">(</span>runMode <span class="token operator">===</span> <span class="token string">"serve"</span> <span class="token operator">||</span> runMode <span class="token operator">===</span> <span class="token string">"watch"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">BUILD_DRAFTS</span> <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2 id="related" tabindex="-1">Related <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/draft-posts/#related">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<ul>
<li>You can see the <a href="https://github.com/11ty/eleventy-base-blog/blob/851eafdc4c3a612142e0e6ae84f54cb0f0eb98b1/eleventy.config.drafts.js">above code in action on the <code>eleventy-base-blog</code> project</a></li>
<li><a href="https://www.11ty.dev/docs/permalinks/#skip-writing-to-the-file-system">Skip Writing to the File System with <code>permalink: false</code></a></li>
<li><a href="https://www.11ty.dev/docs/collections/#how-to-exclude-content-from-collections">How to exclude content from collections with <code>eleventyExcludeFromCollections</code></a></li>
</ul>
Quick Tip #010—Transform Global Data using an `eleventyComputed.js` Global Data File
2020-11-01T00:00:00Z
https://www.11ty.dev/docs/quicktips/create-multiple-computed-data-elements/
<p>You can generate multiple data cascade elements in one <code>eleventyComputed.js</code> file. Following is a working example.</p>
<p>This example generates data cascade elements from multiple <code>.json</code> files in the global data directory.</p>
<p>Assume you have data files named <code>links.json</code> and <code>copyrights.json</code>, and you only want to extract a portion of the json object. In this case, the <code>entry</code> element contains the useful data in the json object, and is a child of the <code>feed</code> element in this case.</p>
<p>The corresponding <code>eleventyComputed.js</code> file contents can look like the following:</p>
<div class="codetitle codetitle-left"><b>Filename </b>_data/eleventyComputed.js</div>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token function-variable function">myCopyrights</span><span class="token operator">:</span> <span class="token parameter">data</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> data<span class="token punctuation">.</span>copyrights<span class="token punctuation">.</span>feed<span class="token punctuation">.</span>entry<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">,</span><br> <span class="token function-variable function">myLinks</span><span class="token operator">:</span> <span class="token parameter">data</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> data<span class="token punctuation">.</span>links<span class="token punctuation">.</span>feed<span class="token punctuation">.</span>entry<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
Quick Tip #009—Cache Data Requests
2020-04-23T00:00:00Z
https://www.11ty.dev/docs/quicktips/cache-api-requests/
<div class="elv-callout elv-callout-info"><div class="elv-callout-label">INFO:</div><div class="elv-callout-c">
Read the full <a href="https://www.11ty.dev/docs/plugins/fetch/">documentation at the <code>eleventy-fetch</code> plugin page</a>.
</div></div>
<p>In <a href="https://www.11ty.dev/docs/quicktips/eliminate-js/">Quick Tip #007</a>, we described a method to fetch data from an API at build time (in this example it was GitHub Stargazers) to display on your site.</p>
<p>However, if you’re working on your site locally, you probably don’t want every Eleventy build to make a request to an external API call. You’d hit the rate limit pretty quickly (on GitHub, 60 per hour) and each request would slow down your build times!</p>
<p>Now there is an easier way. You can use the <a href="https://www.11ty.dev/docs/plugins/fetch/"><code>eleventy-fetch</code></a> utility to cache these requests to save on both API limits and build performance!</p>
<pre><code>npm install @11ty/eleventy-fetch
</code></pre>
<h2 id="features" tabindex="-1">Features <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/cache-api-requests/#features">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<ul>
<li>Makes at most one network request in the <code>duration</code> time span—save on both your API limit count and your build time!</li>
<li>Easy graceful handling of bad network requests to an API.</li>
<li>If your cache expires and it makes another request, and that request fails—it automatically falls back to the expired cache entry! This is especially useful if you’re developing without a network connection (airplane-driven-development)—your site will work the same as it did with the network connection—no changes required to your local development environment.</li>
</ul>
<h2 id="example" tabindex="-1">Example <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/cache-api-requests/#example">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>This code is currently in use on the Eleventy web site to display GitHub stars in the footer. Check out the <a href="https://github.com/11ty/11ty-website/blob/768b97fb27543e3139fe53dfb19cdeafb12e3d1c/_data/github.js">full source code</a>.</p>
<div class="codetitle codetitle-left"><b>Filename </b>_data/github.js</div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> EleventyFetch <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"@11ty/eleventy-fetch"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token comment">// https://developer.github.com/v3/repos/#get</span><br> <span class="token keyword">let</span> json <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">EleventyFetch</span><span class="token punctuation">(</span><span class="token string">"https://api.github.com/repos/11ty/eleventy"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">duration</span><span class="token operator">:</span> <span class="token string">"1d"</span><span class="token punctuation">,</span> <span class="token comment">// 1 day</span><br> <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"json"</span> <span class="token comment">// also supports "text" or "buffer"</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">stargazers</span><span class="token operator">:</span> json<span class="token punctuation">.</span>stargazers_count<br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<div class="elv-callout elv-callout-info"><div class="elv-callout-label">INFO:</div><div class="elv-callout-c">Take note that if you’re using this on a Netlify build, it will not maintain updates to the cache (as it resets the cache to the files that are checked into git) and will likely re-run every time.
<ul>
<li>Current <a href="https://developer.github.com/v3/#rate-limiting">GitHub rate limits</a> are limited to 60 requests per hour, so this will only be a problem if you do more than 60 Netlify builds in an hour.</li>
<li>The <a href="https://blog.npmjs.org/post/164799520460/api-rate-limiting-rolling-out">npm API doesn’t seem to have a hard limit</a>.</li>
</ul></div></div>
<h3 id="failing-even-more-gracefully" tabindex="-1">Failing Even More Gracefully <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/cache-api-requests/#failing-even-more-gracefully">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h3>
<p>Wrap the above code in a nice <code>try catch</code> allows you to return a fake data set if the very first request fails (no expired cache entry is available). <strong>Note that if there is already an expired cache entry available, we use that instead.</strong></p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> EleventyFetch <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"@11ty/eleventy-fetch"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">try</span> <span class="token punctuation">{</span><br> <span class="token comment">// https://developer.github.com/v3/repos/#get</span><br> <span class="token keyword">let</span> json <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">EleventyFetch</span><span class="token punctuation">(</span><span class="token string">"https://api.github.com/repos/11ty/eleventy"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">duration</span><span class="token operator">:</span> <span class="token string">"1d"</span><span class="token punctuation">,</span> <span class="token comment">// 1 day</span><br> <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"json"</span> <span class="token comment">// also supports "text" or "buffer"</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">stargazers</span><span class="token operator">:</span> json<span class="token punctuation">.</span>stargazers_count<br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span> <span class="token keyword">catch</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span><br> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span> <span class="token string">"Failed getting GitHub stargazers count, returning 0"</span> <span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">stargazers</span><span class="token operator">:</span> <span class="token number">0</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
Quick Tip #008—Trigger a Netlify Build Every Day with IFTTT
2019-02-01T00:00:00Z
https://www.11ty.dev/docs/quicktips/netlify-ifttt/
<p>In <a href="https://www.11ty.dev/docs/quicktips/eliminate-js/">Quick Tip #007</a> we talked about migrating away from using a Client-side third-party JavaScript widget to display GitHub stargazer counts and towards a Data fetched at Build time approach.</p>
<p>Updating this data at build time means that the data isn’t necessarily “live” (although the counts are likely cached at by at least one of the upstream dependencies of this widget, with a frequency that is out of your control).</p>
<p>I’m comfortable with these numbers being a little delayed (more than the JS widget method was) and with this new approach I get more control over the frequency of updates BUT I do probably want to run the build at least once a day. To do this, I used an <a href="https://ifttt.com/">IFTTT</a> applet to trigger my Netlify build to run every morning using <a href="https://docs.netlify.com/configure-builds/build-hooks/">Netlify’s Build Hooks</a>.</p>
<p><em>Heavily inspired by <a href="https://www.hawksworx.com/note/tw/1038067638369443840">Phil Hawksworth’s work on RSS Jamstack</a>.</em></p>
<h2 id="get-a-netlify-build-hook" tabindex="-1">Get a Netlify Build Hook <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/netlify-ifttt/#get-a-netlify-build-hook">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<ol>
<li>Go into your <a href="https://app.netlify.com/">Netlify</a> site’s <code>Build & Deploy</code> settings</li>
<li>Select <code>Continuous Deployment</code></li>
<li>Add a <code>Build hook</code></li>
<li>Name it <code>Deploy every day</code> (or whatever you’d like)</li>
<li>I selected the <code>master</code> branch for my site.</li>
<li>Save this and it will provide you with a long URL a la <code>https://api.netlify.com/build_hooks/SOME_ID_HERE</code>. This is the URL you want.</li>
</ol>
<h2 id="add-an-ifttt-applet" tabindex="-1">Add an IFTTT Applet <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/netlify-ifttt/#add-an-ifttt-applet">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<ol>
<li>Go to <a href="https://ifttt.com/create"><code>New Applet</code> on ifttt.com</a></li>
<li>Click <code>+this</code></li>
<li>Select the <code>Date & Time</code> service</li>
<li>Select the <code>Every day at</code> option (or whatever frequency you’d like)</li>
<li>Select the time you’d like the build to run.</li>
<li>Click <code>+that</code></li>
<li>Select the <code>Webhooks</code> service</li>
<li>Select the <code>Make a web request</code> option</li>
<li>For the URL field, use the Build Hook URL you’ve already retrieved from Netlify.</li>
<li>For the Method field, choose <code>POST</code>.</li>
<li>For the Content Type field, choose <code>application/x-www-form-urlencoded</code>.</li>
<li>For the Body field, type <code>{}</code>.</li>
<li>Click the <code>Create action</code> button.</li>
<li>Click <code>Finish</code>.</li>
</ol>
Quick Tip #007—Fetch GitHub Stargazers Count (and More) at Build Time
2019-01-31T00:00:00Z
https://www.11ty.dev/docs/quicktips/eliminate-js/
<p>Older iterations of this website used a third party JavaScript widget to show the number of GitHub Stars the project currently had. You can see it in action on the <a href="https://v0-7-1.11ty.dev/docs/">versioned docs for 0.7.1</a> (scroll to the bottom).</p>
<p>This was in fact the only <code><script></code> tag on the entire <a href="https://www.11ty.dev/">11ty.dev</a> web site and it was from a third party. Naturally, it needed to be annihilated.</p>
<p>Let’s change up our architecture to ruthlessly eliminate this client-side JavaScript.</p>
<h2 id="get-the-stargazers-count-from-the-github-api" tabindex="-1">Get the Stargazers Count from the GitHub API <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/eliminate-js/#get-the-stargazers-count-from-the-github-api">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Read more at the <a href="https://developer.github.com/v3/repos/#get">GitHub API documentation</a>.</p>
<p>This is a bit different from our client-side implementation because this data is only updated as often as your build runs. This is implemented using a global <a href="https://www.11ty.dev/docs/data-js/">JavaScript data file</a> at <code>_data/github.js</code>.</p>
<ul>
<li>Install new dependencies: <code>npm install node-fetch@cjs --save-dev</code></li>
<li>Read more about <a href="https://www.npmjs.com/package/node-fetch"><code>node-fetch</code></a></li>
</ul>
<div class="codetitle codetitle-left"><b>Filename </b>_data/github.js</div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> fetch <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"node-fetch"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span> <span class="token string">"Fetching new github stargazers count…"</span> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token comment">// GitHub API: https://developer.github.com/v3/repos/#get</span><br> <span class="token keyword">return</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">"https://api.github.com/repos/11ty/eleventy"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">res</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// node-fetch option to transform to json</span><br> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">json</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token comment">// prune the data to return only what we want</span><br> <span class="token keyword">return</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">stargazers</span><span class="token operator">:</span> json<span class="token punctuation">.</span>stargazers_count<br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Now in your templates you can output the stargazers count with:</p>
<div class="codetitle codetitle-left"><b>Syntax </b>Liquid, Nunjucks</div>
<pre class="language-html"><code class="language-html">{{ github.stargazers }} GitHub Stars</code></pre>
<p>which outputs</p>
<pre><code>1515 GitHub Stars
</code></pre>
<p>Bonus: I created a <a href="https://github.com/11ty/11ty-website/blob/ac3579909078f860f4af1185c8f7353d56833c22/.eleventy.js#L82"><code>humanReadableNum</code> filter</a>) using the <a href="https://www.npmjs.com/package/human-readable-numbers"><code>human-readable-numbers</code></a> package to format the number.</p>
<h2 id="more-examples" tabindex="-1">More Examples <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/eliminate-js/#more-examples">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>You can look in the footer of this page to see examples of this in use on this very web site. I used it for:</p>
<ul>
<li><a href="https://github.com/11ty/11ty-website/blob/ac3579909078f860f4af1185c8f7353d56833c22/_data/npm.js">NPM Download Count</a></li>
<li><a href="https://github.com/11ty/11ty-website/blob/ac3579909078f860f4af1185c8f7353d56833c22/_data/github.js">GitHub Stargazers Count</a></li>
<li><a href="https://github.com/11ty/11ty-website/blob/ac3579909078f860f4af1185c8f7353d56833c22/_data/twitter.js">Twitter Followers Count</a> (careful here, this one is super brittle but Twitter’s API is historically anti-developer so 😇)</li>
</ul>
<p>These all use the recommended caching mechanism described in the next section.</p>
<h2 id="recommended-cache-the-data-to-the-file-system" tabindex="-1">Recommended: Cache the Data to the File System <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/eliminate-js/#recommended-cache-the-data-to-the-file-system">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<div class="elv-callout elv-callout-info"><div class="elv-callout-label">INFO:</div><div class="elv-callout-c">It is highly <strong>recommended</strong> to cache your API call data to the file system so that you aren’t making a ton of requests to an API with every build. Luckily, we have a <a href="https://www.11ty.dev/docs/quicktips/cache-api-requests/">Quick Tip on how to Cache your Data Requests</a>!</div></div>
<h2 id="update-counts-daily" tabindex="-1">Update Counts Daily <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/eliminate-js/#update-counts-daily">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>If you want to update these counts automatically every day, read <a href="https://www.11ty.dev/docs/quicktips/netlify-ifttt/">Quick Tip #008—Trigger a Netlify Build Every Day with IFTTT</a>.</p>
Quick Tip #006—Adding a 404 Not Found Page to your Static Site
2018-09-20T00:00:00Z
https://www.11ty.dev/docs/quicktips/not-found/
<p>A <code>404: Not Found</code> page is a pretty standard thing on the web. It’s particularly useful when someone shares a broken or mistyped link. You don’t need dynamic middleware to do this, it’s pretty easy to add to a statically generated site. There are a few options, depending on your web host:</p>
<p>But first let’s make our <code>404.html</code> template:</p>
<pre class="language-html"><code class="language-html">---<br>title: Oops! Not Found<br>permalink: 404.html<br>---<br><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">doctype</span> <span class="token name">html</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>utf-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>{{ title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>{{ title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This is where you should tell the user how to find their content. Maybe on the <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>home page?<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span></code></pre>
<p>Eleventy will output this template to <code>404.html</code>.</p>
<p>If you’re using <a href="https://help.github.com/en/github/working-with-github-pages/creating-a-custom-404-page-for-your-github-pages-site">GitHub Pages</a>, <a href="https://docs.gitlab.com/ee/user/project/pages/introduction.html#custom-error-codes-pages">GitLab Pages</a>, or <a href="https://docs.netlify.com/routing/redirects/redirect-options/#custom-404-page-handling">Netlify</a>, there is no step two! A <code>404.html</code> file in your output directory is all you need.</p>
<p>Netlify even has lovely <a href="https://docs.netlify.com/routing/redirects/redirect-options/#custom-404-page-handling">multi-language 404 page support too using <code>Redirects</code></a>.</p>
<h2 id=".htaccess" tabindex="-1">.htaccess <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/not-found/#.htaccess">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>For other hosts, if you use <code>.htaccess</code> for configuration you can use <code>ErrorDocument</code>. Make sure your root directory matches here!</p>
<pre><code>ErrorDocument 404 /404.html
</code></pre>
<h2 id="with-serve" tabindex="-1">With <code>--serve</code> <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/not-found/#with-serve">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<div class="elv-callout elv-callout-info"><div class="elv-callout-label">INFO:</div><div class="elv-callout-c">If you’re using the new <a href="https://www.11ty.dev/docs/watch-serve/#eleventy-dev-server">Eleventy Dev Server</a> <span data-pagefind-ignore="" class="minilink minilink-addedin" data-uncoerced-version="2.0.0">Added in v2.0.0</span>, the <code>404.html</code> convention is now provided to you for free! You can skip this section!<br>
<br>
If you’d like to backport this functionality to Browsersync, keep reading. (Note also that you can <a href="https://www.11ty.dev/docs/dev-server/#swap-back-to-browsersync">use Browsersync with Eleventy 2.0!</a>)<br>
</div></div>
<p>If you're using Browsersync with Eleventy (with <code>eleventy --serve</code>), you can configure it to do the 404 routing by passing a callback in your config. Read more on <a href="https://www.11ty.dev/docs/config/#override-browsersync-server-options">the BrowserSyncConfig option</a>, the <a href="https://browsersync.io/docs/options#option-callbacks">Browsersync callbacks option</a>, and <a href="https://github.com/browsersync/browser-sync/issues/1398">how to provide a 404 using a Browsersync callback</a>.</p>
<div class="codetitle codetitle-left"><b>Filename </b>.eleventy.js</div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"fs"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">const</span> <span class="token constant">NOT_FOUND_PATH</span> <span class="token operator">=</span> <span class="token string">"_site/404.html"</span><span class="token punctuation">;</span><br><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> eleventyConfig<span class="token punctuation">.</span><span class="token function">setBrowserSyncConfig</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token literal-property property">callbacks</span><span class="token operator">:</span> <span class="token punctuation">{</span><br> <span class="token function-variable function">ready</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> bs</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br><br> bs<span class="token punctuation">.</span><span class="token function">addMiddleware</span><span class="token punctuation">(</span><span class="token string">"*"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span><span class="token constant">NOT_FOUND_PATH</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Expected a \`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">NOT_FOUND_PATH</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\` file but could not find one. Did you create a 404.html template?</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">const</span> content_404 <span class="token operator">=</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span><span class="token constant">NOT_FOUND_PATH</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token comment">// Add 404 http status code in request header.</span><br> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string-property property">"Content-Type"</span><span class="token operator">:</span> <span class="token string">"text/html; charset=UTF-8"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token comment">// Provides the 404 content without redirect.</span><br> res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>content_404<span class="token punctuation">)</span><span class="token punctuation">;</span><br> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p><em>Thank you <a href="https://github.com/clottman">Cassey Lottman</a>.</em></p>
Quick Tip #005—Super Simple CSS Concatenation
2018-06-27T00:00:00Z
https://www.11ty.dev/docs/quicktips/concatenate/
<p>In some situations you may want to concatenate content files together into a single top level template. Maybe you want to create a single CSS file with all of your component CSS inside.</p>
<p>Consider this sample <code>theme.njk</code> file:</p>
<pre class="language-markdown"><code class="language-markdown"><span class="token front-matter-block"><span class="token punctuation">---</span><br><span class="token front-matter yaml language-yaml"><span class="token key atrule">permalink</span><span class="token punctuation">:</span> theme.css</span><br><span class="token punctuation">---</span></span><br>{% include "components/header.css" %}<br>{% include "components/footer.css" %}</code></pre>
<p>That’s an easy way to concatenate files and control the include order.</p>
<p>You might imagine creating an <code>include-all</code> <a href="https://www.11ty.dev/docs/shortcodes/">Shortcode</a> that uses <a href="https://www.npmjs.com/package/fast-glob"><code>fast-glob</code></a> to include a glob of files like <code>{% include-all "components/*.css %}</code>, but that’s an exercise left to the reader!</p>
<h2 id="capture-and-minify" tabindex="-1">Capture and Minify <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/concatenate/#capture-and-minify">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>In our <a href="https://www.11ty.dev/docs/quicktips/inline-css/">Inline CSS Quick Tip</a>, we discussed how to capture and minify a CSS file. This approach can be modified, of course, to capture multiple includes too!</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- capture the CSS content as a Nunjucks variable --></span><br>{% set css %}<br> {% include "components/header.css" %}<br> {% include "components/footer.css" %}<br>{% endset %}<br><span class="token comment"><!-- feed it through our cssmin filter to minify --></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css"><br> <span class="token punctuation">{</span><span class="token punctuation">{</span> css | cssmin | safe <span class="token punctuation">}</span><span class="token punctuation">}</span><br></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>style</span><span class="token punctuation">></span></span></code></pre>
<h2 id="work-with-what-you-have" tabindex="-1">Work with what you have <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/concatenate/#work-with-what-you-have">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Of course, Eleventy has no desire to replace your existing build pipeline. This is just a super simple example if you want something up and running quickly.</p>
<p>That said, Eleventy wants to work with what you have. As an example, the <a href="https://github.com/philhawksworth/eleventyone/"><code>EleventyOne</code> project scaffold</a> is a fine example of using Eleventy with Gulp and Sass. The <a href="https://github.com/zachleat/zachleat.com">zachleat.com source code</a> is an older example that works with Grunt and Sass.</p>
<h3 id="warning-about-content-security-policy" tabindex="-1">Warning about Content Security Policy <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/concatenate/#warning-about-content-security-policy">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h3>
<div class="elv-callout elv-callout-warn"><div class="elv-callout-label">WARNING:</div><div class="elv-callout-c">
If you are using a Content Security Policy on your website, make sure the <code>style-src</code> directive allows <code>'unsafe-inline'</code>. Otherwise, your inline CSS will not load.
</div></div>
Quick Tip #004—Zero Maintenance Tag Pages for your Blog
2018-06-08T00:00:00Z
https://www.11ty.dev/docs/quicktips/tag-pages/
<p>This quick tip will show you how to automatically generate Tag Pages (lists of content tagged into a collection).</p>
<p>We’ll use pagination to automatically generate a template for each tag we want to link to.</p>
<p>Here’s a sample pagination template using Nunjucks:</p>
<pre class="language-markdown"><code class="language-markdown"><span class="token front-matter-block"><span class="token punctuation">---</span><br><span class="token front-matter yaml language-yaml"><span class="token key atrule">pagination</span><span class="token punctuation">:</span><br> <span class="token key atrule">data</span><span class="token punctuation">:</span> collections<br> <span class="token key atrule">size</span><span class="token punctuation">:</span> <span class="token number">1</span><br> <span class="token key atrule">alias</span><span class="token punctuation">:</span> tag<br><span class="token key atrule">permalink</span><span class="token punctuation">:</span> /tags/<span class="token punctuation">{</span><span class="token punctuation">{</span> tag <span class="token punctuation">}</span><span class="token punctuation">}</span>/</span><br><span class="token punctuation">---</span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Tagged “{{ tag }}”<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ol</span><span class="token punctuation">></span></span><br>{% set taglist = collections[ tag ] %}<br>{% for post in taglist | reverse %}<br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{{ post.url }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>{{ post.data.title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br>{% endfor %}<br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ol</span><span class="token punctuation">></span></span></code></pre>
<p>First up notice how we’re pointing our <code>pagination</code> to iterate over <code>collections</code>, which is an object keyed with tag names pointing to the collection of content containing that tag.</p>
<p>Consider these two sample markdown posts, one using a <code>tech</code> tag and one using a <code>personal</code> tag:</p>
<pre class="language-markdown"><code class="language-markdown"><span class="token front-matter-block"><span class="token punctuation">---</span><br><span class="token front-matter yaml language-yaml"><span class="token key atrule">title</span><span class="token punctuation">:</span> My First Post<br><span class="token key atrule">tags</span><span class="token punctuation">:</span><br> <span class="token punctuation">-</span> tech</span><br><span class="token punctuation">---</span></span></code></pre>
<pre class="language-markdown"><code class="language-markdown"><span class="token front-matter-block"><span class="token punctuation">---</span><br><span class="token front-matter yaml language-yaml"><span class="token key atrule">title</span><span class="token punctuation">:</span> My Second Post<br><span class="token key atrule">tags</span><span class="token punctuation">:</span><br> <span class="token punctuation">-</span> personal</span><br><span class="token punctuation">---</span></span></code></pre>
<p>Our pagination template above will now generate two pages: <code>/tags/personal/index.html</code> and <code>/tags/tech/index.html</code>.</p>
<p>The great thing here is that we don’t have to manage our tag list in a central place. These tags can be littered throughout our content and individual tag pages will be created automatically.</p>
<h2 id="filtering-/-excluding" tabindex="-1">Filtering / Excluding <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/tag-pages/#filtering-/-excluding">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Have a tag you’d like to exclude from this list? Use <a href="https://www.11ty.dev/docs/pagination/#filtering-values">pagination filtering</a> like this:</p>
<pre class="language-markdown"><code class="language-markdown"><span class="token front-matter-block"><span class="token punctuation">---</span><br><span class="token front-matter yaml language-yaml"><span class="token key atrule">pagination</span><span class="token punctuation">:</span><br> <span class="token key atrule">data</span><span class="token punctuation">:</span> collections<br> <span class="token key atrule">size</span><span class="token punctuation">:</span> <span class="token number">1</span><br> <span class="token key atrule">alias</span><span class="token punctuation">:</span> tag<br> <span class="token key atrule">filter</span><span class="token punctuation">:</span><br> <span class="token punctuation">-</span> tech<br><span class="token key atrule">permalink</span><span class="token punctuation">:</span> /tags/<span class="token punctuation">{</span><span class="token punctuation">{</span> tag <span class="token punctuation">}</span><span class="token punctuation">}</span>/</span><br><span class="token punctuation">---</span></span></code></pre>
<p>Now Eleventy will only generate a <code>/tags/personal/</code> template and <code>tech</code> will be ignored.</p>
<h2 id="in-practice" tabindex="-1">In Practice <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/tag-pages/#in-practice">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>This is currently in use on the <a href="https://github.com/11ty/eleventy-base-blog"><code>eleventy-base-blog</code> sample project</a>. Check out source code in the <a href="https://github.com/11ty/eleventy-base-blog/blob/main/content/tags.njk"><code>tags.njk</code> template</a> and <a href="https://eleventy-base-blog.netlify.com/tags/another-tag/">see a live demo</a>.</p>
Quick Tip #003—Add Edit on GitHub Links to All Pages
2018-06-08T00:00:00Z
https://www.11ty.dev/docs/quicktips/edit-on-github-links/
<p>It’s nice to be able to instantly edit your HTML on GitHub when you spot an error or an improvement you can make. Why not facilitate this by adding an <em>Edit this page on GitHub</em> link to every page? You can see an example of this on our page footer.</p>
<h2 id="use-a-layout-file" tabindex="-1">Use a Layout File <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/edit-on-github-links/#use-a-layout-file">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Make sure you’re using a Layout file so that you can add these to a single place and have the links applied to all of your pages.</p>
<ul>
<li><a href="https://www.11ty.dev/docs/layouts/">Read more about Layouts</a></li>
</ul>
<p>Here’s a sample:</p>
<pre class="language-html"><code class="language-html"> …<br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>footer</span><span class="token punctuation">></span></span><br> © 2019 Eleventy<br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>footer</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span></code></pre>
<h2 id="add-your-link" tabindex="-1">Add your link! <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/edit-on-github-links/#add-your-link">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Edit your layout file to add the link. Provide the URL to the base of your repo and use the Eleventy provided <code>{{ page.inputPath }}</code> variable to point to the correct input file. Yes, this will also work with paginated templates.</p>
<pre class="language-html"><code class="language-html"> …<br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>footer</span><span class="token punctuation">></span></span><br> © 2019 Eleventy<br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://github.com/11ty/11ty-website/blob/main/{{ page.inputPath }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Edit this page on GitHub<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>footer</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span></code></pre>
<p>That’s it!</p>
Quick Tip #002—Inline Minified JavaScript
2018-06-08T00:00:00Z
https://www.11ty.dev/docs/quicktips/inline-js/
<p><em>Originally posted on <a href="https://www.zachleat.com/web/that-could-possibly-work/">The Simplest Web Site That Could Possible Work Well on zachleat.com</a></em></p>
<p>This tip works great if you have small JS utilities that you’d like to have in your <code><head></code>. For example, this works great with the Filament Group <a href="https://github.com/filamentgroup/loadJS"><code>loadJS</code></a> or <a href="https://github.com/filamentgroup/loadCSS"><code>loadCSS</code></a> utilities.</p>
<h2 id="installation" tabindex="-1">Installation <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-js/#installation">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p><code>npm install terser</code> to make the terser minifier available in your project.</p>
<h2 id="configuration" tabindex="-1">Configuration <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-js/#configuration">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Add the following <code>jsmin</code> filter to your Eleventy Config file:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">{</span> minify <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"terser"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>eleventyConfig<span class="token punctuation">.</span><span class="token function">addNunjucksAsyncFilter</span><span class="token punctuation">(</span><span class="token string">"jsmin"</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><br> <span class="token parameter">code<span class="token punctuation">,</span><br> callback</span><br><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">try</span> <span class="token punctuation">{</span><br> <span class="token keyword">const</span> minified <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">minify</span><span class="token punctuation">(</span>code<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token function">callback</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> minified<span class="token punctuation">.</span>code<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span><br> console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"Terser error: "</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token comment">// Fail gracefully.</span><br> <span class="token function">callback</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> code<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="create-your-javascript-file" tabindex="-1">Create your JavaScript File <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-js/#create-your-javascript-file">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Add a sample JavaScript file to your <code>_includes</code> directory. Let’s call it <code>sample.js</code>.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Hi</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Hi"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="capture-and-minify" tabindex="-1">Capture and Minify <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-js/#capture-and-minify">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Capture the JavaScript into a variable and run it through the filter (this sample is using Nunjucks syntax)</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- capture the JS content as a Nunjucks variable --></span><br>{% set js %}<br> {% include "sample.js" %}<br>{% endset %}<br><span class="token comment"><!-- feed it through our jsmin filter to minify --></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br> <span class="token punctuation">{</span><span class="token punctuation">{</span> js <span class="token operator">|</span> jsmin <span class="token operator">|</span> safe <span class="token punctuation">}</span><span class="token punctuation">}</span><br></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
<h3 id="warning-about-content-security-policy" tabindex="-1">Warning about Content Security Policy <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-js/#warning-about-content-security-policy">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h3>
<div class="elv-callout elv-callout-warn"><div class="elv-callout-label">WARNING:</div><div class="elv-callout-c">
If you are using a Content Security Policy on your website, make sure the <code>script-src</code> directive allows <code>'unsafe-inline'</code>. Otherwise, your inline Javascript will not load.
</div></div>
Quick Tip #001—Inline Minified CSS
2018-06-07T00:00:00Z
https://www.11ty.dev/docs/quicktips/inline-css/
<p><em>Originally posted on <a href="https://www.zachleat.com/web/that-could-possibly-work/">The Simplest Web Site That Could Possibly Work Well on zachleat.com</a></em></p>
<p>This tip works well on small sites that don’t have a lot of CSS. Inlining your CSS removes an external request from your critical path and speeds up page rendering times! If your CSS file is small enough, this is a simplification/end-around for <a href="https://www.smashingmagazine.com/2015/08/understanding-critical-css/">Critical CSS approaches</a>.</p>
<h2 id="installation" tabindex="-1">Installation <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-css/#installation">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p><code>npm install clean-css</code> to make the CSS minifier available in your project.</p>
<h2 id="configuration" tabindex="-1">Configuration <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-css/#configuration">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Add the following <code>cssmin</code> filter to your Eleventy Config file:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> CleanCSS <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"clean-css"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> eleventyConfig<span class="token punctuation">.</span><span class="token function">addFilter</span><span class="token punctuation">(</span><span class="token string">"cssmin"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">code</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">CleanCSS</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">minify</span><span class="token punctuation">(</span>code<span class="token punctuation">)</span><span class="token punctuation">.</span>styles<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2 id="create-your-css-file" tabindex="-1">Create your CSS File <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-css/#create-your-css-file">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Add a sample CSS file to your <code>_includes</code> directory. Let’s call it <code>sample.css</code>.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">body</span> <span class="token punctuation">{</span><br> <span class="token property">font-family</span><span class="token punctuation">:</span> fantasy<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2 id="capture-and-minify" tabindex="-1">Capture and Minify <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-css/#capture-and-minify">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p>Capture the CSS into a variable and run it through the filter (this sample is using Nunjucks syntax)</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- capture the CSS content as a Nunjucks variable --></span><br>{% set css %}<br> {% include "sample.css" %}<br>{% endset %}<br><span class="token comment"><!-- feed it through our cssmin filter to minify --></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css"><br> <span class="token punctuation">{</span><span class="token punctuation">{</span> css | cssmin | safe <span class="token punctuation">}</span><span class="token punctuation">}</span><br></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>style</span><span class="token punctuation">></span></span></code></pre>
<h2 id="using-javascript-templates" tabindex="-1">Using JavaScript templates <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-css/#using-javascript-templates">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h2>
<p><em>Contributed by <a href="https://github.com/zgreen">Zach Green</a></em></p>
<p>You can also inline minified CSS in a <a href="https://www.11ty.dev/docs/languages/javascript/">JavaScript template</a>. This technique does not use filters, and instead uses <code>async</code> functions:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"fs/promises"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"path"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">const</span> CleanCSS <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"clean-css"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"><br><style><br> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">await</span> fs<br> <span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">"./sample.css"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">new</span> <span class="token class-name">CleanCSS</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">minify</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">.</span>styles<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"><br></style></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre>
<h3 id="warning-about-content-security-policy" tabindex="-1">Warning about Content Security Policy <a class="direct-link" href="https://www.11ty.dev/docs/quicktips/inline-css/#warning-about-content-security-policy">
<span class="sr-only" data-pagefind-ignore="">Jump to heading</span>
<span aria-hidden="true" data-pagefind-ignore="">#</span>
</a></h3>
<div class="elv-callout elv-callout-warn"><div class="elv-callout-label">WARNING:</div><div class="elv-callout-c">
If you are using a Content Security Policy on your website, make sure the <code>style-src</code> directive allows <code>'unsafe-inline'</code>. Otherwise, your inline CSS will not load.
</div></div>