commit 08893554e1628c77879c9a3460de4ec6d2a6992f
Author: tri <tri@thac.loan>
Date:   Sun Sep 28 08:31:08 2025 +0700

    generate home page

diff --git a/Makefile b/Makefile
index d2a95ea..9762b32 100644
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,6 @@
 watch:
 	zig build run --watch -- demo
+
+# TODO: write a simple zig server instead
+serve:
+	python -m http.server -b localhost -d demo 8000
diff --git a/src/assets/style.css b/src/assets/style.css
new file mode 100644
index 0000000..adbd08c
--- /dev/null
+++ b/src/assets/style.css
@@ -0,0 +1,56 @@
+:root {
+  font-family: serif;
+  font-size: 100%;
+
+  --table-odd-row-bg: #eee;
+  --table-border-color: #ddd;
+  --table-row-hover-bg: blanchedalmond;
+}
+
+table {
+  text-align: left;
+  width: 100%;
+  border-collapse: collapse;
+}
+/*
+tbody tr:nth-child(odd) {
+  background-color: var(--table-odd-row-bg);
+}
+tr {
+  border-top: 1px solid var(--table-border-color);
+}
+*/
+tbody tr:hover {
+  background-color: var(--table-row-hover-bg);
+}
+td,
+th {
+  padding: 0.1rem 5px;
+}
+table {
+  margin-left: -5px;
+}
+
+img {
+  max-width: 100%;
+  max-height: 100%;
+}
+
+@media (prefers-color-scheme: dark) {
+  :root {
+    background-color: #222;
+    color: #ddd;
+    font-family: sans-serif;
+
+    --table-odd-row-bg: #333;
+    --table-border-color: #444;
+    --table-row-hover-bg: #444;
+  }
+
+  a {
+    color: cornflowerblue;
+  }
+  a:visited {
+    color: violet;
+  }
+}
diff --git a/src/main.zig b/src/main.zig
index 9234960..a4c1766 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -3,12 +3,7 @@ const fs = std.fs;
 const println = @import("utils.zig").println;
 const git = @import("git.zig");
 
-const RepoSummary = struct {
-    name: []const u8,
-    commit_count: usize,
-    last_commit_time: []const u8,
-    last_commit_msg: []const u8,
-};
+const web_prefix = "-";
 
 pub fn main() !u8 {
     if (std.os.argv.len != 2) {
@@ -74,21 +69,79 @@ pub fn main() !u8 {
         // TODO: write repo's commits
     }
 
-    try writeHomePage(repo_summaries.items);
+    try writeHomePage(target_dir, repo_summaries.items);
+    try target_dir.writeFile(.{
+        .sub_path = "style.css",
+        .data = @embedFile("assets/style.css"),
+    });
 
     return 0;
 }
 
-pub fn writeHomePage(repos: []RepoSummary) !void {
+const RepoSummary = struct {
+    name: []const u8,
+    commit_count: usize,
+    last_commit_time: []const u8,
+    last_commit_msg: []const u8,
+};
+
+// TODO: decide on some sort of templating system
+pub fn writeHomePage(dir: fs.Dir, repos: []RepoSummary) !void {
+    var file = try dir.createFile("index.html", .{});
+    defer file.close();
+
+    var buf: [4096]u8 = undefined;
+    var writer = file.writer(&buf);
+    try writer.interface.writeAll(
+        \\<!doctype html>
+        \\<html lang="en">
+        \\  <head>
+        \\    <meta charset="utf-8" />
+        \\    <title>Khoe</title>
+        \\    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+        \\  <link rel="stylesheet" href="/style.css">
+        \\  </head>
+        \\  <body>
+        \\    <h1>Repos:</h1>
+        \\    <table>
+        \\      <thead>
+        \\        <tr>
+        \\          <th>Name</th>
+        \\          <th>Commits</th>
+        \\          <th>Last commit</th>
+        \\          <th>Last commit time</th>
+        \\        </tr>
+        \\      </thead>
+        \\      <tbody>
+        \\
+    );
+
     for (repos) |repo| {
-        println(
-            "repo {s}: {d} commits | {s} | {s}",
+        try writer.interface.print(
+            \\<tr>
+            \\  <td><a href="/{0s}/{1s}/">{1s}</a></td>
+            \\  <td>{2d}</td>
+            \\  <td>{3s}</td>
+            \\  <td>{4s}</td>
+            \\</tr>
+            \\
+        ,
             .{
+                web_prefix,
                 repo.name,
                 repo.commit_count,
-                repo.last_commit_time,
                 repo.last_commit_msg,
+                repo.last_commit_time,
             },
         );
     }
+
+    try writer.interface.writeAll(
+        \\      </tbody>
+        \\    </table>
+        \\  </body>
+        \\</html>
+    );
+
+    try writer.interface.flush();
 }