How This Site Was Made
Discover the tech stack that powers this website.
1545 words 5 min Modified
Table of Contents
Overview
This post details the creation and technology stack behind my personal website, built with a focus on minimalism, privacy, and accessibility. The site is powered by Hugo, a fast and flexible static site generator that allows for seamless deployment and management of content. You can also check out the privacy policy to learn more about how I use your data.
Key Features
- Minimalistic Design: The site features a clean and straightforward layout, prioritizing ease of navigation and readability.
- Privacy-Focused: I have intentionally avoided third-party tracking, invasive ads, and unnecessary JavaScript, ensuring a safe browsing experience.
- Automated Deployment: By utilizing GitHub Actions, my blog posts and content are automatically synchronized from my Obsidian Vault and deployed with ease.
- Fast and Secure Hosting: The website is hosted on AWS, with an NGINX server backend, allowing for efficient and secure delivery of content.
Technologies Used
- Hugo: The backbone of my website, providing a powerful static site generation framework.
- HTML and CSS: Core technologies for creating the site’s clean and minimalistic design.
- Obsidian Vault: This is my personal knowledge management tool, where I write and store blog posts, which are synchronized to the website.
- GitHub Actions: Automates the deployment process, ensuring that any new content is seamlessly published.
- AWS (Amazon Web Services): Hosting provider for my website, offering reliable and scalable infrastructure.
- NGINX: Acts as the web server, efficiently handling requests and serving content.
- Cloudflare: Manages DNS and provides a CDN for optimized content delivery.
- Git: Revision control system for managing changes to the website content.
- Obsidian: Personal knowledge management tool for writing and organizing blog posts.
The IndieWeb Movement
This website follows the principles behind the IndieWeb movement, which advocates for decentralized personal websites that prioritize content clarity and user ownership. The IndieWeb movement emphasizes the importance of owning your content and data, rather than relying on third-party platforms. By hosting my website on AWS and using Hugo to generate static content, I maintain full control over my online presence and ensure that my readers can access my content without any intermediaries. I would have went fully self-hosted instead of deploying to an AWS server if I could, but I am on campus and the network blocks incoming connections.
Continuous Deployment
This website is continuously deployed using GitHub Actions, which automates the process of updating content and deploying changes.
My Workflow
My content creation and deployment workflow revolves around a git revisioning system. I use Obsidian to manage all content on the website, as well as notes in my personal life. This allows for easy organization and editing of blog posts before they go live.
Once I’ve completed a blog post, I commit my changes to Git and push them to the repository. My automated GitHub Actions deployment script, which looks like this:
1name: CI
2on:
3 push:
4 branches: [ main ]
5
6jobs:
7 deploy:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v4
11
12 - name: Hugo setup
13 uses: peaceiris/[email protected]
14 with:
15 hugo-version: latest
16 extended: false
17
18 - name: Build
19 run: hugo --environment production
20
21 - name: Deploy via Rsync Deployments Action
22 uses: Burnett01/[email protected]
23 with:
24 switches: -avzr --delete
25 path: public/
26 remote_path: ${{ secrets.REMOTE_PATH }}
27 remote_host: ${{ secrets.REMOTE_HOST }}
28 remote_user: ${{ secrets.REMOTE_USER }}
29 remote_key: ${{ secrets.DEPLOY_KEY }}
30
31 - name: Create SSH key file
32 run: |
33 echo "${{ secrets.DEPLOY_KEY }}" > ssh_key
34 chmod 600 ssh_key
35
36 - name: Restart NGINX
37 run: |
38 ssh -o StrictHostKeyChecking=no -i ssh_key ${{ secrets.REMOTE_USER }}@${{ secrets.REMOTE_HOST }} 'sudo systemctl restart nginx'
39
40 - name: Test Success
41 uses: rjstone/discord-webhook-notify@v1
42 if: success()
43 with:
44 severity: info
45 details: Website deployment successful!
46 webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
47
48 - name: Test Failure
49 uses: rjstone/discord-webhook-notify@v1
50 if: failure()
51 with:
52 severity: error
53 details: Website deployment failed!
54 webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
55
56 - name: Test Canceled
57 uses: rjstone/discord-webhook-notify@v1
58 if: cancelled()
59 with:
60 severity: warn
61 details: Warning while deploying website!
62 webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
This workflow synchronizes content from the Obsidian Vault, builds the website using Hugo, and deploys it via rsync to my AWS server. It even restarts NGINX to ensure that changes are reflected immediately. If there are any issues during deployment, I receive notifications through a Discord webhook, allowing me to address problems promptly.
Accessibility and Inclusive Design
Accessibility
Accessibility is a cornerstone of my website design philosophy. I intentionally avoided using JavaScript, creating a static site that is easier for users with outdated browsers or those accessing the site through parsers or RSS feeds. As highlighted by the HTML Hobbyist:
You were able to land on this website and just start reading… how refreshing was that? No layout shifts caused by loading ads. No begging for you to allow web notifications. No pop-up appeals to sign up for our newsletter. Just simple, relatively unadulterated HTML.
Inclusivity
I strive to create a design that is inclusive for everyone. My primary focus is on supporting underrepresented ways to read a page. Many users don’t interact with a website through a standard web browser. They may be using accessibility tools, navigating on small viewports, or utilizing machine translators. Others may access the site on restricted networks or through uncommon browsers. Acknowledging these diverse needs is crucial to fostering a truly inclusive digital environment.
One of the core principles I embrace is inclusivity by default. Web pages should not rely on overlays or other personalization features if the underlying design can accommodate all users from the outset. Personalization should serve as a fallback rather than the primary solution. For instance, users on the Tor network, students using school computers, or individuals in restrictive corporate environments should not have to “make websites work for them”; that responsibility lies with me as the webmaster.
Moreover, I believe in the idea of restricted enhancement, which limits all design enhancements to those that address specific accessibility, security, performance, or significant usability challenges faced by users. This approach encourages the use of older or widely-supported features while minimizing purely cosmetic changes. I focus on maintaining a textual website that is maximally inclusive by emphasizing semantic HTML (POSH) and keeping unnecessary complexities at bay.
Other than the commenting system for posts, is not a single line of Javascript on this website, and I aim to keep it that way.
Commenting System
I use Cusdis for the commenting system on my website. Cusdis is a privacy-friendly, open-source commenting system that doesn’t track users or require them to sign in. It’s lightweight, easy to integrate, and respects user privacy, making it an ideal choice for my privacy-focused website. To include Cusdis on my site, I simply added the following code snippet to my Hugo single.html
layout:
1 <h4>Comments:</h4>
2 <div id="cusdis_thread" data-host="https://cusdis.com"
3 data-app-id="REDACTED FOR SECURITY"
4 data-page-id="{{ .File.UniqueID }}"
5 data-page-url="{{ .Permalink }}"
6 data-page-title="{{ .Title }}"
7 data-theme="dark">
8 <script async src="https://cusdis.com/js/cusdis.es.js"></script>
9 <script defer>window.CUSDIS_LOCALE = { powered_by: ' ',}</script>
EDIT: I had some problems configuring CORS with Cusdis, so comments on posts have been disabled for the foreseeable future.
Front Matter Variables
I use customized front matter variables in my Hugo content files to provide metadata about each post. These variables include:
- Eyecatcher - A brief description of the post “to catch the eye” of the reader
- Tags - A list of tags that categorize the post
- Reading Time - An estimate of the time required to read the post
- Publication Date - The date the post was published
- Modified Date - The date the post was last modified
- I use the “Obsidian Linter” plugin to automatically populate the last modified date
- Summary - A concise summary of the post’s content (not actually displayed anywhere on the site, but used by search engines and RSS feeds)
- Description - A brief description of the post (used for meta tags and social media sharing)
Here is an example of the front matter for this post:
1author: "Anish Goyal"
2title: "How This Site Was Made"
3description: "A page describing how this website was made."
4summary: "This page details the entire stack on which this website was made, including the layout, posts, and automation, using Hugo, GitHub Actions, and an AWS server."
5eyecatcher: "Discover the tech stack that powers this website."
6tags: [general, backend, hugo, aws, nginx, github-actions]
7readingtime: "5"
8date: 2024-10-12
9modified: 2024-10-13
Hugo Theme
I used the hugo-simple theme to create this website, but it is so heavily modified that it is essentially a custom theme at this point. The theme provides a clean and minimalistic design that aligns with my preferences for a simple and easy-to-navigate layout. I have customized the theme extensively to suit my needs, including modifying the layout, typography, and color scheme to create a unique and personalized look for my website. It’s also worth noting that the theme is designed to be lightweight and fast-loading, ensuring a smooth browsing experience for visitors.
<EOF>
If you’re interested in the source code for this website, you can find it on my projects page, or this GitHub repository. I believe that by keeping the site lightweight and user-friendly, I can create a better experience for my readers while also reflecting my interests in minimalism, privacy, and cybersecurity.