How I’m hosting this website
I self host this website; I bought a server from Hetzner and a domain from Cloudflare.
I used to use Astro as my framework but i found it to be a bit
overkill for a simple site so I decided to switch to plain HTML, CSS and
JS. However there are a lot of niceites you get from frameworks that I
miss which led me to build my own Static Site Generator (SSG). I thought
it would be a good challenge to just use linux utils so I used the
just
command runner.
server_ip := env_var("MY_SERVER_IP")
# Default recipe - build all HTML files
default: build
# Build all HTML files from markdown
build: clean setup-dirs copy-assets blog projects work
# Clean the dist directory
clean:
rm -rf dist
# Create the directory structure and copy assets
setup-dirs:
mkdir -p dist/blog
mkdir -p dist/projects
mkdir -p dist/work
# Copy CSS and other assets to dist
copy-assets:
cp style.css dist/style.css
# Generic function to convert markdown files in a section
convert-section section css_path="../style.css":
#!/usr/bin/env bash
set -euo pipefail
for file in content/{{section}}/*.md; do
filename=$(basename "$file" .md)
pandoc "$file" -o "dist/{{section}}/${filename}.html" \
--standalone \
--template=template.html \
--metadata pagetitle="${filename}" \
--css="{{css_path}}"
done
# Convert blog markdown files to HTML
blog:
just convert-section blog "../style.css"
# Convert projects markdown files to HTML
projects:
just convert-section projects "../style.css"
# Convert work markdown files to HTML
work:
just convert-section work "../style.css"
# Generic function to create an index page for a section
create-section-index section title css_path="./style.css":
#!/usr/bin/env bash
set -euo pipefail
temp_file="temp_{{section}}_index.md"
echo "# {{title}}" > "$temp_file"
for file in content/{{section}}/*.md; do
[ -f "$file" ] || continue
filename=$(basename "$file" .md)
title_line=$(head -n 1 "$file" | sed 's/^# //')
if [ -z "$title_line" ]; then
title_line="$filename"
fi
echo "- [$title_line]($filename.html)" >> "$temp_file"
done
cp {{css_path}} "./dist/{{section}}/"
pandoc "$temp_file" -o "dist/{{section}}/index.html" --css="./style.css" --standalone --metadata pagetitle="{{title}}" --template=template.html
rm "$temp_file"
# Generate index pages for each section
indexes css_path="./style.css":
just create-section-index blog Blog "{{css_path}}"
just create-section-index projects Projects "{{css_path}}"
just create-section-index work Work "{{css_path}}"
# Generate main index page from index.md
main-index:
#!/usr/bin/env bash
if [ -f "content/index.md" ]; then
pandoc content/index.md -o dist/index.html --standalone --metadata pagetitle="Home" --css="style.css" --template=template.html
else
echo "index.md not found, creating a basic one..."
cat > content/index.md << EOF
Add Content here ...
EOF
pandoc content/index.md -o dist/index.html --standalone --metadata pagetitle="Home" --css="style.css" --template=template.html
fi
# Build everything including indexes
build-all: build indexes main-index
# Watch for changes and rebuild (requires watchexec)
watch:
watchexec -e md -i dist -- just build-all
# Serve the site locally
serve:
cd dist && live-server .
deploy: build-all
rsync -azP --delete ./dist/ awais@{{server_ip}}:/home/awais/website
# Build and serve
dev: build-all serve
Running this command generates a dist folder with the output files.
just build-all
The project structure is:
.
├── content # Create the content here
│ ├── index.md
│ ├── blog
│ │ ├── blog1.md
│ │ └── ...
│ ├── projects
│ │ ├── project1.md
│ │ └── ...
│ └── work
│ │ ├── work1.md
│ │ └── ...
├── dist # Output folder (contains the html files)
│ ├── index.md
│ ├── blog
│ │ ├── blog1.md
│ │ ├── style.css
│ │ └── ...
│ ├── projects
│ │ ├── project1.md
│ │ ├── style.css
│ │ └── ...
│ └── work
│ │ ├── work1.md
│ └── style.css
│ │ └── ...
│ ├── style.css
│ └── work
│ ├── acument.html
│ ├── index.html
├── draft # Draft Content
│ ├── home-server.md
│ └── linux-setup.md
├── images
│ ├── email.svg
│ ├── github.svg
│ └── linkedin.svg
├── justfile
├── style.css
└── template.html # Base template all other html files inherit from (contains the navbar, footer etc)
To upload the site, I use rsync to sync only the changed files. Example:
just deploy
For my main site (awais.me) I use nginx
as my http
server for its stability however you can also view (custom.awais.me) to
view the site served by my own custom built server Volk. It’s basic but functional, and I plan to
improve it over time.
For Volk, still use Nginx, but only as a reverse proxy. Volk runs on port 6543, while nginx listens on port 80 and forwards incoming traffic to Volk. This avoids having to reconfigure Volk for port 80.