New year, new website? Well, not really. But when starting to set up and move RAM’s website, I decided that it was probably also time for a fresh look on my own little blog. As always, coming up with the perfect theme and moving everything to your new and fully polished website takes longer than expected. The main reason is that it is hard to settle on the perfect theme. Spoiler alert, there is no such thing. At least not for me. It always involves tweaking and learning new things in JS, CSS, HTML, and all these things I have never been trained in before.
I collected all the essential tweaks that I made to the Hugo Portio theme to make it a good fit for me. I hope my future self (and hopefully also someone else) will find it useful when looking for an answer or some ideas on how to tweak their own theme.
To center my image on the landing page, I replaced the first col-lg-6
class with container centered
in the layouts/partials/hero.html
file. To keep the image right-aligned but to increase the image size, I replaced the second col-lg-6
with col-lg-9
.
I also removed everything in the hero.html
that calls the button or a video (so for instance <a type="button" class="btn btn-lg btn-primary btn-zoom" href="{{ .buttonURL | absURL }}">{{ .buttonName }}</a>
or {{ if .videoURL }} ... {{ end }}
).
Adding now a section like the following allows me to add social media icons next to my image.
<div class="table">
<ul id="horizontal-list">
<li><a href="{{ .mail | absURL }}" target="_blank" rel="noopener"><p style="color:#282f49"><i class="fa fa-envelope" style="font-size: 2em;"></i></p></a></li>
<li><a href="{{ .github | relURL }}" target="_blank" rel="noopener"><p style="color:#282f49"><i class="fa fa-github" style="font-size: 2em;"></i></p></a></li>
<li><a href="{{ .linkedin | relURL }}" target="_blank" rel="noopener"><p style="color:#282f49"><i class="fa fa-linkedin" style="font-size: 2em;"></i></p></a></li>
<li><a href="{{ .twitter | relURL }}" target="_blank" rel="noopener"><p style="color:#282f49"><i class="fa fa-twitter" style="font-size: 2em;"></i></p></a></li>
<li><a href="{{ .orcid | relURL }}" target="_blank" rel="noopener"><p style="color:#282f49"><i class="fa fa-book" style="font-size: 2em;"></i></p></a></li>
</ul>
</div>
And you would also add the following parts to your .css
/.scss
:
i {
display: inline-block;
margin-left: 0.5em;
margin-right: 0.2em;
}
ul#horizontal-list {
/*min-width: 696px;*/
list-style: none;
padding-top: 20px;
width: auto;
}
ul#horizontal-list li {
display: inline-block;
}
My hero.yml
looks like this:
---
enable: true
topTitle:
content: >
# Hello, I am Cosima
I love to work with data
github: https://github.com/cosimameyer
linkedin: https://www.linkedin.com/in/cosimameyer/
twitter: https://twitter.com/cosima_meyer
image: images/hero/avatar.jpg
And the website is like this:
Alternative text
Image showing the landing page with where it says “Hello, I am Cosima. I love to work with data” including a photo and social network icons.
Adding my beloved typing effect couldn’t be easier. I already explained how I did it for Hugo Academic and just did the very same thing for this theme.
<script src="https://cdn.jsdelivr.net/npm/typeit@7.0.4/dist/typeit.min.js"></script>
to the top part of the hero.html
<p class="multipleStrings"></p>
to the hero.html
where you want the typing effect. It’s a placeholder and will be filled in a second.hero.html
:<script>
new TypeIt(".multipleStrings", {
strings: ["This is a great string.", "But here is a better one."],
breakLines: false,
loop: true,
speed: 50
}).go();
</script>
hero.yml
(otherwise it will show up twice).And that’s it, here’s your typing effect π₯³
Alternative text
GIF showing the landing page with a typing effect where the words “I love to work with data” get typed.
The Portio theme does not come with a talk section by default. I thus adjusted the testimonialSection.html
so that it is a good fit.
The main part of the file now looks like this:
<p class="testimonial__slider_item-content"> <b>{{ .title }}</b> </p>
<img src="{{ .thumbnail }}" class="portfolio-item-thumb" alt="" />
{{ if .github }}
<a href="{{ .github | safeURL }}" target="_blank" rel="noopener"> <i class="fa fa-github"></i>{{"GitHub"}}</a>
{{ end }}
{{ if .slides}}
<a href="{{ .slides | safeURL }}" target="_blank" rel="noopener"><i class="fa fa-clipboard"></i> {{"Slides"}}</a>
{{ end }}
{{ if .recording}}
<a href="{{ .recording | safeURL }}" target="_blank" rel="noopener"><i class="fa fa-youtube"></i> {{"Recording"}}</a>
{{ end }}
<p class="testimonial__slider_item-content"> {{ .comment | markdownify }} </p>
<p class="testimonial__slider_item-author"><a href="{{ .event_url | safeURL }}" target="_blank" rel="noopener"><span>{{ .event_name }}</span></a> | {{ .time }}</p>
And this is what the testimonialSection.yml
input file can look like:
- event_name: R-Ladies Bergen
thumbnail: images/talks/nlp-rladies-bergen.png
title: Taking text data to the next level - Using supervised and unsupervised approaches in NLP
comment: Add some Description
time: December 20, 2020
github: https://github.com/cosimameyer/nlp-rladies-bergen
slides: https://cosimameyer.rbind.io/slides/nlp-rladies/talk#1
recording: https://youtu.be/bvqur70ZmyM
event_url: https://www.meetup.com/rladies-bergen/events/274392883/
The snippet allows the user to add an event_name
(usually the conference name or the organizer), a thumbnail
reference to include an image, the title
of the talk, a comment
section to be able to include some more description (in markdown), the time
of the event, a github
link to show the code, slides
for a link to the slide deck, recording
to add the recording link and event_url
to link the event page.
In the following case, I didn’t add a description but the rest looks like this:
Alternative text
Image showing the presentation slide of “Taking text data to the next level” including links to the GitHub repo, slides, and the recording.
The portfolio section links to a short description where you can showcase your service, your client, the challenge, and your solution. I think this is a fantastic approach to also presenting a data science portfolio. My projects are mainly open-source, so there is usually no “real” client involved and instead of services, I usually rely on languages. So this needed some tweaking. After adjusting the portfolio/single.html
for the main part like this:
<div class="container">
<div class="row mb-5">
<div class="col-lg-10 offset-lg-1 text-center">
<div class="case-details-title">
<h1>{{ .Title }}</h1>
</div>
<p>
{{ .Params.shortDescription }}
</p>
<div class="case-details-info">
<div class="case-details-info-item">
<h5 class="text-light">Programming<br>language</h5>
<p>{{ .Params.language }}</p>
</div>
<div class="case-details-info-item">
<h5>Field</h5>
<p>{{ .Params.field }}</p>
</div>
{{ if .Params.links }}
<div class="case-details-info-item">
<h5>Links</h5>
{{ if .Params.website}}
<a href="{{ .Params.website | safeURL }}" target="_blank" rel="noopener"><p style="color:#7e7e8a"><i class="fa fa-globe"></i> {{"Website"}}</p></a>
{{ end }}
{{ if .Params.publication}}
<a href="{{ .Params.publication | safeURL }}" target="_blank" rel="noopener"><p style="color:#7e7e8a"><i class="fa fa-book"></i> {{"Publication"}}</p></a>
{{ end }}
{{ if .Params.github }}
<a href="{{ .Params.github | safeURL }}" target="_blank" rel="noopener"><p style="color:#7e7e8a"><i class="fa fa-github"></i> {{"GitHub"}}</p></a>
{{ end }}
{{ if .Params.slides}}
<a href="{{ .Params.slides | safeURL }}" target="_blank" rel="noopener"><p style="color:#7e7e8a"><i class="fa fa-clipboard"></i> {{"Slides"}}</p></a>
{{ end }}
{{ if .Params.recording}}
<a href="{{ .Params.recording | safeURL }}" target="_blank" rel="noopener"><p style="color:#7e7e8a"><i class="fa fa-youtube"></i> {{"Recording"}}</p></a>
{{ end }}
</div>
{{ end }}
I had the following options for each portfolio.md
file (here’s an example of the Telegram bot):
---
date: "2020-07-20T00:00:00Z"
thumbnail: images/portfolio/telegram-bot.png
title: Telegram Bot
challenge: Learning complex concepts can be demanding and it might be hard to remember everything. Research has shown that repetition can help.
solution: A bot that sends you flashcards every morning and evening in Telegram using Python and AWS Lambda.
language: Python, AWS
field: Software development
github: https://github.com/dennis-hammerschmidt/telegram-bot
links: true
---
The date
option gives a date, with thumbnail
I can link an image, challenge
describes a challenge that I was facing, and solution
the respective solution. These were also the default parameters that Hugo Portio comes with. My tweak addressed the options language
, field
, github
, links
(and, if needed, also slides
, recording
, publication
, and website
). language
allows you to add the programming languages and in field
you can specify which areas the project covers (like software development, ML, …). If the toggle links
is set to true
, the theme will now automatically add all the content that you presented in github
, slides
, recording
, publication
, and website
. The output including links will look like this:
Alternative text
Image showing the portfolio on building a telegram bot (with a link section).
And without links like this:
Alternative text
Image showing the portfolio on computer visions to identify sentiments (without a link section).
If you further add a | markdownify
after challenge and solution (for instance {{ .Params.solution | markdownify }}
), you can pass markdown-based text and the theme automatically converts markdown links.
The default theme has a few dynamic patterns (bubbles and patterns of crosses) moving up and down. I like the dynamic effect the bubbles generate because they are more transparent and clean (you can see both patterns in the right upper corner of the image below).
Alternative text
Image showing R-posts with a pattern on the right side with crosses.
If you are like me and don’t enjoy the cross patterns so much, just look out for
<div class="animate-pattern">
<img src={{"images/service/background-pattern.svg" | absURL }}
alt="background-shape">
</div>
and either delete it or use <!-- Pattern -->
to remove it.
Hugo has a great guide on how to disable all services which I followed.
If you further want to add a cookie consent banner, I followed Felipe’s guideline, added the cookie-consent.html
file, and the {{- template "partials/templates/cookie-consent.html" . }}
line to footer.html
.
I also hosted the fonts myself. To do this, I followed Chris' guide which is really straightforward.
To add the option to unfold code with the common <details> <summary>Summary text</summary> HERE COMES SOME TEXT </details>
logic, I added a detail-tag.html
file to layouts/shortcodes/
which contains:
<details>
<summary>{{ (.Get 0) | markdownify }}</summary>
{{ .Inner | markdownify }}
</details>
Calling now
{{< detail-tag "Summary text" >}} HERE COMES SOME TEXT {{< /detail-tag >}}
generates this:
To do this, I set up another shortcode. It’s really simple - just copy the following lines and create a new toc.html
file and store it in layouts/shortcodes/
.
<div>
<h4>What this post is about</h4>
{{ .Page.TableOfContents }}
</div>
You can now call your table of content using
{{< toc >}}
Images are, by default, quite large in the Portio theme. I added the following code to _common.scss
:
img[alt=smaller_image] {
display: block;
float: none;
margin-left: auto;
margin-right: auto;
max-width: 100%;
height: auto;
width: 500px; }
img[alt=small_image] {
display: block;
float: none;
margin-left: auto;
margin-right: auto;
max-width: 100%;
height: auto;
width: 700px; }
img[alt=very_small_image] {
display: block;
float: none;
margin-left: auto;
margin-right: auto;
max-width: 100%;
height: auto;
width: 30%;}
It defines three different sizes of the image that I can use by calling on the alt
parameter in the image. Here are examples (from top to bottom):
Alternative text
Image showing a small version of the PythonistR logo. The logo is a blue R, an eye-mask and a pirate’s hat with a snake on one leg.
Alternative text
Image showing a smaller version of the PythonistR logo.
Alternative text
Image showing a very small version of the PythonistR logo.
I prefer using HTML code to adjust the image size and leave the alt
parameter to what it is designated to – the alternative text. But I couldn’t find a way to make it work in this case. As a workaround, I currently use the details tag (described above).
I like the integration that GitHub offers - to follow this example, I used Justin’s tutorial and implemented a “Copy” button that shows up next to code lines.
print('This is a great example how to copy your code')
An RSS feed can come in handy if you want to publish the content of your blog, for instance on R-bloggers.
For Hugo Portio, you need to add an rss.xlm
file and tweak it a bit. But that ist straightforward:
layouts/_default/rss.xml
(if there is no file, you need to create this one).<description>{{ .Summary | html }}</description>
, we want <description>{{ .Content | html }}</description>
(it’s at the very bottom of the file). This way, you RSS feed doesn’t show an excerpt but the full text.And that’s all you need π₯³
I added a slideshow.html
file to layouts/shortcodes/slideshow.html
which has the following content:
<iframe src="{{.Get 0}}" width=100% height="400" frameborder="0" scrolling="auto" allowfullscreen="allowfullscreen"></iframe>
Calling now {{< slideshow “https://cosimameyer.com/slides/correlcon2021/talk.html#1" >}} reveals this slide show:
To embed tweets, I follow a similar logic. I created a shortcode in layouts/shortcodes/statictweet.html
with the following content:
<div>
<center>
{{ (getJSON "https://api.twitter.com/1.1/statuses/oembed.json?dnt=1&hide_thread=1&id=" (index
.Params 0)).html | safeHTML }}
</center>
</div>
Calling now {{< statictweet “1570081183081402370” >}} embeds this tweet:
I love it! That's beautiful π I also love code snippets πhttps://t.co/VWjzm5rdum pic.twitter.com/4nr2EBNR4D
— We are R-Ladies (@WeAreRLadies) September 14, 2022
In a similar way, you can also add a toot (that’s what the tweets on Mastodon are called). π I followed the example by Seb here. It’s straightforward:
layouts/shortcodes/
and call it statictoot.html
.{{- $link := .Get "link" -}}
<div style="text-align:center;">
<iframe src="{{ $link }}/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="600" allowfullscreen="allowfullscreen">
</iframe>
<script src="https://fosstodon.org/embed.js" async="async"></script>
</div>
Well, that’s what I have done so far to make it a better fit for me - but there are for sure plenty more options. I did, for instance, not yet include a section on publications (not sure if I will do it in the future because there are always services like Google Scholar or ORCID that have a good overview of your publications). If you have any other ideas or suggestions, feel free to reach out. I’m always curious to learn more cool things βΊοΈ