Creating Your Personal Bragdoc With Eleventy

No Comments

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

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. One of these work seeps into the cracks as a result of our brains should not wired to recollect issues. But come evaluate time, we discover ourselves repeatedly caught when making an attempt to recall what we did over the previous 6 or 12 months.

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

The way you contributed to a projectHelping othersImproving current processesGiving talks or operating workshopsWhat you learnedExtra-curricular actions (e.g. running a blog, talks, private tasks)Awards and profession development

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

Utilizing their website to construct one is a superb concept, however what higher solution to brag about your work than to create your individual brag doc from scratch?

Immediately I need to present you ways I re-created bragdocs.com utilizing the static website generator Eleventy. With a bit little bit of JavaScript and CSS, you may get your individual up and operating!

What are we going to construct?

Beneath is the tip results of following this tutorial. You could find the dwell demo right 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 CSSMarkdown, Nunjucks templating, and JavaScript (all are non-obligatory, however useful)Primary programming ideas, together with if statements, loops, and accessing variables in JSON

What’s Eleventy?

Eleventy is a static website generator. Because of this fairly than constructing a full-stack web site (front-end and back-end), you have got flexibility to put in writing content material in any of the next templating languages accepted by Eleventy: HTML, Markdown, Liquid, Nunjucks, Mustache, and so forth. The content material is then processed (utilizing customized templates should you like) to generate static HTML pages, prepared for internet hosting as a totally functioning website.

Establishing our “Good day, World!” Eleventy challenge

On this tutorial, the repository I’ll be referring to is eleventy-bragdoc, and the ultimate product we’re working in the 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 challenge.

Creating a brand new challenge

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 challenge 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 record of information and folders:

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

Configuring the Eleventy challenge

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 challenge throughout improvement which runs Browsersync for decent 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 referred to 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 informed 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 referred to 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 referred to as index.md

Eleventy works with many templating languages that 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
├── 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, referred to as _includes within src. That is the place the templates, or what Eleventy refers to as layouts, should dwell. 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
├── 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 title=”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 wished 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 supplied protected filter, I informed Eleventy to render as a substitute 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 title=”viewport” content material=”width=device-width, initial-scale=1.0″>
<title>{{ title }}</title>
</head>
<physique>
<h1>{{ title }}</h1>
{ protected }
</physique>
</html>

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


title: “11ty x Bragdocs”
structure: “layouts/base.njk”

That is the house web page.

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

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta title=”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 obligatory for all Eleventy tasks, CSS and self-hosted photographs are at all times 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 wished 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 go it by to the public listing.

You’ll be able to 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.

* {
shade: 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 title=”viewport” content material=”width=device-width, initial-scale=1.0″>
<title>{{ title }}</title>

<hyperlink rel=”stylesheet” href=”{ url }”>

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

<img src=”{ url }”>

{ protected }
</physique>
</html>

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

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 Browsersync the place I may see the outcome at http://localhost:8080/

The outcome up to now

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

Constructing the bragdoc system

With a base Eleventy challenge in a folder construction just 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 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 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 assumed could be helpful to incorporate:

TitleDate (by default, posts are sorted chronologically)Classes (an inventory 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 could be the physique content material of the Markdown file, as this could give me freedom so as to add paragraphs, photographs, code blocks, and so forth. Moreover, I used to be not restricted to Markdown components as I may additionally embrace HTML and magnificence it utilizing CSS.

Beneath 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 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’ll be able to assign as many customized entrance matter properties as you’d like. Simply guarantee that should 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 could break the construct.Lists in entrance matter could be written in a number of methods (e.g. an array or single line).

Assigning entrance matter properties to a set

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 set.

To create a knowledge listing file, it will need to have the identical title 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 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 submit 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 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
│ ├── 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 forth.) 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 latest on the high.

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


title: “11ty x Bragdocs”
structure: “layouts/base.njk”

reverse %
<p>
{{ submit.knowledge.date }} – {{ submit.knowledge.title }}
</p>
{% endfor %}

A little bit 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, comparable to public by a Nunjucks operate, I once more wanted to undergo one other “knowledge” layer.


title: “11ty x Bragdocs”
structure: “layouts/base.njk”

reverse %
{% if submit.knowledge.public %}
<p>
{{ submit.knowledge.date }} – {{ submit.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 typically 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 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
│ ├── 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 challenge, I added a brand new filter in .eleventy.js the place I can name it utilizing the customized title 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”
structure: “layouts/base.njk”

reverse %
{% if submit.knowledge.public %}
<p>
{ dateDisplay } – {{ submit.knowledge.title }}
</p>
{% endif %}
{% endfor %}

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

The posts with up to date date formatting.

To return the physique content material of a submit, I referred to as templateContent and added the protected filter in order that it rendered any HTML within the Markdown file fairly than escaping it.


title: “11ty x Bragdocs”
structure: “layouts/base.njk”

reverse %
{% if submit.knowledge.public %}
<p>
{ dateDisplay } – {{ submit.knowledge.title }}
<br/>
{ protected }
</p>
<br/>
{% endif %}
{% endfor %}

The posts with physique content material.

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


title: “11ty x Bragdocs”
structure: “layouts/base.njk”

reverse %
{% if submit.knowledge.public %}
<p>
{ dateDisplay } – {{ submit.knowledge.title }}
<br/>
{ protected }
{% for class in submit.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 the whole lot besides the content material and snippet.

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

<hyperlink rel=”stylesheet” href=”{ url }”>
</head>
<physique>
{ protected }
<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 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
│ ├── 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 } – {{ submit.knowledge.title }}
<br/>
{ protected }
{% for class in submit.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”
structure: “layouts/base.njk”

reverse %
{% if submit.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”
structure: “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=”{ url }”>
<h1 class=”bragdoc__name”>Emily Y Leung</h1>
<div class=”function”>Computational Designer</div>
</div>
reverse %
{% if submit.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”>{{ submit.knowledge.icon }}</span> {{ submit.knowledge.title }}</h2>
<div class=”bragdoc__entry-content”>
{ protected }
</div>
</div>
<div class=”bragdoc__taglist”>
{% for class in submit.knowledge.classes %}
<span># {{class}}</span>
{% endfor %}
</div>
</div>

Accessing world knowledge

A great way to grasp world knowledge is to think about constructing a HTML template that somebody may use as a base for his or her web site. Reasonably than looking for 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 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 referred to as _data. So, I created a knowledge.json file that’s accessible after I name {{knowledge}} after which pick no matter properties I had supplied 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 challenge:

{
“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=”{ 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=”{{ 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 wished 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 shade theme is “mild” no matter whether or not data-theme is assigned to the <html> tag. However that additionally signifies that if I wished to create a “darkish” theme, I may create a brand new selector html[data-theme=”dark”] in my CSS, and assign different 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 title 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 {
shade: 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. “mild” or “darkish.”

<!DOCTYPE html>
<html lang=”en” data-theme=”mild”>

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;
shade: var(–text);
background-color: var(–background);
margin: 0;
peak: 100vh;
}

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

/* Bragdoc Emblem */

.bragdoc__header {
margin: 0;
padding: 1em;
font-size: 1.5em;
shade: 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 duplicate the bragdoc structure.

/* 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 {
shade: 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 duplicate 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 stable 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;
shade: var(–entry-title);
font-size: 1.5em;
}

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

/* Bragdoc milestone circle */

.bragdoc__entry-milestone {
place: absolute;
peak: 5px;
width: 5px;
border: 2px stable 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;
shade: var(–text);
}

Utilizing CSS media queries, I may additionally management the scale of textual content in addition to the positioning of HTML components. This makes it work nicely when seen 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 could find on this Gist.

Provided that the CSS has been structured just about root variables, we are able to proceed to create extra themes. Have a crack at exploring shade palettes from Shade Hunt or Cooolers.

Deploying the bragdoc to GitHub Pages

Constructing a challenge from scratch is improbable, however sharing it with the world is even higher!

Whereas there are a myriad of how 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 tip 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 arrange GitHub Pages to 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 wished 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 robotically 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 might ask you to log in by way of the terminal or by the GitHub Desktop utility. If the login fails, the terminal might ask you to generate a token of authentication to make use of as a substitute of a password. Here’s a information on create one.

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

Sustaining your bragdoc

Not like reviews and books, a bragdoc have to be maintained repeatedly as a dwell file of your progress and achievements. Consider your bragdoc like a backyard, the place tending requires common consideration and care. Whilst you might not see the advantages immediately, time invested in tending to your doc will result in far better returns. Immediate recall and the power to share what you’ve accomplished are a number of the upsides in forming this behavior.

Whilst you might not be capable of observe down the whole lot because it occurs, Julia Evans suggests setting a block of time to evaluate your progress and replace the doc. Even perhaps making it a bi-weekly group exercise to have a good time 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 location doesn’t take lengthy in any respect! Simply to present you an concept 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-Tips
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 strategy 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 fast entry for deployment when operating the next command:

npm run deploy

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

What’s subsequent?

Properly 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 potential with Eleventy, a small step can lead you to all kinds of instructions. To gasoline your curiosity, take a look at what others are doing with Eleventy.

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

The submit Creating Your Personal Bragdoc With Eleventy appeared first on CSS-Tips. You’ll be able to assist CSS-Tips by being an MVP Supporter.

    About Marketing Solution Australia

    We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.

    Request a free quote

    We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.

    Subscribe to our newsletter!

    More from our blog

    See all posts

    Leave a Comment