Introduction: Why I Built This Blog
In cybersecurity, knowledge sharing isn’t just nice to have—it’s essential. Every CTF I complete, every vulnerability I discover, every technique I learn could help someone else in the community. But I needed a platform that matched the professionalism of the content I wanted to share.
After struggling with slow WordPress sites and complex frameworks, I decided to build something different: a lightning-fast, secure blog that could grow with my knowledge. This is the story of how I built Hri7hik H4cks from scratch—and how you can build yours too.
What You’ll Learn
Over the next few chapters, I’ll walk you through my complete journey:
- Choosing the right tools (and why Hugo won)
- Setting up a professional foundation in under an hour
- Crafting a cybersecurity-themed design that stands out
- Creating templates that make writing effortless
- Building interactive features that engage readers
- Automating workflows to save hours of work
- Deploying to production without breaking the bank
Time Investment: 3-4 hours for a complete build. Follow along, and you’ll have a professional blog by the end.
Chapter 1: The Foundation - Why Hugo Changed My Mind
The Problem with Traditional Platforms
Before Hugo, I tried everything. WordPress was slow and required constant security updates. Ghost looked nice but lacked customization. Gatsby was powerful but felt like overkill for a blog. Each platform promised simplicity but delivered complexity.
I needed something different for my cybersecurity blog because:
- Performance matters (Google penalizes slow sites)
- Security is critical (one breach ruins everything)
- Content quality trumps features (no bloat needed)
- Markdown-first workflow (writing should be distraction-free)
Discovering Hugo
Hugo caught my attention because it’s fundamentally different from other platforms. Instead of generating pages at runtime, Hugo builds everything before deployment. Think of it as cooking a meal vs. cooking to order—Hugo pre-cooks everything, so when readers arrive, the meal is ready instantly.
The Numbers Don’t Lie
Here’s what sold me on Hugo:
Build Speed:
- Initial build: 100-500ms for 50-100 pages (varies by content complexity)
- Incremental builds: <100ms (edit one file, rebuild almost instantly)
- Memory usage: ~50-100MB (runs on anything)
Note: Actual build times depend on site complexity, content volume, and hardware. These are typical benchmarks on modern hardware.
Production Performance:
- Lighthouse Score: 95-100/100 (consistently)
- Time to First Byte: <200ms (globally)
- First Contentful Paint: <1s (incredibly fast)
- Bundle size: 500KB-2MB (lean and mean)
Why This Matters: These aren’t just numbers. In cybersecurity, you’re often sharing time-sensitive vulnerability information. When a new exploit drops, people need that information NOW. A fast blog means your readers can act quickly.
Why Not Other Static Site Generators?
I evaluated several options before choosing Hugo:
Jekyll (Ruby-based):
- ✅ Popular, well-documented
- ❌ Slower builds (seconds, not milliseconds)
- ❌ Ruby dependency issues
- ❌ Limited templating power
Next.js (JavaScript-based):
- ✅ Great developer experience
- ❌ Requires JavaScript runtime
- ❌ Overkill for content-focused sites
- ❌ Larger bundle sizes
Gatsby (React-based):
- ✅ Powerful data layer
- ❌ Complex configuration
- ❌ Slow builds for large sites
- ❌ Steep learning curve
Hugo won because it focused on what mattered:
- Speed (built in Go, incredibly fast)
- Simplicity (configuration over code)
- Flexibility (powerful templating when needed)
- Security (static files = minimal attack surface)
The Decision
For a cybersecurity blog where content quality matters more than dynamic features, Hugo was the obvious choice. The performance metrics sealed the deal—I could build something fast without sacrificing flexibility.
Chapter 2: Laying the Foundation
Step 1: Installing Hugo
I started by installing Hugo on my local machine. The process varies by operating system, but the outcome is the same: a powerful static site generator ready to use.
# macOS (using Homebrew)
brew install hugo
# Ubuntu/Debian
sudo apt install hugo
# Windows (using Chocolatey)
choco install hugo-extended
Pro Tip: Always install the extended version (hugo-extended). It includes features like Sass/SCSS processing that you’ll need later for custom styling.
Step 2: Creating the Site Structure
With Hugo installed, I created the foundation of my blog:
# Create a new site
hugo new site my-blog
# Navigate into the directory
cd my-blog
# Initialize git (essential for version control)
git init
Hugo automatically generates a clean directory structure:
my-blog/
├── archetypes/ # Content templates
├── assets/ # Processed assets (CSS, JS)
├── content/ # Markdown files live here
├── data/ # Data files
├── layouts/ # Template overrides
├── static/ # Static files (images, favicon)
└── themes/ # Installed themes
Why This Structure Matters:
- Separation of Concerns: Each directory has a specific job
- Scalability: Easy to add content without breaking organization
- Flexibility: Can override theme files without modifying the theme itself
Step 3: Adding a Theme (PaperMod)
Raw Hugo is powerful but bare-bones. Instead of building from scratch, I chose to customize an existing theme. After reviewing dozens of options, I chose PaperMod for several reasons:
- Clean Design: Minimal distractions, focus on content
- Dark Mode: Essential for cybersecurity professionals who work late
- Performance: Lightweight, fast-loading
- Customizable: Easy to modify without breaking core functionality
- Active Development: Regular updates and bug fixes
# Add PaperMod as a git submodule
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
# Update submodules
git submodule update --remote
Why Use Git Submodules?
- Updates are simple:
git submodule update --remote - Version control tracks which theme version you’re using
- Easy to contribute back to the theme if desired
- Standard practice in the Hugo community
Step 4: Basic Configuration
The real magic happens in hugo.toml, Hugo’s configuration file. This is where you tell Hugo about your site:
baseURL = "https://hri7hik-h4cks.com/"
languageCode = "en-us"
title = "Hri7hik H4cks"
theme = "PaperMod"
paginate = 10
# Enable minification for production
[minify]
minify = true
[minify.tdewolff.html]
keepComments = false
keepWhitespace = false
[minify.css]
buffer = true
[minify.js]
buffer = true
Why These Settings Matter:
baseURL: Hugo uses this to generate correct linkstheme: Tells Hugo which theme to usepaginate: Controls how many posts appear per page (prevents long-loading index pages)minify: Removes whitespace and comments from HTML/CSS/JS for faster loading
Configuring Custom Taxonomies
One of Hugo’s most powerful features is taxonomies—ways to categorize and tag content. For a cybersecurity blog, I needed more than just categories and tags:
[taxonomies]
category = "categories"
tag = "tags"
difficulty = "difficulties"
platform = "platforms"
tool = "tools"
This creates five ways to organize content:
- Categories: Broad types (CTF, Tutorial, Analysis)
- Tags: Flexible keywords (web, network, forensics)
- Difficulty: Skill level (beginner, intermediate, advanced)
- Platform: Where it’s from (HackTheBox, TryHackMe)
- Tools: Security tools used (nmap, Burp Suite, Metasploit)
Why This Matters: These taxonomies transform a simple blog into a structured knowledge base. Readers can filter by difficulty, find all posts about a specific platform, or see which tools are most commonly featured.
Theme Parameters
Hugo themes can be customized through parameters. PaperMod offers extensive customization:
[params]
defaultTheme = "dark"
customCSS = ["css/custom.css"]
# Content features
showReadingTime = true
showWordCount = true
TocOpen = true
# Home page
[params.homeInfoParams]
Title = "Hri7hik H4cks"
Content = "Cybersecurity Professional | CTF Player | Security Researcher"
[params.homeInfoParams.Icon]
Icon = "🥷"
# Social links
[[params.socialIcons]]
name = "github"
url = "https://github.com/hrithik"
[[params.socialIcons]]
name = "linkedin"
url = "https://linkedin.com/in/hrithik"
# Allow HTML in markdown (needed for shortcodes)
[markup.goldmark.renderer]
unsafe = true
Key Decisions:
defaultTheme = "dark": Default to dark mode (professional cybersecurity aesthetic)customCSS: Points to my custom stylesheet (coming next chapter)showReadingTime: Helps readers plan their timeTocOpen: Table of contents visible by default (useful for long posts)unsafe = true: Allows HTML in markdown (required for custom shortcodes)
Testing the Foundation
With basic configuration complete, I started the development server:
hugo server -D
The -D flag includes draft posts—perfect for testing content before publishing. The server started instantly, and visiting http://localhost:1313 showed a working blog with the PaperMod theme applied.
What I Learned:
- Hugo’s development server automatically rebuilds when files change (live reload)
- Errors appear immediately in the terminal
- The site structure works perfectly out of the box
- PaperMod’s defaults are sensible but customizable
Foundation Complete
At this point, I had a working blog with:
- Professional theme (PaperMod)
- Dark mode support
- Fast build system
- Custom taxonomies for cybersecurity content
- Basic configuration
But it looked like everyone else’s blog. Time to make it my own.
Chapter 3: Making It Beautiful - The Cybersecurity Theme
The Vision
A cybersecurity blog needs to feel professional and tech-focused. I imagined a design that would make readers think “this person knows what they’re doing.” The key elements:
- Dark theme (essential for late-night security work)
- Neon accents (subtle green/cyan highlights)
- Terminal-inspired elements (authentic hacking aesthetic)
- Clear typography (easy to read during long research sessions)
- Difficulty indicators (help readers choose appropriate content)
Color Scheme: The Foundation of Design
The color palette sets the entire tone. I chose a dark base with vibrant accents:
:root {
/* Dark backgrounds */
--bg-primary: #0a0e27; /* Deep dark blue - main background */
--bg-secondary: #151b3d; /* Navy - cards, sidebar */
--bg-tertiary: #1e2749; /* Slate - code blocks, terminals */
/* Neon accents */
--accent-green: #00ff88; /* Neon green - primary accent */
--accent-cyan: #00d4ff; /* Cyan - secondary accent */
/* Additional colors */
--accent-blue: #0066ff;
--accent-purple: #7c3aed;
--accent-pink: #ec4899;
--accent-yellow: #fbbf24;
/* Text colors */
--text-primary: #ffffff; /* Main text */
--text-secondary: #a1a1aa; /* Subtitles */
--text-muted: #71717a; /* Metadata */
/* Status colors */
--success: #22c55e; /* Success states */
--warning: #f59e0b; /* Warnings */
--danger: #ef4444; /* Critical info */
}
Color Psychology:
- Dark backgrounds: Professional, easy on the eyes, reduces eye strain
- Neon green/cyan: Evokes terminals, hacking culture, tech aesthetic
- High contrast: Accessibility and readability
- Consistent palette: Everything works together harmoniously
Pro Tip: Use CSS custom properties (variables) so you can tweak colors globally without searching through hundreds of lines of code.
Typography: Readability is King
For technical content, typography makes or breaks the experience. I chose:
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');
:root {
--font-body: 'Inter', sans-serif; /* Clean, modern for reading */
--font-mono: 'JetBrains Mono', monospace; /* Code, terminal output */
}
Typography Decisions:
- Inter: Modern sans-serif designed for screens, excellent readability
- JetBrains Mono: Developer-friendly monospace with clear distinction between similar characters (0 vs O, l vs 1)
Why This Matters: Cybersecurity content often includes code snippets, command output, and technical details. Readers need to scan quickly and distinguish between similar characters.
Difficulty Badges: Helping Readers Choose
One of my favorite features is visual difficulty indicators. They help readers immediately identify appropriate content:
.difficulty-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
margin: 4px;
}
.difficulty-beginner {
background-color: rgba(34, 197, 94, 0.2);
color: var(--success);
border: 1px solid var(--success);
}
.difficulty-intermediate {
background-color: rgba(251, 191, 36, 0.2);
color: var(--accent-yellow);
border: 1px solid var(--accent-yellow);
}
.difficulty-advanced {
background-color: rgba(239, 68, 68, 0.2);
color: var(--danger);
border: 1px solid var(--danger);
}
Why This Works:
- Color-coded: Instantly recognizable at a glance
- Consistent sizing: Professional appearance
- Informative: Helps readers self-assess and choose appropriately
- Inclusive: Beginners aren’t overwhelmed, experts know what to expect
Usage:
Callout Boxes: Highlighting Important Information
Security content requires special attention to important details. Callout boxes make critical information impossible to miss:
.callout {
padding: 16px;
margin: 16px 0;
border-radius: 8px;
border-left: 4px solid;
position: relative;
}
.callout-info {
background-color: rgba(0, 212, 255, 0.1);
border-left-color: var(--accent-cyan);
}
.callout-warning {
background-color: rgba(251, 191, 36, 0.1);
border-left-color: var(--warning);
}
.callout-success {
background-color: rgba(34, 197, 94, 0.1);
border-left-color: var(--success);
}
.callout-danger {
background-color: rgba(239, 68, 68, 0.1);
border-left-color: var(--danger);
}
Psychology of Color:
- Cyan (Info): Neutral, informational
- Yellow (Warning): Caution, be careful
- Green (Success): Achievement, positive result
- Red (Danger): Critical, potential harm
Usage:
Terminal Styling: Authentic Command-Line Experience
Cybersecurity is synonymous with command-line work. Terminal styling makes code examples feel authentic:
.terminal-block {
margin: 20px 0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.terminal-header {
background-color: #1e1e1e;
padding: 8px 12px;
display: flex;
align-items: center;
gap: 6px;
}
.terminal-controls {
display: flex;
gap: 6px;
}
.terminal-dot {
width: 12px;
height: 12px;
border-radius: 50%;
}
.terminal-controls span:nth-child(1) { background: #ff5f56; }
.terminal-controls span:nth-child(2) { background: #ffbd2e; }
.terminal-controls span:nth-child(3) { background: #27c93f; }
.terminal-body {
background-color: #000000;
padding: 16px;
font-family: var(--font-mono);
color: #00ff00;
overflow-x: auto;
}
Design Elements:
- Mac-style controls: Red, yellow, green dots (universal terminal aesthetic)
- Black background: Authentic terminal feel
- Green text: Classic terminal colors
- Box shadow: Makes it look real, three-dimensional
Usage:
Tool Badges: Highlighting Technologies
Readers want to know what tools are featured. Tool badges make it obvious:
.tool-badge {
display: inline-block;
padding: 4px 10px;
margin: 2px;
background-color: rgba(0, 255, 136, 0.1);
border: 1px solid var(--accent-green);
border-radius: 6px;
font-size: 0.85rem;
font-family: var(--font-mono);
color: var(--accent-green);
}
.tool-badge::before {
content: "⚙️ ";
margin-right: 4px;
}
Why This Works:
- Gear icon: Immediately recognizable as “tool”
- Monospace font: Technical, code-like appearance
- Subtle styling: Informative without being distracting
- Reusable: Consistent across all posts
Usage:
nmap
burp suite
metasploit
(Displays as badge-styled tags with gear icons)
Or in front matter:
tools: ["nmap", "burp suite", "metasploit"]
Interactive Code Blocks: Copy Made Easy
Every technical blog needs code copying. Instead of requiring readers to manually select and copy, I added automatic copy buttons:
pre {
position: relative;
padding: 20px;
border-radius: 8px;
background-color: #1e1e1e;
overflow-x: auto;
}
.copy-button {
position: absolute;
top: 8px;
right: 8px;
padding: 4px 8px;
background-color: rgba(0, 255, 136, 0.2);
border: 1px solid var(--accent-green);
border-radius: 4px;
color: var(--accent-green);
font-size: 0.75rem;
cursor: pointer;
opacity: 0;
transition: opacity 0.2s;
}
pre:hover .copy-button {
opacity: 1;
}
JavaScript (assets/js/copy-buttons.js):
document.addEventListener('DOMContentLoaded', function() {
const codeBlocks = document.querySelectorAll('pre code');
codeBlocks.forEach(block => {
const button = document.createElement('button');
button.className = 'copy-button';
button.textContent = 'Copy';
button.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(block.textContent);
button.textContent = 'Copied!';
setTimeout(() => {
button.textContent = 'Copy';
}, 2000);
} catch (err) {
console.error('Failed to copy:', err);
}
});
block.parentNode.appendChild(button);
});
});
User Experience:
- Hover to reveal: Doesn’t clutter the interface
- Clear feedback: “Copied!” confirms success
- Modern API: Uses Clipboard API for reliability
- Error handling: Graceful failure if clipboard isn’t available
Responsive Design: Mobile Matters
Many readers check blogs on mobile devices during commutes or breaks. The design needs to work everywhere:
@media (max-width: 768px) {
.terminal-block {
margin: 10px 0;
}
.terminal-body {
padding: 12px;
font-size: 0.85rem;
}
.callout {
padding: 12px;
margin: 12px 0;
}
.tool-badge {
font-size: 0.75rem;
padding: 3px 8px;
}
}
Mobile Considerations:
- Smaller margins: Prevent content from feeling cramped
- Smaller padding: Maintain readability on small screens
- Adjusted font sizes: Ensure text isn’t too small to read
- Touch-friendly: Buttons large enough for fingers
Pro Tip: Always test on real devices. Browser dev tools are helpful but don’t capture everything.
Why This Matters
This custom theme transforms a generic blog into a professional cybersecurity platform. Readers immediately understand the content’s nature and can navigate efficiently. The dark theme reduces eye strain during long research sessions. Difficulty badges help readers choose appropriate content. Tool badges highlight relevant technologies.
Most importantly, it conveys professionalism. A well-designed blog suggests the author pays attention to details—a crucial trait in cybersecurity.
Chapter 4: Speaking the Language - Content Architecture
The Content Challenge
After building the foundation and design, I faced a critical question: how do I structure content for a cybersecurity blog? Unlike a general tech blog, security content has specific requirements:
- Step-by-step guidance (CTF writeups)
- Prerequisites and warnings (safety first)
- Tool references (what software is used)
- Difficulty levels (audience targeting)
- Platform context (which CTF platform)
I needed a system that made writing easy while ensuring consistency.
Front Matter: Metadata That Matters
Every post starts with front matter—metadata that Hugo uses to organize and display content. For cybersecurity content, the front matter needed to be comprehensive:
---
title: "HackTheBox: Meow Walkthrough"
date: 2025-11-01
draft: false
categories: ["CTF"]
tags: ["telnet", "beginner", "enumeration"]
difficulties: ["beginner"]
platforms: ["HackTheBox"]
tools: ["nmap", "telnet"]
description: "A beginner-friendly walkthrough of the HackTheBox Meow machine"
---
Why Each Field Matters:
- title: Clear, descriptive, includes platform name
- date: Chronological organization
- draft: Control publication status
- categories: Broad content type (CTF, Tutorial, Analysis)
- tags: Flexible keywords for filtering and searching
- difficulties: Help readers choose appropriate content
- platforms: Which CTF platform or source
- tools: Security tools featured in the post
- description: Summary for previews and social sharing
Pro Tip: Consistent front matter makes content easier to manage and enables powerful Hugo features like taxonomies and related content suggestions.
Templates: Consistency Without Effort
Writing the same front matter structure repeatedly is error-prone and tedious. Archetypes solve this problem by providing templates for new content.
CTF Walkthrough Template
The most important template for a cybersecurity blog:
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
categories: ["CTF"]
tags: [""]
difficulties: ["beginner"]
platforms: ["HackTheBox"]
tools: []
description: ""
---
## Introduction
Machine: **{{ replace .Name "-" " " | title }}**
### Target Information
- **OS**: Linux
- **IP**: 10.10.11.XXX
- **Difficulty**: [difficulty badge]
---
## Initial Reconnaissance
Let's start with port scanning:
```bash
nmap -sC -sV 10.10.11.XXX
Port Scan Results
PORT STATE SERVICE VERSION
Service Enumeration
Initial Access
Privilege Escalation
Flag Finding
cat /home/*/flag.txt
Summary & Lessons Learned
Key takeaways from this machine.
Related Posts
**Template Features**:
- **Dynamic title**: Hugo automatically formats the filename
- **Current date**: Auto-filled with today's date
- **Pre-filled structure**: Standard CTF walkthrough sections
- **Shortcode examples**: Shows proper usage of custom elements
- **Placeholder content**: Reminds you what to write
**Usage**:
```bash
hugo new posts/htb-new-machine.md --kind ctf-walkthrough
The --kind flag tells Hugo which archetype to use. This creates a new file with the template pre-loaded.
Tutorial Template
For educational content:
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
categories: ["Tutorial"]
tags: [""]
difficulties: ["beginner"]
platforms: []
tools: []
description: ""
---
## Prerequisites
List what readers need before starting:
- Required tools
- Background knowledge
- System requirements
---
## Introduction
Brief overview of what will be covered.
---
## Step 1: Getting Started
---
## Step 2: Implementation
---
## Step 3: Advanced Techniques
---
## Best Practices
---
## Common Mistakes
[Warning callout]: Common mistakes to avoid
---
## Conclusion
Key takeaways and next steps.
Tutorial Features:
- Prerequisites section: Ensures readers are prepared
- Progressive steps: Logical flow from basic to advanced
- Best practices: Instill good habits early
- Common mistakes: Help readers avoid pitfalls
- Warning callout: Highlights critical information
Creating Content: The Workflow
With templates in place, creating content became frictionless:
# Create a new CTF walkthrough
hugo new posts/htb-sunday.md --kind ctf-walkthrough
# Create a new tutorial
hugo new posts/sql-injection-basics.md --kind tutorial
# Create a generic post
hugo new posts/thoughts-on-security.md
Each command creates a new Markdown file with appropriate template and structure. No more forgetting front matter fields or struggling with formatting.
The Workflow:
- Run
hugo newcommand - Hugo creates file from template
- Edit content in Markdown
- Save file
- Hugo automatically rebuilds (in development mode)
- Review in browser
- Repeat until satisfied
- Set
draft: falsewhen ready to publish
Pro Tip: Keep development server running (hugo server -D) while writing. Changes appear instantly in the browser.
Taxonomies in Action
With templates defined, taxonomies become powerful organizing tools. A typical CTF post uses all five:
categories: ["CTF"] # Content type
tags: ["linux", "enumeration"] # Keywords
difficulties: ["beginner"] # Skill level
platforms: ["HackTheBox"] # Source platform
tools: ["nmap", "telnet"] # Software used
What This Enables:
- Filtering: Readers can find all beginner posts
- Related content: Hugo suggests similar posts
- Statistics: See which tools appear most often
- Navigation: Browse by platform or difficulty
- SEO: Rich metadata improves search visibility
Example Filtering:
- Show me all TryHackMe tutorials for intermediates
- Show me all posts using Burp Suite
- Show me all beginner-friendly content
Shortcodes: Reusable Components
Hugo shortcodes are reusable components that add functionality without writing complex HTML. They make content more interactive and consistent.
Callout Shortcode
File: layouts/shortcodes/callout.html
<div class="callout callout-{{ .Get "type" }}">
<div class="callout-title">
{{ with .Get "title" }}{{ . }}{{ else }}{{ .Get "type" | title }}{{ end }}
</div>
<div class="callout-content">
{{ .Inner }}
</div>
</div>
Usage:
Information callout - for general information:
📋 Information
Important info
Warning callout - for cautions and warnings:
⚠️ Warning
Be careful!
Success callout - for achievements and positive results:
✅ Success
Task completed
Danger callout - for critical warnings:
🚨 Danger
Critical warning
Additional callout types:
💡 Tip
Helpful hint
❓ Question
Common question
📌 Example
Code example
📌 Note
Important note
📝 Abstract
Summary
💬 Quote
Quote
🐛 Bug
Bug report
This creates visually distinct, semantic callout boxes. The supported types include: info, note, tip, success, warning, danger, question, abstract, example, quote, and bug.
Real-world example from a CTF walkthrough:
Machine Information
This is a Linux box rated as Beginner difficulty.
Pro Tip
Always start with a full port scan to understand the attack surface.
⚠️ Warning
Don't run this exploit on systems you don't own.
Rooted!
Successfully gained root access to the target system.
**When to use callouts**:
- **info**: Machine details, tool information, background context
- **warning**: Security warnings, destructive commands, potential pitfalls
- **tip**: Best practices, pro tips, alternative approaches
- **success**: Confirmation of successful completion
- **danger**: Critical security warnings, dangerous commands
### Terminal Shortcode
File: `layouts/shortcodes/terminal.html`
```html
<div class="terminal-block">
<div class="terminal-header">
<div class="terminal-controls">
<span class="terminal-dot"></span>
<span class="terminal-dot"></span>
<span class="terminal-dot"></span>
</div>
<div class="terminal-title">Terminal</div>
</div>
<div class="terminal">
<div class="prompt">
<span class="user">hrithik@local</span>
<span class="path">~</span>
<span class="symbol">$</span>
<span class="command">{{ .Get "command" }}</span>
</div>
<div class="output">
{{ .Inner }}
</div>
</div>
</div>
Usage:
Basic terminal output with command:
Terminal
hrithik@local
~
$
nmap -sC -sV 10.10.10.10
Starting Nmap scan...
Host is up (0.050s latency).
Multiple lines of output:
```html
Terminal
hrithik@local
~
$
ls -la /home/victim
total 32
drwxr-xr-x 3 victim victim 4096 Nov 1 10:00 .
drwxr-xr-x 1 victim victim 4096 Nov 1 10:00 ..
-rw-r--r-- 1 victim victim 220 Nov 1 10:00 .bash_logout
-rw-r--r-- 1 victim victim 3771 Nov 1 10:00 .bashrc
-rw-r--r-- 1 victim victim 807 Nov 1 10:00 .profile
drwx------ 2 victim victim 4096 Nov 1 11:30 .ssh
-rw------- 1 root root 33 Nov 1 11:30 user.txt
Real-world CTF example:
```html
Terminal
hrithik@local
~
$
ssh victim@10.10.10.10
victim@10.10.10.10's password: ********
Welcome to Ubuntu 20.04.2 LTS
Last login: Mon Nov 1 11:30:00 2025
$ whoami
victim
**Features**:
- **Mac-style window controls**: Red, yellow, green dots
- **Command prompt**: Shows user, host, and current path
- **Output section**: Clean display for command results
- **Monospace font**: JetBrains Mono for perfect alignment
- **Scrollable**: Horizontal scrolling for long output
**When to use terminal blocks**:
- Command output from scanning tools (nmap, masscan)
- Shell interaction examples
- Enumeration results
- Exploit output
- File system exploration
### Tool Badge Shortcode
File: `layouts/shortcodes/tool.html`
```html
{{ $tool := .Get "tool" }}
<span class="tool-badge">{{ $tool }}</span>
Usage in Content:
See SHORTCODE_EXAMPLES.md for complete syntax and usage examples of all shortcodes.
In CTF Front Matter:
---
title: "HackTheBox: Meow"
categories: ["CTF"]
platforms: ["HackTheBox"]
difficulties: ["beginner"]
tools: ["nmap", "telnet"]
---
Display: The tool badges appear throughout the post as visually distinct tags:
- Green background with neon green border
- Gear icon (⚙️) prefix
- Monospace font (JetBrains Mono)
- Consistent styling across all posts
When to use tool badges:
- In front matter: Automatically displays on post header and taxonomy pages
- Inline in content: Highlight specific tools used in a particular step
- Tool comparisons: Show which tools you tested (even if one failed)
- Tool recommendations: Suggest alternatives or next tools to try
Real-world example from a CTF walkthrough:
---
title: "SQL Injection on Web App"
platforms: ["VulnHub", "HackTheBox"]
difficulties: ["intermediate"]
tools: ["burp suite", "sqlmap", "nmap", "dirb"]
---
See SHORTCODE_EXAMPLES.md for complete usage examples.
Difficulty Shortcode
File: layouts/shortcodes/difficulty.html
{{ $level := .Get "level" | lower }}
{{ $label := .Get "label" | default (title $level) }}
<div class="difficulty-badge difficulty-{{ $level }}">{{ $label }}</div>
Usage:
See SHORTCODE_EXAMPLES.md for complete syntax and usage examples.
In Front Matter:
---
title: "HackTheBox: Starting Point"
categories: ["CTF"]
difficulties: ["beginner"]
platforms: ["HackTheBox"]
tools: ["nmap", "ftp"]
---
See SHORTCODE_EXAMPLES.md for complete usage examples and real-world patterns.
Features:
- Color-coded badges: Green (beginner), yellow (intermediate), red (advanced)
- Auto-generated labels:
level="beginner"automatically displays “Beginner” - Custom labels: Override default with
label="Custom Text" - Consistent styling: Matches cybersecurity theme colors
- Accessible: Screen reader compatible
Best practices:
- Use in front matter for overall post difficulty
- Use inline to show difficulty of specific sections
- Match difficulty to your actual experience level
- Be honest - don’t oversell difficulty
- Consider audience in your difficulty assessment
Shortcode Summary
Shortcodes are your secret weapon for consistent, professional content. Here’s a quick reference:
| Shortcode | Purpose | Best Used For |
|---|---|---|
callout | Visual emphasis boxes | Warnings, tips, info, examples |
terminal | Command-line output | Tool results, shell interactions |
tool | Highlight tools | Tool names in content and front matter |
difficulty | Skill level indicators | Difficulty badges and assessments |
Pro Tips for Using Shortcodes:
Consistency: Use the same shortcode type for the same purpose (e.g., always use
warningfor security cautions)Moderation: Don’t overuse callouts - they lose impact if everything is highlighted
Context matters: A
warningin a tutorial means something different than in a CTF walkthroughSEO benefit: Shortcodes create structured data that search engines understand
Reader-friendly: Visual elements help scanners (people who skim) while detailed explanations help readers
Common Patterns:
See SHORTCODE_EXAMPLES.md for complete markdown patterns including:
- Machine introduction with difficulty and platform
- CTF walkthrough structure with callouts and terminal blocks
- Tutorial patterns with warnings and tips
- Content organization examples
When NOT to use shortcodes:
- Don’t use
terminalfor text that’s not command output - Don’t use
toolfor general technology mentions (only security tools) - Don’t use
difficultyon every section (use it strategically) - Don’t use
calloutfor every paragraph (save for truly important info)
Shortcodes transform markdown from plain text into an engaging, interactive experience. Use them thoughtfully, and your readers will thank you for the clarity and professionalism.
Content Quality: The Real Differentiator
Templates, shortcodes, and taxonomies are tools. What makes a cybersecurity blog valuable is content quality:
- Accurate information: Verify steps and commands
- Clear explanations: Help readers understand why, not just how
- Safety warnings: Highlight potential risks
- Alternative approaches: Show multiple solutions
- Real-world context: Connect theory to practice
What I Learned:
- Templates speed up writing but don’t replace good content
- Shortcodes enhance readability but shouldn’t be overused
- Taxonomies help organize but require consistent tagging
- The best blog design is invisible—readers should focus on content
Chapter 5: Superpowers - Interactive Features
Beyond Plain Markdown
After establishing content architecture, I wanted to add features that would enhance reader engagement and make the blog feel more professional. Static sites don’t have to be static—interactive features can make content more engaging.
Copy Buttons: Small Touch, Big Impact
Code examples are central to cybersecurity content. Readers need to copy commands quickly and accurately. Adding copy buttons to code blocks seemed like a small improvement, but it dramatically improved the user experience.
The implementation combines CSS and JavaScript:
CSS (already shown in Chapter 3):
- Positioning the button in the top-right corner
- Making it visible on hover
- Styling it to match the cybersecurity theme
JavaScript (already shown in Chapter 3):
- Finding all code blocks on the page
- Adding a button to each
- Handling the click event
- Using the Clipboard API for modern, reliable copying
- Providing visual feedback (“Copied!”)
Why This Matters:
- Time savings: No manual selecting and copying
- Accuracy: Prevents typos from manual copying
- User experience: Small touches matter
- Professional feel: Shows attention to detail
Pro Tip: Always provide feedback when an action completes. The “Copied!” message seems trivial, but it gives users confidence the action succeeded.
Live Table of Contents
Long security posts need navigation. Hugo’s Table of Contents (ToC) feature automatically generates a navigation menu from heading structure. With TocOpen = true in the configuration, the ToC is visible by default.
What Makes It Special:
- Automatic generation: Hugo creates it from markdown headings
- Nested structure: Respects heading hierarchy (H2, H3, H4)
- Smooth scrolling: Clicking a link smoothly scrolls to that section
- Active state: Shows which section you’re currently reading
Configuration:
[params]
TocOpen = true # Show ToC by default
Impact: Readers can jump between sections easily, especially useful for:
- CTF walkthroughs with multiple phases
- Tutorials with step-by-step instructions
- Long-form analysis posts
Syntax Highlighting: Code That Pops
Hugo includes syntax highlighting for code blocks. The PaperMod theme integrates this seamlessly:
nmap -sC -sV 10.10.10.10
import socket
def scan_port(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
result = sock.connect_ex((host, port))
sock.close()
return result == 0
Benefits:
- Readability: Keywords, strings, and comments are color-coded
- Accuracy: Makes typos more obvious
- Professional appearance: Code looks polished
- Learning aid: Helps readers understand syntax
Configuration: Hugo uses Chroma for syntax highlighting, built into the extended version. No additional setup required.
Image Optimization
Cybersecurity posts often include screenshots, diagrams, and tool outputs. Hugo automatically optimizes images:
- Resizing: Images are resized to appropriate dimensions
- Format conversion: Converts to modern formats (WebP) when beneficial
- Lazy loading: Images load as readers scroll
- Responsive: Different sizes for different screen sizes
Usage:

Hugo handles the optimization automatically. Just place images in the static/ directory and reference them in markdown.
Pro Tip: Use descriptive alt text for accessibility: 
Search Functionality (Optional)
Hugo includes built-in search functionality that creates a JSON index of all content. While not enabled by default in PaperMod, it can be added:
[params]
enableSearch = true
Features:
- Full-text search: Finds content across all posts
- Fast results: Client-side search for speed
- Highlighted matches: Shows where the search terms appear
Considerations:
- Adds complexity to the theme
- Requires additional JavaScript
- May not be necessary for smaller blogs
I chose not to enable search initially, preferring to keep the site lean. It can always be added later.
Social Sharing Made Easy
PaperMod includes social sharing buttons by default. With the configuration:
[[params.socialIcons]]
name = "github"
url = "https://github.com/hrithik"
[[params.socialIcons]]
name = "linkedin"
url = "https://linkedin.com/in/hrithik"
Readers can easily:
- Share posts on social media
- Follow on GitHub or LinkedIn
- Contact through professional networks
Why This Matters:
- Community building: Helps grow readership
- Professional networking: Connects with other security professionals
- Content distribution: Makes it easy to share valuable content
What I Learned About Interactive Features
Small improvements add up: Copy buttons, syntax highlighting, and ToC seem minor individually but combine to create a professional experience
Performance matters: Every feature must be fast. Hugo’s static generation ensures even interactive features don’t slow down the site
User-centric design: Features should solve real problems, not just look cool
Progressive enhancement: Start simple, add features as needed
Accessibility: Ensure all features work with screen readers and keyboard navigation
The result is a blog that feels modern and professional without sacrificing the speed and security that static sites provide.
Chapter 6: Writing at Speed - The Obsidian Workflow
The Problem with Traditional Writing Workflows
After building the foundation and design, I faced a new challenge: writing content efficiently. Markdown is great, but switching between:
- Writing content in an editor
- Managing front matter metadata
- Converting wikilinks to markdown links
- Optimizing images
- Managing templates
…became a workflow bottleneck. I wanted to focus on content, not tooling.
Discovering Obsidian
I started using Obsidian for my security research and note-taking. Its features were perfect for a cybersecurity blog:
- Linked thinking: Connect ideas with
[[wikilinks]] - Callouts: Rich, visual content organization
- Templates: Pre-built structures for different content types
- Graph view: Visualize connections between posts
- Fast writing: Distraction-free editor
But Obsidian saves in a specific format, and Hugo needs standard markdown. I needed a bridge.
Building the Bridge: Obsidian to Hugo Converter
I created a Python-based converter that automatically transforms Obsidian notes into Hugo-compatible posts. This isn’t just syntax conversion—it’s intelligent transformation.
The Architecture
┌─────────────────┐
│ Obsidian Vault │ (Write here!)
│ obsidian-vault│
│ /posts/ │
└────────┬────────┘
│
│ Auto-conversion
↓
┌─────────────────┐
│ Python │
│ Converter │
│ (400+ lines) │
└────────┬────────┘
│
↓
┌─────────────────┐
│ Hugo Content │
│ content/posts │
│ │
└────────┬────────┘
↓
(Hugo builds)
↓
┌─────────────────┐
│ Static Site │
│ public/ │
└─────────────────┘
Key Features
The converter handles everything:
1. Wikilink Conversion
# Obsidian format
See my analysis of [[SQL Injection]] and [[XSS Prevention]].
# Converts to Hugo format
See my analysis of [SQL Injection](/tags/sql-injection/) and [XSS Prevention](/tags/xss-prevention/).
2. Callout Transformation
# Obsidian callout
> [!info] Information
> Important details here.
# Converts to HTML
<div class="callout callout-info">
<div class="callout-title">Information</div>
<div class="callout-content">Important details here.</div>
</div>
3. Image Handling
# Obsidian

# Automatically:
# 1. Copies to static/images/
# 2. Optimizes (resizes to max 1200px, converts to JPEG)
# 3. Updates path to /images/network.jpg
4. Metadata Extraction The converter automatically detects:
- Tools: Scans for mentions of
nmap,burp suite,metasploit, etc. - Platforms: Finds references to
HackTheBox,TryHackMe, etc. - Difficulty: Analyzes content to suggest difficulty level
- Tags: Extracts from content and wikilinks
5. Front Matter Generation Automatically creates Hugo front matter:
---
title: "SQL Injection Basics"
date: 2025-11-01
draft: false
categories: ["Tutorial"]
tags: ["web", "sql", "injection"]
difficulties: ["beginner"]
platforms: ["General"]
tools: ["burp suite"]
description: "A beginner's guide to SQL injection vulnerabilities"
---
The Automation Framework
Instead of manually running the converter, I built a complete workflow system with scripts/workflow.sh:
Setup (One-Time)
# Install Python dependencies
pip3 install -r requirements.txt
# Create directory structure
./scripts/workflow.sh setup
# This creates:
# - obsidian-vault/posts/ (your writing location)
# - obsidian-vault/attachments/ (for images)
# - obsidian-templates/ (reusable templates)
Daily Workflow
Option 1: Convert on Demand
# Write in Obsidian
# ...
# Convert to Hugo
./scripts/workflow.sh convert
# Hugo auto-rebuilds (if server running)
Option 2: Watch Mode (Recommended)
# Auto-convert when files change
./scripts/workflow.sh watch
# Runs in background, monitors obsidian-vault/
# Converts instantly when you save in Obsidian
Option 3: Serve with Auto-Conversion
# Combines conversion + local server
./scripts/workflow.sh serve
# Converts, builds, and serves at http://localhost:1313
# Auto-rebuilds when Obsidian files change
Content Creation Flow
Step 1: Copy a Template
# Copy CTF walkthrough template
cp obsidian-templates/ctf-walkthrough.md obsidian-vault/posts/htb-sunday.md
# Copy tutorial template
cp obsidian-templates/tutorial.md obsidian-vault/posts/sql-injection-basics.md
Step 2: Write in Obsidian Use the template structure with Obsidian features:
[[wikilinks]]to link related posts> [!callout]for visual emphasis[[attachments/image.png]]for images#hashtagsfor topics
Step 3: Auto-Convert
# Manual convert
./scripts/workflow.sh convert
# Or use watch mode (automatic)
./scripts/workflow.sh watch
Step 4: Preview
# Serve locally
./scripts/workflow.sh serve
# Visit http://localhost:1313
Step 5: Build & Deploy
# Build for production
./scripts/workflow.sh build
# Deploy the public/ directory
Obsidian Templates Included
CTF Walkthrough Template
---
title: "{{ title }}"
tags: ["ctf"]
difficulty: "beginner"
platform: "HackTheBox"
---
# {{ title }}
> [!info] Machine Information
> - **Name**: {{ title }}
> - **OS**: Linux
> - **IP**: 10.10.11.XXX
> - **Difficulty**: Beginner
## Initial Reconnaissance
> [!tip] Pro Tip
> Start with basic port scanning.
```bash
nmap -sC -sV 10.10.11.XXX
Service Enumeration
Initial Access
Privilege Escalation
Flag Finding
cat /home/*/flag.txt
Summary
Key lessons learned.
Tools: {{ tools }} Tags: {{ tags }}
### Tutorial Template
```markdown
---
title: "{{ title }}"
tags: ["tutorial"]
difficulty: "beginner"
---
# {{ title }}
> [!abstract] Abstract
> Brief overview of what this tutorial covers.
## Prerequisites
- List requirements here
- Background knowledge needed
## Introduction
## Step 1: Getting Started
## Step 2: Implementation
## Step 3: Advanced Techniques
## Best Practices
## Common Mistakes
> [!warning] Warning
> Common pitfalls to avoid.
## Conclusion
Key takeaways.
Advanced Features
Custom Converter Configuration
Edit scripts/config.yaml:
# Source and destination paths
paths:
source: "obsidian-vault"
output: "content/posts"
attachments: "obsidian-vault/attachments"
# Image optimization
images:
max_width: 1200
quality: 85
format: "jpeg"
# Auto-extraction settings
auto_extract:
tools: true
platforms: true
difficulty: true
tags: true
Environment Detection
The converter intelligently determines:
- Content type: CTF vs. tutorial vs. analysis
- Difficulty: Based on keywords and complexity
- Tools used: Scans for security tool names
- Platform: Detects HTB, THM, etc. from content
Error Handling
The workflow includes comprehensive error handling:
$ ./scripts/workflow.sh check
✓ Hugo installed (v0.119.0)
✓ Python dependencies installed
✓ Directory structure created
✓ Configuration files present
✓ Git submodules initialized
All dependencies satisfied!
Why This Matters
The Obsidian workflow transformed my writing process:
Speed: Previously, creating a post took 30-45 minutes (setup, formatting, metadata). Now: 15-20 minutes.
Consistency: Templates ensure all posts have the same structure and quality.
Flexibility: Write in Obsidian with its powerful features, publish as Hugo with its performance.
Focus: Less time managing tools, more time creating content.
Organization: Graph view shows connections between posts, helping identify content gaps.
Real-World Example
Here’s how a real CTF walkthrough flows:
In Obsidian (obsidian-vault/posts/htb-meow.md):
# HTB: Meow
> [!info] Machine Info
> - Name: Meow
> - OS: Linux
> - Difficulty: Beginner
This is my first HackTheBox machine!
## Recon
Let me scan with [[nmap]]:
> [!terminal]
> ```
> nmap -sC -sV 10.10.10.10
> ```
## Access
I found port 23 (telnet) open. Let me try [[telnet]] access...
## Lessons
Learned about [[enumeration]] basics.
Auto-converts to Hugo (content/posts/htb-meow.md):
---
title: "HTB: Meow"
date: 2025-11-01
draft: false
categories: ["CTF"]
tags: ["linux", "enumeration", "telnet"]
difficulties: ["beginner"]
platforms: ["HackTheBox"]
tools: ["nmap", "telnet"]
description: "Beginner-friendly HackTheBox walkthrough"
---
# HTB: Meow
<div class="callout callout-info">
<div class="callout-title">Machine Info</div>
<div class="callout-content">
- Name: Meow<br>
- OS: Linux<br>
- Difficulty: Beginner
</div>
</div>
This is my first HackTheBox machine!
## Recon
Let me scan with <span class="tool-badge">nmap</span>:
<div class="terminal">nmap -sC -sV 10.10.10.10</div>
## Access
I found port 23 (telnet) open. Let me try <span class="tool-badge">telnet</span> access...
## Lessons
Learned about <span class="tool-badge">enumeration</span> basics.
Technical Implementation Details
The converter (scripts/obsidian_to_hugo_converter.py) is a 400+ line Python script using:
- python-frontmatter: For YAML parsing
- Pillow: For image optimization
- pyyaml: For configuration
- re: For regex-based transformations
Key transformations:
- Parse Obsidian markdown with regex
- Convert wikilinks to markdown or Hugo cross-references
- Transform callouts to HTML with appropriate CSS classes
- Process images: Copy, optimize, update paths
- Extract metadata: Auto-detect tools, platforms, difficulty
- Generate front matter: Create Hugo-compliant metadata
- Write Hugo markdown: Save to content/posts/
What I Learned
The Obsidian workflow taught me:
- Tooling matters: Good tools remove friction and enable creativity
- Automation pays off: The time invested in building the converter saves hours every week
- Consistency enables quality: Templates and auto-formatting ensure professional output
- Flexibility in, standards out: Write freely in Obsidian, publish cleanly via Hugo
- Speed enables volume: Faster workflow = more content published
The result is a writing system that’s both powerful and simple. I can focus on sharing cybersecurity knowledge, not managing markdown formatting.
Chapter 7: Going Live - Deployment Strategy
The Final Challenge
After building and testing locally, the final step is deployment—getting your blog online where readers can find it. For a cybersecurity blog, the deployment choice matters for three reasons:
- Speed: Fast loading times improve search rankings and reader experience
- Security: Static sites are inherently secure, but hosting still matters
- Cost: Budget matters, especially when starting out
I evaluated several deployment options, weighing cost, performance, and ease of use.
Option 1: GitHub Pages (Free & Simple)
GitHub Pages is the most straightforward option for open-source projects.
Setup Process:
# 1. Push to GitHub
git remote add origin https://github.com/yourusername/your-blog.git
git push -u origin main
# 2. Enable GitHub Pages in repository settings
# Source: GitHub Actions
# 3. Create .github/workflows/deploy.yml
GitHub Actions Workflow (.github/workflows/deploy.yml):
name: Deploy Hugo site
on:
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
- name: Build
run: hugo --minify
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
Pros:
- Free for public repositories
- Integrated with GitHub (natural for developers)
- Automatic deployment on every push
- Custom domain support
- CDN included
Cons:
- No server-side processing
- Build time limit (10 minutes for free tier)
- Private repositories cost money ($3/month)
Best For: Open-source blogs, developers comfortable with GitHub, budget-conscious projects
Option 2: Netlify (Recommended for Performance)
Netlify offers excellent performance and developer experience with a generous free tier.
Setup Process:
# Method 1: Git integration
# 1. Push to GitHub/GitLab/Bitbucket
# 2. Connect repository to Netlify
# 3. Build command: hugo --minify
# 4. Publish directory: public
# 5. Auto-deploys on every push!
# Method 2: Manual deploy
netlify deploy --prod --dir=public
Netlify Configuration (netlify.toml):
[build]
command = "hugo --minify"
publish = "public"
[build.environment]
HUGO_VERSION = "latest"
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
X-Content-Type-Options = "nosniff"
[[headers]]
for = "/css/*"
[headers.values]
Cache-Control = "public, max-age=31536000"
Pros:
- Global CDN for fast loading worldwide
- Form handling (free tier includes 100 submissions/month)
- Serverless functions
- Branch previews (test changes before publishing)
- Split testing (Pro feature)
Cons:
- Free tier has bandwidth limits (100GB/month)
- Must upgrade for advanced features ($19/month Pro plan)
Best For: Professional blogs, performance-critical sites, blogs expecting growth
Cost: Free tier (suitable for most blogs), Pro plan $19/month for advanced features
Option 3: Vercel (Developer-Friendly)
Vercel is designed for frontend developers and offers excellent performance.
Setup Process:
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel --prod
# Or connect GitHub repository for auto-deploy
Vercel Configuration (vercel.json):
{
"builds": [
{
"src": "hugo.toml",
"use": "@vercel/static-build",
"config": {
"distDir": "public"
}
}
]
}
Pros:
- Extremely fast deployments (edge network)
- Automatic HTTPS
- Git integration
- Analytics included
- Generous free tier
Cons:
- Less Hugo-specific documentation
- Geared toward JavaScript frameworks
Best For: Developers who like Vercel’s workflow, performance-focused sites
Cost: Free tier (100GB bandwidth), Pro $20/month
Option 4: Traditional VPS (Full Control)
For maximum control and customization, a VPS (Virtual Private Server) is an option.
Providers:
- DigitalOcean Droplet: $5-6/month
- Vultr: $2.50-5/month
- AWS EC2: $3-10/month
- Google Cloud: $5-15/month
- Linode: $5/month
Setup Process:
# 1. Create Ubuntu 22.04 VPS
# 2. SSH into server
ssh root@your-server-ip
# 3. Install Nginx
apt update
apt install nginx git
# 4. Build and deploy
git clone https://github.com/yourusername/your-blog.git
cd your-blog
hugo --minify
cp -r public/* /var/www/html/
# 5. Configure Nginx
# Edit /etc/nginx/sites-available/default
server {
listen 80;
server_name yourdomain.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# 6. Restart Nginx
systemctl restart nginx
systemctl enable nginx
Pros:
- Full control over server environment
- Can run additional services (monitoring, analytics, etc.)
- No platform lock-in
- Educational value (learning server management)
Cons:
- More complex setup
- Responsible for security updates
- Manual deployment process
- Must manage backups
Best For: Learning experience, enterprise requirements, custom integrations
My Decision: Netlify
After evaluating all options, I chose Netlify for several reasons:
- Performance: Global CDN ensures fast loading worldwide
- Ease of use: Simple setup, automatic deployments
- Features: Branch previews, form handling, serverless functions
- Cost: Free tier sufficient for initial launch
- Professional feel: Reliable infrastructure
The Process:
- Created Netlify account
- Connected GitHub repository
- Configured build settings:
- Build command:
hugo --minify - Publish directory:
public
- Build command:
- Deployed!
Pro Tip: Start with the free tier. You can always upgrade later if you outgrow it.
Cost Comparison
| Platform | Cost | Bandwidth | Custom Domain | SSL | Difficulty |
|---|---|---|---|---|---|
| GitHub Pages | Free | 100GB | ✅ | ✅ | Easy |
| Netlify | Free/Pro | 100GB/1TB | ✅ | ✅ | Easy |
| Vercel | Free/Pro | 100GB | ✅ | ✅ | Easy |
| DigitalOcean | $5/mo | Unlimited | ✅ | ✅ | Medium |
| AWS S3+CloudFront | $5-25/mo | Pay-per-use | ✅ | ✅ | Medium |
| Traditional VPS | $5-20/mo | Unlimited | ✅ | ✅ | Hard |
Deployment Best Practices
- Environment variables: Store sensitive data (analytics IDs) securely
- Build caching: Enable to speed up deployments
- Custom domain: Use your own domain for professionalism
- SSL certificate: Ensure HTTPS is enabled
- Redirects: Handle URL changes properly
- Build logs: Check logs if deployments fail
What I Learned About Deployment
- Start simple: GitHub Pages or Netlify free tier is sufficient for most blogs
- Performance matters: Choose a platform with a global CDN
- Automation is key: Manual deployments are error-prone
- Monitor usage: Keep an eye on bandwidth and build time
- Plan for growth: Choose a platform that can scale with you
The deployment platform you choose today can be changed later. Start with what’s easiest and most cost-effective, then optimize as needed.
Appendix A: Troubleshooting Guide
During development and deployment, you might encounter issues. Here are solutions to common problems.
Build Errors
Error: “unable to find config file”
Problem: Hugo can’t find hugo.toml
Solution:
# Make sure you're in the correct directory
ls -la hugo.toml
# If missing, check the current directory
pwd
# You should be in /path/to/my-blog/
# If in wrong directory, navigate correctly
cd /path/to/my-blog/
Error: “theme not found” or “module not found”
Problem: PaperMod theme submodule not properly initialized
Solution:
# Initialize submodules
git submodule update --init --recursive
# Or for PaperMod specifically
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
# Verify theme exists
ls -la themes/PaperMod/
Error: “unexpected end of file” in templates
Problem: Missing closing tags in shortcode templates
Solution: Check layouts/shortcodes/ files for syntax errors:
# Example correct syntax
layouts/shortcodes/tool.html:
<span class="tool-badge">{{ .Get 0 }}</span>
# Common mistake: missing closing }}
Error: “front matter error” or “yaml error”
Problem: Invalid YAML syntax in front matter
Solution:
- Check for missing closing quotes
- Verify indentation (use spaces, not tabs)
- Ensure correct date format (YYYY-MM-DD)
Example correct front matter:
---
title: "My Post"
date: 2025-11-01
categories: ["Tutorial"]
tags: ["tag1", "tag2"]
---
Local Development Issues
Site loads but looks broken (no styling)
Problem: Custom CSS not loading
Solution:
# Check if custom.css exists
ls -la assets/css/custom.css
# Verify hugo.toml references it correctly
grep "customCSS" hugo.toml
# Should show:
# customCSS = ["css/custom.css"]
# Clear cache and restart server
hugo server --disableFastRender
Pages not updating on file changes
Problem: Hugo server cache not clearing
Solution:
# Stop server (Ctrl+C)
# Clear cache
rm -rf .hugo_build.lock
# Restart with cache disabled
hugo server --disableFastRender
“Port 1313 already in use” error
Problem: Multiple Hugo servers running
Solution:
# Find and kill process on port 1313
lsof -ti:1313 | xargs kill -9
# Or use a different port
hugo server -p 1314
Git/GitHub Issues
Error: “submodule update failed”
Problem: Git submodule issues
Solution:
# Deinitialize and re-add submodule
git submodule deinit themes/PaperMod
git rm themes/PaperMod
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
# Or force update
git submodule update --remote --force
GitHub Actions build failing
Problem: Workflow not configured correctly
Solution: Ensure .github/workflows/deploy.yml has:
- name: Checkout
uses: actions/checkout@v4 # Use v4, not v3
with:
submodules: recursive # Important for PaperMod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest' # Or specific version
“Permission denied” when pushing
Problem: GitHub authentication issues
Solution:
# Configure git with your GitHub email/name
git config --global user.email "your-email@example.com"
git config --global user.name "Your Name"
# Use GitHub personal access token (not password)
git remote set-url origin https://username:token@github.com/username/repo.git
Deployment Issues
Site builds locally but fails on Netlify
Problem: Missing environment variables or build command
Solution:
- Check Netlify build logs
- Verify build command:
hugo --minify - Verify publish directory:
public - Check
netlify.toml:
[build]
command = "hugo --minify"
publish = "public"
404 errors on deployed site
Problem: Base URL not set correctly
Solution: In hugo.toml:
# Must match your actual domain
baseURL = "https://yourdomain.com/" # Include trailing slash
# If testing locally, you can use:
# baseURL = "http://localhost:1313/"
CSS/JS not loading after deploy
Problem: Static files not being served
Solution:
- Check that
static/directory exists with files - Verify Hugo is copying files:
# Hugo should copy static/ to public/ during build
ls public/css/
- If using Netlify, check headers in
netlify.toml:
[[headers]]
for = "/css/*"
[headers.values]
Cache-Control = "public, max-age=31536000"
Images not displaying
Problem: Incorrect image paths
Solution:
# Wrong (relative path)

# Correct (from static root)

# Or place images in static/images/ and reference as:

Obsidian Converter Issues
“Module not found” error when running converter
Problem: Python dependencies missing
Solution:
# Install dependencies
pip3 install -r requirements.txt
# Verify installation
pip3 list | grep -E "(frontmatter|Pillow|pyyaml)"
Files not converting
Problem: Wrong paths or permissions
Solution:
# Check directory structure
ls -la obsidian-vault/posts/
# Verify converter config
cat scripts/config.yaml
# Check file permissions
chmod +x scripts/workflow.sh
Images not copying or optimizing
Problem: Pillow not installed or wrong paths
Solution:
# Reinstall Pillow
pip3 uninstall Pillow
pip3 install Pillow
# Check image paths in Obsidian
# Use: 
# NOT: 
“Permission denied” when watching files
Problem: Missing inotify-tools
Solution:
# Ubuntu/Debian
sudo apt install inotify-tools
# macOS (using Homebrew)
brew install inotify-tools
# Then try watch mode again
./scripts/workflow.sh watch
Performance Issues
Slow build times
Problem: Large images or excessive content
Solution:
- Optimize images before adding:
# Use ImageMagick to resize
convert large-image.png -resize 1200x quick-image.jpg
- Check for unnecessary files:
# Remove drafts from production
hugo --buildDrafts=false
# Check site size
du -sh public/
- Update Hugo to latest version:
# For binary install
brew upgrade hugo # macOS
sudo apt upgrade hugo # Ubuntu
# Check version
hugo version
Large bundle size
Problem: Unoptimized CSS/JS
Solution:
# Verify minification is enabled in hugo.toml
[minify]
minify = true
# Check custom CSS size
wc -c assets/css/custom.css
# Consider splitting CSS if very large
Getting Help
If you’re still stuck:
- Check Hugo docs: https://gohugo.io/documentation/
- Check PaperMod issues: https://github.com/adityatelange/hugo-PaperMod/issues
- Hugo Discord community: https://discord.gg/hugo
- Check build logs: Look for specific error messages
- Simplify and test: Create minimal test case to isolate issue
Useful Debug Commands
# Check Hugo version and configuration
hugo version
hugo config
# Test build without serving
hugo --gc # Garbage collect first
hugo
# Check for missing pages
hugo --renderToMemory
# Build with verbose output
hugo --verbose
# Analyze site
hugo --printStats
Creating an Issue
When asking for help, include:
- Hugo version (
hugo version) - OS and version
- Complete error message
- Relevant configuration file contents
- Steps to reproduce
Appendix B: Analytics Implementation
Analytics help you understand your readers. For a cybersecurity blog, choose privacy-focused solutions that don’t compromise reader trust.
Option 1: Plausible Analytics (Recommended)
Plausible is privacy-friendly, GDPR-compliant, and doesn’t use cookies or collect personal data.
Setup
Step 1: Create Account
- Go to https://plausible.io/
- Sign up for an account
- Add your domain (e.g.,
yourdomain.com)
Step 2: Get Tracking Code Your dashboard shows a tracking script like:
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.js"></script>
Step 3: Add to Hugo
Add to layouts/_default/single.html (for posts) or create layouts/partials/head.html:
<!-- Add before closing </head> tag -->
{{ if not .Site.IsServer }}
<!-- Plausible Analytics -->
<script defer data-domain="{{ .Site.Params.plausibleDomain | default .Site.BaseURL }}" src="https://plausible.io/js/script.js"></script>
{{ end }}
Step 4: Configure in hugo.toml
[params]
plausibleDomain = "yourdomain.com"
Features You Get
- Real-time visitors: See who’s online now
- Page views: Most popular content
- Referrers: Where traffic comes from
- Countries: Geographic distribution
- Devices: Desktop vs. mobile
- No cookies: Compliant with privacy laws
- No data collection: Visitors can’t be tracked across visits
Privacy Benefits
- No cookies: Nothing stored in browser
- No IP logging: Anonymized and aggregated
- No tracking: Can’t follow users across web
- Open source: Code is auditable
- EU-based: Subject to GDPR protection
Option 2: Google Analytics 4
Google Analytics offers comprehensive tracking but requires cookie consent.
Setup
Step 1: Create GA4 Property
- Go to https://analytics.google.com/
- Create new property
- Choose GA4 (not Universal Analytics)
- Get Measurement ID (G-XXXXXXXXXX)
Step 2: Add to Hugo
Create layouts/partials/analytics.html:
<!-- Google Analytics 4 -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
Add to layouts/_default/single.html:
{{ partial "analytics.html" . }}
Step 3: Configure Cookie Consent
For GDPR compliance, add consent prompt before loading GA. Use cookie consent library:
<!-- Cookie Consent -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css"/>
<script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js"></script>
Google Analytics 4 Features
- Detailed tracking: Comprehensive visitor insights
- Cross-platform: Web + mobile app tracking
- Machine learning: Predictive metrics
- Free: No cost for standard features
- Integration: Works with Google Ads, Search Console
Privacy Concerns
- Cookies required: Subject to GDPR/CCPA
- Data collection: Extensive tracking
- Third-party: Data goes to Google
- Ad targeting: Can be used for advertising
- Retention: Data stored for 14 months
Option 3: Self-Hosted Analytics (Privacy-First)
Umami or Fathom provide privacy-focused analytics you control.
Using Umami (Open Source)
Step 1: Deploy Umami
# Using Docker
docker run -d --name umami \
-p 3000:3000 \
-e DATABASE_URL=postgresql://user:password@db:5432/umami \
ghcr.io/umami-software/umami:latest
# Or use Umami Cloud (paid)
Step 2: Add Tracking
Get tracking script from Umami dashboard:
<script async src="https://your-umami-instance.com/umami.js" data-website-id="YOUR-ID"></script>
Step 3: Configure hugo.toml
[params]
umamiUrl = "https://your-umami-instance.com"
umamiId = "your-website-id"
Umami Features
- Self-hosted: Run on your own server
- Privacy-focused: GDPR compliant
- Open source: Transparent code
- No cookies: No personal data collection
- Simple dashboard: Clean, usable interface
What Analytics Reveal for a Security Blog
Traffic Sources:
- Reddit (r/cybersecurity, r/netsec)
- Twitter/X security researchers
- LinkedIn professional network
- Search engines (Google, Bing)
- Direct visits
Popular Content:
- Beginner CTF writeups
- Tool tutorials (nmap, Burp Suite)
- Specific machine walkthroughs
- Security research posts
Reader Behavior:
- Time spent on page
- Bounce rate for tutorials
- Exit points
- Device breakdown
Growth Metrics:
- New vs. returning visitors
- Geographic distribution
- Organic search performance
Privacy-First Approach for Security Blog
For cybersecurity content, privacy is paramount:
Why Plausible Works Best:
- Trust: Security professionals value privacy
- Compliance: No cookie consent required
- Transparency: Open source, auditable
- Performance: Lightweight script (1KB)
- Professional: Matches cybersecurity ethics
Implementation in hugo.toml:
[params]
# Analytics
analytics = "plausible" # or "google" or "umami"
plausibleDomain = "yourdomain.com"
# Optional: Custom domain for Plausible
# plausibleScript = "https://plausible.yourdomain.com/js/script.js"
Check Analytics Results:
# Test if tracking works
hugo server -D
# Check browser console for errors
# Visit pages to see real-time data
What to Track (and What NOT to Track)
Track (for Content Improvement)
- Page views per post
- Referrer sources
- Time on page
- Bounce rate
- Device/browser types
Don’t Track (for Privacy)
- User IDs or personas
- Cross-site tracking
- IP addresses (beyond basic geolocation)
- Personal information
- Behavioral tracking across visits
Understanding Your Audience
Analytics help you create better content:
If most traffic is beginners:
- Add more CTF tutorials
- Explain basic concepts more
- Include prerequisites
If mobile traffic is high:
- Improve mobile readability
- Ensure code blocks scroll well
- Test on mobile devices
If traffic comes from Reddit:
- Share more community-driven content
- Ask for topic suggestions
- Engage in comments
If search traffic is high:
- Optimize for SEO
- Add more meta descriptions
- Improve keyword targeting
Setting Goals
Analytics without goals are just numbers. Set measurable objectives:
Content Goals:
- 1 new post per week
- 1000 page views per month
- 5 minute average time on page
Engagement Goals:
- Social shares (track via URL parameters)
- Comments/feedback
- Newsletter signups
Community Goals:
- Reader submissions
- Guest posts
- Collaboration requests
My Recommendation: Start Simple
For a cybersecurity blog, I recommend:
- Start with Plausible: Privacy-focused, no compliance work
- Wait 3 months: Let analytics accumulate
- Review quarterly: Adjust content strategy based on data
- Keep it minimal: Don’t overwhelm yourself with metrics
Pro Tip: Analytics help you understand what’s popular, but write what you’re passionate about. The best security content comes from genuine interest, not just what the data says.
Appendix C: SEO Optimization
Search Engine Optimization helps readers discover your cybersecurity content. Hugo makes SEO straightforward with built-in features.
Why SEO Matters for Security Blogs
Cybersecurity is a rapidly evolving field. When a new vulnerability is disclosed:
- Time-sensitive: Information needs to be found quickly
- Technical audience: People search for specific terms
- Global readership: International audience searching in different languages
- Community-focused: Reddit, Twitter, and forums amplify good content
Good SEO ensures your hard-earned knowledge reaches the people who need it.
Hugo’s SEO Features (Built-In)
Hugo includes excellent SEO features by default:
Automatic Features
- Clean URLs:
/posts/my-ctf-walkthrough/instead of/posts/my-ctf-walkthrough.html - XML Sitemap: Auto-generated at
/sitemap.xml - Robots.txt: Generated for search crawlers
- Schema.org structured data: JSON-LD metadata for rich snippets
- RSS feeds: Auto-generated for content updates
- Canonical URLs: Prevents duplicate content issues
Enable in hugo.toml
# Site information (appears in search results)
baseURL = "https://yourdomain.com/"
title = "Your Security Blog"
description = "Cybersecurity research, CTF writeups, and tutorials"
# Enable SEO features
[sitemap]
changefreq = "weekly"
priority = 0.7
filename = "sitemap.xml"
# RSS
[outputs]
home = ["HTML", "RSS"]
# Search engine crawler instructions
[robots]
userAgent = "*"
allowAll = true
Sitemap = "https://yourdomain.com/sitemap.xml"
Content-Level SEO
Title Optimization
Best Practices:
- Keep under 60 characters (appears fully in search results)
- Include target keyword early
- Make it compelling for human readers
- Avoid keyword stuffing
Examples:
# Good
title: "HackTheBox - Meow: Beginner CTF Walkthrough"
# Avoid (too generic)
title: "CTF Walkthrough"
Meta Descriptions
Add to each post’s front matter:
---
title: "SQL Injection Basics"
description: "Learn SQL injection fundamentals with practical examples. Covers detection, exploitation, and prevention techniques for web applications."
---
Best Practices:
- 150-160 characters
- Unique per post
- Include call-to-action
- Summarize value proposition
Structured Data (Schema.org)
Hugo automatically adds structured data. Enhance with custom markup in layouts/_default/single.html:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "{{ .Title }}",
"description": "{{ .Description }}",
"datePublished": "{{ .Date.Format "2006-01-02" }}",
"dateModified": "{{ .Lastmod.Format "2006-01-02" }}",
"author": {
"@type": "Person",
"name": "{{ .Site.Params.author | default "Your Name" }}"
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "{{ .Permalink }}"
}
}
</script>
Technical SEO
Page Speed (Hugo’s Superpower)
Hugo’s static generation gives you automatic performance:
# Check build stats
hugo --printStats
# Example output:
# Total in 127 ms
# Dist: 12.375 MB (errors: 0)
Performance Tips:
- Optimize images: Use
layouts/shortcodes/image.htmlwith automatic resizing - Minification: Already enabled in our config
- Code splitting: Not needed with static generation
- Caching: Configure on deployment platform
URL Structure
Best Practices:
# Use pretty URLs (default in Hugo)
[permalinks]
posts = "/:slug/" # /posts/my-post/
# OR
posts = "/:year/:month/:slug/" # /posts/2025/11/my-post/
Avoid:
- Query parameters (
?p=123) - Session IDs
- Multiple URLs for same content
Internal Linking
Use Hugo’s cross-reference features:
See my post on [SQL injection](ref "/posts/sql-injection.md").
Or use wikilinks via Obsidian converter:
[[SQL Injection]] → auto-converts to proper links
Benefits:
- Helps readers find related content
- Distributes page authority
- Keeps visitors longer
Content SEO for Security Topics
Keyword Research for Security Content
Tools:
- Google Keyword Planner: Free, good for search volume
- AnswerThePublic: Finds questions people ask
- Semrush/Ahrefs: Paid, comprehensive
- Reddit: See what security professionals discuss
Security-Specific Keywords:
- “HackTheBox [machine] walkthrough”
- “[Tool] tutorial”
- “[Vulnerability] CVE-202X-XXXX”
- “[Topic] for beginners”
- “[Platform] writeups”
Content Clusters
Group related content together:
Cybersecurity Blog
├── Web Security
│ ├── SQL Injection Basics
│ ├── XSS Prevention
│ ├── CSRF Protection
│ └── Web Security Checklist
├── Network Security
│ ├── Nmap Tutorial
│ ├── Wireshark Analysis
│ ├── Network Segmentation
│ └── VPN Security
└── CTF Writeups
├── HackTheBox: Starting Point
├── HackTheBox: Academy
└── TryHackMe: Fundamentals
Update Strategy
Fresh Content Wins:
- Update posts when new CVEs are published
- Add new CTF writeups regularly
- Review and refresh old tutorials
- Mark update dates in front matter:
---
title: "SQL Injection Basics"
date: 2023-01-15
lastmod: 2025-11-01 # Shows when updated
---
Social Media Optimization
Open Graph Tags
Enable in hugo.toml:
[markup]
[markup.goldmark.renderer]
unsafe = true # Required for OG tags in markdown
[params]
# Open Graph / Facebook
og_image = "/images/og-image.png"
og_type = "website"
# Twitter
twitter_card = "summary_large_image"
twitter_site = "@yourhandle"
twitter_image = "/images/twitter-card.png"
Social Sharing Buttons
PaperMod includes this by default. Configure in hugo.toml:
[params]
ShowShareButtons = true
ShowReadingTime = true
ShowWordCount = true
Submit to Search Engines
Google Search Console
- Verify ownership: Add HTML meta tag to
layouts/_default/head.html:
<meta name="google-site-verification" content="your-verification-code" />
- Submit sitemap: Go to https://search.google.com/search-console
- Request indexing: For new posts
Bing Webmaster Tools
- Verify site: Add meta tag or upload XML file
- Submit sitemap: https://www.bing.com/webmasters/
- Configure: Set geographic targeting and crawl speed
Submit Sitemaps
After deploying, submit these URLs:
- Google:
https://yourdomain.com/sitemap.xml - Bing:
https://yourdomain.com/sitemap.xml - Yandex:
https://yourdomain.com/sitemap.xml
Local SEO (If Applicable)
If you offer local security services:
[params]
# Add to organization schema
[params.localBusiness]
name = "Your Security Services"
address = "City, Country"
geo = "latitude,longitude"
Monitoring SEO Performance
Tools to Track
- Google Search Console: Shows how Google sees your site
- Plausible Analytics: Track organic traffic
- Bing Webmaster Tools: Bing search performance
Key Metrics
- Impressions: How often your site appears in search
- Click-through rate: % who click from results
- Average position: Ranking for target keywords
- Indexed pages: Are your posts being discovered?
Fix Common Issues
“Page not indexed”:
- Check robots.txt
- Verify no “noindex” tags
- Ensure content is original
- Check for crawl errors
“Low click-through rate”:
- Improve title tags
- Write better meta descriptions
- Add structured data
- Test different headlines
“Ranking dropping”:
- Content may be outdated
- Competitors published better content
- Site speed issues
- Algorithm updates
SEO Checklist for Each Post
Before publishing, verify:
- Title includes target keyword
- Meta description written (150-160 chars)
- At least one image with alt text
- Internal links to 2-3 related posts
- External links to authoritative sources
- H1, H2, H3 structure used
- Front matter completed (tags, categories, tools)
- Difficulty level specified
- Platform mentioned (HTB, THM, etc.)
My SEO Strategy for Security Blog
Content-First Approach:
- Write valuable, accurate content
- Hugo’s speed gives SEO advantage
- Share on social media naturally
- Build backlinks through quality
- Update regularly with fresh content
What Works:
- Tutorial posts rank well (evergreen content)
- CTF writeups get traffic from specific searches
- Tool reviews attract backlinks
- Vulnerability analysis gets social shares
What Doesn’t Work:
- Keyword stuffing (sounds unnatural)
- Thin content (Hugo helps avoid this)
- Duplicate content (avoid copying others)
- Clickbait titles (damages credibility)
Measuring Success
90-Day Goals:
- 20+ posts published
- 500+ organic visitors/month
- 10+ keywords ranking in top 10
- 5+ backlinks from security sites
Tools:
- Google Search Console (free)
- Plausible Analytics (free/paid)
- Google Analytics 4 (free)
Pro Tip: SEO is a marathon, not a sprint. Focus on creating valuable content. Technical SEO (which Hugo handles) is table stakes—content quality is what wins.
Conclusion: Lessons Learned & Next Steps
What I Built
Through this journey, I created a professional cybersecurity blog from scratch:
- Foundation: Fast, secure Hugo static site
- Design: Custom cybersecurity theme with dark mode, neon accents, terminal styling
- Architecture: Five custom taxonomies for organizing security content
- Templates: Reusable archetypes for CTF walkthroughs and tutorials
- Features: Interactive elements (copy buttons, syntax highlighting, callout boxes)
- Deployment: Production-ready site on Netlify
The Result: A platform that makes sharing cybersecurity knowledge effortless and professional.
Key Takeaways
Start with the right foundation: Choosing Hugo was the best decision I made. Fast builds and static generation provide the perfect balance of flexibility and performance.
Design with intent: Every design decision should serve your readers. Dark mode for late-night security work, difficulty badges for audience targeting, tool badges for technology awareness.
Automate consistency: Templates and archetypes ensure content quality without adding friction to the writing process.
User experience matters: Small features like copy buttons and syntax highlighting dramatically improve reader experience.
Deploy early, iterate often: Getting the blog live was motivating. I could focus on content instead of endless tweaking.
Security is paramount: Even for a static site, hosting choice and configuration matter. The cybersecurity industry holds blogs to higher standards.
Common Pitfalls to Avoid
- Perfectionism: Start with basic features, add complexity later
- Over-engineering: Don’t build features you don’t need
- Ignoring mobile: Many readers will access on mobile devices
- No analytics: You can’t improve what you don’t measure
- Inconsistent content: Templates ensure quality and consistency
Performance Achieved
After implementing all optimizations:
- Build time: <200ms for 50+ pages
- Lighthouse Performance: 95-100/100
- Time to First Byte: <200ms
- First Contentful Paint: <1s
- Bundle size: <2MB (including all assets)
These metrics are achievable because Hugo generates static files with zero runtime processing.
Next Steps
The blog is live and functional, but there’s always room for improvement:
Immediate Enhancements
- Add analytics (Plausible for privacy-focused tracking)
- Enable search functionality (for better content discovery)
- Add a comments system (Giscus for GitHub-based comments)
- Create RSS feed (automatic content distribution)
- Submit to search engines (Google Search Console, Bing Webmaster)
Content Strategy
- Regular posting schedule: Commit to a schedule (weekly CTF writeups, bi-weekly tutorials)
- Content calendar: Plan topics in advance, coordinate with CTF events
- SEO optimization: Research keywords, optimize meta descriptions
- Community engagement: Share posts on security forums, Reddit, Discord servers
Long-term Vision
- Guest posts: Invite other security professionals to contribute
- Email newsletter: Build a mailing list for important updates
- Video content: Complement written posts with video walkthroughs
- Workshops: Host online workshops using the blog as a foundation
- Podcast: Audio version of blog posts for commutes
Final Thoughts
Building this blog taught me that the best platforms disappear into the background. Readers should focus on content, not fighting with the interface. Hugo provides the perfect foundation—fast, secure, flexible—allowing me to focus on what matters: sharing cybersecurity knowledge.
The cybersecurity community thrives on knowledge sharing. Every CTF writeup helps someone learn. Every tutorial reduces the barrier to entry. Every research post advances our collective understanding.
This blog isn’t just a personal project—it’s a contribution to that community. By making it fast, professional, and easy to use, I’m helping ensure that valuable cybersecurity knowledge reaches as many people as possible.
If you’re a cybersecurity professional considering a blog, I hope this journey inspires you. The tools are free, the process is well-documented, and the community is welcoming. Your knowledge matters—make sure it’s easily accessible.
Start building today. The community is waiting for what you’ll create.
Additional Resources
Hugo Learning Resources
Deployment Platforms
Cybersecurity Communities
Tools Mentioned
The journey from idea to production blog took just a few hours. Imagine what you could build with a few more.