From 52cdeaf4cc9da9d32926821c78fd331bc8d2f14a Mon Sep 17 00:00:00 2001 From: Alexander Kassouni Date: Tue, 29 Sep 2026 23:29:28 -0700 Subject: restructure for cgit css --- configuration.nix | 31 ++++++++++++++++++++++++++++++ flake.nix | 8 +++++++- git/cgit.scss | 27 ++++++++++++++++++++++++++ git/default.nix | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ git/theme.nix | 20 +++++++++++++++++++ nix/configuration.nix | 31 ------------------------------ nix/git.nix | 51 ------------------------------------------------- nix/site.nix | 23 ++++++++++++++++++++++ nix/web.nix | 36 ++++++++++++++++++++++++++++------ site/sass/_fonts.scss | 28 --------------------------- site/sass/_palette.scss | 51 ------------------------------------------------- site/sass/style.scss | 22 +++++++++++++++++++-- style/_fonts.scss | 28 +++++++++++++++++++++++++++ style/_palette.scss | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 288 insertions(+), 170 deletions(-) create mode 100644 configuration.nix create mode 100644 git/cgit.scss create mode 100644 git/default.nix create mode 100644 git/theme.nix delete mode 100644 nix/configuration.nix delete mode 100644 nix/git.nix create mode 100644 nix/site.nix delete mode 100644 site/sass/_fonts.scss delete mode 100644 site/sass/_palette.scss create mode 100644 style/_fonts.scss create mode 100644 style/_palette.scss diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..9477c6f --- /dev/null +++ b/configuration.nix @@ -0,0 +1,31 @@ +{config, ...}: { + imports = [ + ./git + ./nix/hardware-configuration.nix + ./nix/minecraft.nix + ./nix/options.nix + ./nix/ssh.nix + ./nix/web.nix + ]; + + boot.loader = { + systemd-boot = { + enable = true; + graceful = true; # TODO: drop after v261+ + }; + efi.canTouchEfiVariables = true; + }; + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + networking.hostName = "chariot"; + networking.networkmanager.enable = true; + + users.users.kassouni = { + extraGroups = [ "wheel" ]; + isNormalUser = true; + openssh.authorizedKeys.keys = config.my.adminKeys; + }; + + system.stateVersion = "26.05"; +} diff --git a/flake.nix b/flake.nix index 05ea6bf..7c3b59d 100644 --- a/flake.nix +++ b/flake.nix @@ -9,9 +9,15 @@ outputs = inputs: { nixosConfigurations.kassouni-net = inputs.nixpkgs.lib.nixosSystem { specialArgs = { inherit inputs; }; - modules = [ ./nix/configuration.nix ]; + modules = [ ./configuration.nix ]; }; + packages = builtins.mapAttrs (system: pkgs: rec { + website = import ./nix/site.nix { inherit pkgs; }; + cgit-theme = import ./git/theme.nix { inherit pkgs; }; + default = website; + }) inputs.nixpkgs.legacyPackages; + devShells = builtins.mapAttrs (system: pkgs: { default = pkgs.mkShell { packages = with pkgs; [ diff --git a/git/cgit.scss b/git/cgit.scss new file mode 100644 index 0000000..3d0c4fb --- /dev/null +++ b/git/cgit.scss @@ -0,0 +1,27 @@ +// Stylesheet for cgit on git.kassouni.net, layered over cgit's stock cgit.css. +// Rules here have to match `div#cgit ...` to win on specificity, so they nest +// under the same id. Compiled by ./theme.nix. +@use "fonts"; + +div#cgit { + font-family: fonts.$mono; + + // cgit.css asks for generic `monospace` on these; point them at the webfont + a.ls-blob, + a.ls-dir, + .ls-mod, + .oid, + div.commit-msg, + div.notes, + table.bin-blob th, + table.bin-blob td, + table.diff td, + table.list td.commitgraph, + table.list td.logmsg, + table.list td.logsubject, + table.ssdiff td, + td.ls-mode, + td.ls-size { + font-family: fonts.$mono; + } +} diff --git a/git/default.nix b/git/default.nix new file mode 100644 index 0000000..f46c3ab --- /dev/null +++ b/git/default.nix @@ -0,0 +1,51 @@ +{config, inputs, pkgs, ...}: let + domain = "git.kassouni.net"; + repoRoot = "/srv/git"; + theme = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.cgit-theme; +in { + users.users.git = { + isSystemUser = true; + group = "git"; + home = repoRoot; + createHome = true; + homeMode = "750"; + shell = "${pkgs.git}/bin/git-shell"; + openssh.authorizedKeys.keys = config.my.gitKeys; + }; + users.groups.git = { }; + + environment.systemPackages = [ pkgs.git ]; + + services.openssh.extraConfig = '' + Match user git + AllowTcpForwarding no + AllowAgentForwarding no + PermitTTY no + ''; + + services.cgit.${domain} = { + enable = true; + scanPath = repoRoot; + group = "git"; # so cgit can traverse a non-world-readable repoRoot + gitHttpBackend.checkExportOkFiles = true; + settings = { + # cgit adds one per css entry, in order + css = [ "/cgit.css" "/theme.css" ]; + strict-export = "git-daemon-export-ok"; + remove-suffix = true; + readme = [ ":README.md" ":README" ":readme.md" ]; + clone-url = "git@${domain}:$CGIT_REPO_URL https://${domain}/$CGIT_REPO_URL"; + source-filter = "${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py"; + about-filter = "${pkgs.cgit}/lib/cgit/filters/about-formatting.sh"; + }; + }; + + services.nginx.virtualHosts.${domain} = { + forceSSL = true; + enableACME = true; + locations = { + "= /theme.css".alias = "${theme}/theme.css"; + "/fonts/".alias = "${theme}/fonts/"; + }; + }; +} diff --git a/git/theme.nix b/git/theme.nix new file mode 100644 index 0000000..4d4a395 --- /dev/null +++ b/git/theme.nix @@ -0,0 +1,20 @@ +{ pkgs }: + +# The extra stylesheet for cgit, served next to cgit's stock cgit.css, plus the +# webfont it references. Fonts ship here rather than being pulled from +# kassouni.net so they stay same-origin and need no CORS headers. +pkgs.runCommand "cgit-theme" + { + nativeBuildInputs = [ pkgs.dart-sass ]; + + meta = { + description = "cgit stylesheet matching kassouni.net"; + license = pkgs.lib.licenses.mit; + platforms = pkgs.lib.platforms.all; + }; + } + '' + mkdir -p $out + sass --no-source-map --load-path=${../style} ${./cgit.scss} $out/theme.css + cp -r ${../site/static/fonts} $out/fonts + '' diff --git a/nix/configuration.nix b/nix/configuration.nix deleted file mode 100644 index 96c5e48..0000000 --- a/nix/configuration.nix +++ /dev/null @@ -1,31 +0,0 @@ -{config, ...}: { - imports = [ - ./hardware-configuration.nix - ./minecraft.nix - ./options.nix - ./git.nix - ./ssh.nix - ./web.nix - ]; - - boot.loader = { - systemd-boot = { - enable = true; - graceful = true; # TODO: drop after v261+ - }; - efi.canTouchEfiVariables = true; - }; - - nix.settings.experimental-features = [ "nix-command" "flakes" ]; - - networking.hostName = "chariot"; - networking.networkmanager.enable = true; - - users.users.kassouni = { - extraGroups = [ "wheel" ]; - isNormalUser = true; - openssh.authorizedKeys.keys = config.my.adminKeys; - }; - - system.stateVersion = "26.05"; -} diff --git a/nix/git.nix b/nix/git.nix deleted file mode 100644 index 4b3b493..0000000 --- a/nix/git.nix +++ /dev/null @@ -1,51 +0,0 @@ -{config, pkgs, ...}: let - domain = "git.kassouni.net"; - repoRoot = "/srv/git"; -in { - users.users.git = { - isSystemUser = true; - group = "git"; - home = repoRoot; - createHome = true; - homeMode = "750"; - shell = "${pkgs.git}/bin/git-shell"; - openssh.authorizedKeys.keys = config.my.gitKeys; - }; - users.groups.git = { }; - - environment.systemPackages = [ pkgs.git ]; - - services.openssh.extraConfig = '' - Match user git - AllowTcpForwarding no - AllowAgentForwarding no - PermitTTY no - ''; - - services.cgit.${domain} = { - enable = true; - scanPath = repoRoot; - group = "git"; # so cgit can traverse a non-world-readable repoRoot - gitHttpBackend.checkExportOkFiles = true; - settings = { - strict-export = "git-daemon-export-ok"; - remove-suffix = true; - readme = [ ":README.md" ":README" ":readme.md" ]; - clone-url = "git@${domain}:$CGIT_REPO_URL https://${domain}/$CGIT_REPO_URL"; - source-filter = "${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py"; - about-filter = "${pkgs.cgit}/lib/cgit/filters/about-formatting.sh"; - }; - }; - - services.nginx.virtualHosts.${domain} = { - forceSSL = true; - enableACME = true; - }; - - security.acme = { - acceptTerms = true; - defaults.email = "alex@kassouni.net"; - }; - - networking.firewall.allowedTCPPorts = [ 80 443 ]; -} diff --git a/nix/site.nix b/nix/site.nix new file mode 100644 index 0000000..45209ff --- /dev/null +++ b/nix/site.nix @@ -0,0 +1,23 @@ +{ pkgs }: + +pkgs.stdenvNoCC.mkDerivation { + pname = "kassouni-net"; + version = "0.1.0"; + + # style/ sits outside the zola project because cgit shares its partials + src = pkgs.lib.fileset.toSource { + root = ../.; + fileset = pkgs.lib.fileset.unions [ ../site ../style ]; + }; + + nativeBuildInputs = [ pkgs.zola ]; + + buildPhase = "zola --root site build"; + installPhase = "cp -r site/public $out"; + + meta = { + description = "The personal website of Alex Kassouni"; + license = pkgs.lib.licenses.mit; + platforms = pkgs.lib.platforms.all; + }; +} diff --git a/nix/web.nix b/nix/web.nix index b34f8d8..0013d4f 100644 --- a/nix/web.nix +++ b/nix/web.nix @@ -1,8 +1,32 @@ -{...}: { - # dont serve git.kassouni.net traffic to other subdomains - services.nginx.virtualHosts."_" = { - default = true; - rejectSSL = true; - locations."/".return = 444; +{inputs, pkgs, ...}: let + domain = "kassouni.net"; +in { + services.nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + + virtualHosts = { + # dont serve kassouni.net traffic to other subdomains + "_" = { + default = true; + rejectSSL = true; + locations."/".return = 444; + }; + + ${domain} = { + forceSSL = true; + enableACME = true; + root = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.website; + }; + }; }; + + security.acme = { + acceptTerms = true; + defaults.email = "alex@${domain}"; + }; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; } diff --git a/site/sass/_fonts.scss b/site/sass/_fonts.scss deleted file mode 100644 index 2299bca..0000000 --- a/site/sass/_fonts.scss +++ /dev/null @@ -1,28 +0,0 @@ -@use "sass:list"; - -$-faces: ( - 100: ("Thin", "ThinItalic"), - 200: ("ExtraLight", "ExtraLightItalic"), - 300: ("Light", "LightItalic"), - 400: ("Regular", "Italic"), - 450: ("Text", "TextItalic"), - 500: ("Medium", "MediumItalic"), - 600: ("SemiBold", "SemiBoldItalic"), - 700: ("Bold", "BoldItalic"), -); - -$-styles: normal italic; - -@each $weight, $names in $-faces { - @for $i from 1 through 2 { - @font-face { - font-family: "IBM Plex Mono"; - src: url("/fonts/mono/IBMPlexMono-#{list.nth($names, $i)}.woff2") format("woff2"); - font-weight: $weight; - font-style: list.nth($-styles, $i); - font-display: swap; - } - } -} - -$mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; diff --git a/site/sass/_palette.scss b/site/sass/_palette.scss deleted file mode 100644 index b61eb94..0000000 --- a/site/sass/_palette.scss +++ /dev/null @@ -1,51 +0,0 @@ -@mixin ayu-dark { - color-scheme: dark; - - --bg: #0F1419; // base00 default background - --bg-alt: #131721; // base01 raised background - --bg-sel: #272D38; // base02 selection background - --grey: #3E4B59; // base03 comments, invisibles - --fg-dim: #BFBDB6; // base04 muted foreground - --fg: #E6E1CF; // base05 default foreground - --fg-alt: #E6E1CF; // base06 - --fg-bright: #F3F4F5; // base07 brightest foreground - - --red: #F07178; // base08 - --orange: #FF8F40; // base09 - --yellow: #FFB454; // base0A - --green: #B8CC52; // base0B - --cyan: #95E6CB; // base0C - --blue: #59C2FF; // base0D - --purple: #D2A6FF; // base0E - --brown: #E6B673; // base0F -} - -@mixin ayu-light { - color-scheme: light; - - --bg: #FAFAFA; // base00 - --bg-alt: #F3F4F5; // base01 - --bg-sel: #F8F9FA; // base02 - --grey: #ABB0B6; // base03 - --fg-dim: #828C99; // base04 - --fg: #5C6773; // base05 - --fg-alt: #242936; // base06 - --fg-bright: #1A1F29; // base07 - - --red: #F07178; // base08 - --orange: #FA8D3E; // base09 - --yellow: #F2AE49; // base0A - --green: #86B300; // base0B - --cyan: #4CBF99; // base0C - --blue: #36A3D9; // base0D - --purple: #A37ACC; // base0E - --brown: #E6BA7E; // base0F -} - -:root { @include ayu-light; } -@media (prefers-color-scheme: dark) { - :root { @include ayu-dark; } -} - -:root[data-theme="dark"] { @include ayu-dark; } -:root[data-theme="light"] { @include ayu-light; } diff --git a/site/sass/style.scss b/site/sass/style.scss index 5ce9f88..1daba2d 100644 --- a/site/sass/style.scss +++ b/site/sass/style.scss @@ -1,5 +1,6 @@ -@use "palette"; -@use "fonts"; +// shared with the cgit stylesheet, hence the reach out of the zola project +@use "../../style/palette"; +@use "../../style/fonts"; body { background: var(--bg); @@ -102,6 +103,23 @@ time { color: var(--fg-dim); } +h1, h2, h3, h4, h5, h6 { + line-height: 1.3; + + &::before { + color: var(--grey); + font-weight: 400; + margin-right: 0.4em; + } +} + +h1::before { content: "#"; } +h2::before { content: "##"; } +h3::before { content: "###"; } +h4::before { content: "####"; } +h5::before { content: "#####"; } +h6::before { content: "######"; } + strong { color: var(--orange); font-weight: 600; diff --git a/style/_fonts.scss b/style/_fonts.scss new file mode 100644 index 0000000..2299bca --- /dev/null +++ b/style/_fonts.scss @@ -0,0 +1,28 @@ +@use "sass:list"; + +$-faces: ( + 100: ("Thin", "ThinItalic"), + 200: ("ExtraLight", "ExtraLightItalic"), + 300: ("Light", "LightItalic"), + 400: ("Regular", "Italic"), + 450: ("Text", "TextItalic"), + 500: ("Medium", "MediumItalic"), + 600: ("SemiBold", "SemiBoldItalic"), + 700: ("Bold", "BoldItalic"), +); + +$-styles: normal italic; + +@each $weight, $names in $-faces { + @for $i from 1 through 2 { + @font-face { + font-family: "IBM Plex Mono"; + src: url("/fonts/mono/IBMPlexMono-#{list.nth($names, $i)}.woff2") format("woff2"); + font-weight: $weight; + font-style: list.nth($-styles, $i); + font-display: swap; + } + } +} + +$mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; diff --git a/style/_palette.scss b/style/_palette.scss new file mode 100644 index 0000000..b61eb94 --- /dev/null +++ b/style/_palette.scss @@ -0,0 +1,51 @@ +@mixin ayu-dark { + color-scheme: dark; + + --bg: #0F1419; // base00 default background + --bg-alt: #131721; // base01 raised background + --bg-sel: #272D38; // base02 selection background + --grey: #3E4B59; // base03 comments, invisibles + --fg-dim: #BFBDB6; // base04 muted foreground + --fg: #E6E1CF; // base05 default foreground + --fg-alt: #E6E1CF; // base06 + --fg-bright: #F3F4F5; // base07 brightest foreground + + --red: #F07178; // base08 + --orange: #FF8F40; // base09 + --yellow: #FFB454; // base0A + --green: #B8CC52; // base0B + --cyan: #95E6CB; // base0C + --blue: #59C2FF; // base0D + --purple: #D2A6FF; // base0E + --brown: #E6B673; // base0F +} + +@mixin ayu-light { + color-scheme: light; + + --bg: #FAFAFA; // base00 + --bg-alt: #F3F4F5; // base01 + --bg-sel: #F8F9FA; // base02 + --grey: #ABB0B6; // base03 + --fg-dim: #828C99; // base04 + --fg: #5C6773; // base05 + --fg-alt: #242936; // base06 + --fg-bright: #1A1F29; // base07 + + --red: #F07178; // base08 + --orange: #FA8D3E; // base09 + --yellow: #F2AE49; // base0A + --green: #86B300; // base0B + --cyan: #4CBF99; // base0C + --blue: #36A3D9; // base0D + --purple: #A37ACC; // base0E + --brown: #E6BA7E; // base0F +} + +:root { @include ayu-light; } +@media (prefers-color-scheme: dark) { + :root { @include ayu-dark; } +} + +:root[data-theme="dark"] { @include ayu-dark; } +:root[data-theme="light"] { @include ayu-light; } -- cgit v1.3.1