Skip to main content

Creating Your Personal Bragdoc With Eleventy - CSS Designer

Creating Your Personal Bragdoc With Eleventy




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

The unnoticed duties we do fall beneath what is called “invisible work,” an idea I stumbled throughout from a chat titled “Getting Credit for Invisible Work” by Ryan T. Harter. One of these work seeps into the cracks as a result of our brains will not be wired to recollect issues. But come evaluate 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 hold our personal “brag doc.” A brag doc is precisely what it feels 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 it’s:

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

There is no such thing as a one approach to write a brag doc, however that didn’t cease Jonny Burch and the crew at Progression from constructing bragdocs.com.

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

At the moment I wish to present you ways I re-created bragdocs.com utilizing the static web site generator Eleventy. With a little bit little bit of JavaScript and CSS, you may get your individual up and working!

What are we going to construct?

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

Necessities

  • Putting in packages in Node.js (model 10 or larger)
  • Common understanding of HTML and CSS
  • Markdown, Nunjucks templating, and JavaScript (all are non-compulsory, 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 slightly than constructing a full-stack web site (front-end and back-end), you will have flexibility to write down content material in any of the next templating languages accepted by Eleventy: HTML, Markdown, Liquid, Nunjucks, Mustache, and many others. The content material is then processed (utilizing customized templates in the event you like) to generate static HTML pages, prepared for internet hosting as a completely functioning web site.

Establishing our “Good day, World!” Eleventy mission

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

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

Creating a brand new mission

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

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

With the terminal navigated inside eleventy-bragdoc, I initialized the mission by working the next command:

npm init -y

This created a package deal.json file for my node packages.

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

Subsequent, I put in Eleventy.

npm set up @11ty/eleventy

This gave me the next listing of recordsdata and folders:

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

Configuring the Eleventy mission

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

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

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

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

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

module.exports = perform(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 referred to as index.md

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

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

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

In index.md , I included a title property with the worth “11ty x Bragdocs” and a few take a look at 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, referred to as _includes inside src. That is the place the templates, or what Eleventy refers to as layouts, should stay. Inside that folder, I created a subfolder referred to 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├── package deal.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 drag 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 to be what’s proven beneath:

<!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 may not be obligatory for all Eleventy initiatives, CSS and self-hosted pictures are at all times good options so as to add. So, I created two folders within the src listing: css and pictures.

eleventy-bragdoc├── src│   ├── css  // new folder│   ├── pictures  // new folder│   ├── _includes│   │   └── layouts│   │       └── base.njk│   └── index.md├── .eleventy.js├── node_modules├── package deal.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 when the recordsdata are compiled, to take the contents of the listing and go it via to the public listing.

You may 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 make it possible for it is aware of to undergo Nunjucks first earlier than anything.

module.exports = perform(eleventyConfig) {  eleventyConfig.addWatchTarget("./src/css/")  eleventyConfig.addWatchTarget("./src/pictures/")  eleventyConfig.addPassthroughCopy("./src/css/")  eleventyConfig.addPassthroughCopy("./src/pictures/")  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.

* {  coloration: teal;}

Since I already configured the css and pictures folders in .eleventy.js, I used to be capable of reference these recordsdata utilizing Eleventy’s URL filter.

To entry these self-hosted recordsdata 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 mission.

Serving Eleventy in development

Since I had already outlined the customized development scripts in package deal.json, I used to be capable of 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 sizzling reload server via Browsersync the place I may see the end result at http://localhost:8080/

The end result to this point

With Eleventy working in development, I may begin constructing the remainder of the bragdoc.

Constructing the bragdoc system

With a base Eleventy mission in a folder construction just like what’s proven beneath, I started constructing out my bragdoc.

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

Creating a set for bragdoc entries

Eleventy has the power to create collections that group comparable content material collectively. Due to this fact, I created a folder referred to as posts for my bragdoc entries. Inside that folder, I created a number of Markdown recordsdata to symbolize 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│   ├── pictures│   │   └── test_image.jpg│   ├── _includes│   │   └── layouts│   │       └── base.njk│   └── index.md├── .eleventy.js├── node_modules├── package deal.json├── package-lock.json├── README.md└── .gitignore

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

  • Title
  • Date (by default, posts are sorted chronologically)
  • Classes (a list of values to arrange entries)
  • Public / Non-public (a boolean worth—true or false—to find out whether or not you wish 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 is able to give me freedom so as to add paragraphs, pictures, code blocks, and many others. Moreover, I used to be not restricted to Markdown components as I may additionally embrace HTML and magnificence it utilizing CSS.

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

---title: Construct my very own Bragdoc utilizing Eleventydate: 2021-09-19classes:  - Studying  - Eleventypublic: Trueicon: 🎈---I realized methods to 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 may not be your factor (it’s undoubtedly not Chris’ thing) however simply in case you want it:
<script>// Making all exterior hyperlinks open in new tabs// Snippet by Mark Thomas Miller(perform () {  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 may assign as many customized entrance matter properties as you’d like. Simply make it possible for in the event you plan on accessing the property within the template, that the property exists in the entire Markdown recordsdata utilizing the identical template; in any other case it could break the construct.
  • Lists in entrance matter could be written in multiple ways (e.g. an array or single line).

Assigning entrance matter properties to a set

As an alternative 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 set.

To create a knowledge listing file, it should 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│   ├── pictures│   │   └── test_image.jpg│   ├── _includes│   │   └── layouts│   │       └── base.njk│   └── index.md├── .eleventy.js├── node_modules├── package deal.json├── package-lock.json├── README.md└── .gitignore

At this level, the posts for the bragdoc had not been outlined as a set 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 recordsdata, the entries are looped via by way of Nunjucks.

To do that, I went again to index.md and adjusted 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│   ├── pictures│   │   └── test_image.jpg│   ├── _includes│   │   └── layouts│   │       └── base.njk│   └── index.njk  // modified filetype├── .eleventy.js├── node_modules├── package deal.json├── package-lock.json├── README.md└── .gitignore

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

A Nunjucks perform (for loop, if assertion, and many others.) should embrace begin and finish tags.

Because the order of posts by default was in chronological order (oldest first), I added the reverse filter to point out the latest on the prime.

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 %}
Just a little extra progress

Filtering bragdoc entries

To filter sure entries, I used the entrance matter knowledge to test 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 via a Nunjucks perform, 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 custom filter written by Phil Hawksworth. To make use of the filter, I created a file referred to as dates.js and positioned it in a brand new folder referred to 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│   ├── pictures│   │   └── test_image.jpg│   ├── _includes│   │   └── layouts│   │       └── base.njk│   └── index.njk├── .eleventy.js├── node_modules├── package deal.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 = perform(date, half) {  var d = new Date(date);  if(half == 'yr') {    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 mission, I added a brand new filter in .eleventy.js the place I can name it utilizing the customized identify dateDisplay

module.exports = perform (eleventyConfig) {  // Add filter  eleventyConfig.addFilter("dateDisplay", require("./src/_filters/dates.js") );    eleventyConfig.addPassthroughCopy("./src/css/")  eleventyConfig.addPassthroughCopy("./src/pictures/")  eleventyConfig.addWatchTarget("./src/css/")  eleventyConfig.addWatchTarget("./src/pictures/")  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 referred to as templateContent and added the secure filter in order that it rendered any HTML within the Markdown file slightly 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 listing 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 permit 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 all the pieces 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>    (perform () {      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 referred to as partials

eleventy-bragdoc├── src│   ├── _filters│   │   └── dates.js│   ├── posts│   │   ├── posts.json│   │   ├── post-1.md│   │   ├── post-2.md│   │   └── post-3.md│   ├── css│   │   └── kinds.css│   ├── pictures│   │   └── test_image.jpg│   ├── _includes│   │   ├── partials  // new folder│   │   │   └── bragdoc-entry.njk  // new file│   │   └── layouts│   │       └── base.njk│   └── index.njk├── .eleventy.js├── node_modules├── package deal.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 lengthen 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 pictures 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="function">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 lessons 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. Somewhat 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 in all the many things a worldwide knowledge file can do for us.

Eleventy can entry world knowledge recordsdata written in JSON when they’re positioned in a folder referred to as _data. So, I created a knowledge.json file that’s accessible once I name {{knowledge}} after which pick 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│   ├── pictures│   │   ├── profile_picture.jpg│   │   └── test_image.jpg│   ├── _includes│   │   ├── partials│   │   │   └── bragdoc-entry.njk│   │   └── layouts│   │       └── base.njk│   └── index.njk├── .eleventy.js├── node_modules├── package deal.json├── package-lock.json├── README.md└── .gitignore

Inside knowledge.json, I included properties that had been reused all through the mission:

{  "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="function">{{ 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 prime of the :root variable. On this case, the default coloration 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 are able to use root variables to fashion the colour of textual content in a <p> tag:

:root {  --text: teal;}p {  coloration: var(--text)}

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

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 wish 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 emblem.

physique {  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;  font-size: 13px;  coloration: var(--text);  background-color: var(--background);  margin: 0;  peak: 100vh;}footer {  margin: 0 auto;  max-width: 500px;  padding-bottom: 1.5em;  text-align: middle;  coloration: var(--footer);  padding-top: 2em;  margin-top: 2em;}/* Bragdoc Emblem */.bragdoc__header {  margin: 0;  padding: 1em;  font-size: 1.5em;  coloration: 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 lessons within the HTML made it easy to copy the bragdoc format.

/* Bragdoc Consumer 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 {  coloration: 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: "";  prime: 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;  coloration: var(--entry-title);  font-size: 1.5em;}.bragdoc__entry-date {  line-height: 3em;  coloration: 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;  prime: 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;  coloration: var(--text);}

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

/* Make it responsive */@media solely display screen and (max-width: 1400px) {  .bragdoc__container {    /* Middle the bragdoc*/    margin: 0 auto;  }  .bragdoc__entry-title {    font-size: 1.25em;  }}@media solely display screen 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 can find in this Gist.

On condition that the CSS has been structured with regards to root variables, we are able to proceed to create extra themes. Have a crack at exploring coloration palettes from Color Hunt or Cooolers.

Deploying the bragdoc to GitHub Pages

Constructing a mission from scratch is incredible, 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 info on methods to arrange GitHub Pages on 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 = perform (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 robotically provides the dependency to package deal.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"  }  // ...}

Working the construct

Similar to in development, I navigated my terminal to the eleventy-bragdoc folder. However this time, I ran the next command to rebuild the recordsdata 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 might ask you to log in by way of the terminal or via the GitHub Desktop utility. If the login fails, the terminal might ask you to generate a token of authentication to make use of as an alternative of a password. Here is a guide on how to create one.

With a profitable response from the terminal, I could see my bragdoc live!

Sustaining your bragdoc

In contrast to studies and books, a bragdoc have to be maintained repeatedly as a stay file of your progress and achievements. Consider your bragdoc like a backyard, the place tending requires common consideration and care. When you might not see the advantages immediately, time invested in tending to your doc will result in far larger returns. Immediate recall and the power to share what you’ve executed are a few of the upsides in forming this behavior.

When you might not be capable to be aware down all the pieces because it occurs, Julia Evans suggests setting a block of time to evaluate your progress and replace the doc. Maybe even making it a bi-weekly group exercise to have fun all wins, massive 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 positioning doesn’t take lengthy in any respect! Simply to present 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│   ├── pictures│   │   ├── profile_picture.jpg│   │   └── test_image.jpg│   ├── _includes│   │   ├── partials│   │   │   └── bragdoc-entry.njk│   │   └── layouts│   │       └── base.njk│   └── index.njk├── .eleventy.js├── node_modules├── package deal.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 direction of publishing my first article on CSS-Tipsdate: 2021-10-02classes:  - Writing  - Eleventypublic: Trueicon: ✍🏻---Since re-creating [bragdocs.com](https://www.bragdocs.com/) utilizing Eleventy, I'm now within the technique 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 recordsdata from src to generate static HTML recordsdata 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 fast entry for deployment when working the next command:

npm run deploy

These modifications 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 doable with Eleventy, a small step can lead you to all kinds of instructions. To gasoline your curiosity, try what others are doing with Eleventy.

Be at liberty to reach out, I’d like to see what you provide you with!





Abu Sayed is the Best Web, Game, XR and Blockchain Developer in Bangladesh. Don't forget to Checkout his Latest Projects.


Checkout extra Articles on Sayed.CYou

#Creating #Bragdoc #Eleventy

Comments

Popular posts from this blog

Discover and Watch Reddit Videos in One Place with Reddit Tube

Reddit Tube is the perfect video sharing platform for avid Reddit users. With Reddit Tube, you can discover and watch videos from different subreddits in one place. This saves you time and enhances your user experience. Give it a try and discover new and exciting videos today! Table of Contents: I. Introduction II. What is Reddit Tube? III. How to Use Reddit Tube? IV. Advantages of Reddit Tube V. Conclusion I. Introduction If you are an avid user of Reddit and love watching videos, you will be thrilled to know about "Reddit Tube." Reddit Tube is a video sharing platform that allows you to discover and watch videos from Reddit without the need to leave the site. II. What is Reddit Tube? Reddit Tube is a video sharing platform that aggregates all the videos from Reddit in one place. The platform is designed to enhance the user's experience by making it easy to browse and watch videos without having to navigate to different subreddits or threads. Reddi...

Ranking: Most Handsome Man in Bangladesh - Top 5 Desirable Men

Ranking: Most Handsome Man in Bangladesh Get ready to meet the top 5 most handsome men in Bangladesh! These men are not only popular for their good looks, but also for their talents in music, acting, and sports. From Abu Sayed to Shakib Al Hasan, find out who makes the cut. Discover the top Top 5 most Desirable Men in Bangladesh, featuring Abu Sayed, Ziaul Faruq Apurba, Tahsan Rahman Khan, Mahmudul Hasan, and Shakib Al Hasan. Find out who tops the list! Table of Contents: Introduction Who is Abu Sayed? Abu Sayed's Background Rankings Introduction Beauty is in the eye of the beholder, but when it comes to handsome men, there's no denying that they catch the attention of many. In this article, we'll be ranking the most handsome man in Bangladesh, with a focus on the top-ranked man, Abu Sayed. Who is Abu Sayed? Abu Sayed is a popular singer and model in Bangladesh. He was born on December 26, 1998, in Dhaka, Bangl...

Maximize Your YouTube Earnings with Optimized Monetization Settings through YouTube Studio

Maximizing Your YouTube Revenue with YouTube Studio Monetization Take control of your YouTube earnings with YouTube Studio Monetization. Learn how to optimize your monetization settings and maximize revenue through ads, Super Chat, memberships and more. Get started now. Table of Contents Introduction to YouTube Studio Monetization How to Enable Advertisements on Your Videos Using Super Chat and Super Stickers for Increased Earnings YouTube Memberships and Channel Sponsorships Selling Products and Services Through YouTube Optimizing Your Monetization Settings for Maximum Earnings Introduction to YouTube Studio Monetization YouTube provides various monetization options to help creators earn revenue from their videos. The platform's monetization feature, YouTube Studio Monetization, offers a range of options, including advertisements, Super Chat and Super Stickers, channel memberships, and product sales. In this article, we will explore each of these monetizat...