Building My Personal Website

A modern approach to static site generation

Why these tools?

Tool Purpose Scope
ESLint Code quality & patterns JS, TS, Astro
Stylelint Style quality & patterns CSS
dprint Code formatting JS, TS, JSON, Markdown
terraform fmt Code formatting HCL (Terraform)
terraform validate Configuration verification HCL (Terraform)

Static Site Generation requires tools purpose-built for that workflow rather than general bundlers adapted for static output. Astro’s zero-JS-by-default approach and TypeScript-native architecture provide better performance and developer experience than configuring general-purpose tools.

Solo development benefits significantly from automated tooling that catches errors and enforces consistency. Without collaborative code review, linters and formatters serve as a safety net for maintaining code quality standards across the entire codebase.

Infrastructure work happens infrequently but has high stakes. Terraform’s declarative approach combined with good organization ensures that both current configuration and historical reasoning remain accessible when returning to infrastructure tasks months later.

Top

Project setup and structure

The project began as a Parcel-based static site that was migrated to Astro for its enhanced static site generation capabilities and built-in performance optimizations. Starting with Astro’s blog template provided a solid foundation that was customized to meet specific requirements.

Strict configuration files for TypeScript, ESLint, and Stylelint were implemented to enforce code quality standards. These configurations were carefully researched to incorporate both established best practices and recently maintained plugins that enhance development efficiency.

I reduced project root clutter through file organization that improves findability of configuration files through well-known locations. The docs directory structure anticipates potential GitHub Pages integration.

Developing the website

Rather than relying on JavaScript frameworks, the site uses native Custom Elements for interactive features. This approach provides progressive enhancement with minimal JavaScript footprint while enabling modern functionality like scroll tracking for navigation highlights and dynamic content updates.

PWA features were implemented because Vite and Workbox integration with Astro made them essentially free to add. CSP with SRI hashes was prioritized despite poor tooling because security remains important even for small websites.

The development workflow was optimized by configuring Sublime Text with appropriate linting and Language Server Protocol packages. This setup provides real-time code quality feedback and TypeScript type checking during the development process.

Deployment and hosting

The site was migrated from S3/CloudFront to AWS Amplify to better support directory-level index.html files without compromising on SSL or performance. Despite some limitations in Terraform’s support for Amplify and challenges with custom configurations, the service provides an effective hosting solution for static sites.

Infrastructure as code provides documentation that can detect drift and verify accuracy, though it requires maintenance to prevent provider compatibility issues. Budget alerts protect against unexpected cloud costs that can escalate rapidly. Even static sites warrant baseline security practices regardless of limited interactivity.

The scripted approach reduces the need for complex CI/CD pipelines while ensuring consistent results and providing the foundation for future automation if needed. Content Security Policy headers with SRI hashes are automatically updated during the build process but must work around Terraform provider limitations.

Lessons learned

Managing rapidly evolving AWS infrastructure through Terraform requires a regular maintenance schedule to avoid complicated catch-up scenarios. Scheduled quarterly Terraform plan runs help identify drift and necessary updates before they become unmanageable. Similarly, navigating Astro’s ecosystem of community integrations and keeping up with linting tool plugin changes showed the importance of evaluating maintenance status and compatibility before adoption.

Implementing Progressive Web App features revealed knowledge gaps around Workbox configuration that would benefit from deeper understanding for optimal implementation. Using TypeScript for configuration files provides better editor support and type checking, but can introduce additional complexity when tools and plugins have not fully embraced TypeScript.