Building "The Odyssey of Gaurav" : From Free Domain to Core Foundation

Dive deep into the technical journey behind my blog. This post unpacks how I leveraged a free domain, navigated SSG choices, and set up essential structure, metadata, and content pipeline from scratch. Learning from the decisions, challenges, and moments of laying a robust site foundation.

June 4, 2025
....
Views

My last post was about why “The Odyssey of Gaurav” exists. This one? It’s about the how. The messy, fun, frustrating, and ultimately rewarding journey of actually building this digital home. Expect a direct, no-fluff breakdown.

The Spark - Free Domain from GitHub Education

The very first spark for this site was an unexpected free domain.

I’d tried claiming the GitHub Education pack a couple of times before, and it just… didn’t work out. I never bothered to dig into why. But this time, out of sheer curiosity, I tried again. And boom – it worked. Didn’t even know half the perks it offered, like free domains from various providers, GitHub Foundations exam coupons, and more. You can explore the full list here.

Getting that domain made it real. The initial thought was: a portfolio site? But what would I put there? Just a list of skills and hobbies? Didn’t feel adventurous. It lacked rich content. How could it be truly useful to me, and maybe even to others? I love working with a community, learning together.

Then it hit me. I’d been constantly delaying documenting my projects. This was it. The push I needed. Plus, I was tired of feeling restricted by specific platforms – they just didn’t feel “me.” I needed my own unique space. So, I decided: build a site to share not just projects, but how I did them, my full thought process. In simple terms: a blog. If I wanted to add an “About Me” or anything else, it was just a single route away.

Naming - The Odyssey of Finding “The Odyssey”

Okay, I had the domain. Now, what to name the site? No grand story here, just straight-up ChatGPT. I dumped my thoughts on it, and it started spitting out domain name and branding ideas.

Some were overwhelmingly generic: “Building the Future | Gaurav Bankar,” “Building Worlds | Gaurav Bankar.” Others were just… general: “Gaurav Bankar | Tech & Innovation,” “Gaurav’s Studio,” “Gaurav’s Vault.” Then, some interesting ones popped up: “Bankar’s Lab.”

With a bit more back-and-forth, it uttered “Gaurav’s Odyssey.” This felt right. I experimented further, and “The Odyssey of Gaurav” clicked. “The” just added a sense of grandness, like a singular, defining journey. I loved it. Don’t ask me why, it just felt epic. So, that was the site name.

Now, for the domain part itself. With the name set, filtering options should be easy, right? gauravsodyssey.me, theodysseyofgaurav.me?

But I was wrong—it wasn’t easy at all. A key realization hit me: I was misspelling “theodysseyofgaurav.me” sometimes myself. If I was doing it, others likely would too. That means people might not even try again. I didn’t want that. I needed something small, memorable. But then, I was back to square one, essentially re-selecting a domain name brand.

My username gaurav23b is pretty consistent across platforms, so gaurav23b.me was a thought. But honestly, how many times do you feel confident clicking a URL with numbers in it? Not often. Dumped that idea too.

After a bit more fidgeting, gauravb.me felt like the best option. It has no branding pressure, feels personal, and isn’t restrictive. It works for both tech and personal projects. Crucially, it was available – otherwise, I would have aimed for gaurav.me.

(why .me? - got free .me, so I didn’t have to put much thought into it. like .com, .tech, .in, etc. which to choose? also .me felt personal, and I liked it.)

From Verbose HTML to Static Site Generators

Domain claimed, site name decided. Time to build. But with what stack? I didn’t have a defined plan, but I wanted interesting tech. Pure HTML, CSS, JS felt too verbose. I love minimalism, but that route would take ages when well-defined strategies like templating, components, etc. exist for reusability.

So, I dug deeper. Static Site Generators (SSGs). A whole new adventure. I visited countless homepages, read “getting started” blogs, and compared them. Reddit discussions and other blogs showed how people were using them. Since my exact content plan wasn’t fully formed, I didn’t meticulously gather links to every discussion that shaped my views. However, going forward, I intend to do so. My experience tells me that real-world User Experience (UX) and Developer Experience (DX) often matter more than theoretical claims.

After research, Hugo SSG really convinced me. I followed the getting started guide, and results were almost instant. A site was ready in minutes. SSGs typically use concept of “themes” – predefined, styled templates that get you going quickly. I went through Hugo’s theme store, opening almost every demo page. Papermod and Congo captured my heart – minimal, simple, everything a blog needs.

After some comparisons, I settled on the Congo theme. Editing the config file, my simple website was “ready.” Or was it? Not really. It felt too abstracted. Every site built with Congo would look similar. Back to the web and ChatGPT I went, looking at how other people built their sites. This process is fascinating; you learn so much.

Taking inspiration, I came back. The options were: edit the theme’s layouts and partials, or build my own theme from scratch. Questions flooded my mind: “Why did I install the theme then?” “Am I ready to build a theme from scratch?” Yes. It’s my site. I want to configure every part and have full control.

Browse portfolio sites showed me what “full control” looked like. People were doing amazing things. Originally, I’d planned to write posts in Markdown, but exploring these sites introduced me to Markdown Extended (MDX). I won’t detail it here, but it’s amazing – it lets you make your Markdown interactive. Josh Comeau’s site is an excellent example of MDX in action.

Back to Hugo. I was transitioning from using a full-blown theme to making my own. I wanted MDX in my blogs – I’m adventurous; I want the latest and greatest, haha! So, I immediately searched for how to integrate MDX into Hugo. No native support. Customizing the theme, MDX support, missing JavaScript flexibility… it felt like I was reverse-engineering. While all this might be possible with Hugo, I started questioning its actual goal for my needs.

I left the Hugo site as it was, thinking I’d get back to it. My focus shifted to other projects and academics. This led to a 2-2.5 month gap, during which I even started building a file-sharing Android app for local networks (which I later paused after discovering LocalSend - a really good app, by the way).

Small but good experience with Hugo, it delivered on its promises, i ended up hosting my incomplete site on GitHub Pages and connecting it to the domain at the time. During the gap, I opened the site occasionally, although it was just a placeholder with an “Awesome content coming soon” message.

…End of the story? Nah. How would we be here then?

The Comeback

Around four weeks ago, while sifting through my “dump thoughts-queue” notes, I saw “SS - Astro Blog Template.” And suddenly, my gauravb.me plan revived. I went straight to the Astro’s website. After navigating for 5-10 minutes, I started the tutorial. Things just felt right. It’s unopinionated. Every decision is mine. It offered so much more control and options. None of the features I wanted were missing (MDX, JS when needed). It felt perfect for my use case. Within a day, I completed the Build a Blog Tutorial and gained pretty good confidence that Astro was the one.

Why Astro? - It Just Felt Right

  • Unopinionated: This was huge. Every decision was mine.
  • Fast and Light by Default: I wanted my site to be performant, and Astro delivers.
  • Zero JS by Default (JS When Needed): I loved this philosophy. Only load JavaScript if absolutely necessary.
  • Control and Options: The tutorial showcased its flexibility. It’s marketed for blogs, and I felt that taste in the tutorial.

At this point, I didn’t worry much about which JavaScript framework I’d use. I just kept going. Most of my site is static, and I didn’t need to instantly decide on a JS framework to start building the core structure.

Like Hugo, Astro also has themes that serve as excellent references. I did the same thing: opened many, scrutinizing how things were done, could be done, and needed to be done.

Here are some that inspired me, or at least specific ideas I liked:

I was overwhelmed by all this inspiration, so I gave myself a bit of time. Instead of instantly focusing on styling, I started building the structure. This time, I knew I wanted full control, so I’d build my own “theme” (site from scratch). Some of the above sites were also good references for code structure, not just the visuals.

Diving into the Code - Building the Foundation

Now, the most interesting part: the actual coding. I’ll focus on what I did differently and share useful resources, rather than explaining obvious steps and things explained in the documentation.

npm create astro@latest

Astro offers several project initialization options: regular (recommended), blog, docs, and minimal. While there isn’t a huge configuration difference, these provide boilerplate code and integrations tailored for specific site types. Although I was building a blog, I chose the minimal template. Why? It felt like a great opportunity to learn and leverage Astro’s full power. I initialized two projects: a blog one for reference and a minimal one for my actual site. This way, I got the best of both worlds – understanding how to structure things from the blog template while having complete control over my minimal project, only adding what I wanted, with almost no effort. It felt great.

Following Astro’s official blog tutorial(highly recommended if you are building, as I will be referencing this many times throughout the article) and using the initialized blog project as a reference, I quickly grasped how to proceed. The website tutorial offered greater breadth, while the initialized blog project provided deeper insights into project structure and boilerplate code.

You’ll love how things are configured in Astro.

The BaseHead.astro and Metadata Obsession

I particularly loved the BaseHead.astro component. This is where we set up the core metadata for the site, like the title, description, and Open Graph tags. Astro’s <head> management is straightforward, and I loved how it allowed me to define global metadata that could be overridden on a per-page basis. I ended up adding a JSON-LD schema and more Twitter and Facebook meta tags for blog post details such as publish date, updated date, etc. (didn’t use “Facebook” as “Meta,” as it would’ve sounded like “Twitter and Meta meta tags,” haha!).

I spent a good amount of time here before moving to styling, ensuring my structure was solid. This way, when styling, I’d make minimal structural changes.

First: The Favicon. Lacking a specific design idea, I simply searched “G icons” on Google. I found a simple, elegant “G” icon on Flaticon in the interface icon section. That’s a good, simple, no-brainer option: an icon as your name’s letter!

light icon
normal icon
solid icon


There are many favicon generators. I didn’t bother much with finding the perfect one. I used RealFaviconGenerator, and it worked perfectly. It generated the icon, SVG, PNG, manifest (yay, PWA!), and everything. You can even configure dark mode/light mode icons there. It was seamless. It also offers a favicon checker Favicon Checker you can use after deployment.

Second: The OG Image (1200x630). Generator? I searched, found this, but for some reason, images weren’t exporting. Without wasting time, I went to Canva. Benefit? Not dependent on a generator, and it’s mostly a one-time setup, so totally worth it.

Default Open Graph Image


I went a little crazy while setting up BaseHead. The idea was to keep the og:image and og:image:alt dynamic, so each post could have unique images. (Spoiler: I ended up not using this, a consequence of over-complicating things sometimes). Fallbacks were set to the /blog route’s OG image (which you might see if you share my post!) and the og:alt fallback is the blog title.

While setting meta tags, I also set up the author(and many more..) meta tag. How could I miss my name? It’s a one-liner:

<meta name="author" content="Gaurav B" />


This worked initially, but it’s not optimal to put strings directly. Why? Header, footer, everywhere else I might want my name. What if I wanted “Gaurav Bankar” instead of “Gaurav B” later? Pain. You might know this, but it’s worth telling this story because it led to a better solution.

I ended up creating a site.config.ts file inside /src to store such constants and export them. It was a savior throughout development. Now, constants looked like config.twitter, config.author, all socials, nav links, etc.

I also created src/utils/globals.ts to define my config to be available globally, saving myself from importing it everywhere, as these constants were needed in many files. Phew, from a simple author name to a full config file, but it felt good.

{/* No import nothing just use it */}
<meta name="author" content={config.author} />

Going Live (and Checking the Meta)

With the Basehead almost complete(We will come back to it later, just one meta tag left to add), I moved on. To check how the meta and OG tags looked, I didn’t wait for local host tools (if they exist, idk). I immediately deployed my site to Vercel, a platform I’d used confidently for previous projects. I used the free domain for testing and didn’t connected it to ‘gauravb.me’, I wanted to ensure everything worked smoothly before making it public. Initially, I used heymeta to inspect the meta tags, but later discovered that Vercel itself provides this information under the “Deployments” section. (Remember to use the correct site URL in your meta tags, leveraging config.url from your configuration file – a mistake I made at first!).

Content Collections, Integrations, and Helpers

If you’re building something similar, the Blog tutorial follows file-based routing. There’s a last, optional chapter introducing Content Collections. It’s super useful for organizing blogs and icons. The benefits are worth it: schema definition (already set up by Zod and validated by TS, which Astro defaults for us). It was all given in the docs, not much effort. The initialized blog project also provided an excellent reference for this.

I added some more fields to the schema – some optional, some mandatory – like the og:image we discussed earlier. I made heroImage mandatory(later ended up making this optional, after styling postcard component and all, huuu pain! - we will discuss this).

Dealing with lots of content(I copied from the blog project as it is, it was good placeholder data and saved me a lot of time), I created utils/post.ts for helper functions like formatDate, getLatestXPosts, etc., which simplified content management.

When initializing my Astro project with the minimal option, I was missing some important integrations that the blog template offered. I installed MDX and Sitemap integrations, and created rss.xml.js(actually copied, ha!) and robots.txt.ts to help crawlers (yes, I want my site to be listed on Google!).

// Standard Robots.txt
import type { APIRoute } from 'astro';

const getRobotsTxt = (sitemapURL: URL) => `
User-agent: *
Allow: /

Sitemap: ${sitemapURL.href}
`;

export const GET: APIRoute = ({ site }) => {
  const sitemapURL = new URL('sitemap-index.xml', site);
  return new Response(getRobotsTxt(sitemapURL));
};


I also created types/index.ts for SiteMetadataProps, SiteConfig, and PaginationProps for better type-checking and good experience.

Pagination props? Yes, you might not see Pagination component because there are fewer posts right now, and I’ve capped it at 6 posts per page. I found this blog post by Phil Nash very useful. I ended up implementing a minimal version of this. I also set up tags as explained in the Astro website’s blog tutorial example, just added pagination to it.

So, at this point, my site’s pages were filled with lorem ipsum and headings like “This is my blogs page, this is my about.” Since we set up content collections and I copied sample content from the blog init project, everything was working properly, but it just wasn’t styled yet.

Coming Up Next: The Visual Odyssey Continues

Now comes the styling part—one of the toughest decisions in building this blog. Initially, I planned to cover the entire build process in a single post. But as I started writing, it became clear that squeezing everything in would mean sacrificing depth. This adventurous journey is simply too rich for one article!

So, we’ll need a couple more posts to truly do it justice.

What about styles, colors? Obviously Tailwind, or did I dump it? Get ready to dive into the styling decisions, my experiments with different design systems, and how I’m making “The Odyssey of Gaurav” look good without losing that fast, minimal philosophy.

Like this post!