A personal portfolio website built with Go and modern web technologies, showcasing projects, blog posts, and skills.
This portfolio website is built using Go with templ for generating HTML templates, Alpine.js for client-side interactivity, and Tailwind CSS for styling.
It follows a modern server-side rendering approach with HTMX for dynamic content loading without full page refreshes.
- Server-side rendered pages with templ templates
- Content organization by projects, posts, and tags
- Dynamic content loading with HTMX for a smooth user experience
- Responsive design with Tailwind CSS
- Client-side interactions powered by Alpine.js
- Full-text search capabilities
- Tag-based navigation to easily find related content
- Backend: Go
- Templates: templ
- CSS: Tailwind CSS
- Frontend Interactivity: Alpine.js
- Dynamic Content: HTMX
- Build/Development: Nix, air (for live reloading)
├── cmd/ # Entry points for executables
│ ├── conneroh/ # Main web application
│ │ ├── layouts/ # Layout templates
│ │ ├── views/ # View templates
│ │ ├── components/ # Component templates
│ │ └── _static/ # Static assets
│ └── update/ # Content update utility
├── internal/ # Private application code
│ ├── data/ # Data access layer
│ │ ├── assets/ # Assets Data Structure definitions
│ │ ├── docs/ # Markdown content (posts, projects, tags)
│ │ │ ├── posts/ # Blog posts
│ │ │ ├── projects/# Project descriptions
│ │ │ └── tags/ # Tag descriptions
│ │ └── gen/ # Generated data structures
│ └── routing/ # HTTP routing
└── [various config files]
The site organizes content into three main types:
- Posts - Blog articles
- Projects - Portfolio projects
- Tags - Skills and categories
Content relationships are maintained through associations between these entities.
- Go 1.24 or later
- Nix (optional, for reproducible development environment)
Nix provides a consistent development environment with all dependencies locked:
# Clone the repository
git clone https://github.com/conneroisu/conneroh.com.git
cd conneroh.com
# Enter development shell
nix develop
# Generate code and assets
nix-generate-all
# Initialize the database
update
# Run the application with live reloading
run
<!-- BEGIN_MARKER -->
clean - Clean Project
dx - Edit flake.nix
format - Format code files
generate-all - Generate all files in parallel
generate-css - Update the generated html and css files.
generate-db - Update the generated go files from the md docs.
generate-docs - Update the generated documentation files.
generate-js - Generate JS files
generate-reload - Code Generation Steps for specific directory changes.
gx - Edit go.mod
interpolate - Interpolate templates; Usage: interpolate input_file start_marker end_marker replacement_text
lint - Run Nix/Go Linting Steps.
reset-db - Reset the database
run - Run the application with air for hot reloading
test - Run Vitest tests
test-ci - Run Vitest tests for CI
test-ui - Run Vitest with UI
tests - Run all go tests
<!-- END_MARKER -->
Content is managed through Markdown files located in internal/data/
. The format for content files is:
---
title: Example Post Title
slug: example-post-slug
description: Short description of the post
created_at: 2025-03-27T05:48:53.000-06:00
updated_at: 2025-03-27T14:13:10.000-06:00
banner_path: /dist/img/example-banner.jpg # Optional
tags:
- go
- web-development
projects:
- related-project-slug # Optional related projects
---
# Markdown Content
The actual content of the post in Markdown format...
To update the database with new or modified content:
# With Nix
update
# Without Nix
go run ./cmd/update
The project uses Vitest with Playwright for comprehensive testing including unit tests and browser-based integration tests.
# Enter development shell (if using Nix)
nix develop
# Install dependencies
bun install
# Run all tests
test
# or
bun test
# Run tests with UI
test-ui
# or
bun test:ui
# Run tests once (CI mode)
test-ci
# or
bun test:run
# Coverage report
bun test:coverage
# Run comprehensive test suite (includes app startup)
nix run .#runTests
tests/browser/
- Browser integration tests using Playwrighttests/unit/
- Unit tests for utility functionstests/setup.ts
- Test setup and utilities
Tests cover:
- Homepage functionality and navigation
- Project and blog post pages
- HTMX dynamic content loading
- Alpine.js interactivity
- Responsive design across viewports
- Accessibility compliance
Tests run automatically before deployment:
- On PR creation/updates before preview deployment
- On main branch pushes before production deployment
The site is deployed using Fly.io. The deployment process is automated in the GitHub workflow located in .github/workflows/fly-deploy.yml
.
To deploy manually:
nix run .#deployPackage
The application uses templ for type-safe HTML templates:
// Example of a templ component (simplified)
templ Post(post assets.Post) {
<article>
<h1>{post.Title}</h1>
<div class="content">
@templ.Raw(post.Content)
</div>
</article>
}
The site uses HTMX for navigation and content loading:
<!-- Example of HTMX usage for navigation -->
<a
hx-get="/morph/projects"
hx-target="#bodiody"
hx-swap="outerHTML"
hx-push-url="/projects"
>
Projects
</a>
This project is personal, but suggestions and bug reports are most welcome. Please open an issue or submit a pull request.
Conner Ohnesorge