How I Made This Website
How I Made This Website
word count: 3332
reading time: 16 minutes
creation date:
last modified:
why? why not!
I believe that at some point in each of us arises the desire to share what we have learned, what we have achieved or intend to achieve, or simply the desire to order our ideas and keep track of them over time, following a common logical thread.
With this thought in mind, some time ago I decided, in a very unoriginal way, to create a portfolio in which to showcase my work and present my ideas, sharing my results whenever possible, hoping to be useful to someone, and therefore try to repay the favor to all those who spend part of their time every day sharing their knowledge with the net.
From the beginning, it was clear to me that this site would become my own project, so I chose, at some point, to try to create it from scratch, even though I'm not a web developer (be lenient with me).
Initially, I spent some of my time searching for the technologies that would allow me to achieve my goal. I certainly didn’t want to reinvent the wheel, I didn’t have the presumption to think that I could understand more than the professionals out there.
My project would be loaded on github, hence my first contact with Jekyll. It didn’t take me long to realize that it wasn’t what I was looking for. Of course, like many, I went through Wordpress and Google Sites, but my contact was very brief, let’s write some code here! ๐
Soon I moved on to React and then ended up on Gatsby, until University requirements led me to get to know Django.
If you don’t know these tools don’t worry, I’ll leave you some links to resources to learn more.
study, study, study
The study begins, and the more you learn, the more ideas you get, even more you have to study in order to realize them. Basically an endless loop ๐
Complex technologies, however, require time to be mastered, and the risk of using tools that may turn out not perfectly coherent with one’s ideas is always just around the corner.
Moreover, these tools can quickly become obsolete, forcing you to review the entire project over time. In addition to this, it must be considered that these technologies do not allow you to truly understand how things work under the hood (it’s not a bad thing, but it’s not what I like).
the turning point
While browsing between topics, I was struck by one of my wild ideas: โ what if I tried to create a website without the help of any framework? Why just a site and not a system? โ
I had already gained a certain familiarity with HTML CSS and Javascript and I had also consolidated my knowledge through the study of the technologies I had come across.
The initial idea had turned into something else. I had gone from wanting to create a personal site, to wanting to create a system that would allow me to generate a personal site, simple in content but modular. Once the system was created, I could easily upload new content, add functionality, and why not, distribute my work.
The activity was challenging; piece by piece I built my environment with Javascript, customized the experience through CSS, modeled the structure through HTML.
Trying to imitate Bootstrap in some way, I used Media Queries to make the output responsive. Content and configuration files were written in Json, having gained a certain familiarity with manipulating this type of file in the past. The system was taking shape quickly but I hadn’t thought to prepare documentation as my initial idea was completely different.
sudo killall
At some point, University commitments imposed a stop on the development of the project. The long pause, and my well-known memory problems ๐ , made it complicated to resume the development from where it had stopped, causing a little frustration in me.
As I was immersed in my thoughts and trying to understand whether or not it was worth investing time and effort to take the project back in hand, I came across Hugo and it was love at first sight.
the rebirth
Hugo was exactly what I needed, the system I was trying to create, developed naturally better than I could have hoped to do myself.
Long story short, I recovered what could be recovered from the old project and brought it into Hugo, with disarming simplicity, which made me love it even more.
What you see is the result of this porting. Probably over time, I will add new features to this project. However, I will not fail to update this post in case.
Before briefly illustrating the functioning of my template, know that the code will soon be available on github, in case you have pleasure in extending its functionalities, improving it with your knowledge, or simply using it as it is.
In the meantime, if you’ve made it this far, thank you!
hugo config
Hugo uses the config.toml, config.yaml, or config.json (if found in the site root) as the default site config file. It offers extensive customization options regarding configuration parameters. You can find more details here: โgetting-startedโ.
However, my project is intended to be simple, so I do not exploit many of the framework’s capabilities. To better understand the development criteria I used, you need to study some documentation; it would be too long to explain everything in this post.
Anyway, the documentation explains it better than I do ๐
NOTE:My project implements various features despite its simplicity. Additional features will certainly be added over time (as needed). However, I do not exclude the possibility of modifying existing features if necessary.
It would be pointless and boring to explain in detail how the template works. Therefore, I will provide you with a brief overview of my work.
Remember that you can refer to the code available on github (I am still considering whether to add more material before distributing it). In the meantime, I’ll give you some fragments of the configuration file that allows manipulation of a significant part of the project.
The first feature I present to you is related to the splash screen. It is indeed possible to enable or disable it, choose the font, style, transition duration, and, of course, the message. Take a look here:
FONT - SPLASH SCREEN
# FONT
fontFamily = "my-font-family" # default style provided
WOFF2fontURL = "/fonts/woff2/my-font-family.woff2" # default style provided
TTFfontURL = "/fonts/ttf/my-font-family.ttf" # default style provided
# SPLASH SCREEN (it works only in home)
splashscreenEnabled = true # default false
splashscreenMessage = "about santo" # splashscreen text
# bold = true # default false
splashscreenDelay = 5000 # default time provided
We can change the title of the navbar that takes us back to the home, add new sections to the navbar (customize it to our liking), and personalize the toggle that allows us to change the theme.
HOMESCREEN
# NAVBAR
navbar = "seems to be a portfolio" # default value available
# THEME SWITCHING
brandLight = "/images/navbar/my-light.ext" # icon
brandDark = "/images/navbar/my-dark.ext" # icon
# FEATHER ICONS 4 NAV (uncheck # pre -> to hide)
[menu]
[[menu.main]]
name = "about"
pre = "at-sign"
url = "/about/"
weight = 1
[[menu.main]]
name = "coding"
pre = "code"
url = "/coding/"
weight = 2
[[menu.main]]
name = "blog"
pre = "edit-3"
url = "/blog/"
weight = 3
Well, we can manipulate practically anything!
We can choose to change the photo (of course), modify or remove the brief message, add our personal interaction action (in my case, email), social links, animated greetings, the welcome message, and enable or disable the latest content section.
We have a maximum of 4 cards available to present the latest published content.
# HERO
heroProfile = "/images/my-image.ext" # default image provided
heroDefault = "/images/default/default-image.ext" # default image
# BRIEF MESSAGE
heroShortMessage1 = "..." # optional
heroShortMessage2 = "..." # optional
# INTENT
heroMailIntent = "..." # optional
# SOCIAL
linkedin = "..." # optional
github = "..." # optional
instagram = "..." # optional
# ANIMATED GREETINGS
heroJumbo = "..." # jumbo text
jumboIcon = "/images/hand.ext" # icon (with animation)
# WELCOME MESSAGE (dynamic length)
heroDescription =
[
"...", # message
"", # blank 4 vertical space
"..." # last message
]
# LATEST
latestInHome = true # default false # enable/disable latest section
latestMessage = "Latest on this site"
# CARDS IN HOME
navbarSections = ["coding", "blog"] # min 1 - max 4
# COMING SOON
comingSoon = true # default false # enable/disable coming soon banner in home
# topics >= 1 required
topics =
[
{ title = "android", icon = "fa-brands fa-android fa-2xs", description = "..." },
{ title = "...", icon = "", description = "..." }
]
# you can add as many topics as you like # you can also leave the icon field empty if you do not need it
# csoonDelay = (num or string) # default value provided # delay on restart # ms
# csoonHeight = (num or string) # default value provided # banner height
# the height of the banner is dynamic and adapts to the size of the content to be presented
Of course, we can also customize the cards by setting their height or allowing them to dynamically adjust to the content. We can define a default image if the content we want to present doesn’t have a cover image.
We can include references to open source resources. This is very important to me. I think that proper acknowledgments to the authors should always be included.
# CARDS
cardImage = "/images/default/default-card.ext" # default card image when the content does not have one
cardImageReference = "https://..." # optional # default card image reference
fixedSize = 192 # in px # optional # same height for all images
FOOTER
The footer provides a good level of customization. Although I didn’t need many options for my project, I still decided to implement all the functionalities that came to mind, with the aim of making this template highly customizable for anyone who wants to use it. This reasoning applies equally to both the footer and the entire template.
# FOOTER
# footerMultiline = true # default false
footerLines = ["...", "love", "..."] # you can use 'love' keyword for the beating heart # case insensitive
footerDate = true # default false # enable current year at the end of the page
copyright = true # default false # enable c-message at the end of the page
copyrightMessage = "..." # copyright true required
# if you exceed the default space (multi-line case), you can always increase the footer height in "footer.css"
You can choose to display the text on a single line or on multiple lines (there is no limit to the text you can input). You can also use a special key to get a beating heart for you and your users. Do you want to add the current date or a copyright notice? You can do both.
If the footer detects that the data analysis feature has been activated, it will automatically include the appropriate section for the privacy policy, as required by current regulations. Of course, you can customize the policy according to your needs. Pretty neat, isn’t it?
ANALYTICS 'N' POLICY
I’m not a big fan of profiling activities, I’ll be honest. I have no interests whatsoever in data or user profiling, and I don’t gain anything from this project. My main goal is simply to share what I do, genuinely. However, knowing which content is more or less popular is important to me, as it allows me to provide consistently interesting insights, or at least try to do so ๐
Your privacy is safe with me, so no worries!
# GOOGLE ANALYTICS TAG (GA4)
googleAnalytics = 'G-your-tag' # optional # anonymized IP by default # custom implementation
# OWNERS
mainOwner = "..." # default value provided
dataOwner = "..." # owner of website and owner of data may be different
dataOwnerMail = "..." # data owner's address
# PLACES
# U_S_A = false # default true # place of processing personal data
europe = true # default false # place of processing personal data
europePOI = "Ireland" # point of interest in Europe
# DOCS
analyticsDocumentation = "https://..."
analyticsPrivacy = "https://..."
analyticsOptOut = "https://..."
# DATE
policyDate = "YYYY-MM-dd" # current date by default # field printed in 'dateFormat' style (see below)
I think the fields are quite self-explanatory, but if not, take a look here.
CONTENT LIST
# LIST HEADER
# listHeader = false # default true # enable/disable list parameters
listCustomMessage = true # default false # enable/disable 'listMessage'
listMessage = ["...", "..."] # you can write anything here # [str1, str2, ..., strN]
# listMultiline = true # default false # it works only when 'listCustomMessage' is true
appendTitle = true # default false # it works only when 'listCustomMessage' is true
# LIST FOOTER
lastMessage = true # default false
listLastMessage = "..." # it works only when 'lastMessage' is true
# LIST CONTENT
# calendar = false # default true # enable/disable calendar info
calendarIcon = true # default false
# tags = false # default true # enable/disable tags info
tagsIcon = true # default false
# summary = false # default true # enable/disable summary # summary len: 70 words
As seen earlier with the footer, in the content section, you can work with multiple lines. You can choose to enable or disable the header and footer of the page, insert a custom message, and add the title of the current page. For each list item, you can also enable or disable the calendar information, tag search, and table of contents.
If a piece of content has been modified, the system presents not only the creation date but also the date of the last modification.
CONTENT
# CONTENT
# contentWithSummary = true # default false # enable/disable table of contents on the content page
# wordCount = false # default true
# readingTime = false # default true # words per minute 220 by default
# creationDate = false # default true
# lastModified = false # default true
# CODE BLOCK IN CONTENT # only styles available from CDN or local path
codeLight = "styles/my-light-style" # default style provided
codeDark = "styles/my-dark-style" # default style provided
# NOTE: if you want to add code style from CDN you must insert integrity SRI (not required on default)
integrityLight = "sha512-V..." # CDN = true # custom theme
integrityDark = "sha512-1..." # CDN = true # custom theme
# SIDEBAR
contentSidebar = true # enable/disable sidebar in content
# sidebarWidthMIN = 5 # default MIN. 4 # higher value required
# sidebarWidthMAX = 14 # default value 15 # MAX > MIN required
# Three-level list available # hyperlinks required in content
Other info about SRI.
EDIT: I have added the ability to insert a sidebar. The sidebar only appears if the screen is large enough to accommodate it. Additionally, it is possible to customize its minimum (contraction) and maximum (extension) size.
404 'N' ABOUT
For the 404 error, I kept it simple by simply allowing the option to upload up to a maximum of 2 images in order to create compositions.
As for the ‘about’ section, I am still considering how to implement and personalize it. Currently, you can assign an original name to the tab or leave the default one.
# 404
UP = true # default false
UPresource = "/images/404/404-image.ext" # it works only if UP is true
UPreference = "https://..." # optional
DOWN = true # default false
DOWNresource = "/images/404/404-image-2.ext" # it works only if DOWN is true
DOWNreference = "https://..." # optional
# ABOUT
sectionAboutTitle = "who am i" # default value provided
CONFIG PARAMS AND SURROUNDING
Through the parameters I’m presenting below, you can decide whether to enable browser caching, choose whether to use a CDN to retrieve content or serve it locally, define a global date format, include a favicon or not, choose a default theme for the initial load, assign new audio resources, or redefine the switcher animation.
The template provides a set of tags (tags can be used for searching specific content of interest) ready to use, but you can always decide to add new ones if you deem it necessary or modify the existing ones by editing the appropriate file.
# CONFIG
noCache = true # default false
# CDN = true # default false
dateFormat = "2 January 2006" # default value provided # see docs for further specs
favicon = "/images/ico/favicon.ext" # optional
# THEME INTERNAL
defaultThemeLight = false # default true # light and dark themes are availables
storedTheme = "your-theme" # default value provided # this parameter identifies the current theme in browser
audioON = "/audio/res.ext" # default value provided # see theme switching
audioOFF = "/audio/res.ext" # default value provided # see theme switching
forwardAnimation = "" # default value provided # see theme switching # reference in header.css
reverseAnimation = "" # default value provided # see theme switching # reference in header.css
# TAGS
tagMap =
[
{ name = "HTML", icon = "fa-brands fa-html5 fa-xl" }, # font awesome
{ name = "..." , icon = "..." }, # whatever you want
{ name = "C++" , icon = "" } # empty icon for unknown tag
]
# Blank icons are handled by theme
# if you want to add a new custom icon for a tag, you can edit the style in index.css
SHORTCODES
To understand what we’re talking about, take a look here. The content served by Hugo is written in Markdown ( ) and customized through the use of shortcodes. For this template, at the time of writing, I have implemented the following functionalities:
- code block
- emphasize
- header
- highlight
- linebreak
- link
- list
- slideshow
- summary
- sym-link
- table
- wrap
These functionalities can be combined with each other. The content I have published up to this point has been created using these tools.
It seems that we’re done for now… I believe I’ve given you a good overview, or at least I hope so! I skipped a few things here and there to keep it concise, but everything I haven’t mentioned will still be part of the code I’ll distribute, so no worries.
I’m considering adding a comments section to the template as well. Let’s see, I’ll think about it some more. Most likely, I’ll include a ‘coming soon’ feature and maybe even a connected RSS feed. Who knows? EDIT: I have added a ‘coming soon’ banner (no rss feed for now). See above for customisation.
If you want to stay updated, drop by here from time to time. Take care and be well ๐ค
NEW FEATURE - STARRY NIGHT
Those who know me know how much I love astronomy. I cannot remain indifferent to the beauty and complexity of the space that surrounds us. So I thought, why not bring a bit of that beauty here, in this small space? I hope it can brighten your browsing, just as it brightens mine.
For now, it’s just a small animation, maybe in the future I’ll add more details in the style of the Hubble Ultra Deep Field. Then hey, who knows, maybe one day I’ll get to observe certain images up close ๐
“…del doman non vโรจ certezza” as someone once said, right? (ref.)
# STARRY NIGHT
starryNight = true # enable/disable starry night in home # default false
# stars = 2000 # number of stars in home # default value provided
# starSize = 2 # size of star in px # default value provided
# starColor = "red" # default value provided
# starTime = 100 # moving stars (seconds) # default value provided
# it works only in dark mode