dotfiles

My PC Dotfiles & Website
commit 34454b581f3aab01af0ae5795af2924089ad03f6
parent b1533d2444556e9b136f9f7e4f48b0c9a5ba0690
Author: maydayv7 <maydayv7@gmail.com>
Date:   Sat,  3 Jan 2026 12:43:46 +0530

feat(site): Improve `git` Frontend

Diffstat:

M.gitignore | 2++
MCHANGELOG.md | 2+-
Mflake.lock | 6+++---
Msite/README.md | 9++++-----
Msite/content/blog/nixos/prelude.md | 2+-
Msite/flake.nix | 3+++
Msite/git/base.css | 222+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msite/git/default.nix | 22+++++++++++-----------
Msite/git/index.js | 58++++++++++++++++++++++++++++++----------------------------
Msite/git/repos.nix | 18++++++++++++++++++
Msite/git/wrangler.toml | 1-
Msite/sass/_search.scss | 22++++++++++++----------
Msite/static/js/scroll.js | 36+++++++++++++++++++-----------------
13 files changed, 315 insertions(+), 88 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,4 +1,6 @@ ~* result public +.wrangler +node_modules site/static/processed_images diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -5,7 +5,7 @@ - Website Changes - Start blogging! - Fix comments - - Host `stagit` generated site + - `git` frontend using `stagit` ## 2025 diff --git a/flake.lock b/flake.lock @@ -747,11 +747,11 @@ ] }, "locked": { - "lastModified": 1767360683, - "narHash": "sha256-flWHlN2Wx9sSDDswFlkuUVxX2Q6PfK6FKsPf0ykbbMw=", + "lastModified": 1767422312, + "narHash": "sha256-EIiMVhO0kO5GjZgSfTZBjJSCeqvi0m322rwkvyLUyaU=", "owner": "maydayv7", "repo": "stagit", - "rev": "af747fbf9d6a7833144e70a3089c69f934dfd0c7", + "rev": "deb822c63f0298af256d313754b7d81bec708ab5", "type": "github" }, "original": { diff --git a/site/README.md b/site/README.md @@ -46,9 +46,8 @@ To override the URL, run: <pre><code>nix build --impure --expr "with import ../p - [x] GitHub : Star Count - <code>{{ github(repo="<b>USER</b>/<b>NAME</b>") }}</code> - [x] YouTube : Embed Video - <code>{{ youtube(id="<b>ID</b>") }}</code> -#### Credits +## Git frontend -Huge thanks to: - -- [zerm](https://github.com/ejmg/zerm) for the theme -- [jdisaacs.com](https://github.com/jordanisaacs/jdisaacs.com) for the basic repository structure +The [`git`](./git) directory contains the configuration for my static `git` frontend, hosted at [git.maydayv7.cc](https://maydayv7.cc) +It is built using my `stagit` [fork](https://github.com/maydayv7/stagit) to generate static HTML pages for my repositories +To build it, run `nix run .#build-stagit` diff --git a/site/content/blog/nixos/prelude.md b/site/content/blog/nixos/prelude.md @@ -34,7 +34,7 @@ The fear that if you delete the wrong file, mess with the wrong package, or even > That's \*\*\*\*\*\*\* it I'm switching back to Windows forever > > --> **Me** -> (right after the 69420th distro-hop that caused my system to crash and burn) +> ~~(right after the 69420th distro-hop that caused my system to crash and burn)~~ **NixOS is different.** diff --git a/site/flake.nix b/site/flake.nix @@ -3,7 +3,10 @@ _: { perSystem = { lib, pkgs, ... }: { + # Website packages.website = pkgs.callPackage ./. { inherit pkgs; }; + + # 'git' Frontend apps.build-stagit = { type = "app"; program = "${pkgs.callPackage ./git { inherit lib pkgs; }}/bin/build-stagit"; diff --git a/site/git/base.css b/site/git/base.css @@ -26,7 +26,7 @@ body { font-family: var(--font-main); color: var(--fg); background-color: var(--bg); - padding: 1rem; + padding: 0; margin: 0; line-height: 1.5; } @@ -40,6 +40,55 @@ a { } } +.container { + max-width: 900px; + margin: 0 auto; + padding: 30px; + border-left: 1px solid var(--border-subtle); + border-right: 1px solid var(--border-subtle); + min-height: 100vh; + display: flex; + flex-direction: column; +} + +@media (max-width: 684px) { + .container { + padding: 20px; + } +} + +/* Navigation Styling */ +.menu-desktop { + margin-top: 10px; +} + +.menu-inner { + display: flex; + flex-wrap: wrap; + list-style: none; + margin: 0; + padding: 0; +} + +.menu-inner li { + flex: 0 0 auto; +} + +.menu-inner li:not(:last-child) { + margin-right: 20px; +} + +.menu-inner li a { + font-weight: bold; + color: var(--fg); + text-decoration: underline; + text-underline-offset: 4px; +} + +.menu-inner li a:hover { + color: var(--secondary); +} + /* Header */ .header { display: flex; @@ -105,24 +154,44 @@ a { /* Repo Header */ #repo-header { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1rem; margin-bottom: 1rem; - text-align: left; + padding-bottom: 1rem; + border-bottom: 1px solid var(--border-subtle); +} - h1 { - margin: 0; - font-size: 1.5em; - } +.repo-title h1 { + margin: 0; + font-size: 1.5em; + line-height: 1.2; } -/* Navigation Row */ -#nav { - margin-bottom: 1rem; +.repo-title .desc { + font-size: 0.9em; + margin-top: 0.2rem; + color: var(--fg-dim); +} + +#repo-header .url { + font-family: var(--font-main); + background-color: var(--bg-code); + padding: 0.5em 0.8em; + border-radius: 4px; + font-size: 0.9em; + white-space: nowrap; + border: 1px solid var(--border-subtle); } /* Tables */ table { width: 100%; border-collapse: collapse; + table-layout: fixed; + min-width: 800px; } td, @@ -131,6 +200,8 @@ th { text-align: left; border: 1px solid var(--bg); white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } td:empty { @@ -147,6 +218,116 @@ th { border-bottom: 1px solid var(--border); } +/* Index Page */ +#index td:nth-child(1) { + /* Name */ + width: 7em; + font-weight: bold; +} +#index td:nth-child(2) { + /* Description */ + width: auto; +} +#index td:nth-child(3) { + /* Owner */ + width: 5em; + text-align: center; +} +#index td:nth-child(4) { + /* Last Commit */ + width: 10em; +} + +/* Log Page */ +#log td:nth-child(1) { + /* Date */ + width: 10em; +} +#log td:nth-child(2) { + /* Message */ + width: auto; +} +#log td:nth-child(3) { + /* Author */ + width: 6em; +} +#log td:nth-child(4) { + /* Files */ + width: 4em; + text-align: right; +} +#log td:nth-child(5) { + /* + */ + width: 3em; + text-align: right; +} +#log td:nth-child(6) { + /* - */ + width: 3em; + text-align: right; +} + +/* Files Page */ +#files td:nth-child(1) { + /* Mode */ + width: 8em; +} +#files td:nth-child(2) { + /* Name */ + width: auto; +} +#files td:nth-child(3) { + /* Size */ + width: 6em; + text-align: right; +} + +/* Refs Page */ +#branches td:nth-child(1), +#tags td:nth-child(1) { + /* Name */ + width: auto; +} +#branches td:nth-child(2), +#tags td:nth-child(2) { + /* Date */ + width: 10em; +} +#branches td:nth-child(3), +#tags td:nth-child(3) { + /* Author */ + width: 10em; +} + +/* Diffstat Table */ +#diffstat td:nth-child(1) { + /* Status */ + width: 2em; + text-align: center; + padding: 0.25em 0; +} +#diffstat td:nth-child(2) { + /* Filename */ + width: auto; +} +#diffstat td:nth-child(3) { + /* Separator */ + width: 2em; + text-align: center; + color: var(--fg-dim); +} +#diffstat td:nth-child(4) { + /* Changes */ + width: 3em; + text-align: right; + font-variant-numeric: tabular-nums; +} +#diffstat td:nth-child(5) { + /* +/- */ + width: auto; + color: var(--fg-dim); +} + /* Code Blocks */ pre { font-family: var(--font-main); @@ -160,12 +341,21 @@ pre { /* Diff (File View) */ .i { color: var(--diff-add); + &:hover { + color: var(--diff-add); + } } .d { color: var(--diff-del); + &:hover { + color: var(--diff-del); + } } .h { color: var(--diff-mod); + &:hover { + color: var(--diff-mod); + } } pre span.i, pre span.d, @@ -206,6 +396,15 @@ pre span.h { margin-top: 0.2rem; } +/* Commits Remaining */ +#log-msg { + text-align: center; + padding: 1em 0.5em; + font-weight: bold; + color: var(--fg-dim); + border-top: 1px solid var(--border-subtle); +} + /* Syntax Highlighting */ table#blob.chroma { @@ -228,14 +427,15 @@ table#blob.chroma { } #blob.chroma td.num { - width: 1%; - min-width: 2.5em; + width: 3em; text-align: right; border-right: 1px solid var(--border-subtle); background-color: var(--code-bg-line-num); color: var(--fg-dim); user-select: none; white-space: nowrap; + overflow: visible; + text-overflow: clip; } #blob.chroma td.code { diff --git a/site/git/default.nix b/site/git/default.nix @@ -3,13 +3,17 @@ pkgs, site ? "https://git.maydayv7.cc", sitename ? "maydayv7", - repos ? import ./repos.nix, + test ? false, }: let theme = import ./theme.nix pkgs; - buildCommands = lib.concatMapStrings (repo: '' - build_repo "${repo.name}" "${repo.description}" "${repo.owner}" "${repo.url}" - '') repos; + buildCommands = + if test then + ''build_repo test "A long description just for testing" Me "$(pwd)"'' + else + lib.concatMapStrings (repo: '' + build_repo "${repo.name}" "${repo.description}" "${repo.owner}" "${repo.url}" + '') (import ./repos.nix); in pkgs.writeShellApplication { name = "build-stagit"; @@ -28,7 +32,6 @@ pkgs.writeShellApplication { FONTS_SRC="./site/static/fonts" FAVICON_SRC="./site/static/desktop.ico" - rm -rf "$OUTPUT_DIR" mkdir -p "$OUTPUT_DIR" mkdir -p "$OUTPUT_DIR/fonts" @@ -69,20 +72,17 @@ pkgs.writeShellApplication { echo "---------------------------------------" echo "Processing $NAME..." REPO_DIR="$BUILD_ROOT/$NAME.git" - git clone --bare "$URL" "$REPO_DIR" + git clone --bare --filter=blob:limit=2m "$URL" "$REPO_DIR" # Metadata echo "$DESC" > "$REPO_DIR/description" echo "$OWNER" > "$REPO_DIR/owner" echo "$URL" > "$REPO_DIR/url" + mkdir -p "$OUTPUT_DIR/$NAME" + ln -sf ../favicon.png "$OUTPUT_DIR/$NAME/favicon.png" # Run Stagit - mkdir -p "$OUTPUT_DIR/$NAME" (cd "$OUTPUT_DIR/$NAME" && stagit -l 50 -n ${sitename} -u "$BASE_URL/$NAME" "$REPO_DIR") - - # Link Global Assets - ln -sf ../style.css "$OUTPUT_DIR/$NAME/style.css" - ln -sf ../favicon.png "$OUTPUT_DIR/$NAME/favicon.png" echo "---------------------------------------" } diff --git a/site/git/index.js b/site/git/index.js @@ -1,47 +1,49 @@ +function getCookie(cookieHeader, name) { + if (!cookieHeader) return null; + const cookies = cookieHeader.split(";"); + + for (const cookie of cookies) { + const [k, ...v] = cookie.trim().split("="); + if (k === name) return v.join("="); + } + return null; +} + export default { async fetch(request, env) { const url = new URL(request.url); // Theme Switching - const cookieHeader = request.headers.get("Cookie") || ""; - const cookies = Object.fromEntries( - cookieHeader.split(";").map((c) => c.trim().split("=")) - ); - const themeCookie = cookies["theme_color"]; if (url.pathname.endsWith("style.css")) { - let theme = "red"; // Default - if (themeCookie === "blue") theme = "blue"; - if (themeCookie === "black") theme = "black"; - if (theme !== "red") { + const theme = getCookie(request.headers.get("Cookie"), "theme_color"); + if (theme && theme !== "red") { const themeUrl = new URL(url); themeUrl.pathname = themeUrl.pathname.replace( "style.css", - `style-${theme}.css` + `style-${theme}.css`, ); - let themeResponse = await env.ASSETS.fetch( - new Request(themeUrl, request) - ); - if (themeResponse.ok) { - const newHeaders = new Headers(themeResponse.headers); - newHeaders.set("Vary", "Cookie"); - newHeaders.set("Cache-Control", "private, max-age=60"); - return new Response(themeResponse.body, { - ...themeResponse, - headers: newHeaders, + + const themed = await env.ASSETS.fetch(new Request(themeUrl, request)); + + if (themed.ok) { + const headers = new Headers(themed.headers); + headers.set("Vary", "Cookie"); + headers.set("Cache-Control", "no-store"); + return new Response(themed.body, { + status: themed.status, + headers, }); } } } // Serve assets - let response = await env.ASSETS.fetch(request); - - if (response.ok) { - const newHeaders = new Headers(response.headers); - newHeaders.set("Cache-Control", "public, max-age=60, s-maxage=60"); - return new Response(response.body, { ...response, headers: newHeaders }); + const response = await env.ASSETS.fetch(request); + if (response.status === 404) { + const fallbackUrl = new URL(request.url); + fallbackUrl.pathname = "/index.html"; + return env.ASSETS.fetch(new Request(fallbackUrl, request)); } - - return new Response("Repository not found.", { status: 404 }); + return response; }, }; diff --git a/site/git/repos.nix b/site/git/repos.nix @@ -1,5 +1,23 @@ [ { + name = "dotfiles"; + url = "https://github.com/maydayv7/dotfiles"; + description = "My PC Dotfiles & Website"; + owner = "V7"; + } + { + name = "stagit"; + url = "https://github.com/maydayv7/stagit"; + description = "Personal Stagit Fork"; + owner = "V7"; + } + { + name = "creek"; + url = "https://github.com/maydayv7/creek"; + description = "The AI Image Editor of 2030"; + owner = "V7"; + } + { name = "matiru"; url = "https://github.com/maydayv7/matiru"; description = "Blockchain-Based Supply Chain Transparency for Agricultural Produce"; diff --git a/site/git/wrangler.toml b/site/git/wrangler.toml @@ -5,7 +5,6 @@ compatibility_date = "2025-12-15" [assets] binding = "ASSETS" directory = "./public" -not_found_handling = "none" run_worker_first = true [env.production] diff --git a/site/sass/_search.scss b/site/sass/_search.scss @@ -3,9 +3,9 @@ .search { &-container { display: inline-block; - left: 660px; + left: 670px; position: relative; - top: -31px; + top: -32px; transition: all 0.5s ease-out; width: 160px; margin-bottom: -20px; @@ -19,16 +19,17 @@ } } + @media (max-width: $tablet-max-width) { + left: 300px; + width: 300px; + } + @media (max-width: $phone-max-width) { left: 0 !important; margin-bottom: 20px; top: 20px; width: 100%; } - - @media (max-width: $tablet-max-width) { - left: 225px; - } } &-results { @@ -45,12 +46,13 @@ right: 0; width: 300%; - @media (max-width: $phone-max-width) { - width: 100%; - } - @media (max-width: $tablet-max-width) { left: 0; + width: 300px; + } + + @media (max-width: $phone-max-width) { + width: 100%; } &__number { diff --git a/site/static/js/scroll.js b/site/static/js/scroll.js @@ -1,23 +1,25 @@ var scrollButton = document.querySelector(".scroll-back"); var rootElement = document.documentElement; -function handleScroll() { - var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight; - if (rootElement.scrollTop / scrollTotal > 0.5) { - scrollButton.style.visibility = "visible"; - scrollButton.style.opacity = 100; - } else { - scrollButton.style.visibility = "hidden"; - scrollButton.style.opacity = 0; +if (scrollButton) { + function handleScroll() { + var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight; + if (rootElement.scrollTop / scrollTotal > 0.5) { + scrollButton.style.visibility = "visible"; + scrollButton.style.opacity = 100; + } else { + scrollButton.style.visibility = "hidden"; + scrollButton.style.opacity = 0; + } } -} -function scrollBack() { - rootElement.scrollTo({ - top: 0, - behavior: "smooth", - }); -} + function scrollBack() { + rootElement.scrollTo({ + top: 0, + behavior: "smooth", + }); + } -scrollButton.addEventListener("click", scrollBack); -document.addEventListener("scroll", handleScroll); + scrollButton.addEventListener("click", scrollBack); + document.addEventListener("scroll", handleScroll); +}