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 thecss
folder).addPassthroughCopy
tells Eleventy that when the recordsdata are compiled, to take the contents of the listing and go it via to thepublic
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/

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 inbase.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 inYYYY-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 %}

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 %}

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.

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 %}

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!
Checkout extra Articles on Sayed.CYou
Comments
Post a Comment