How do I access data defined in a layout's front matter? - jekyll

I'd like to add some data to a layout file, to be used in my site's nav. I have a writings collection with many articles, and they use a writing layout:
// _layouts/writing.html
---
layout: default
site-section: writings
---
<div id="{{ page.site-section }}">
<article>
{{ content }}
</article>
{% include comments.html %}
</div>
I tried access the site-section variable via page.site-section, but it's not working.
How can I access that data?

It works here.
Try to do a {{ page }} it is supposed to show all the variables.

Related

liquid variables stop working when layout is defined

Big thanks to anyone who looks at this! I think the question is straightforward. It is only long because I wanted to be very thorough/ well-documented. I have taken the following example code from the jekyll documentation and edited it only so that I can find it with a permalink:
---
food: Pizza
permalink: "/pizza"
---
<h1>{{ page.food }}</h1>
When I run jekyll serve, the variable is outputted as it should be, but it has no layout. When I try to add a layout that I wrote to the page, the variable no longer outputs, as seen here.
Ultimately, I want to write an archive page that loops through categories, exactly like this code in the documentation:
{% for category in site.categories %}
<h3>{{ category[0] }}</h3>
<ul>
{% for post in category[1] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
But, because the liquid variables are not working, I cannot make the archive without either putting in in the _layouts directory or manually copy-pasting my layout to the archive page.
Sorry if I'm coming across as a jekyll newbie (I am) or if the answer is in the docs somewhere and I could not find it, but here are my questions:
Why is this behavior happening? Is it something about how jekyll works or is it my layout that is causing this?
What would be the best practice for writing the archive/ correcting this error?
The github repository for this entire project is here
It looks like you are using the wrong liquid tag for trying to get the content. When injecting the page content, use {{ content }} not {{ page.content }}. You can see an example in the docs.
Looking at your includes for post_body.html and body.html, you just need to fix the above and it should work.

How to render background image in a page generated by Jekyll?

As a novice starting out on GitHub Pages, I am lost among the sea of materials on the web that seem to help with my following problem:
I am using Jekyll to build my blog hosted via GitHub Pages and would like to add a background image in my default homepage like this.
So, how do I do it? I have started out, but have little to no knowledge of HTML / CSS and would thus be grateful for a simple way to do the same.
I am currently using the default minima theme! :)
Minima doesn't have a provision to easily render a "cover photo" like you expect to. But that doesn't mean, it is impossible to render one.
When using Minima, your homepage is rendered via the file ./index.md and layout file _layouts/home.html. So, if your working directory doesn't contain the home layout, create the _layouts directory with a file named home.html.
The home layout in Minima
I'll explain what the layout contains so that you'll be able to use that knowledge in other areas.
The layout contains the following code. Copy the entire code below into the _layouts/home.html file you just created in the above step:
---
layout: default
---
<div class="home">
{%- if page.title -%}
<h1 class="page-heading">{{ page.title }}</h1>
{%- endif -%}
{{ content }}
{%- if site.posts.size > 0 -%}
<h2 class="post-list-heading">{{ page.list_title | default: "Posts" }}</h2>
<ul class="post-list">
{%- for post in site.posts -%}
<li>
{%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
<span class="post-meta">{{ post.date | date: date_format }}</span>
<h3>
<a class="post-link" href="{{ post.url | relative_url }}">
{{ post.title | escape }}
</a>
</h3>
{%- if site.show_excerpts -%}
{{ post.excerpt }}
{%- endif -%}
</li>
{%- endfor -%}
</ul>
<p class="rss-subscribe">subscribe via RSS</p>
{%- endif -%}
</div>
Let's dissect the layout chunk by chunk:
---
layout: default
---
This is a front matter block that tells Jekyll the 'home' layout is a subset of the 'default' layout.
<div class="home">
This opens up a container for everything else on the home page and is closed by the </div> on the very last line.
{%- if page.title -%}
<h1 class="page-heading">{{ page.title }}</h1>
{%- endif -%}
This a template instruction that would render the home page's title if it was provided in the front matter inside file ./index.md.
{{ content }}
This is another template instruction that pulls in content (anything apart fron the front matter) from the file using this layout. In our case, that would be ./index.md.
The remaining chunk {%- if site.posts.size > 0 -%} cycles through the posts in your site and renders a list of those posts.
The cover image
We now have a fair idea regarding what our template is made of. But there is no mention of the code to render the cover-photo.
Agreed. So, let us code that in then. Insert the code from the following steps before the line with {{ content }} in the layout
First, add a container for the image.
<div class="hero">
</div>
Then insert the HTML markup to render the image of your choice (say, ./assets/home-feature.jpg) within it:
<div class="hero">
<img class="feature-img" src="{{ 'assets/home-feature.jpg' | relative_url }}" />
</div>
With just the above markup, your image would perhaps be too big for your page. So we should constrain the size with some CSS styling.
Minima uses Sass partials to generate the CSS for your site. Therefore, we'll need to overwrite a partial with some custom code.
Create a new directory named _sass with a subdirectory named minima and finally a file inside the _sass/minima directory named _layout.scss. Copy the contents at this link into that file.
Now add the following custom code towards the end of the file:
/* Cover Image */
.hero {
.feature-img: {
max-width: 100%;
}
}
Rendering background image
All of the above is to just render a cover-photo. To render the image as a proper background-image, you can do the following..
First, we need to adjust the markup to render text in the foreground and image only as the background:
<div class="hero">
{{ page.hero_text }}
</div>
With the above in place you are now able to control the text over your background-image via front matter in ./index.md.
And then bring back the image using CSS:
/* Cover Image */
.hero {
background: url('../home-feature.jpg');
}
Getting the url to your image is a little tricky since we can't use Liquid instructions inside sass partials in vanilla Jekyll. So you'll have to experiment with it for your particular site.
For more tips regarding CSS backgrounds, check this link
Have you look into the inspector tool? Another easy way is to look at the code snippet of that website which you can find here: https://github.com/mnp-club/mnp-club.github.io
I'm pulling up the exact code for what they do to achieve that effect this will :
https://github.com/mnp-club/mnp-club.github.io/blob/master/_layouts/page.html
<div id="main" role="main">
<article class="entry">
{% if page.image.feature %}<img src="{{ site.url }}/images/{{ page.image.feature }}" class="entry-feature-image" alt="{{ page.title }}"{% endif %}
// Alternatively a simpler way will be to just include the img src code.
// <img src="insert-image-url.jpg" class="entry-feature-image"/>
// Whole bunch of code for body here
</article>
</div>
And to make it a full-width header image, just give it a css of
.entry-feature-image {
width: 100%;
}
My blog run on jekyll minima and github pages as well and I have a default header for certain pages. Making it full width is just a matter of CSS.
https://github.com/wing-puah/thegeekwing-jekyll/blob/master/_layouts/default.html
What you can do is just add the html code for the image to the _layouts/default.html file.
There are different ways to achieve what you want. Understand that you have little experience with html and css but I will suggest to pull up the inspector tools and see the code to identify which code does what. Hope that helps!

How to show content of about.md on homepage as default in jekyll?

I am working on github pages with jekyll. I want to put the about me on my homepage by default.
I've searched a lot but found little help for this demand.
One easy method is to put the about.md file in the _posts directory with the first date. Then, when Jekyll indexes _posts, you can always assume that site.posts.first is the about.md.
Some sample code below:
---
layout: default
---
<section class="main-content">
{% assign post = site.posts.first %}
{% assign content = post.content %}
<article class="module color-3">
{{ content }}
</article>
</section>

Jekyll and modular/atomic design

I am currently looking at developing a "static" website, few pages only. However, by design, I can tell there is going to be repetitive layouts/patterns. I am thinking doing a data-oriented approach, with my HTMLs being as reusable as possible. Here is an example:
index.html:
<div>
{% include organisms/topBanner.html
tp-title=site.data.home.topbanner.title
tp-select-blurb=site.data.home.topbanner.select.blurb
button-text=site.data.generic.buttons.getstarted
button-link=site.data.generic.links.gosomewhere
%}
</div>
then my organisms/topBanner.html:
<div class="tb">
<h1>
{{ include.tp-title }}
</h1>
<div>
<h2>{{ include.tp-select-blurb }}</h2>
<div>
{% include atoms/button.html
%}
</div>
</div>
</div>
finally my atoms/button.html:
<a class="button" href="{{ include.button-link }}">{{ include.button-text }}</a>
I have multiple JSON file under _data that basically hold the texts. An example for the button would be a _data/generic/buttons.json:
{
"getstarted": "GET STARTED",
"completesurvey": "COMPLETE THE SURVEY"
}
or links.json:
{
"gosomewhere": "/go-somwhere",
"surveypage": "/survey"
}
So this means you need to pass all your data from the top level include of the organism so every bits in it would have its data. That way the example of that button is that the HTML is defined only once and the data is bound to it. And for a second button to be in the topBanner you could do something like this:
index.html:
<div>
{% include organisms/topBanner.html
tp-title=site.data.home.topbanner.title
tp-select-blurb=site.data.home.topbanner.select.blurb
b-getstarted-text=site.data.generic.buttons.getstarted
b-getstarted-link=site.data.generic.links.gosomewhere
b-survey-text=site.data.generic.buttons.completesurvey
b-survey-link=site.data.generic.links.surveypage
%}
</div>
and in the topBanner.html, you rebind the data to the dedicated button:
<div class="tb">
<h1>
{{ include.tp-title }}
</h1>
<div>
<h2>{{ include.tp-select-blurb }}</h2>
<div id="getstarted">
{% include atoms/button.html
button-text=include.b-getstarted-text
button-link=include.b-getstarted-link
%}
</div>
<div id="survey">
{% include atoms/button.html
button-text=include.b-survey-text
button-link=include.b-survey-link
%}
</div>
</div>
</div>
This approach means everything is data driven, there is no repetition/'copy/paste' of HTML, it all works through includes and you can apply atomic design pattern (http://patternlab.io/).
Wanna change the text of the button from 'GET STARTED' to 'LET'S START'? Go to the data/generic/buttons.json and change it there. The whole website now has the text changed.
The drawback is the fact that all the data has to trickle down from top level. Readability might be bad.
First use of Jekyll for me, and waned to have your opinion on this. What is good practice for static website dev like this? Is it easier to have a buttonGetStarted.html that includes a more generic button.html, and pass the data to button.html from buttonGetStarted.html? Like:
buttonGetStarted.html:
{% include atoms/button.html
button.text=site.data.generic.buttons.getstarted
button.text=site.data.generic.links.gosomewhere
%}
and then include buttonGetStarted every time I need it on the page? But then if I need a new button for the survey, I need to create another html buttonSurvey.html and so on... Sure on the code you see an {% include buttonSurvey.html %} which is easy to read and understandable straight away what this button is about. So this:
{% include button.html button.text=site.data.generic.buttons.getstarted %}
with only one file button for all the buttons, or
{% include buttonGetStarted.html %}
with creation of a new HTML file everytime I need a new button?
Thanks
F.
Disclaimer : As this question is primarily opinion-based (see SO help on this), I've voted to close it.
However, I can give my two cents. Quote are from Atomic Design Methodology.
Atom
[...] elements that can’t be broken down any further without ceasing to be functional
atom/buttons.html
<a class="button" href="{{ include.datas.button-link }}">
{{ include.dats.button-text }}
</a>
Molecule
[...] molecules are relatively simple groups of UI elements functioning together as a unit.
Here the question is : "do we need datas from organism / page for our molecule to work ?"
Yes : Datas will be passed by the parent organism. molecule/buttonGetStarded.html looks like (Note : this molecule is Homonuclear, but is functionnal.)
{% include button.html datas=include.buttonDatas %}
No : Datas will be set from inside the molecule (imaginary data structure)
{% include button.html datas=site.data.buttonDatas.getStarted %}
So in your case, I think that organism/topBanner.html can be composed like this (simplified for readability) :
{{ include.tp-title }}
<h2>{{ include.tp-select-blurb }}</h2>
<div id="getstarted"> {% include molecules/buttonGetStarted.html %}</div>
<div id="survey"> {% include molecules/buttonSurvey.html %}</div>
As I guess that your data files can be used for Internationalization (I18n) purpose. The molecule language doesn't need to be passed all the way down. It can be guessed by the molecule itself.
{% if page.language == nil %}
// if no language variable in page's front matter
// we default to site language set in _config.yml
{% assign language = site.language %}
{% else %}
// language variable present in front matter
{% assign language = page.language %}
{% endif %}
// get datas depending on guessed language
{% assign datas = site.data[language] %}
// this can even be more atomic with
{% assign datas = site.data[language]['buttonSurvey'] %}
// include the atom with correct language datas
{% include atom/button.html datas=datas %}
Note that this logic can even be factorized.

{{ content }} Liquid tag not showing blog posts

Link to repo: https://github.com/AlvSovereign/AlvSovereign.github.io
I am coding my portfolio site, with a link to my blog. The fully processed portfolio site sits in _site/index.html which contains a link to the blog (fully processed link exists in _site/blog.html)
Blog.html at the root of the repo has in the front matter a layout of "bl", which is defined in my layouts folder under "bl.html".
"bl.html" is the layout I want for my blog page, which contains my includes etc. It also contains the {{ content }} liquid tag.
If I am thinking about this the right way, my posts are being parsed (I think this is the right terminology) into "post.html" - which has the front matter "layout: bl", which then parsed into "bl.html", and that this is so as they both have {{ content }} in each files.
Now all my posts are showing correctly (i think) within _site/(year)/(month) etc. However, they are not ending being parsed through my "blog.html" file, and then visible on my webpage. How I know this is that the fully processed "blog.html" file does not have any of the posts in them.
What will I need to do to solve this issue?
If it helps, I use Prepros for LiveReload, and using LANYON template, http://lanyon.getpoole.com/
{{ content }} refers to all the content that in the file that is being converted to HTML code.
For example, if you are passing a blog post on 'What is Jekyll' to any layout that has the {{ content }} tag, all text other than the YAML front matter will be put in that place. Basically the content of the post. You can also limit the scope by using {{ post.content }}, see Variables for more info here.
So the Liquid {{ content }} variable works as intended.
Looking at your website, I believe you're trying to display all the posts in your blog.html file, so what you're actually asking about is why aren't my posts being displayed (not parsed) in your blog.html file, hence not visible on your webpage.
The reason for that is because you shouldn't use {{ content }} tag for that, what you want instead is something like this snippet of code as mentioned in the Jekyll docs, that will grab all your posts, and display them by post title, as well as a link to that post. Here's the code to display a list of your posts. (taken from the website I linked you)
<ul>
{% for post in site.posts %}
<li>
{{ post.title }}
</li>
{% endfor %}
</ul>
So just swap out {{ content }} in your bl.html layout with that code snippet and you've got what you want.
Additionally, if you also want to display the content/excerpt in the list of posts, just add the liquid tag {{ post.content }} or {{post.excerpt}} like so:
<ul>
{% for post in site.posts %}
<li>
{{ post.title }}
{{ post.content }} /* or post.excerpt */
</li>
{% endfor %}
</ul>
Of course, edit the HTML accordingly for your preference. Read the documentation on how to set up post excerpts here, which uses the <!--more--> comment separator for excerpts.
I strongly recommend reading the JekyllRb documentation for more information, it's a lot to read and not always easily understandable, but keep referring to it and you'll understand more in no time.