How I Made This Website

word count: 3332

reading time: 16 minutes

creation date:

last modified:

In this first post I briefly describe the steps that led me to the creation of this site. In the second part of this post I provide an overview of how my template works. This post will be updated in the future based on new features that I am going to introduce.                                    

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

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 ๐Ÿ˜


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:


  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 are currently on the homepage. What can we do here?

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.


  navbar = "seems to be a portfolio"                       # default value available
  brandLight = "/images/navbar/my-light.ext"               # icon
  brandDark = "/images/navbar/my-dark.ext"                 # icon

# FEATHER ICONS 4 NAV (uncheck # pre -> to hide)
    name = "about"
    pre = "at-sign"
    url = "/about/"
    weight = 1
    name = "coding"
    pre = "code"
    url = "/coding/"
    weight = 2
    name = "blog"
    pre = "edit-3"
    url = "/blog/"
    weight = 3

And what about the content?

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.

  heroProfile = "/images/my-image.ext"                 # default image provided
  heroDefault = "/images/default/default-image.ext"    # default image

  heroShortMessage1 = "..."                            # optional
  heroShortMessage2 = "..."                            # optional

  heroMailIntent    = "..."                            # optional

  linkedin  = "..."                                    # optional
  github    = "..."                                    # optional
  instagram = "..."                                    # optional

  heroJumbo = "..."                                    # jumbo text
  jumboIcon = "/images/hand.ext"                       # icon (with animation)

# WELCOME MESSAGE (dynamic length)
  heroDescription =
    "...",        # message
    "",           # blank 4 vertical space
    "..."         # last message

  latestInHome = true                                  # default false # enable/disable latest section
  latestMessage = "Latest on this site"

  navbarSections = ["coding", "blog"]                  # min 1 - max 4

  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.

  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


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.

  # 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?


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!

  googleAnalytics = 'G-your-tag'           # optional # anonymized IP by default # custom implementation

  mainOwner     = "..."                    # default value provided
  dataOwner     = "..."                    # owner of website and owner of data may be different
  dataOwnerMail = "..."                    # data owner's address

  # 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

  analyticsDocumentation = "https://..."
  analyticsPrivacy       = "https://..."
  analyticsOptOut        = "https://..."

  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.


  # 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
  lastMessage       = true                 # default false
  listLastMessage   = "..."                # it works only when 'lastMessage' is true

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


  # 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

  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

  sectionAboutTitle = "who am i"                     # default value provided


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.

  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

  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

  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


To understand what we’re talking about, take a look here. The content served by Hugo is written in Markdown ( 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 ๐Ÿค—


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

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