+201223538180

Web site Developer I Advertising I Social Media Advertising I Content material Creators I Branding Creators I Administration I System SolutionCreating Your Personal Bragdoc With Eleventy

Web site Developer I Advertising I Social Media Advertising I Content material Creators I Branding Creators I Administration I System SolutionCreating Your Personal Bragdoc With Eleventy

Web site Developer I Advertising I Social Media Advertising I Content material Creators I Branding Creators I Administration I System Resolution

It doesn’t matter what stage you’re at as a developer, the duties we full—whether or not large or small—make a big impact in our private {and professional} progress. Sadly, these duties aren’t all the time acknowledged as a result of they’ll simply get misplaced within the sea of different issues that must get completed.

The unnoticed duties we do fall below what is called “invisible work,” an idea I stumbled throughout from a chat titled “Getting Credit score for Invisible Work” by Ryan T. Harter. This kind of work seeps into the cracks as a result of our brains should not wired to recollect issues. But come evaluation time, we discover ourselves repeatedly caught when attempting to recall what we did over the previous 6 or 12 months.

To unravel this long-established downside, Julia Evans wrote an article suggesting that we preserve our personal “brag doc.” A brag doc is strictly what it appears like. It’s a doc the place you give your self permission to brag about all the precious work you probably did. Whether or not or not it’s:

  • The way you contributed to a venture
  • Serving to others
  • Bettering current processes
  • Giving talks or operating workshops
  • What you realized
  • Further-curricular actions (e.g. running a blog, talks, private initiatives)
  • Awards and profession development

There isn’t a one strategy to write a brag doc, however that didn’t cease Jonny Burch and the crew at Development from constructing bragdocs.com.

Utilizing their web site to construct one is a superb thought, however what higher strategy to brag about your work than to create your personal brag doc from scratch?

At this time I need to present you the way I re-created bragdocs.com utilizing the static web site generator Eleventy. With a bit little bit of JavaScript and CSS, you will get your personal up and operating!

What are we going to construct?

Under is the top results of following this tutorial. You’ll find the reside demo right here. It imitates bragdocs.com as a place to begin so that you can create one from scratch and make it your personal.

Necessities

  • Putting in packages in Node.js (model 10 or greater)
  • Basic understanding of HTML and CSS
  • Markdown, Nunjucks templating, and JavaScript (all are optionally available, however useful)
  • Fundamental programming ideas, together with if statements, loops, and accessing variables in JSON

What’s Eleventy?

Eleventy is a static web site generator. Which means somewhat than constructing a full-stack web site (front-end and back-end), you might have flexibility to put in writing content material in any of the next templating languages accepted by Eleventy: HTML, Markdown, Liquid, Nunjucks, Mustache, and so on. The content material is then processed (utilizing customized templates in case you like) to generate static HTML pages, prepared for internet hosting as a completely functioning web site.

Establishing our “Good day, World!” Eleventy venture

On this tutorial, the repository I’ll be referring to is eleventy-bragdoc, and the ultimate product we’re working in the direction of will likely be known as a “bragdoc.”

With a GitHub repository created with a README.md and .gitignore file for Node, I began establishing an Eleventy venture.

Creating a brand new venture

Inside eleventy-bragdoc, I started with the next information:

eleventy-bragdoc
├── README.md
└── .gitignore // .gitignore for node

With the terminal navigated within eleventy-bragdoc, I initialized the venture by operating the next command:

npm init -y

This created a bundle.json file for my node packages.

eleventy-bragdoc
├── bundle.json // new file
├── README.md
└── .gitignore

Subsequent, I put in Eleventy.

npm set up @11ty/eleventy

This gave me the next checklist of information and folders:

eleventy-bragdoc
├── node_modules  // new folder
├── bundle.json
├── package-lock.json  // new file
├── README.md
└── .gitignore

Configuring the Eleventy venture

With Eleventy put in, I up to date the scripts within the bundle.json file to incorporate the next instructions:

  • The begin command serves the venture throughout improvement which runs Browsersync for warm reload.
  • The construct command creates manufacturing prepared HTML information in order that it may be hosted onto a server.
{
  // ...
  "scripts": {
    "begin": "eleventy --serve",
    "construct": "eleventy"
  },
 //  ...
}

Subsequent, I created the required configuration file known as .eleventy.js to specify the customized enter and output directories.

eleventy-bragdoc
├── .eleventy.js  // new file
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Inside .eleventy.js, I instructed Eleventy that it’s going to reference what’s within the src folder to construct the HTML information. The output is then saved inside a folder known as public:

module.exports = operate(eleventyConfig) {
  return {
    dir: {
      enter: "src",
      output: "public"
    }
  }
}

Creating front-facing content material

To make my first web page, I created the src folder that I declared because the enter listing in .eleventy.js . Inside it, I added my first web page, a Markdown file known as index.md

Eleventy works with many templating languages you can combine and match: HTML, Markdown, Liquid, Nunjucks, JavaScript, Handlebars, Mustache, EJS, Haml, Pug.

eleventy-bragdoc
├── src
│   └── index.md  // new file
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

In Eleventy, any key worth pairs written between the dashes (---) above and under is taken into account entrance matter.

In index.md , I included a title property with the worth “11ty x Bragdocs” and a few check content material beneath the entrance matter.

---
title: "11ty x Bragdocs"
---

That is the house web page.

Constructing templates

Subsequent, I created a folder which Eleventy expects, known as _includes within src. That is the place the templates, or what Eleventy refers to as layouts, should reside. Inside that folder, I created a subfolder known as layouts for my first template, base.njk

The .njk filetype refers back to the templating language Nunjucks.

eleventy-bragdoc
├── src
│   ├── _includes  // new folder
│   │   └── layouts  // new folder
│   │       └── base.njk  // new file
│   └── index.md
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

I added an HTML5 boilerplate inside base.njk:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta identify="viewport" content material="width=device-width, initial-scale=1.0">
  <title>Doc</title>
</head>
<physique>
    
</physique>
</html>

Creating pages with templates and entrance matter

In base.njk , between the <title> tags, I needed to tug within the title property outlined within the entrance matter of index.md, so I used double curly braces, i.e. {{title}}, to entry this variable. Equally, within the physique, I added <h1> tags and set it with the identical title property.

Subsequent, I introduced in the remainder of the physique content material from index.md utilizing the content material property. Utilizing the offered secure filter, I instructed Eleventy to render as an alternative of escape any HTML that lives contained in the content material of the Markdown file.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta identify="viewport" content material="width=device-width, initial-scale=1.0">
  <title>{{ title }}</title>
</head>
<physique>
  <h1>{{ title }}</h1>
  { secure }
</physique>
</html>

I then jumped again to index.md and added a format property to the entrance matter and referenced base.njk

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

That is the house web page.

To provide you an thought of what occurs once we run the construct, the template specified within the format entrance matter property is used to wrap the Markdown content material. On this instance, the compiled HTML will appear like what’s proven under:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta identify="viewport" content material="width=device-width, initial-scale=1.0">
  <title>11ty x Bragdocs</title>
</head>
<physique>
  <h1>11ty x Bragdocs</h1>
  <p>That is the house web page.</p>
</physique>
</html>

Connecting CSS and picture folders in construct

Whereas this half won’t be needed for all Eleventy initiatives, CSS and self-hosted photographs are all the time good options so as to add. So, I created two folders within the src listing: css and photographs.

eleventy-bragdoc
├── src
│   ├── css  // new folder
│   ├── photographs  // new folder
│   ├── _includes
│   │   └── layouts
│   │       └── base.njk
│   └── index.md
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Then, in .eleventy.js, since I needed the content material inside these folders to be accessible when hosted, I referenced these folders by including the next configurations:

  • addWatchTarget tells Eleventy that it ought to recompile once we make a change to a file on this listing (e.g. kinds.css within the css folder).
  • addPassthroughCopy tells Eleventy that after the information are compiled, to take the contents of the listing and cross it by way of to the public listing.

You possibly can learn extra about how passthrough file copy works within the documentation.

Since I used to be utilizing the Nunjucks templating system, I added the markdownTemplateEngine property and set it to njk to guarantee that it is aware of to undergo Nunjucks first earlier than anything.

module.exports = operate(eleventyConfig) {
  eleventyConfig.addWatchTarget("./src/css/")
  eleventyConfig.addWatchTarget("./src/photographs/")
  eleventyConfig.addPassthroughCopy("./src/css/")
  eleventyConfig.addPassthroughCopy("./src/photographs/")

  return {
    dir: {
      enter: "src",
      output: "public"
    },
    markdownTemplateEngine: "njk"
  }
}

Then I created a kinds.css file within the css folder and gave it one thing to check with to ensure it labored.

* {
  colour: teal;
}

Since I already configured the css and photographs folders in .eleventy.js, I used to be in a position to reference these information utilizing Eleventy’s URL filter.

To entry these self-hosted information I used Eleventy’s URL filters within the href and src property of the css and picture tags, respectively.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta identify="viewport" content material="width=device-width, initial-scale=1.0">
  <title>{{ title }}</title>

  <hyperlink rel="stylesheet" href="https://css-tricks.com/creating-your-own-bragdoc-with-eleventy/{ url }">

</head>
<physique>
  <h1>{{ title }}</h1>

  <img src="https://css-tricks.com/creating-your-own-bragdoc-with-eleventy/{ url }">

  { secure }
</physique>
</html>

Now I used to be able to serve my Eleventy venture.

Serving Eleventy in improvement

Since I had already outlined the customized improvement scripts in bundle.json, I used to be in a position to run the next command:

npm begin

This compiled index.md within the src listing and generated a HTML file within the public folder. Moreover, it launched a scorching reload server by way of Browsersync the place I may see the consequence at http://localhost:8080/

The consequence thus far

With Eleventy operating in improvement, I may begin constructing the remainder of the bragdoc.

Constructing the bragdoc system

With a base Eleventy venture in a folder construction much like what’s proven under, I started constructing out my bragdoc.

eleventy-bragdoc
├── src
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   └── test_image.jpg
│   ├── _includes
│   │   └── layouts
│   │       └── base.njk
│   └── index.md
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Creating a group for bragdoc entries

Eleventy has the power to create collections that group comparable content material collectively. Subsequently, I created a folder known as posts for my bragdoc entries. Inside that folder, I created a number of Markdown information to signify every entry.

The filenames post-1.md, post-2.md, post-3.md don’t have an effect on something that’s rendered on the webpage

eleventy-bragdoc
├── src
│   ├── posts
│   │   ├── post-1.md  // new file
│   │   ├── post-2.md  // new file
│   │   └── post-3.md  // new file
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   └── test_image.jpg
│   ├── _includes
│   │   └── layouts
│   │       └── base.njk
│   └── index.md
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

The customized properties that I believed can be helpful to incorporate:

  • Title
  • Date (by default, posts are sorted chronologically)
  • Classes (a listing of values to prepare entries)
  • Public / Personal (a boolean worth—true or false—to find out whether or not you need to present it on the bragdoc )
  • Icon (a Notion-inspired design component to visually arrange entries)

I made a decision that the outline for every entry can be the physique content material of the Markdown file, as this might give me freedom so as to add paragraphs, photographs, code blocks, and so on. Moreover, I used to be not restricted to Markdown parts as I may additionally embrace HTML and elegance it utilizing CSS.

Under is an instance of a bragdoc entry in a Markdown file:

---
title: Construct my very own Bragdoc utilizing Eleventy
date: 2021-09-19
classes:
  - Studying
  - Eleventy
public: True
icon: 🎈
---

I realized how you can use Eleventy to construct my very own bragdoc!

Some issues to notice:

  • Hyperlinks written in Markdown by default don’t open in a brand new clean window. So after some analysis, I stumbled upon a snippet by Mark Thomas Miller, which I added simply earlier than the closing <physique> tag in base.njk. This won’t be your factor (it’s positively not Chris’ factor) however simply in case you want it:
<script>
// Making all exterior hyperlinks open in new tabs
// Snippet by Mark Thomas Miller

(operate () {
  const hyperlinks = doc.querySelectorAll("a[href^='https://'], a[href^='http://']")
  const host = window.location.hostname

  const isInternalLink = hyperlink => new URL(hyperlink).hostname === host

  hyperlinks.forEach(hyperlink => {
    if (isInternalLink(hyperlink)) return

    hyperlink.setAttribute("goal", "_blank")
    hyperlink.setAttribute("rel", "noopener")
  })
})()
</script>
  • The date entrance matter property have to be written in YYYY-MM-DD format.
  • You possibly can assign as many customized entrance matter properties as you’d like. Simply guarantee that in case you plan on accessing the property within the template, that the property exists in the entire Markdown information utilizing the identical template; in any other case it might break the construct.
  • Lists in entrance matter will be written in a number of methods (e.g. an array or single line).

Assigning entrance matter properties to a group

As a substitute of repeatedly assigning entrance matter properties with the identical worth in every Markdown file, I created a knowledge listing JSON file to assign the identical key-value pair solely as soon as throughout a group.

To create a knowledge listing file, it will need to have the identical identify as the gathering, i.e. posts.json. Moreover, the file should even be positioned inside the gathering folder, i.e. the posts folder.

eleventy-bragdoc
├── src
│   ├── posts
│   │   ├── posts.json  // new file
│   │   ├── post-1.md
│   │   ├── post-2.md
│   │   └── post-3.md
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   └── test_image.jpg
│   ├── _includes
│   │   └── layouts
│   │       └── base.njk
│   └── index.md
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

At this level, the posts for the bragdoc had not been outlined as a group but. To do that, I added the tags property in posts.json. Right here I assigned the worth “posts” to that property in order that I may entry the gathering by calling collections.posts

And since I didn’t want every put up to have its personal web page, i.e. http://localhost:8080/posts/post-1/, I switched off it’s auto-generated permalink.

{
  "tags": "posts",
  "permalink": false
}

Itemizing bragdoc entries

Merely put, the bragdoc is a web page made up of the entries within the posts assortment. To entry the entrance matter properties and physique content material of the Markdown information, the entries are looped by way of by way of Nunjucks.

To do that, I went again to index.md and altered the filetype from Markdown to Nunjucks, i.e. index.njk

eleventy-bragdoc
├── src
│   ├── posts
│   │   ├── posts.json
│   │   ├── post-1.md
│   │   ├── post-2.md
│   │   └── post-3.md
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   └── test_image.jpg
│   ├── _includes
│   │   └── layouts
│   │       └── base.njk
│   └── index.njk  // modified filetype
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Subsequent, I changed the content material of index.njk with a Nunjucks for loop.

A Nunjucks operate (for loop, if assertion, and so on.) should embrace begin and finish tags.

For the reason that order of posts by default was in chronological order (oldest first), I added the reverse filter to indicate the newest on the high.

To entry entrance matter and render it in HTML (such because the date and title of a put up), I needed to undergo one other “knowledge” layer. Accessing properties in entrance matter requires double curly braces.

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

 reverse %
  <p>
    {{ put up.knowledge.date }} - {{ put up.knowledge.title }}
  </p>
{% endfor %}
A bit of extra progress

Filtering bragdoc entries

To filter sure entries, I used the entrance matter knowledge to examine if the public property was set to True. If the property was set to False, the entry didn’t seem within the bragdoc.

Equally, when accessing entrance matter properties, reminiscent of public by way of a Nunjucks operate, I once more wanted to undergo one other “knowledge” layer.

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

 reverse %
  {% if put up.knowledge.public %}
    <p>
      {{ put up.knowledge.date }} - {{ put up.knowledge.title }}
    </p>
  {% endif %}
{% endfor %}
The posts are ordered with the title.

Including customized knowledge filters

By default, the date property renders one thing that we’re usually unfamiliar with. So, after some analysis, I discovered a customized filter written by Phil Hawksworth. To make use of the filter, I created a file known as dates.js and positioned it in a brand new folder known as _filters

eleventy-bragdoc
├── src
│   ├── _filters  // new folder
│   │   └── dates.js  // new file
│   ├── posts
│   │   ├── posts.json
│   │   ├── post-1.md
│   │   ├── post-2.md
│   │   └── post-3.md
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   └── test_image.jpg
│   ├── _includes
│   │   └── layouts
│   │       └── base.njk
│   └── index.njk
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Then, inside dates.js, I added the next:

/*
A date formatter filter for Nunjucks 
Written by Phil Hawksworth
*/
module.exports = operate(date, half) {
  var d = new Date(date);
  if(half == '12 months') {
    return d.getUTCFullYear();
  }
  var month = [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December"
  ];
  var ordinal = {
    1 : "st",
    2 : "nd",
    3 : "rd",
    21 : "st",
    22 : "nd",
    23 : "rd",
    31 : "st"
  };
  return month[d.getMonth()] + " " + d.getDate() + (ordinal[d.getDate()] || "th") + " " +d.getUTCFullYear();
}

To entry the date filter within the venture, I added a brand new filter in .eleventy.js the place I can name it utilizing the customized identify dateDisplay

module.exports = operate (eleventyConfig) {

  // Add filter
  eleventyConfig.addFilter("dateDisplay", require("./src/_filters/dates.js") );
  
  eleventyConfig.addPassthroughCopy("./src/css/")
  eleventyConfig.addPassthroughCopy("./src/photographs/")
  eleventyConfig.addWatchTarget("./src/css/")
  eleventyConfig.addWatchTarget("./src/photographs/")

  return {
    dir: {
      enter: "src",
      output: "public"
    },
    markdownTemplateEngine: "njk"
  }
}

In index.njk, I assigned the dateDisplay filter to the date variable, rendering it in a human-readable format.

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

 reverse %
  {% if put up.knowledge.public %}
    <p>
      { dateDisplay } - {{ put up.knowledge.title }}
    </p>
  {% endif %}
{% endfor %}

The server must be restarted each time you modify one thing within the configuration file.

The posts with up to date date formatting.

To return the physique content material of a put up, I known as templateContent and added the secure filter in order that it rendered any HTML within the Markdown file somewhat than escaping it.

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

 reverse %
  {% if put up.knowledge.public %}
    <p>
      { dateDisplay } - {{ put up.knowledge.title }} 
      <br/>
      { secure }
    </p>
    <br/>
  {% endif %}
{% endfor %}
The posts with physique content material.

Lastly, I included one other for loop to checklist the values within the classes entrance matter property.

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

 reverse %
  {% if put up.knowledge.public %}
    <p>
      { dateDisplay } - {{ put up.knowledge.title }}
      <br/>
      { secure }
      {% for class in put up.knowledge.classes %}
        <span># {{class}}</span>
      {% endfor %}
    </p>
    <br/>
  {% endif %}
{% endfor %}

Having completed extracting knowledge from the posts assortment, it was time to construct out the HTML construction.

Structuring the bragdoc

Partials in Eleventy enable us to repeatably use bits of HTML or templating. This additionally simplifies the code from one large template file to manageable items that match collectively.

Contained in the <physique> tags of base.njk , I eliminated every thing besides the content material and snippet.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta identify="viewport" content material="width=device-width, initial-scale=1.0">
  <title>{{ title }}</title>

  <hyperlink rel="stylesheet" href="https://css-tricks.com/creating-your-own-bragdoc-with-eleventy/{ url }">
</head>
<physique>
  { secure }
  <script>
    (operate () {
      const hyperlinks = doc.querySelectorAll("a[href^='https://'], a[href^='http://']")
      const host = window.location.hostname

      const isInternalLink = hyperlink => new URL(hyperlink).hostname === host

      hyperlinks.forEach(hyperlink => {
        if (isInternalLink(hyperlink)) return

        hyperlink.setAttribute("goal", "_blank")
        hyperlink.setAttribute("rel", "noopener")
      })
    })()
  </script>
</physique>
</html>

Subsequent, I created bragdoc-entry.njk which lives inside a brand new folder known as partials

eleventy-bragdoc
├── src
│   ├── _filters
│   │   └── dates.js
│   ├── posts
│   │   ├── posts.json
│   │   ├── post-1.md
│   │   ├── post-2.md
│   │   └── post-3.md
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   └── test_image.jpg
│   ├── _includes
│   │   ├── partials  // new folder
│   │   │   └── bragdoc-entry.njk  // new file
│   │   └── layouts
│   │       └── base.njk
│   └── index.njk
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Inside bragdoc-entry.njk, I introduced over the content material that make up the bragdoc entry, written in index.njk. Discover that it doesn’t require any entrance matter since it’s handled as a snippet.

Partials don’t prolong a template, so they don’t want any entrance matter.

<p>
  { dateDisplay } - {{ put up.knowledge.title }}
  <br/>
  { secure }
  {% for class in put up.knowledge.classes %}
      <span># {{class}}</span>
  {% endfor %}
</p>
<br/>

Then, between the if assertion in index.njk, I added an embrace tag that references the bragdoc-entry.njk partial. By doing this, the content material inside bragdoc-entry.njk is repeatably added till the for loop finishes.

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

 reverse %
  {% if put up.knowledge.public %}
    {% embrace 'partials/bragdoc-entry.njk' %}
  {% endif %}
{% endfor %}

Subsequent, I wrapped the complete for loop with some customized HTML, together with a header, profile container and footer. At this level, I additionally included a profile image within the photographs folder and referenced it within the customized HTML utilizing Eleventy’s URL filter.

---
title: "11ty x Bragdocs"
format: "layouts/base.njk"
---

<div class="bragdoc__section" id="bragdoc__section">
<h1 class="bragdoc__header">{{ title }}</h1>
<div class="bragdoc__container">
  <div class="bragdoc__profile">
    <img class="bragdoc__photo" src="https://css-tricks.com/creating-your-own-bragdoc-with-eleventy/{ url }">
    <h1 class="bragdoc__name">Emily Y Leung</h1>
    <div class="position">Computational Designer</div>
  </div>
   reverse %
    {% if put up.knowledge.public -%}
      {% embrace 'partials/bragdoc-entry.njk' %}
    {% endif %}
  {% endfor %}
  </div>
  <footer>
    <div><a goal="_blank" href="https://www.bragdocs.com/">Bragdocs</a> impressed theme constructed with <a goal="_blank" href="https://www.11ty.dev/">11ty</a></div>
    <div>Made with ♥ by <a goal="_blank" href="https://emilyyleung.github.io/">Emily Y Leung</a></div>
  </footer>
</div>

Then, inside bragdoc-entry.njk, I up to date the HTML construction and included courses for styling:

<div class="bragdoc__entry">
  <div class="bragdoc__entry-milestone"></div>
  <div class="bragdoc__entry-block">
    <span class="bragdoc__entry-date">
      { dateDisplay }
    </span>
    <br/>
    <h2 class="bragdoc__entry-title"><span class="bragdoc__icon">{{ put up.knowledge.icon }}</span> {{ put up.knowledge.title }}</h2>
    <div class="bragdoc__entry-content">
        { secure }
    </div>
  </div>
  <div class="bragdoc__taglist">
  {% for class in put up.knowledge.classes %}
    <span># {{class}}</span>
  {% endfor %}
  </div>
</div>

Accessing world knowledge

A great way to know world knowledge is to think about constructing a HTML template that somebody may use as a base for his or her web site. Relatively than trying to find particular HTML tags to switch the textual content, they solely want to switch sure values in an exterior file which then updates the content material. That is one among the various issues a worldwide knowledge file can do for us.

Eleventy can entry world knowledge information written in JSON when they’re positioned in a folder known as _data. So, I created a knowledge.json file that’s accessible once I name {{knowledge}} after which select no matter properties I had offered within the JSON object.

eleventy-bragdoc
├── src
│   ├── _data  // new folder
│   │   └── knowledge.json  // new file
│   ├── _filters
│   │   └── dates.js
│   ├── posts
│   │   ├── posts.json
│   │   ├── post-1.md
│   │   ├── post-2.md
│   │   └── post-3.md
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   ├── profile_picture.jpg
│   │   └── test_image.jpg
│   ├── _includes
│   │   ├── partials
│   │   │   └── bragdoc-entry.njk
│   │   └── layouts
│   │       └── base.njk
│   └── index.njk
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Inside knowledge.json, I included properties that have been reused all through the venture:

{
  "mywebsite": "https://emilyyleung.github.io/",
  "myname": "Emily Y Leung",
  "myrole": "Computational Designer"
}

One nice use case was to switch the content material within the profile and footer in index.njk

<!-- Profile -->
<div class="bragdoc__profile">
  <img class="bragdoc__photo" src="https://css-tricks.com/creating-your-own-bragdoc-with-eleventy/{ url }">
  <h1 class="bragdoc__name">{{ knowledge.myname }}</h1>
  <div class="position">{{ knowledge.myrole }}</div>
</div>
<!-- Footer -->
<footer>
  <div><a goal="_blank" href="https://www.bragdocs.com/">Bragdocs</a> impressed theme constructed with <a goal="_blank" href="https://www.11ty.dev/">11ty</a></div>
  <div>Made with ♥ by <a goal="_blank" href="https://css-tricks.com/creating-your-own-bragdoc-with-eleventy/{{ knowledge.mywebsite }}">{{ knowledge.myname }}</a></div>
</footer>

Styling the bragdoc

With the bragdoc construction accomplished, I up to date the styling in kinds.css

To mimic bragdocs.com, I chosen a few of their colours and saved them in a root variable.

Moreover, I needed to create a number of themes, so I added a customized data-theme property on high of the :root variable. On this case, the default colour theme is “gentle” no matter whether or not data-theme is assigned to the <html> tag. However that additionally signifies that if I needed to create a “darkish” theme, I may create a brand new selector html[data-theme="dark"] in my CSS, and assign various colours to the identical variables as laid out in :root

:root, html[data-theme="light"] {
  --logo: black;
  --name: black;
  --entry-title: black;
  --date: #BDBDBD;
  --text: #676a6c;
  --entry-line: #f1f1f1;
  --entry-circle: #ddd;
  --background: white;
  --text-code: gray;
  --code-block: rgba(0,0,0,0.05);
  --link-text: #676a6c;
  --link-hover: orange;
  --quote-block-edge: rgba(255, 165, 0, 0.5);
  --quote-block-text: #676a6c;
  --table-border: #676a6c;
  --footer: #BDBDBD;
  --tag: #BDBDBD;
}

To reference root variables, name var() the place the argument is the identify of the property.

Right here is an instance of how we will use root variables to type the colour of textual content in a <p> tag:

:root {
  --text: teal;
}

p {
  colour: var(--text)
}

For enjoyable, I added a darkish model impressed by Google Materials.

html[data-theme="dark"] {
  --logo: #FFF;
  --name: #FFF;
  --entry-title: #dedede;
  --date: rgba(255,255,255,0.3);
  --text: #999999;
  --entry-line: rgba(255,255,255,0.2);
  --entry-circle: rgba(255,255,255,0.3);
  --background: #121212;
  --code-text: rgba(255,255,255,0.5);
  --code-block: rgba(255,255,255,0.1);
  --link-text: rgba(255,255,255,0.5);
  --link-hover: orange;
  --quote-block-edge: rgb(255, 165, 0);
  --quote-block-text: rgba(255, 165, 0,0.5);
  --table-border: #999999;
  --footer: rgba(255,255,255,0.3);
  --tag: rgba(255,255,255,0.3);
}

To regulate what theme you need to use, add the data-theme property to the <html> tag in base.njk. From there, assign the worth related to the corresponding CSS selector, i.e. “gentle” or “darkish.”

<!DOCTYPE html>
<html lang="en" data-theme="gentle">

Subsequent, I added styling to the <physique>, <footer>, bragdoc part, and brand.

physique {
  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  colour: var(--text);
  background-color: var(--background);
  margin: 0;
  peak: 100vh;
}

footer {
  margin: 0 auto;
  max-width: 500px;
  padding-bottom: 1.5em;
  text-align: middle;
  colour: var(--footer);
  padding-top: 2em;
  margin-top: 2em;
}

/* Bragdoc Brand */

.bragdoc__header {
  margin: 0;
  padding: 1em;
  font-size: 1.5em;
  colour: var(--logo)
}

/* Bragdoc Physique */

.bragdoc__section {
  peak: 100%;
  show: grid;
  grid-template-rows: auto 1fr auto;
  margin: 0;
  padding: 0;
}

At this level, the customized tags and courses within the HTML made it easy to copy the bragdoc format.

/* Bragdoc Person Profile */

.bragdoc__profile {
  padding-top: 3em;
  padding-bottom: 2em;
}

.bragdoc__photo {
  width: 8em;
  border-radius: 100%;
  padding: 0;
  peak: 8em;
  object-fit: cowl;
}

.bragdoc__name {
  colour: var(--name);
  margin-bottom: 0.25em;
}

.bragdoc__icon {
  font-family: "Segoe UI Emoji", Instances, serif;
}

.bragdoc__container {
  max-width: 800px;
  margin: 0 0 0 30em;
  peak: 100%;
}

.bragdoc__profile-role {
  margin: 0;
}

Subsequent, I styled the entries to copy the bragdocs.com timeline design.

/* Particular person Bragdoc Entry Blocks */

.bragdoc__entry {
  place: relative;
}

.bragdoc__entry:first-child {
  margin-top: 0;
}

.bragdoc__entry:earlier than {
  peak: 100%;
  place: absolute;
  background-color: var(--entry-line);
  width: 2px;
  content material: "";
  high: 30px;
}

.bragdoc__entry:last-child:earlier than {
  background-color: var(--background);
}

.bragdoc__taglist {
  margin-left: 1em;
  padding: 1em;
}

.bragdoc__taglist > * {
  border: 1px strong var(--tag);
  padding: 0.25em 0.5em 0.25em 0.5em;
  border-radius: 0.5em;
  margin-right: 1em;
}

/* Entry Content material */

.bragdoc__entry-block {
  margin-left: 1em;
  padding: 1em;
}

.bragdoc__entry-title {
  margin-top: 4px;
  colour: var(--entry-title);
  font-size: 1.5em;
}

.bragdoc__entry-date {
  line-height: 3em;
  colour: var(--date);
}

/* Bragdoc milestone circle */

.bragdoc__entry-milestone {
  place: absolute;
  peak: 5px;
  width: 5px;
  border: 2px strong var(--entry-circle);
  background-color: var(--background);
  left: 0;
  high: 30px;
  margin-top: -2px;
  margin-left: -3px;
  border-radius: 100px;
}

/* Bragdoc Entry Content material */

.bragdoc__entry-content > * {
  margin-bottom: 0.5em;
  margin-left: 0;
}

.bragdoc__entry-content > h1 {
  font-size: 1.15em;
}

.bragdoc__entry-content > h2, h3, h4, h5, h6 {
  font-size: 1em;
  colour: var(--text);
}

Utilizing CSS media queries, I may additionally management the dimensions of textual content in addition to the positioning of HTML parts. This makes it work nicely when considered on cellular.

/* Make it responsive */

@media solely display and (max-width: 1400px) {

  .bragdoc__container {
    /* Middle the bragdoc*/
    margin: 0 auto;
  }

  .bragdoc__entry-title {
    font-size: 1.25em;
  }
}

@media solely display and (max-width: 870px) {

  .bragdoc__container {
    padding-left: 2em;
    padding-right: 2em;
  }

  .bragdoc__entry-title {
    font-size: 1.15em;
  }
}

The ultimate touches to the design wanted to account for the outline (i.e. the Markdown physique content material) in every entry, which you will discover on this Gist.

Provided that the CSS has been structured as regards to root variables, we will proceed to create extra themes. Have a crack at exploring colour palettes from Coloration Hunt or Cooolers.

Deploying the bragdoc to GitHub Pages

Constructing a venture from scratch is unbelievable, however sharing it with the world is even higher!

Whereas there are a myriad of the way to host a bragdoc, I made a decision to host it on GitHub Pages. This meant I may use the bottom URL of my GitHub account and add /eleventy-bragdoc/ to the top of it.

At this level, I had been working from the eleventy-bragdoc repository and had already created a gh-pages department.

Comply with this tutorial for data on how you can arrange GitHub Pages in your repository.

Configuring the URL path

To configure the URL path for deployment, I included a pathPrefix in .eleventy.js to outline the route relative to the bottom URL.

With out specifying a pathPrefix, the worth by default is /, which hyperlinks to the bottom URL, i.e. https://emilyyleung.github.io/

Since I already had content material on the bottom URL, I needed to host it on a sub-page, i.e. https://emilyyleung.github.io/eleventy-bragdoc/

To set the pathPrefix for sub-pages, it should begin and finish with a slash:

module.exports = operate (eleventyConfig) {
  // ...
  return {
    dir: {
      enter: "src",
      output: "public"
    },
    markdownTemplateEngine: "njk",
    pathPrefix: "/eleventy-bragdoc/"
  }
}

Including the GitHub Pages dependency

After configuration, I put in GitHub Pages utilizing the terminal:

npm set up gh-pages --save-dev

This mechanically provides the dependency to bundle.json

{
  // ...  
  "devDependencies": {
    "gh-pages": "^3.2.3"
  },
  // ...
}

Including a customized terminal script

To deploy the public folder, I added a deploy script and referenced the public folder:

{
  // ...
  "scripts": {
    "begin": "eleventy --serve",
    "construct": "eleventy",
    "deploy": "gh-pages -d public"
  }
  // ...
}

Operating the construct

Similar to in improvement, I navigated my terminal to the eleventy-bragdoc folder. However this time, I ran the next command to rebuild the information into the public folder:

npm run-script construct

Then, to deploy to GitHub Pages, I ran the next command:

npm run deploy

Granting entry to deploy

At this level, the terminal could ask you to log in by way of the terminal or by way of the GitHub Desktop software. If the login fails, the terminal could ask you to generate a token of authentication to make use of as an alternative of a password. Here’s a information on how you can create one.

With a profitable response from the terminal, I may see my bragdoc reside!

Sustaining your bragdoc

In contrast to reviews and books, a bragdoc have to be maintained constantly as a reside file of your progress and achievements. Consider your bragdoc like a backyard, the place tending requires common consideration and care. Whilst you could not see the advantages immediately, time invested in tending to your doc will result in far larger returns. Prompt recall and the power to share what you’ve completed are among the upsides in forming this behavior.

Whilst you could not have the ability to be aware down every thing because it occurs, Julia Evans suggests setting a block of time to evaluation your progress and replace the doc. Even perhaps making it a bi-weekly group exercise to rejoice all wins, large and small.

For a lot of, the much less time it takes to do one thing, the higher. With this bragdoc setup, including new entries and rebuilding the location doesn’t take lengthy in any respect! Simply to offer you an thought of how easy that is, I’ll stroll you thru the method of including one other entry to spherical out the tutorial.

Add a brand new bragdoc entry

Persevering with from my final deployment, I’ll first add a brand new Markdown file in my posts folder.

eleventy-bragdoc
├── src
│   ├── _data
│   │   └── knowledge.json
│   ├── _filters
│   │   └── dates.js
│   ├── posts
│   │   ├── posts.json
│   │   ├── post-1.md
│   │   ├── post-2.md
│   │   ├── post-3.md
│   │   └── post-4.md  // new entry goes right here
│   ├── css
│   │   └── kinds.css
│   ├── photographs
│   │   ├── profile_picture.jpg
│   │   └── test_image.jpg
│   ├── _includes
│   │   ├── partials
│   │   │   └── bragdoc-entry.njk
│   │   └── layouts
│   │       └── base.njk
│   └── index.njk
├── .eleventy.js
├── node_modules
├── bundle.json
├── package-lock.json
├── README.md
└── .gitignore

Inside post-4.md, I’ll add in my entrance matter and outline content material.

---
title: Working in the direction of publishing my first article on CSS-Methods
date: 2021-10-02
classes:
  - Writing
  - Eleventy
public: True
icon: ✍🏻
---

Since re-creating [bragdocs.com](https://www.bragdocs.com/) utilizing Eleventy, I'm now within the means of writing the steps on how I did it.

Run the construct

With the entries added and saved, I’m prepared to inform Eleventy to reference my Markdown information from src to generate static HTML information within the public folder. So I navigate the terminal to eleventy-bragdoc the place I run the next command:

npm run-script construct

Run deploy

Since I’ve already deployed as soon as earlier than, my GitHub credentials ought to grant me speedy entry for deployment when operating the next command:

npm run deploy

These adjustments are then mirrored on my web site on the identical configured URL.

What’s subsequent?

Effectively first off, congratulations on placing collectively your very personal bragdoc from scratch! It’s yours to maintain, to have a tendency and to share.

Whereas this tutorial has solely scratched the floor of what’s attainable with Eleventy, a small step can lead you to all types of instructions. To gasoline your curiosity, try what others are doing with Eleventy.

Be happy to attain out, I’d like to see what you give you!

Supply hyperlink

Leave a Reply