Coder Social home page Coder Social logo

google / eleventy-high-performance-blog Goto Github PK

View Code? Open in Web Editor NEW
4.0K 113.0 281.0 25.83 MB

A high performance blog template for the 11ty static site generator.

Home Page: https://www.industrialempathy.com/posts/eleventy-high-performance-blog/

License: MIT License

JavaScript 65.13% CSS 22.05% Shell 0.13% Nunjucks 12.69%
eleventy 11ty 11ty-template

eleventy-high-performance-blog's Introduction

eleventy-high-performance-blog

A starter repository for building a blog with the Eleventy static site generator implementing a wide range of performance best practices.

Screenshot showing that the site achieves 100 points on Lighthouse by default

Based on the awesome eleventy-base-blog.

Demo

Deploy with Vercel

Getting Started

1. Generate a new repository from this repository template

Click the "Use this template" button. Alternatively you can clone this repo yourself and push your copy to your favorite git repository.

2. Clone your new repository

git clone https://github.com/YOUR_REPO

3. Navigate to the directory

cd my-blog-name

4. Install dependencies

npm install

5. Build, serve, watch and test

npm run watch

6. Build and test

npm run build

Customize

  • Search for "Update me" across files in your editor to find all the site specific things you should update.
  • Update the favicons in 'img/favicon/'.
  • Otherwise: Knock yourself out. This is a template repository.
  • For a simple color override, adjust these CSS variables at the top of css/main.css.
:root {
  --primary: #e7bf60;
  --primary-dark: #f9c412;
}

Features

Performance outcomes

Performance optimizations

Images

  • Generates multiple sizes of each image and uses them in srcset.
  • Generates a blurry placeholder for each image (without adding an HTML element or using JS).
  • Transcodes images to AVIF and webp and generates picture element.
  • Transcodes GIFs to muted looping autoplaying MP4 videos for greatly reduced file size.
  • Lazy loads images (using native loading=lazy).
  • Async decodes images (using decoding=async).
  • Lazy layout of images and placeholders using content-visibility: auto.
  • Avoids CLS impact of images by inferring and providing width and height (Supported in Chrome, Firefox and Safari 14+).
  • Downloads remote images and stores/serves them locally.
  • Immutable URLs.

CSS

  • Defaults to the compact "classless" Bahunya CSS framework.
  • Inlines CSS.
  • Dead-code-eliminates / tree-shakes / purges (pick your favorite word) unused CSS on a per-page basis with PurgeCSS.
  • Minified CSS with csso.

Miscellaneous

  • Immutable URLs for JS.
  • Sets immutable caching headers for images, fonts, and JS (CSS is inlined). Automatically configured when deploying on Vercel
  • Uses html-minifier with aggressive options.
  • Uses rollup to bundle JS and minifies it with terser.
  • Prefetches same-origin navigations when a navigation is likely.
  • If an AMP files is present, optimizes it.

Fonts

  • Serves fonts from same origin.
  • Makes fonts display:optional.

Analytics

  • Supports locally serving Google Analytics's JS and proxying it's hit requests to a Vercel Edge Function (other proxies could be easily added).
  • Supports sending Core Web Vitals metrics to Google Analytics as events.
  • Support for noscript hit requests.
  • Avoids blocking onload on analytics requests.
  • To turn this on, specify googleAnalyticsId in metadata.json. (Note, that this is not compatible with the not-yet-commonly used version 4 of Google Analytics.)

DX features

  • Uses 🚨 as favicon during local development.
  • Supports a range of default tests.
  • Runs build and tests on git push.
  • Sourcemap generated for JS.

SEO & Social

  • Share button preferring navigator.share() and falling back to Twitter. Using OS-like share-icon.
  • Support for OGP metadata.
  • Support for Twitter metadata.
  • Support for schema.org JSON-LD.
  • Sitemap.xml generation.

Largely useless glitter

  • Read time estimate.
  • Animated scroll progress bar…
  • …with an optimized implementation that should never cause a layout.

Security

Generates a strong Content-Security-Policy (CSP) for the base template.

  • Default-src is self.
  • Disallows plugins.
  • Generates hash based CSP for the JS used on the site.
  • To extend the CSP with new rules, see CSP.js

Build performance

  • Downloaded remote images, and generated sizes are cached in the local filesystem…
  • …and SHOULD be committed to git.
  • .persistimages.sh helps with this.

Disclaimer

This is not an officially supported Google product, but rather Malte's private best-effort open-source project.

eleventy-high-performance-blog's People

Contributors

andrealeardini avatar benjifs avatar clottman avatar cramforce avatar dependabot[bot] avatar dhoman avatar fschoenfeldt avatar indcoder avatar krzychukula avatar lancechentw avatar lonekorean avatar mathiasbynens avatar mesaugat avatar mufidu avatar nhoizey avatar nick-novak avatar nickfalcone avatar nilsmielke avatar nlbao avatar omair-inam avatar onezerodigits avatar pierlon avatar pkvach avatar robdodson avatar spekulatius avatar stevedunn avatar styfle avatar verlok avatar zachleat avatar zoltanveres avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eleventy-high-performance-blog's Issues

Typos

Some typos in Readme and css including in the test
Check under the File tab with PR associated that closes these.

Hasha

Am I not understanding hash?
You hash files
callback(null, ${absolutePath}?hash=${hash.substr(0, 10)});
page source
link href="/img/favicon/favicon-192x192.png?hash=2089033c93" rel="icon" type="image/png"
script async="" defer="" src="/js/min.js?hash=c372ec6a84"></script
files in _site
min.js (no hash)
favicon-192x192.png (no hash)
Shouldn't hash be appended to file name to upload to server?
BTW, js hash is sha512 (fist 10 digits) but .png is unknown?
sha512 would be 062F6715E3 not 2089033c93 (probably does not matter?)

Where best to change the width of the main article?

Hi,

I would like to make the width of 'article' a little bigger. I think I've found the place in main.css:

@media (min-width: 37.5em) {
  :root {
    --main-width: calc(37.5em - 3em);
  }
}

I'm guessing that's the right place to change it. It seems to work both locally and when I publish to Netlify.

A couple of points:

  1. I understand this isn't an issue per-se, but I thought I'd raise it here as I'm sure others would like to know
  2. May I ask why 37.5em was chosen? It looked a little narrow. The new size of 45.0em looks OK to me on both my desktop and a phone, but I wouldn't want to worsen the reading experience for anyone else

Thankyou for such a fantastic template and thanks in advance for any assistance with this issue.

Steve

Cache.js is not linted?

What are the reasonings to not lint cache.js ?
image

My query stems from the following Lighthouse advice that there is a 3x potential savings.

image

Blurred placeholders and images with transparent background

Hi Malte,
Blurred placeholders are visible as a background when the image is loaded if the image has an alpha (transparency) channel.
Can they be made optional for a specific image or have them removed once the image is loaded (without affecting performance)?

Andrea

Smartcrop with Sharp

Do you think there is a straightforward way to include Smartcrop with Sharp to process the images?

Perhaps as part of the srcset.js script?

This is a really elegant and fantastic starter template and is exceptional work so this would be my only feature request to help with the art direction case for responsive images.

Build took too long because one image

I'm migrating my blog to Eleventy and tried to deploy it on Cloudflare, but it failed in every build. So I moved to Netlify, and it turns out that my build took up to 30 minutes. And there is a single image that needs 20 minutes itself.

netlifybuild

The pic is about 4MB in size. Is it too big?

Unable to use custom JavaScript

Hello.

I'm a self taught programmer. I really liked this starter and I'm trying to rebuild my website on top of it, but I'm having a very hard time connecting my Javascript. Facebook share button, back to top, everything works perfectly fine on my website (https://ornelasnarciso.com/art/biclas/) but it does not work using your starter. I'm missing something here but i can't figure it out. It seems to be file structure.

Could use some help. Thanks.

drafts showing

Why is post This is my fifth post which is marked as a draft, show up on the homepage blog post list and in the /posts/ archive page?

If it's a draft, shouldn't it be hidden?

Why are all source files not located in src/?

I found it quite overwhelming to maintaining the posts, as they are located in the main folder, mixed with all configurations. Wouldn't it be better if all contents (containing *.md and *.njk files) are separated in the src/ folder? There is just one main.js file in that folder now.

Or is there any reason they are arranged this way?

Other than that, this template is amazing. Thank you.

Refused to execute inline script after npm run watch

Nice to meet you, this is a great template!
The npm run watch was successful and the blog appeared well, but I got the following text in the dev tool.

Refused to execute inline script because it violates the following Content Security Policy directive:
 "script-src 'self' 'sha256-Ky9qZOPnMhQV/s7Fdb9TYAOfU4KtWNqCZaFK8tSzXa0=' 'sha256-ThhI8UaSFEbbl6cISiZpnJ4Z44uNSq2tPKgyRTD3LyU='". 
Either the 'unsafe-inline' keyword, a hash ('sha256-d8xVpEfOlXT388lPL445U0wcaE4cweRSVh5BQpm9scE='), 
or a nonce ('nonce-...') is required to enable inline execution.

How can I stop this from appearing in the quickest way possible?

Unit Test assumes there will be more than one post during start of blog

While creating the blog from the template, usually a new blog will start with one post and then add subsequent posts after the deploy but the test assumes there will be more than one blog for all those who have created blogs from the template which is erroneous. Since Git Push is tied to all unit test passing, this is a hindrance in getting the blog deployed.x

Build failed with cloudflare pages

Hello.

The starter works perfectly fine with Netlify but wont build with cloudflare pages (as expected).

I have no intention on storing my website on Netlify. Is there a quick fix for the starter to work with cloudflare pages?

Thank you.

Guidance for base of the blog other than root

Most blogs will be under the subdirectory blog on their domain, but the repo assumes the blog will be at the root folder.

Is there any guidance/advice for folks with the above scenario? Thanks.

Cookie banner

How about a cookie banner? Wouldn't that be necessary for a blog using Google analytics?

Fall back image

If you use a large image (6000 x 4000), the 'const widths' does optimize images into smaller sizes and various formats.
However, the large image is used for fall back image (img src="too-large-image.jpg). This not ideal. Starting with small image and upscaling, not ideal.
Is there a way to use the smallest or second smallest 'constant widths' to generate the fall back image?
if (img.tagName == "IMG") in img-dim.js
Could I use img.getattribute("src") and then change image.jpg to image-608w.jpg? with img.setattribute("src")
Or is there a better way?

Unable to serve the files , see attached screenshot

How do I run and see the blog on local. I m afraid to say that the read me steps are not helping me and getting blocked by several errors despite installing all npm modules:

image

On build command:
image

I have installed sharp using npm install sharp

image

Am I missing something here??
I m new to 11ty and have never used this before. Please help.

Testing css

During development, npm run watch, how is one suppose to test css if the code has been minified? There are no line references because everything is on line 1.

Add support for web-vitals library

Hi @cramforce, is there any interest in adding support for the Web Vitals library? I did this on my own version of the blog and got it sending CLS, FID, and LCP to Google Analytics. My steps were:

  1. Add new file /js/web-vitals.js containing the UMD web vitals library
  2. Reference from base.njk as <script defer src="{{ "/js/web-vitals.js" | addHash }}"></script>
  3. Send to Google Analytics from base.njk, wrapping the analytics.js example in a <script csp-hash> tag

I am still seeing perfect Lighthouse scores, and started getting event data ~24 hours after deploy (LCP below). Happy to open a pull request with these changes for feedback. 😃

lcp

Slash wrong direction

If I try to insert local image on html blog post
<img src="../../img/exercise.jpg" width="750" height="427" alt="No sleep 'til Brooklyn" >

The slash is wrong direction in srcset /img. It also needs ../../ ?
<source sizes="(max-width: 608px) 100vw, 608px" srcset="/img\exercise-1920w.avif 1920w (snip)
but ok in fallback image - note back slash and ../../
<img height="427" src="../../img/exercise.jpg" (snip)`

Relative paths to images in markdown causing errors

  1. Add an image named image.jpg to the posts directory
  2. Edit blog post firstpost.md, insert ![image](./image.jpg)

Notice it will break the build with an error like:

[0] Error writing templates: (more in DEBUG output)
[0] > Having trouble writing template: _site/posts/firstpost/index.html
[0] 
[0] `TemplateWriterWriteError` was thrown
[0] > ENOENT: no such file or directory, open '/path/to/blog/_site/image.jpg'

img-dim is slow and not cached

Hello,

I realized that the img processing is executed multiple times per image - typically, if I add an image to a blog post, it will get processed 3 times (the blog post page itself, the /posts list page, the / list page) + once per tag . I have a site icon processed 22 times per build, for a total of 1721ms according to the 11ty benchmark log.

Caching would be great ; I see a solution in 2 steps :

  • keep an in-memory, transient cache indexed by path: should be easy to do. fill the cache in img-dim, invalidate it when the image changes. pay the cost once per image when starting watch mode, still way better
  • then get to a persistent cache. we could write an image-hashes.json file with the previous hash and generated file path, check it once during watch startup and compare the stored hashes against the actual hashes to invalidate or not the cache entries.

Thoughts ?

Also: it looks like gif2mp4 (which is even slower) is not running if an mp4 file already exists in the source folder (see

if (await exists(dest)) {
). is that intended to act as a basic cache ? in that case it should be if (await exists(join("_site", dest))) { instead of if (await exists(dest)) {

Error: executing "npm run watch" fails after following readme steps

Hey this template seems awesome thats why I wanted to test it for myself.
Thanks for publishing it.

I have a problem where I cannot run the npm watch script without getting errors by following the steps in the readme.
More precisely, I can't run any npm scripts that start with the "./node_modules..." string. But I do have the node modules folder installed properly.

Steps to reproduce on my computer:

  1. Clone repository on my computer.
  2. Open folder in my code editor.
  3. run npm install from that folder
  4. run npm watch (concurrently "eleventy --serve" "npm run js-build-watch" "npm run test-watch")
  5. console outputs many errors where the first error says that the "." command is unknown (all npm scripts that start with a dot fail)

Hope this helps thank you again.
Alex

EDIT: do I need some kind of global dependencies on my computer ? I have not seen it mentionned in the readme and I never used eleventy before.

Visual indications for Draft posts

@cramforce
This issue is really should be discussion. Before i start working on something specific, i wanted to ask your opinion about it:
On #101 you mentioned that it would be nice to have some sort of visual indication for the draft post on the page.
I do know that the template has a different favicon displayed, when the site is served in devmode, which is rather helpful.
Now that we have basically 3 types of posts (draft, scheduled, published), wonder what would you consider and ideal UI indication for draft and schedule post?
There's two places where we can have visual indication:

  1. The post itself
  2. The collection of posts, which is displayed in the main index page

I was thinking to create a shortcode, which prepends [draft] (for draft posts) or [2029-06-06] (for scheduled posts) before the title of the collection, both on the page and both on the main index page.
What do you think? Does this even worth doing?

The optimized images are 3K to 68K in size - 335 to 2010px wide. The fall back is 273K in size, 5184px wide. But "contain" will limit width but not file size. Original file size is 1734K.

The optimized images are 3K to 68K in size - 335 to 2010px wide. The fall back is 273K in size, 5184px wide. But "contain" will limit width but not file size. Original file size is 1734K.
Fallback probably shown by older browsers with slow internet? 1 to 2% of users?
2010px is 3x 670px - very high end mobile?
If fallback was -670w.jpg it would be 15K, instead of 273K

Originally posted by @jakefuller1 in #81 (comment)

Potential secret identified by GitGuardian

In js/cached.js, GitGuardian found a key when I cloned this repo:

(c||"https://ampcid.google.com/v1/publisher:getClientId")+"?key=<removed>"

I'm not sure if this is a problem for whoever owns this key, or other people who copy this repo, but I figured it was better to open an issue than ignore it. Apologies if this is a nuisance; I didn't see any existing issues which mentioned this.

AMP issues

for amp pages ...
only the files jpg create a scrset

Google Analytics is not working

Hello!! First off!, Thank you for this wonderful wonderful blog!! I'm learning a lot from it!! Recently I have used this project as a base for a blog I was working on and I did configure the GA as expected but I am not sure why I cannot really get any stats in the GA? (There are no errors in the console too!)

Here's the website I am talking about: https://jsandfriends.dev/

Stupid Question/ Easy for most, but frustrating for me

How do I change the template to have a white background and black text? I understand the black and yellow is for accessibility reasons, but I can follow WCAG 2.0 guidelines using black text on white background, I think :)

I have tried changing practically anything black(#000000), to white (#FFFFFF). Or even anything close. I'd look up color codes and try and see where they were used on the site. I used https://unminify.com to get the code in a condition I could read it.
Here is what I got, but still no luck.

      html {
    line-height: 1.15;
    -webkit-text-size-adjust: 100%;
}
body {
    margin: 0;
}
h1 {
    font-size: 2em;
    margin: 0.67em 0;
}
hr {
    box-sizing: content-box;
    height: 0;
    overflow: visible;
}
pre {
    font-family: monospace, monospace;
    font-size: 1em;
}
a {
    background-color: #ffffff;
}
abbr[title] {
    border-bottom: none;
    text-decoration: underline;
    text-decoration: underline dotted;
}
b,
strong {
    font-weight: 700;
}
code,
kbd,
samp {
    font-family: monospace, monospace;
    font-size: 1em;
}
small {
    font-size: 80%;
}
sub,
sup {
    font-size: 75%;
    line-height: 0;
    position: relative;
    vertical-align: baseline;
}
sub {
    bottom: -0.25em;
}
sup {
    top: -0.5em;
}
img {
    border-style: none;
}
button,
input,
optgroup,
select,
textarea {
    font-family: inherit;
    font-size: 100%;
    line-height: 1.15;
    margin: 0;
}
button,
input {
    overflow: visible;
}
button,
select {
    text-transform: none;
}
[type="button"],
[type="reset"],
[type="submit"],
button {
    -webkit-appearance: button;
}
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner,
button::-moz-focus-inner {
    border-style: none;
    padding: 0;
}
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring,
button:-moz-focusring {
    outline: 1px dotted ButtonText;
}
fieldset {
    padding: 0.35em 0.75em 0.625em;
}
legend {
    box-sizing: border-box;
    color: inherit;
    display: table;
    max-width: 100%;
    padding: 0;
    white-space: normal;
}
progress {
    vertical-align: baseline;
}
textarea {
    overflow: auto;
}
[type="checkbox"],
[type="radio"] {
    box-sizing: border-box;
    padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
    height: auto;
}
[type="search"] {
    -webkit-appearance: textfield;
    outline-offset: -2px;
}
[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
}
::-webkit-file-upload-button {
    -webkit-appearance: button;
    font: inherit;
}
details {
    display: block;
}
summary {
    display: list-item;
}
[hidden],
template {
    display: none;
}
h1 {
    font-size: 3em;
    line-height: 1.25;
    margin-bottom: 0.5em;
}
h2 {
    font-size: 2.5em;
    line-height: 1.2;
    margin-bottom: 0.6em;
}
h3 {
    font-size: 2em;
    line-height: 1.125;
    margin-bottom: 0.75em;
}
h4 {
    font-size: 1.5em;
    margin-bottom: 1em;
}
h4,
h5 {
    line-height: 1.5em;
}
h5 {
    font-size: 1.25em;
    margin-bottom: 1.2em;
}
h6 {
    font-size: 1em;
    line-height: 1.5em;
    margin-bottom: 1.5em;
}
body,
ol,
p,
pre,
ul {
    font-size: 1em;
    line-height: 1.5;
}
ol,
p,
pre,
ul {
    margin-bottom: 1.5em;
}
h1 {
    font-size: 2.074rem;
}
h1,
h2 {
    line-height: 2.4rem;
    margin-bottom: 1.36rem;
}
h2 {
    font-size: 1.728rem;
}
h3 {
    font-size: 1.4rem;
}
h3,
h4 {
    line-height: 1.6rem;
    margin-bottom: 1.36rem;
}
h4 {
    font-size: 1.2rem;
}
h5,
h6 {
    font-size: 1rem;
    line-height: 1.6rem;
    margin-bottom: 1.36rem;
}
body,
ol,
p,
pre,
ul {
    font-size: 1rem;
    line-height: 1.6;
}
ol,
p,
pre,
ul {
    margin-bottom: 1.36rem;
}
@media (min-width: 600px) {
    h1 {
        font-size: 4.3978rem;
        line-height: 4.4rem;
    }
    h1,
    h2 {
        margin-bottom: 1.496rem;
    }
    h2 {
        font-size: 3.1097rem;
        line-height: 3.52rem;
    }
    h3 {
        font-size: 2.1989rem;
        line-height: 2.64rem;
        margin-bottom: 1.496rem;
    }
    h4 {
        font-size: 1.5554rem;
    }
    h4,
    h5 {
        line-height: 1.76rem;
        margin-bottom: 1.496rem;
    }
    h5,
    h6 {
        font-size: 1.1rem;
    }
    h6 {
        line-height: 1.76rem;
        margin-bottom: 1.496rem;
    }
    body,
    ol,
    p,
    pre,
    ul {
        font-size: 1.1rem;
        line-height: 1.6;
    }
    ol,
    p,
    pre,
    ul {
        margin-bottom: 1.496rem;
    }
}
@media (min-width: 1200px) {
    h1 {
        font-size: 6.0756rem;
        line-height: 6.72rem;
    }
    h1,
    h2 {
        margin-bottom: 1.632rem;
    }
    h2 {
        font-size: 4.05rem;
        line-height: 4.8rem;
    }
    h3 {
        font-size: 2.7rem;
        line-height: 2.88rem;
        margin-bottom: 1.632rem;
    }
    h4 {
        font-size: 1.8rem;
    }
    h4,
    h5 {
        line-height: 1.92rem;
        margin-bottom: 1.632rem;
    }
    h5,
    h6 {
        font-size: 1.2rem;
    }
    h6 {
        line-height: 1.92rem;
        margin-bottom: 1.632rem;
    }
    body,
    ol,
    p,
    pre,
    ul {
        font-size: 1.2rem;
        line-height: 1.6;
    }
    ol,
    p,
    pre,
    ul {
        margin-bottom: 1.632rem;
    }
}
th {
    font-weight: 600;
}
td,
th {
    border-bottom: 1px solid #595959;
    overflow: auto;
    padding: 0.75em;
    text-align: left;
    vertical-align: top;
}
thead th {
    border-bottom: 1px solid #f9c412;
}
table {
    display: table;
}
code,
pre,
table {
    overflow-x: auto;
}
pre {
    font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;
}
pre code:not([class]) {
    padding: 1.5em;
    overflow-x: scroll;
}
code,
kbd {
    border-radius: 0.3em;
    color: #e2777a;
    padding: 0 0.3em;
    font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;
    font-size: 90%;
}
code,
kbd {
    background: #2d2d2d;
}
kbd {
    color: #7ec699;
}
mark {
    background: #f9c412;
    padding: 0 0.3em;
}
h1,
h2,
h3,
h4,
h5,
h6 {
    font-family: eb_garamondregular;
}
h2,
h4,
h6 {
    font-style: italic;
}
a {
    color: #f9c412;
    text-decoration: none;
}
a:hover {
    text-decoration: underline;
}
small {
    color: #ccc;
}
hr {
    border-bottom: 1px solid #eee;
}
figcaption {
    color: #ccc;
    margin-top: 0.75em;
    font-size: 80%;
}
dt {
    font-weight: 600;
}
@media (max-width: 767px) {
    fieldset {
        min-width: 0;
    }
    fieldset * {
        flex-grow: 1;
        page-break-before: auto;
    }
    x:-moz-any-link {
        display: table-cell;
    }
}
html {
    font-family: eb_garamondregular;
}
@supports (font-variation-settings: normal) {
    html {
        font-family: eb_garamondregular;
    }
}
form {
    padding: 1.5em 1.5em 0;
    border: 0.2rem solid #202020;
    margin-bottom: 1.5em;
}
form small {
    font-style: italic;
}
fieldset {
    padding: 0;
    margin: 0;
}
fieldset legend {
    font-size: 150%;
    margin-bottom: 0.75em;
}
button,
input,
select,
textarea {
    border-radius: 0.3em;
    display: inline-block;
    padding: 0.75em;
    max-width: 100%;
}
button + input[type="checkbox"],
button + input[type="radio"],
button + label,
input + input[type="checkbox"],
input + input[type="radio"],
input + label,
select + input[type="checkbox"],
select + input[type="radio"],
select + label,
textarea + input[type="checkbox"],
textarea + input[type="radio"],
textarea + label {
    page-break-before: always;
}
input,
select,
textarea {
    margin-bottom: 1.5em;
}
textarea {
    min-height: 7.5em;
    min-width: 15em;
}
label {
    display: inline-block;
}
label + * {
    page-break-before: always;
}
fieldset > * {
    display: block;
}
input,
select {
    display: inline;
}
fieldset > *,
form > :not(fieldset) {
    margin-right: 0.75em;
}
button,
input[type="reset"],
input[type="submit"] {
    background: #f2f2f2;
    color: #191919;
    cursor: pointer;
    display: inline-block;
    padding: 0.75em 1.5em;
    text-align: center;
    margin: 0 0.75em 1.5em 0;
}
button:hover,
input[type="reset"]:hover,
input[type="submit"]:hover {
    background: #d9d9d9;
    color: #000;
}
button[disabled],
input[type="reset"][disabled],
input[type="submit"][disabled] {
    background: #e6e6e6;
    color: #404040;
    cursor: not-allowed;
}
button:not([disabled]),
button[type="submit"],
input[type="submit"] {
    background: #f9c412;
    color: #181818;
}
button:not([disabled]):hover,
button[type="submit"]:hover,
input[type="submit"]:hover {
    background: #ba9005;
    color: #000;
}
input[type="color"],
input[type="date"],
input[type="datetime-local"],
input[type="datetime"],
input[type="email"],
input[type="file"],
input[type="month"],
input[type="number"],
input[type="password"],
input[type="phone"],
input[type="range"],
input[type="search"],
input[type="tel"],
input[type="text"],
input[type="time"],
input[type="url"],
input[type="week"],
select,
textarea {
    border: 1px solid #595959;
    padding: 0.75em;
}
input[type="checkbox"],
input[type="radio"] {
    flex-grow: 0;
    margin: 0.75em 0.375em 0.75em 0;
    vertical-align: middle;
}
input[type="checkbox"] + label,
input[type="radio"] + label {
    page-break-before: avoid;
}
select[multiple] {
    min-width: 15em;
}
* {
    border: 0;
    box-sizing: border-box;
}
img {
    max-width: 100%;
}
body {
    font-family: eb_garamondregular;
    background: #181818;
    color: #eee;
}
section {
    margin-left: auto;
    margin-right: auto;
    width: 900px;
}
#menu-toggle {
    display: none;
}
header label {
    display: block;
}
#menu-toggle:checked ~ a {
    display: block;
    padding: 0.75em 0;
    margin: 0 1.5em;
    text-align: center;
    border-bottom: 1px solid #ccc;
}
#menu-toggle:checked ~ a:last-of-type {
    padding-bottom: 0;
    border: 0;
}
#menu-toggle:checked ~ label {
    border-bottom: 1px solid #aaa;
    padding-bottom: 0.75em;
}
#menu-toggle:not(:checked) ~ a {
    display: none;
}
header {
    padding: 4.5em 1.5em 3em;
    width: 37.5em;
    margin: 0 auto;
    text-align: center;
    max-width: 100%;
    display: flex;
    align-items: center;
    flex-direction: column;
}
header p {
    margin-top: 0;
}
header nav {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    padding: 0.375em 1.5em;
    background: hsla(0, 0%, 100%, 0.9);
    font-weight: 200;
    text-align: right;
}
header nav h1 {
    float: left;
    font-size: inherit;
    line-height: inherit;
    margin: 0;
    text-align: left;
}
header nav a {
    font-weight: 700;
    text-decoration: none;
    font-family: eb_garamondregular;
    color: #181818;
    margin-left: 1.5em;
}
header nav a:first-of-type {
    margin-left: auto;
}
header nav a:last-of-type {
    margin-right: 1.5em;
}
header nav label {
    color: #000;
    cursor: pointer;
    margin: 0;
    font-style: normal;
    text-align: right;
}
main {
    max-width: 70rem;
    margin: 0 auto;
    border-top: 0.5px solid #ccc;
}
footer {
    background: rgba(0, 0, 0, 0.8);
    color: #fff;
    padding: 3em;
    text-align: center;
}
footer > * {
    margin: 1.5em;
}
footer nav a img {
    vertical-align: middle;
}
footer nav,
footer p {
    font-size: 90%;
}
article {
    max-width: 100%;
    padding: 1.5em;
    width: 37.5em;
    margin: 0 auto;
}
ol,
ul {
    margin-top: 0;
}
li dl,
li ol,
li ul {
    margin-bottom: 0;
}
dl {
    display: inline-block;
    margin: 0 0 1.5em;
}
dt {
    padding-top: 0.75em;
    padding-left: 0.75em;
}
dd {
    padding-bottom: 0.75em;
    margin-left: 2.25em;
}
dd + dt {
    border-top: 1px solid #f9c412;
}
blockquote {
    border-left: 1px solid #f9c412;
    padding: 0 1.5em;
    margin: 1.5em 0 1.5em 1.5em;
}
blockquote footer {
    background: none;
    display: block;
    color: #ccc;
    padding: 0.75em 0;
    font-size: 90%;
    text-align: start;
}
img {
    height: auto;
    margin: 0 auto;
}
figure {
    margin: 1.5em;
}
figure img {
    display: block;
}
code[class*="language-"],
pre[class*="language-"] {
    color: #ccc;
    background: none;
    font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;
    text-align: left;
    white-space: pre;
    word-spacing: normal;
    word-break: normal;
    word-wrap: normal;
    line-height: 1.5;
    -moz-tab-size: 4;
    -o-tab-size: 4;
    tab-size: 4;
    -webkit-hyphens: none;
    -moz-hyphens: none;
    -ms-hyphens: none;
    hyphens: none;
}
pre[class*="language-"] {
    padding: 1em;
    margin: 0.5em 0;
    overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
    background: #2d2d2d;
}
:not(pre) > code[class*="language-"] {
    padding: 0.1em;
    border-radius: 0.3em;
    white-space: normal;
}
.token.block-comment,
.token.cdata,
.token.comment,
.token.doctype,
.token.prolog {
    color: #999;
}
.token.punctuation {
    color: #ccc;
}
.token.attr-name,
.token.deleted,
.token.namespace,
.token.tag {
    color: #e2777a;
}
.token.function-name {
    color: #6196cc;
}
.token.boolean,
.token.function,
.token.number {
    color: #f08d49;
}
.token.class-name,
.token.constant,
.token.property,
.token.symbol {
    color: #f8c555;
}
.token.atrule,
.token.builtin,
.token.important,
.token.keyword,
.token.selector {
    color: #cc99cd;
}
.token.attr-value,
.token.char,
.token.regex,
.token.string,
.token.variable {
    color: #7ec699;
}
.token.entity,
.token.operator,
.token.url {
    color: #67cdcc;
}
.token.bold,
.token.important {
    font-weight: 700;
}
.token.italic {
    font-style: italic;
}
.token.entity {
    cursor: help;
}
.token.inserted {
    color: green;
}

Firefox or any browser Network tools helped a little, but I was not successful. I don't code, but I thought I could try it without help. I was wrong. Can anyone point me in the right direction.

Useful Glitter

Google Analytics report - Events / selection, will show you which pages and/or text are copied most.
Note: if you copy protect part of your page, Adsense will not show ads in that section. (not fully tested)

can't access property getBoundingClientRect error

I'm getting the following error with Firefox (dev edition), regardless it seems to not affect the page itself.
https://thoughts-on-coding.com/2021/03/11/from-wordpress-to-11ty/

Uncaught TypeError: can't access property "getBoundingClientRect", document.querySelector(...) is null
    <anonymous> main.js:232
    ResizeObserverCallback* main.js:229
    <anonymous> main.js:270
main.js:232:15
    <anonym> main.js:232
    (Async: ResizeObserverCallback)
    <anonym> main.js:229
    <anonym> main.js:270

Unable to place my javascript

Hello.

The starter is really good, strong CSP and very well optimized, but is also very unclear in how to use it (I'm a front end developer and I'm not really that good on back end). I've spent a lot of hours on it and I still can't use jquery, use my own JavaScript and also I'm unable to change the CSS without breaking the website.

Any plans on creating instructions on how to use jquery, place our own JavaScript and change the CSS, making this starter more friendly to use? The starter works fine as it is, but the layout (UI and UX) is bit bad (sorry).

I know that I've been here a few times but I really want to use this starter for my personal website, he is too good not to be used.

gif and mp4 not playing/showing up

First of all, thanks for the really nice template. Unfortunately, I got problems shipping gifs and mp4.
I'm new to eleventy and have problems here. The gif is not playing and the mp4 not showing up at all.
https://thoughts-on-coding.netlify.app/2020/04/20/a-c++-github-template-repository-utilizing-circleci-cmake-docker-and-doxygen/

![Example job invocation of the CircleCI CLI](/img/circlecicli.gif)
![Example of a docker image generation for the cpptemplate](/img/cpptemplateimage.mp4)

CSP to allow YouTube iframe

How can I modify CSP configuration to allow YouTube iframes?

When using the https://github.com/gfscott/eleventy-plugin-youtube-embed plugin I'm getting an error in console:
Refused to frame 'https://www.youtube-nocookie.com/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.

And the plugin generates this markup:

<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="100%" src="https://www.youtube-nocookie.com/embed/enTb2E4vEos" style="position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;" title="Embedded YouTube video" width="100%"></iframe>

If I try to use the share functionality from inside YouTube with it's generated markup I have the same error:
Refused to frame 'https://www.youtube.com/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.

<iframe width="560" height="315" src="https://www.youtube.com/embed/enTb2E4vEos" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.