feat: add minimal base CSS with dark mode support

- static/style.css: CSS variable-based theming with:
  - Typography (system fonts, monospace for code)
  - Layout (centered content, nav/main/footer structure)
  - Dark mode via prefers-color-scheme
  - Component styles (posts, cards, tags, hero)

- src/main.rs: Add copy_static_assets() to copy static/
  directory to public/ during build

Phase 1 complete. Ready for syntax highlighting.
This commit is contained in:
Timothy DeHerrera
2026-01-24 20:27:22 -07:00
parent d4003686a0
commit 5317da94c4
4 changed files with 295 additions and 2 deletions

View File

@@ -1,7 +1,7 @@
//! Content discovery and frontmatter parsing.
use crate::error::{Error, Result};
use gray_matter::{Matter, engine::YAML};
use gray_matter::{engine::YAML, Matter};
use std::fs;
use std::path::{Path, PathBuf};

View File

@@ -22,11 +22,15 @@ fn main() {
fn run() -> Result<()> {
let content_dir = Path::new("content");
let output_dir = Path::new("public");
let static_dir = Path::new("static");
if !content_dir.exists() {
return Err(Error::ContentDirNotFound(content_dir.to_path_buf()));
}
// 0. Copy static assets
copy_static_assets(static_dir, output_dir)?;
// 1. Process blog posts
let mut posts = process_blog_posts(content_dir, output_dir)?;
@@ -208,3 +212,41 @@ fn write_output(
eprintln!("{}", out_path.display());
Ok(())
}
/// Copy static assets (CSS, etc.) to output directory
fn copy_static_assets(static_dir: &Path, output_dir: &Path) -> Result<()> {
if !static_dir.exists() {
return Ok(()); // No static dir is fine
}
fs::create_dir_all(output_dir).map_err(|e| Error::CreateDir {
path: output_dir.to_path_buf(),
source: e,
})?;
for entry in walkdir::WalkDir::new(static_dir)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file())
{
let src = entry.path();
let relative = src.strip_prefix(static_dir).unwrap();
let dest = output_dir.join(relative);
if let Some(parent) = dest.parent() {
fs::create_dir_all(parent).map_err(|e| Error::CreateDir {
path: parent.to_path_buf(),
source: e,
})?;
}
fs::copy(src, &dest).map_err(|e| Error::WriteFile {
path: dest.clone(),
source: e,
})?;
eprintln!("copying: {}{}", src.display(), dest.display());
}
Ok(())
}

View File

@@ -1,7 +1,7 @@
//! HTML templates using maud.
use crate::content::{Content, Frontmatter};
use maud::{DOCTYPE, Markup, PreEscaped, html};
use maud::{html, Markup, PreEscaped, DOCTYPE};
/// Render a blog post with the base layout.
pub fn render_post(frontmatter: &Frontmatter, content_html: &str) -> Markup {