feat(web/website): init

This adds a new Website/Docs for Snix, using Thulite / Doks, which is
mostly hugo and a bit of npm.

Change-Id: Iea10d4068fa783ec0ddd6bcaba5c8d92b1a1168f
This commit is contained in:
Florian Klink 2025-03-16 13:36:18 +01:00
parent 2705517e6d
commit 91d8b86b39
55 changed files with 6205 additions and 0 deletions

5
web/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
/node_modules
/public
/hugo_stats.json
/resources/_gen
/.hugo_build.lock

14
web/README.md Normal file
View file

@ -0,0 +1,14 @@
# snix-website
This is the Snix website, hosted on https://snix.dev.
It uses [Doks](https://getdoks.org/), which uses [Thulite](https://thulite.io).
You can either `mg build :website` to use the Nix build, or get an interactive,
live-reloading version.
```console
$ mg shell :shell
$ npm i
$ npm run dev
```

BIN
web/assets/cover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 263 KiB

BIN
web/assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
web/assets/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

1
web/assets/favicon.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M32.415 9.586l-9-9C23.054.225 22.553 0 22 0c-1.104 0-1.999.896-2 2 0 .552.224 1.053.586 1.415l-3.859 3.859 9 9 3.859-3.859c.362.361.862.585 1.414.585 1.104 0 2.001-.896 2-2 0-.552-.224-1.052-.585-1.414z"/><path fill="#CCD6DD" d="M22 0H7C4.791 0 3 1.791 3 4v28c0 2.209 1.791 4 4 4h22c2.209 0 4-1.791 4-4V11h-9c-1 0-2-1-2-2V0z"/><path fill="#99AAB5" d="M22 0h-2v9c0 2.209 1.791 4 4 4h9v-2h-9c-1 0-2-1-2-2V0zm-5 8c0 .552-.448 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h8c.552 0 1 .448 1 1zm0 4c0 .552-.448 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h8c.552 0 1 .448 1 1zm12 4c0 .552-.447 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h20c.553 0 1 .448 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1z"/></svg>

After

Width:  |  Height:  |  Size: 972 B

View file

1
web/assets/js/custom.js Normal file
View file

@ -0,0 +1 @@
// Put your custom JS code here

8
web/assets/jsconfig.json Normal file
View file

@ -0,0 +1,8 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": ["*", "..\\node_modules\\@thulite\\doks-core\\assets\\*"]
}
}
}

1
web/assets/mask-icon.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M32.415 9.586l-9-9C23.054.225 22.553 0 22 0c-1.104 0-1.999.896-2 2 0 .552.224 1.053.586 1.415l-3.859 3.859 9 9 3.859-3.859c.362.361.862.585 1.414.585 1.104 0 2.001-.896 2-2 0-.552-.224-1.052-.585-1.414z"/><path fill="#CCD6DD" d="M22 0H7C4.791 0 3 1.791 3 4v28c0 2.209 1.791 4 4 4h22c2.209 0 4-1.791 4-4V11h-9c-1 0-2-1-2-2V0z"/><path fill="#99AAB5" d="M22 0h-2v9c0 2.209 1.791 4 4 4h9v-2h-9c-1 0-2-1-2-2V0zm-5 8c0 .552-.448 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h8c.552 0 1 .448 1 1zm0 4c0 .552-.448 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h8c.552 0 1 .448 1 1zm12 4c0 .552-.447 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h20c.553 0 1 .448 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1z"/></svg>

After

Width:  |  Height:  |  Size: 972 B

View file

@ -0,0 +1 @@
// Put your custom SCSS code here

View file

@ -0,0 +1 @@
// Put your custom SCSS variables here

43
web/assets/snix-logo.svg Normal file
View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="1200pt"
height="1200pt"
version="1.1"
viewBox="0 0 1200 1200"
id="svg1"
sodipodi:docname="snix-logo.svg"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="pt"
inkscape:zoom="0.57290673"
inkscape:cx="824.74158"
inkscape:cy="780.23171"
inkscape:window-width="1320"
inkscape:window-height="346"
inkscape:window-x="45"
inkscape:window-y="29"
inkscape:window-maximized="0"
inkscape:current-layer="svg1" />
<path
d="M 1016.7023,455.30233 H 183.42233 l -90.237995,-15.961 c -3.8398,-0.71875 -7.9219,0.35938 -10.922,2.8789 -3.0001,2.51952 -4.8008,6.3594 -4.8008,10.199 v 295.08 c 0,3.9609 1.8008,7.6797 4.8008,10.199 3,2.5195 7.0781,3.6016 10.922,2.8789 l 90.237995,-15.961 h 833.27997 l 90.238,15.961 c 3.8398,0.71875 7.9219,-0.35938 10.922,-2.8789 3,-2.5195 4.8008,-6.2383 4.8008,-10.199 v -294.96 c 0,-3.9609 -1.8008,-7.6797 -4.8008,-10.199 -3,-2.5195 -7.0781,-3.6016 -10.922,-2.8789 z m -9.9609,262.68 h -31.80097 v -235.92 h 31.80097 z m -813.35997,-235.92 h 31.801 v 235.92 h -31.801 z m 54.121,235.92 v -31.68 h 503.64 c 4.9219,0 8.8789,-3.9609 8.8789,-8.8789 0,-4.9219 -3.9609,-9.0039 -8.8828,-9.0039 h -503.64 v -186.36 h 705.12 l -0.004,235.92 z m -143.28,-31.68 h 32.281 c 4.9219,0 8.8789,-3.9609 8.8789,-8.8789 0,-4.9219 -3.9609,-8.8789 -8.8789,-8.8789 l -32.281,-0.004 v -59.52 h 32.281 c 4.9219,0 8.8789,-3.9609 8.8789,-8.8789 0,-4.9219 -3.9609,-8.8789 -8.8789,-8.8789 l -32.281,-0.004 v -59.52 h 32.281 c 4.9219,0 8.8789,-3.9609 8.8789,-8.8789 0,-4.9219 -3.9609,-8.8789 -8.8789,-8.8789 h -32.281 v -45.238 l 66.84,11.762 v 239.28 l -66.84,11.762 z m 991.67997,-172.56 h -39.48 c -4.9219,0 -8.8789,3.9609 -8.8789,8.8789 0,4.9219 3.9609,8.8789 8.8789,8.8789 h 39.48 v 59.52 h -39.48 c -4.9219,0 -8.8789,3.9609 -8.8789,8.8789 0,4.9219 3.9609,8.8789 8.8789,8.8789 h 39.48 v 59.645 h -39.48 c -4.9219,0 -8.8789,3.9609 -8.8789,8.8789 0,4.9219 3.9609,8.8789 8.8789,8.8789 h 39.48 v 45.238 l -66.84,-11.762 v -239.4 l 66.84,-11.762 z"
id="path1" />
<path
style="font-weight:bold;font-size:174.083px;font-family:'ComicShannsMono Nerd Font Propo';-inkscape-font-specification:'ComicShannsMono Nerd Font Propo Bold';letter-spacing:6.885px;stroke-width:5.93464"
d="m 474.40628,538.76714 c 1.39266,0.34817 2.95941,0.52225 4.70024,0.52225 0.52225,0 1.21858,0 1.91491,0 4.178,-0.34816 6.09291,-4.17799 6.09291,-7.48557 0,-3.82982 -2.26308,-8.1819 -6.96332,-9.92273 -5.39657,-1.91491 -19.14913,-2.61124 -23.32712,-2.61124 -30.81269,0 -49.09141,16.88605 -49.09141,36.03518 0,14.10072 13.75256,24.02345 26.46062,25.24203 32.37944,3.1335 34.12027,13.92664 34.12027,21.41221 0,12.88214 -16.53789,21.76037 -28.7237,21.76037 -10.96723,0 -16.18972,-6.0929 -17.93055,-8.87823 -2.08899,-2.95941 -4.35207,-5.57065 -8.1819,-5.57065 -1.74083,0 -3.48166,0.52224 -5.57065,1.39266 -2.089,0.87041 -5.04841,3.48166 -5.04841,8.00782 0,5.91882 4.70024,12.53397 14.44889,17.93055 6.0929,3.48166 13.40439,5.0484 21.76037,5.0484 24.71979,0 49.78774,-14.79705 49.78774,-41.60583 0,-30.29044 -29.94228,-34.46844 -41.43175,-34.99068 -18.10463,-0.87042 -18.97505,-10.96723 -18.97505,-12.88215 0,-9.92273 14.44889,-15.66747 27.15695,-15.66747 8.00782,0 10.61906,0.17409 18.80096,2.26308 z m 50.40562,31.33494 c 0,-3.82982 0,-7.65965 -0.17408,-11.31539 13.40439,29.94227 37.07967,66.67378 41.43175,76.07427 2.08899,4.17799 7.65965,4.52615 9.57456,4.52615 2.26308,0 4.35208,-0.34816 6.44107,-1.04449 5.39658,-1.56675 6.44107,-4.35208 7.13741,-22.45671 0.87041,-18.80096 1.04449,-37.77601 1.04449,-51.1804 0,-8.00782 -0.17408,-13.92664 -0.17408,-16.71197 -0.17408,-13.40439 -0.17408,-18.97504 -1.74083,-22.4567 -1.91491,-3.1335 -6.0929,-3.30758 -8.53007,-3.30758 -4.52615,0 -9.05231,3.13349 -9.05231,7.83373 0,2.26308 1.74083,7.13741 1.74083,49.78774 0,10.2709 -0.17408,19.67138 -0.17408,25.93837 -12.01173,-20.01955 -36.20927,-63.01805 -41.08359,-77.29285 -2.26308,-5.91882 -8.87823,-5.91882 -10.79315,-6.09291 -0.34816,0 -1.04449,0 -1.91491,0 -11.14131,0 -11.83764,7.48557 -11.83764,9.57457 0,0.17408 0.34816,5.74474 0.34816,21.06404 0,29.07186 -1.21858,74.33344 -1.21858,75.02977 0,3.13349 0.34817,5.74474 1.39267,7.83373 1.21858,2.089 4.35207,3.1335 7.1374,3.1335 4.87432,0 9.40048,-3.1335 9.40048,-9.40048 0,-0.17409 0,-0.52225 0,-0.69634 0,-0.69633 1.0445,-45.60974 1.0445,-58.84005 z m 160.94832,68.76278 c 6.61515,0 7.65965,-6.26698 7.65965,-9.40048 v 0 c -0.52225,-7.1374 -5.57066,-8.35598 -8.87823,-8.35598 -0.17409,0 -0.17409,0 -0.17409,0 -17.75646,0 -18.62688,0 -24.02345,0 0.17408,-12.35989 1.0445,-21.41221 1.0445,-35.33885 0,-9.40048 -0.34817,-14.10072 -0.34817,-24.71978 0,-5.39658 0,-11.83765 0.34817,-21.58629 6.44107,0.34816 16.71197,0.87041 21.41221,1.56674 0.52225,0 1.04449,0.17409 1.74083,0.17409 6.0929,0 8.53006,-5.74474 8.53006,-9.74865 0,0 0,0 0,0 v -0.17409 c -0.52225,-6.61515 -6.26698,-8.00781 -9.40048,-8.1819 -10.79314,-1.21858 -23.32712,-1.74083 -39.34275,-1.74083 -7.48557,0 -16.01564,0.17409 -25.41612,0.52225 -9.92273,0.34817 -10.2709,8.00782 -10.2709,8.87824 0,5.39657 3.82983,9.05231 9.92273,9.05231 0.87042,0 3.48166,-0.34816 11.14131,-0.34816 3.48166,0 7.13741,0.17408 10.96723,0.17408 0,0.17408 -0.52225,10.27089 -0.52225,12.53397 0,8.70415 0.34817,31.85719 0.34817,32.72761 0,14.79705 0,15.14522 -1.0445,37.07967 -9.05231,0.34817 -16.01563,0.52225 -21.93446,0.69634 -9.57456,0.34816 -10.09681,6.96332 -10.09681,8.53006 0,0.17409 0,0.34817 0,0.34817 0,6.96332 7.65965,7.65965 10.44498,7.65965 0.69633,0 40.73542,-1.21858 52.74715,-1.21858 11.31539,0 13.2303,0.87041 15.14522,0.87041 z m 111.50874,-4.70024 c 0,-2.95941 -1.21858,-6.26698 -3.82983,-10.27089 -2.95941,-4.178 -8.35598,-12.88214 -14.2748,-22.80488 -4.35208,-6.78923 -8.87824,-14.2748 -13.40439,-20.88995 0.17408,-0.34817 11.66356,-17.93055 14.79705,-22.80488 13.40439,-22.4567 14.97114,-25.06795 14.97114,-28.20144 0,-2.95941 -3.1335,-7.65965 -9.40048,-7.65965 -3.1335,0 -6.44107,1.56674 -8.87824,4.52615 -6.0929,8.35599 -17.58238,28.37553 -22.28262,36.55743 -10.27089,-16.01563 -16.3638,-25.5902 -20.54179,-31.50902 -5.22249,-6.96332 -7.48557,-8.87823 -11.14131,-8.87823 -3.1335,0 -11.48948,0.69633 -11.48948,7.83373 0,3.30758 1.21858,5.22249 8.1819,16.53789 1.91491,2.78533 6.61515,9.74865 22.10854,32.03127 -8.35598,13.23031 -22.10854,33.59802 -24.37162,36.90559 -6.0929,9.74865 -8.35598,13.57848 -8.35598,17.23422 0,2.95941 3.65574,8.1819 9.74865,8.1819 2.78532,0 5.74473,-1.39266 8.00781,-4.00391 1.39267,-1.56675 4.17799,-6.44107 8.00782,-13.05622 5.39657,-8.70415 12.35989,-20.19363 17.93055,-28.37553 1.56675,2.61124 3.30758,5.39657 5.22249,8.35598 14.97114,25.93837 21.06404,36.73151 29.24594,36.73151 3.65574,0 9.74865,-1.91491 9.74865,-6.44107 z"
id="text1"
aria-label="SNIX" />
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

0
web/assets/svgs/.gitkeep Normal file
View file

View file

@ -0,0 +1,86 @@
title = "Snix"
baseurl = "http://snix.dev/"
canonifyURLs = false
disableAliases = true
disableHugoGeneratorInject = true
# disableKinds = ["taxonomy", "term"]
enableEmoji = true
enableGitInfo = false
enableRobotsTXT = true
languageCode = "en-US"
pagerSize = 10
rssLimit = 10
summarylength = 20 # 70 (default)
# Multilingual
defaultContentLanguage = "en"
disableLanguages = ["de", "nl"]
defaultContentLanguageInSubdir = false
copyRight = "Copyright (c) 2025 The Snix Project"
[build.buildStats]
enable = true
[outputs]
home = ["HTML", "RSS", "searchIndex"]
section = ["HTML", "RSS", "SITEMAP"]
[outputFormats.searchIndex]
mediaType = "application/json"
baseName = "search-index"
isPlainText = true
notAlternative = true
# Add output format for section sitemap.xml
[outputFormats.SITEMAP]
mediaType = "application/xml"
baseName = "sitemap"
isHTML = false
isPlainText = true
noUgly = true
rel = "sitemap"
[sitemap]
changefreq = "monthly"
filename = "sitemap.xml"
priority = 0.5
[caches]
[caches.getjson]
dir = ":cacheDir/:project"
maxAge = -1 # "30m"
[taxonomies]
contributor = "contributors"
category = "categories"
tag = "tags"
[permalinks]
blog = "/blog/:slug/"
docs = "/docs/:sections[1:]/:slug/"
# docs = "/docs/1.0/:sections[1:]/:slug/"
[minify.tdewolff.html]
keepWhitespace = false
[related]
threshold = 80
includeNewer = true
toLower = false
[[related.indices]]
name = "categories"
weight = 100
[[related.indices]]
name = "tags"
weight = 80
[[related.indices]]
name = "date"
weight = 10
[imaging]
anchor = "Center"
bgColor = "#ffffff"
hint = "photo"
quality = 85
resampleFilter = "Lanczos"

View file

@ -0,0 +1,9 @@
[en]
languageName = "English"
contentDir = "content/en"
weight = 10
[en.params]
languageISO = "EN"
languageTag = "en-US"
footer = ''
# alertText = '<a class="alert-link stretched-link fw-normal" href="/blog/example-post/">Doks version 1.0 just shipped!</a>'

View file

@ -0,0 +1,33 @@
defaultMarkdownHandler = "goldmark"
[goldmark]
[goldmark.extensions]
linkify = false
[goldmark.parser]
autoHeadingID = true
autoHeadingIDType = "github"
[goldmark.parser.attribute]
block = true
title = true
[goldmark.renderer]
unsafe = true
[highlight]
anchorLineNos = false
codeFences = true
guessSyntax = false
hl_Lines = ''
hl_inline = false
lineAnchors = ''
lineNoStart = 1
lineNos = false
lineNumbersInTable = false
noClasses = false
noHl = false
style = 'monokai'
tabWidth = 2
[tableOfContents]
endLevel = 3
ordered = false
startLevel = 2

View file

@ -0,0 +1,105 @@
# [[docs]]
# name = "Prologue"
# weight = 10
# identifier = "prologue"
# url = "/docs/prologue/"
# [[docs]]
# name = "Help"
# weight = 60
# identifier = "help"
# url = "/docs/help/"
# [[docs]]
# name = "Lorem"
# weight = 70
# identifier = "lorem"
# url = "/docs/lorem/"
[[guide]]
name = "Lorem"
weight = 10
identifier = "lorem"
url = "/guide/lorem/"
[[tutorial]]
name = "Lorem"
weight = 10
identifier = "lorem"
url = "/tutorial/lorem/"
[[main]]
name = "About"
url = "/about/"
weight = 10
[[main]]
name = "Docs"
url = "/docs/components/architecture/"
# url = "/docs/1.0/prologue/introduction/"
weight = 20
# [[main]]
# name = "Blog"
# url = "/blog/"
# weight = 30
[[main]]
name = "Contact"
url = "/contact/"
weight = 31
# [[social]]
# name = "X"
# pre = '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-x" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 4l11.733 16h4.267l-11.733 -16z"></path><path d="M4 20l6.768 -6.768m2.46 -2.46l6.772 -6.772"></path></svg>'
# url = "https://twitter.com/getdoks"
# weight = 10
#
# [[social]]
# name = "Discord"
# pre = '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-discord" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M14 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8.5 17c0 1 -1.356 3 -1.832 3c-1.429 0 -2.698 -1.667 -3.333 -3c-.635 -1.667 -.476 -5.833 1.428 -11.5c1.388 -1.015 2.782 -1.34 4.237 -1.5l.975 1.923a11.913 11.913 0 0 1 4.053 0l.972 -1.923c1.5 .16 3.043 .485 4.5 1.5c2 5.667 2.167 9.833 1.5 11.5c-.667 1.333 -2 3 -3.5 3c-.5 0 -2 -2 -2 -3"></path><path d="M7 16.5c3.5 1 6.5 1 10 0"></path></svg>'
# url = "https://getdoks.org/chat"
# weight = 20
[[social]]
name = "Gerrit"
pre = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-brand-git"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M16 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /><path d="M12 8m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /><path d="M12 16m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /><path d="M12 15v-6" /><path d="M15 11l-2 -2" /><path d="M11 7l-1.9 -1.9" /><path d="M13.446 2.6l7.955 7.954a2.045 2.045 0 0 1 0 2.892l-7.955 7.955a2.045 2.045 0 0 1 -2.892 0l-7.955 -7.955a2.045 2.045 0 0 1 0 -2.892l7.955 -7.955a2.045 2.045 0 0 1 2.892 0z" /></svg>'
url = "https://cl.snix.dev"
weight = 30
[[social]]
name = "Code"
pre = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-code"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 8l-4 4l4 4" /><path d="M17 8l4 4l-4 4" /><path d="M14 4l-4 16" /></svg>'
url = "https://git.snix.dev/snix/snix"
weight = 31
[[social]]
name = "Rustdoc"
pre = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" id="Cubes--Streamline-Font-Awesome" height="16" width="16"><desc>Cubes Streamline Icon: https://streamlinehq.com</desc><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m8.074847222222221 2.352027777777778 2.133852777777778 0.8083611111111111 -2.210061111111111 0.849186111111111 -2.210061111111111 -0.849186111111111 2.133852777777778 -0.8083611111111111c0.04899166666666666 -0.019049999999999997 0.10342499999999999 -0.019049999999999997 0.15513888888888888 0Zm-4.213266666666667 1.19485v3.0538027777777774c-0.03538333333333333 0.010886111111111112 -0.07076666666666666 0.021772222222222224 -0.10615 0.03538333333333333l-2.6128777777777774 0.9907166666666666C0.5519333333333333 7.8499638888888885 0.15999999999999998 8.418808333333333 0.15999999999999998 9.050255555555553v3.244325c0 0.6042277777777777 0.35655 1.1513 0.9117861111111111 1.3962583333333334l2.6128805555555554 1.1485777777777777c0.39193055555555556 0.17146944444444445 0.8355777777777778 0.17146944444444445 1.2275083333333332 0l3.086463888888889 -1.3581527777777778 3.089186111111111 1.3581527777777778c0.3919333333333333 0.17146944444444445 0.8355777777777778 0.17146944444444445 1.2275083333333332 0l2.6128805555555554 -1.1485777777777777c0.5525166666666667 -0.2422361111111111 0.9117861111111111 -0.7920305555555556 0.9117861111111111 -1.3962583333333334V9.050255555555553c0 -0.6341694444444445 -0.39193055555555556 -1.2002916666666668 -0.9825527777777776 -1.4261972222222221l-2.6128777777777774 -0.9907166666666666c-0.03538333333333333 -0.013608333333333333 -0.07076666666666666 -0.024497222222222222 -0.10615 -0.03538333333333333V3.5468777777777776c0 -0.6341694444444445 -0.39193055555555556 -1.2002916666666668 -0.9825499999999999 -1.4261972222222221l-2.6128805555555554 -0.9907166666666666c-0.3483833333333333 -0.13064444444444442 -0.73215 -0.13064444444444442 -1.0805333333333333 0l-2.6128805555555554 0.9907166666666666c-0.5960638888888888 0.22590555555555555 -0.9879944444444444 0.79475 -0.9879944444444444 1.4261972222222221Zm6.967677777777777 3.2143861111111107 -2.242722222222222 0.849186111111111v-2.4278027777777775l2.242722222222222 -0.8600722222222221v2.4386888888888887Zm-6.455988888888889 1.0968638888888889 2.13385 0.8083611111111111 -2.210061111111111 0.8464638888888888 -2.2100583333333335 -0.8464638888888888 2.13385 -0.8083611111111111c0.04899166666666666 -0.019052777777777776 0.10342777777777777 -0.019052777777777776 0.15513888888888888 0Zm0.5116888888888889 5.563258333333333V10.686027777777777l2.242722222222222 -0.860075V12.43611111111111l-2.242722222222222 0.985275Zm6.739052777777777 -5.563258333333333c0.04898888888888889 -0.019052777777777776 0.10342499999999999 -0.019052777777777776 0.15513888888888888 0l2.13385 0.8083611111111111 -2.2127805555555553 0.8464638888888888 -2.210061111111111 -0.8464638888888888 2.13385 -0.8083611111111111Zm2.776183333333333 4.635141666666667 -2.112077777777778 0.9281166666666666V10.686027777777777l2.242722222222222 -0.860075v2.4686277777777774c0 0.08709722222222221 -0.051713888888888886 0.16330555555555554 -0.13064444444444442 0.1986888888888889Z" fill="currentColor" stroke-width="0.0278"></path></svg>'
url = "https://snix.dev/rustdoc"
weight = 32
# [[sidebar_docs]]
# name = "Guides"
# pageRef = "/docs/guides"
# weight = 10
#
# [[sidebar_docs]]
# name = "Reference"
# pageRef = "/docs/reference"
# weight = 20
#
# [[sidebar_docs]]
# name = "Resources"
# pageRef = "/docs/resources"
# weight = 30
# [[footer]]
# name = "Privacy Policy"
# url = "/privacy/"
# weight = 10
# [[footer]]
# name = "Terms of Service"
# url = "/terms/"
# weight = 20

View file

@ -0,0 +1,87 @@
# mounts
## archetypes
[[mounts]]
source = "node_modules/@thulite/doks-core/archetypes"
target = "archetypes"
[[mounts]]
source = "archetypes"
target = "archetypes"
## assets
[[mounts]]
source = "node_modules/@thulite/core/assets"
target = "assets"
[[mounts]]
source = "node_modules/@thulite/images/assets"
target = "assets"
[[mounts]]
source = "node_modules/@thulite/doks-core/assets"
target = "assets"
[[mounts]]
source = "node_modules/@tabler/icons/icons"
target = "assets/svgs/tabler-icons"
[[mounts]]
source = "assets"
target = "assets"
## content
[[mounts]]
source = "content"
target = "content"
## data
[[mounts]]
source = "node_modules/@thulite/doks-core/data"
target = "data"
[[mounts]]
source = "data"
target = "data"
## i18n
[[mounts]]
source = "node_modules/@thulite/doks-core/i18n"
target = "i18n"
[[mounts]]
source = "i18n"
target = "i18n"
## layouts
[[mounts]]
source = "node_modules/@thulite/core/layouts"
target = "layouts"
[[mounts]]
source = "node_modules/@thulite/seo/layouts"
target = "layouts"
[[mounts]]
source = "node_modules/@thulite/images/layouts"
target = "layouts"
[[mounts]]
source = "node_modules/@thulite/doks-core/layouts"
target = "layouts"
[[mounts]]
source = "node_modules/@thulite/inline-svg/layouts"
target = "layouts"
[[mounts]]
source = "layouts"
target = "layouts"
## static
[[mounts]]
source = "node_modules/@thulite/doks-core/static"
target = "static"
[[mounts]]
source = "static"
target = "static"

View file

@ -0,0 +1,138 @@
# Hugo
title = "My Docs"
description = "Congrats on setting up a new Doks project!"
images = ["cover.png"]
# mainSections
mainSections = ["docs"]
[social]
twitter = "getdoks"
# Doks (@thulite/doks-core)
[doks]
# Color mode
colorMode = "auto" # auto (default), light or dark
colorModeToggler = true # true (default) or false (this setting is only relevant when colorMode = auto)
# Navbar
navbarSticky = true # true (default) or false
containerBreakpoint = "lg" # "", "sm", "md", "lg" (default), "xl", "xxl", or "fluid"
## Button
navBarButton = false # false (default) or true
navBarButtonUrl = "/docs/prologue/introduction/"
navBarButtonText = "Get started"
# FlexSearch
flexSearch = true # true (default) or false
searchExclKinds = [] # list of page kinds to exclude from search indexing (e.g. ["home", "taxonomy", "term"] )
searchExclTypes = [] # list of content types to exclude from search indexing (e.g. ["blog", "docs", "legal", "contributors", "categories"])
showSearch = [] # [] (all pages, default) or homepage (optionally) and list of sections (e.g. ["homepage", "blog", "guides"])
indexSummary = false # true or false (default); whether to index only the `.Summary` instead of the full `.Content`; limits the respective JSON field size and thus increases loading time
## Search results
showDate = false # false (default) or true
showSummary = true # true (default) or false
searchLimit = 99 # 0 (no limit, default) or natural number
# Global alert
alert = false # false (default) or true
alertDismissable = true # true (default) or false
# Bootstrap
bootstrapJavascript = false # false (default) or true
# Nav
sectionNav = ["docs"] # ["docs"] (default) or list of sections (e.g. ["docs", "guides"])
toTopButton = false # false (default) or true
breadcrumbTrail = false # false (default) or true
headlineHash = true # true (default) or false
scrollSpy = true # true (default) or false
# Multilingual
multilingualMode = false # false (default) or true
showMissingLanguages = true # whether or not to show untranslated languages in the language menu; true (default) or false
# Versioning
docsVersioning = false # false (default) or true
docsVersion = "1.0"
# UX
headerBar = false # true (default) or false
backgroundDots = true # true (default) or false
# Homepage
sectionFooter = false # false (default) or true
# Blog
relatedPosts = false # false (default) or true
imageList = true # true (default) or false
imageSingle = true # true (default) or false
# Repository
editPage = false # false (default) or true
lastMod = false # false (default) or true
repoHost = "GitHub" # GitHub (default), Gitea, GitLab, Bitbucket, or BitbucketServer
docsRepo = "https://github.com/h-enk/doks"
docsRepoBranch = "main" # main (default), master, or <branch name>
docsRepoSubPath = "" # "" (none, default) or <sub path>
# SCSS colors
# backGround = "yellowgreen"
## Dark theme
# textDark = "#dee2e6" # "#dee2e6" (default), "#dee2e6" (orignal), or custom color
# accentDark = "#5d2f86" # "#5d2f86" (default), "#5d2f86" (original), or custom color
## Light theme
# textLight = "#1d2d35" # "#1d2d35" (default), "#1d2d35" (orignal), or custom color
# accentLight = "#8ed6fb" # "#8ed6fb" (default), "#8ed6fb" (orignal), or custom color
# [doks.menu]
# [doks.menu.section]
# auto = true # true (default) or false
# collapsibleSidebar = true # true (default) or false
# Debug
[render_hooks.image]
errorLevel = 'ignore' # ignore (default), warning, or error (fails the build)
[render_hooks.link]
errorLevel = 'ignore' # ignore (default), warning, or error (fails the build)
highlightBroken = false # true or false (default)
# Images (@thulite/images)
[thulite_images]
[thulite_images.defaults]
decoding = "async" # sync, async, or auto (default)
fetchpriority = "auto" # high, low, or auto (default)
loading = "lazy" # eager or lazy (default)
widths = [480, 576, 768, 1025, 1200, 1440] # [640, 768, 1024, 1366, 1600, 1920] for example
sizes = "auto" # 100vw (default), 75vw, or auto for example
process = "" # "fill 1600x900" or "fill 2100x900" for example
lqip = "16x webp q20" # "16x webp q20" or "21x webp q20" for example
# Inline SVG (@thulite/inline-svg)
[inline_svg]
iconSetDir = "tabler-icons" # "tabler-icons" (default)
# SEO (@thulite/seo)
[seo]
[seo.title]
separator = " | "
suffix = ""
[seo.favicons]
sizes = []
icon = "favicon.png" # favicon.png (default)
svgIcon = "favicon.svg" # favicon.svg (default)
maskIcon = "mask-icon.svg" # mask-icon.svg (default)
maskIconColor = "white" # white (default)
[seo.schemas]
type = "Organization" # Organization (default) or Person
logo = "favicon-512x512.png" # Logo of Organization — favicon-512x512.png (default)
name = "Thulite" # Name of Organization or Person
sameAs = [] # E.g. ["https://github.com/thuliteio/thulite", "https://fosstodon.org/@thulite"]
images = ["cover.png"] # ["cover.png"] (default)
article = [] # Article sections
newsArticle = [] # NewsArticle sections
blogPosting = ["blog"] # BlogPosting sections
product = [] # Product sections

View file

@ -0,0 +1,17 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
browsers: [
// Best practice: https://github.com/babel/babel/issues/7789
'>=1%',
'not ie 11',
'not op_mini all'
]
}
}
]
]
};

View file

@ -0,0 +1,2 @@
# Overrides for next environment
baseurl = "/"

View file

@ -0,0 +1,64 @@
const autoprefixer = require('autoprefixer');
const purgecss = require('@fullhuman/postcss-purgecss');
const whitelister = require('purgecss-whitelister');
module.exports = {
plugins: [
autoprefixer(),
purgecss({
content: ['./hugo_stats.json'],
extractors: [
{
extractor: (content) => {
const els = JSON.parse(content).htmlElements;
return els.tags.concat(els.classes, els.ids);
},
extensions: ['json']
}
],
dynamicAttributes: [
'aria-expanded',
'data-bs-popper',
'data-bs-target',
'data-bs-theme',
'data-dark-mode',
'data-global-alert',
'data-pane', // tabs.js
'data-popper-placement',
'data-sizes',
'data-toggle-tab', // tabs.js
'id',
'size',
'type'
],
safelist: [
'active',
'btn-clipboard', // clipboards.js
'clipboard', // clipboards.js
'disabled',
'hidden',
'modal-backdrop', // search-modal.js
'selected', // search-modal.js
'show',
'img-fluid',
'blur-up',
'lazyload',
'lazyloaded',
'alert-link',
'container-fw ',
'container-lg',
'container-fluid',
'offcanvas-backdrop',
'figcaption',
'dt',
'dd',
'showing',
'hiding',
'page-item',
'page-link',
'not-content',
...whitelister(['./assets/scss/**/*.scss', './node_modules/@thulite/doks-core/assets/scss/components/_code.scss', './node_modules/@thulite/doks-core/assets/scss/components/_expressive-code.scss', './node_modules/@thulite/doks-core/assets/scss/common/_syntax.scss'])
]
})
]
};

View file

@ -0,0 +1,2 @@
# Overrides for production environment
baseurl = "/"

13
web/content/_index.md Normal file
View file

@ -0,0 +1,13 @@
---
title: "Snix"
description: "A modern Rust re-implementation of the components of the Nix package manager."
lead: "A modern Rust re-implementation of the components of the Nix package manager."
date: 2023-09-07T16:33:54+02:00
lastmod: 2023-09-07T16:33:54+02:00
draft: false
seo:
title: "" # custom title (optional)
description: "" # custom description (recommended)
canonical: "" # custom canonical URL (optional)
robots: "" # custom robot tags (optional)
---

57
web/content/about.md Normal file
View file

@ -0,0 +1,57 @@
---
title: "About Snix"
slug: about
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 999
toc: false
---
<center>
{{< inline-svg src="snix-logo.svg" width="200px" height="200px" class="svg-inline-custom svg-monochrome" >}}
</center>
Snix is a modern Rust re-implementation of the components of the Nix package
manager.
Snix modularity & composability allows recombining its parts in novel ways. It
also provides library access to Nix data formats and concepts. In the long-run,
Snix aims to produce a Nixpkgs-compatible alternative to [NixOS/nix][] with
respects to evaluation and building Nix expressions & systems.
{{< callout >}}
Snix still is in its early stages of development. None of our current APIs
should be considered stable in any way.
There is no full-featured drop-in replacement for Nix on your machine yet.
{{</callout>}}
Snix already provides a few binaries / tools exposing some usecases, such as:
* A `snix-store` binary, providing access to `snix-[ca]store`
* run a gRPC daemon exposing contents to other parties
* import local files or copy store paths into `snix-store`
* provide FUSE or virtiofs views into `snix-store`.
* `nar-bridge`, a Nix HTTP Binary Cache frontend for `snix-store`.
It allows Nix to interact with `snix-store`, both to substitute from as well
as copy into.
* `snix-boot`, tooling to boot microVMs off of `snix-store` (using virtiofs)
* `snix-cli`, combining various components together to provide a Nix evaluator
CLI and REPL.
* `snixbolt`, a version of the Snix evaluator running in your browser (using
WASM)
{{<callout>}}
Early adopters are encouraged to use (and extend) Snix to solve their
own usecases.
If you're missing certain functionality, or run into bugs, [reach out](),
so we can coordinate how to add/fix it.
{{</callout>}}
Snix is developed as a GPLv3-licensed free software project with source code
available on [our own Forgejo](https://git.snix.dev/) instance.
[NixOS/nix]: https://github.com/NixOS/nix

View file

@ -0,0 +1,14 @@
---
title: "Blog"
description: ""
summary: ""
date: 2023-09-07T16:21:44+02:00
lastmod: 2023-09-07T16:21:44+02:00
draft: false
weight: 50
categories: []
tags: []
contributors: []
pinned: false
homepage: false
---

44
web/content/contact.md Normal file
View file

@ -0,0 +1,44 @@
---
title: "Contact"
slug: contact
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 1000
toc: false
---
## IRC
Discussion on Snix primarily happens on IRC. We're on the [Hackint][hackint] network.
Feel free to join the `#snix` channel, best through your IRC client or via the
[Webchat][snix-webchat] [^1].
### Bridges to Matrix and XMPP
Hackint also bridges to [XMPP][hackint-xmpp] ([link][snix-xmpp]) and
[Matrix][hackint-matrix] ([link][snix-matrix]), though the bridges sometimes
don't work reliably, which is outside our control.
## Issue tracking
We use the [Issue Tracker][issues] on our [Forgejo Instance][code] to track
issues.
If you want to work on some of these issues, it's best to reach out first, to
make sure noone is already working on this and to exchange ideas on how to solve
it.
## Contributing
Please also check out our [Contribution Guide]({{< ref "/docs/guides/contributing" >}}),
which describes how to send changes.
[^1]: please be patient, it might take a while to get a response.
[hackint]: https://hackint.org/
[hackint-matrix]: https://hackint.org/transport/matrix
[hackint-xmpp]: https://hackint.org/transport/xmpp
[snix-xmpp]: xmpp:#snix@irc.hackint.org?join
[snix-matrix]: https://matrix.to/#/#snix:hackint.org
[snix-webchat]: https://chat.hackint.org/?join=snix
[issues]: https://git.snix.dev/snix/snix/issues
[code]: https://git.snix.dev/snix/snix

View file

@ -0,0 +1,11 @@
---
title: "Docs"
description: ""
summary: ""
date: 2023-09-07T16:12:03+02:00
lastmod: 2023-09-07T16:12:03+02:00
draft: false
weight: 999
toc: true
---

View file

@ -0,0 +1,12 @@
---
title: "Components"
description: ""
summary: ""
date: 2023-09-07T16:12:37+02:00
lastmod: 2023-09-07T16:12:37+02:00
draft: false
weight: 30
toc: true
sidebar:
collapsed: false
---

View file

@ -0,0 +1,26 @@
---
title: "Architecture"
slug: architecture
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 31
toc: true
---
Snix is more decoupled than the existing, monolithic Nix implementation.
In practice, we expect to gain several benefits from this, such as:
* Ability to use different builders
* Ability to use different store implementations
* No monopolisation of the implementation, allowing users to replace components
that they are unhappy with (up to and including the language evaluator)
* Less hidden intra-dependencies between tools due to explicit RPC/IPC
boundaries
In addition to many individual backend implementations, Builders and Store
backends also provide a gRPC server and clients, allowing to plug in your own
implementation.

View file

@ -0,0 +1,13 @@
---
title: "Builder"
description: ""
summary: ""
date: 2023-09-07T16:12:37+02:00
lastmod: 2023-09-07T16:12:37+02:00
draft: false
weight: 40
toc: true
sidebar:
collapsed: true
---

View file

@ -0,0 +1,17 @@
---
title: "OCI Builder"
slug: oci
description: ""
summary: ""
date: 2023-09-07T16:12:37+02:00
lastmod: 2023-09-07T16:12:37+02:00
draft: false
weight: 42
toc: true
sidebar:
collapsed: true
---
The OCI builder creates a OCI Runtime specification out of the received
`BuildRequest`, then mounts the specified inputs using snix-castore, and then
invokes `runc`.

View file

@ -0,0 +1,35 @@
---
title: "Protocol"
slug: protocol
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 41
toc: true
---
One goal of the builder protocol is to not be too tied to the Nix implementation
itself, allowing it to be used for other builds/workloads in the future.
This means the builder protocol is versatile enough to express the environment a
Nix build expects, while not being aware of "what any of this means".
For example, it is not aware of how certain environment variables are set in a
nix build, but allows specifying environment variables that should be set.
It's also not aware of what nix store paths are. Instead, it allows:
- specifying a list of paths expected to be produced during the build
- specifying a list of castore root nodes to be present in a specified
`inputs_dir`.
- specifying which paths are write-able during build.
In case all specified paths are produced, and the command specified in
`command_args` succeeds, the build is considered to be successful.
This happens to be sufficient to *also* express how Nix builds works.
Check `build/protos/build.proto` for a detailed description of the individual
fields, and the tests in `glue/src/tvix_build.rs` for some examples.

View file

@ -0,0 +1,45 @@
---
title: "Reference Scanning"
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 45
toc: true
---
At the end of a build, Nix does scan a store path for references to other store
paths (*out of the set of all store paths present during the build*).
It does do this by (only) looking for a list of nixbase32-encoded hashes in
filenames (?), symlink targets and blob contents.
As outlined in the [Builder Protocol]({{< relref "protocol" >}}) page, we
don't want to introduce Nix specifics to the builder protocol, but if we simply
do refscanning on the coordinator side, that side would need to download the
produced inputs and scan them locally.
This is undesireable, as the builder already has all produced
outputs locally, and it'd make more sense for it do do it.
Instead, we want to describe reference scanning in a generic, non-Nix-specific
fashion.
## Proposal
One way to do this is to add an additional field `refscan_needles` to the
`BuildRequest` message.
If this is an non-empty list, all `outputs` are scanned for these.
The `Build` response message would then be extended with an `outputs_needles`
field, containing the same number of elements as the existing `outputs` field,
describing which `refscan_needles` are found for each output.
If there's needles found, they will be a list of indexes into the
`refscan_needles` field specified in the `BuildRequest` field.
For Nix, `refscan_needles` would be populated with the nixbase32 hash parts of
every input store path and output store path. The latter is necessary to scan
for references between multi-output derivations.
This is sufficient to construct the referred store paths in each build output on
the build client.

View file

@ -0,0 +1,98 @@
---
title: "Component Overview"
slug: overview
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 32
toc: true
---
This diagram gives an overview over the different crates in the repository, the
different contained components and the dependencies in between them.
If you scroll further down, you find a textual description of what each component does.
Check the individual documentation pages for more details.
{{< inline-svg src="crate-diagram.svg" width="800px" height="800px" class="svg-inline-custom" >}}
## Castore
`snix-castore` is a content-addressed data storage / syncing engine.
It uses a merkle structure to store filesystem trees, as well as a chunked blob
storage for individual file contents.
It is not Nix-specific.
## Store
`snix-store` is a Nix store implementation using `snix-castore` for the
underlying data structure.
It only stores metadata like store path names, nar hashes, references,
signatures etc, and offloads content storage to `snix-castore`, by storing the
root node describing the contents.
There's also a CLI entrypoint that can be used to host a gRPC server endpoint,
copy into a store, or mount a store as a FUSE/virtiofs.
## Nix-Compat
`nix-compat` is a library providing access to various data formats, protocols
and concepts of Nix.
It does not depend on other Snix crates, making it a low-dependency crate to
include in other (non-snix) projects as well.
Other snix crates are usually the primary consumers and drive new functionality
in there - new formats etc. are usually "factored out into nix-compat".
## Builder
The builder consumes build requests from a client, runs builds and sends
logs/telemetry to the client.
There currently exists an OCI builder, as well as gRPC server adapter and client
implementations, allowing to run the builder both locally or remotely.
## Eval
`snix-eval` is a bytecode interpreter evaluator. It knows about basic Nix
language data structures and semantics, constructs bytecode and provides a VM
executing this bytecode.
It also provides some "core" builtins, though builtins are pluggable - you can
construct an evaluator and bring your own builtins.
It also defines the `EvalIO` trait and provides some very simple implementations
of it, which is how the evaluator does do IO.
## Glue
`snix-glue` provides some more builtins (those interacting with the Builder and
Store mostly).
It allows keeping `snix-eval` relatively simple.
## CLI
`snix-cli` is a REPL interface, constructing an Evaluator and populating it with
most builtins present in Nix. It is our main vehicle to evaluate Nixpkgs and
check for differences.
## Serde
`snix-serde` is a crate allowing (de)-serialisation of Rust data structures
to/from Nix. It allows you to use (a subset of) Nix as a configuration language
in/for your application.
## Tracing
`snix-tracing` contains some common tracing / logging / progress reporting code
that's used in various CLI entrypoints.
## Nar-Bridge
`nar-bridge` provides a Nix HTTP Binary cache server endpoint (read-write),
using `snix-[ca]store` to store the underlying data. It allows you to host your
own binary cache that Nix can talk to.
## Snixbolt
This uses `snix-eval`, providing a WASM bytecode explorer running in your
browser.

View file

@ -0,0 +1,10 @@
---
title: "Guides"
description: ""
summary: ""
date: 2023-09-07T16:06:50+02:00
lastmod: 2023-09-07T16:06:50+02:00
draft: false
weight: 10
toc: true
---

View file

@ -0,0 +1,73 @@
---
title: "Building Snix"
slug: building
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 11
toc: true
---
This document describes how to build the project locally, both for interactive
development as well as referring to it from Nix code (for example, to run one of
its binaries on your machine).
{{<callout>}}
Please check the [Contribution Guide]({{< relref "contributing" >}}) on how to
contribute after following this guide.
{{</callout>}}
### Requirements
- Ensure you have [Direnv][] installed and [hooked into your shell][direnv-inst].
- Ensure you have [Nix][] installed.
### Getting the sources
Snix is hosted in its own Forgejo instance, hosted on [git.snix.dev](https://git.snix.dev/snix/snix), and a
(read-only) mirror on [GitHub](https://github.com/snix-project/snix).
Check out the source code as follows:
```console
$ git clone https://git.snix.dev/snix-project/snix.git
```
### Interactive development
```console
$ direnv allow
$ mg shell //snix:shell
```
This provides all the necessary tools and dependencies to interactively build
the source code, using `cargo build` etc.
### Building only
It is also possible to build the different Snix crates with Nix,
in which you don't need to enter the shell.
From the root of the repository, you can build as follows:
```console
$ nix-build -A snix.cli
```
Alternatively, you can use the `mg` wrapper from anywhere in the repository (requires the direnv setup from above):
```console
$ mg build //snix:cli
```
This uses [crate2nix][] to build each crate dependency individually.
Checkout the [Component Overview]({{< ref "/docs/components/overview" >}})
to learn more about the project structure.
[Direnv]: https://direnv.net
[direnv-inst]: https://direnv.net/docs/installation.html
[Nix]: https://nixos.org/nix/
[mg]: https://code.tvl.fyi/tree/tools/magrathea
[crate2nix]: https://github.com/nix-community/crate2nix/

View file

@ -0,0 +1,127 @@
---
title: "Contributing"
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 12
toc: true
---
You want to start contributing? Nice!
We do use [Gerrit](https://www.gerritcodereview.com) for Code Review.
It allows a more granular review (per-commit granularity rather than PR
granularity), as well as keeping track as how commits change over time.
It greatly simplifies the review process, and leads to overall more high-quality
contributions.
While it might initially look a bit intimidating, you hopefully will spend less
time learning its workflow than writing actual Snix code.
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-mood-wink-2"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 21a9 9 0 1 1 0 -18a9 9 0 0 1 0 18z" /><path d="M9 10h-.01" /><path d="M14.5 15a3.5 3.5 0 0 1 -5 0" /><path d="M15.5 8.5l-1.5 1.5l1.5 1.5" /></svg>
{{<callout>}}
This assumes you have the repo already cloned and the necessary tools installed
as described in [Building Snix]({{< relref "./building" >}}), so make sure you
went through these instructions first.
{{</callout>}}
### Creating a Gerrit account
- Navigate to [our Gerrit instance][snix-gerrit]. Hit the "Sign in" button
(which allows SSO with a GitHub account) [^1]
- In the User settings, paste an SSH public key and hit the "Add New SSH key"
button. [^2]
- Alternatively, you can also create "HTTP Credentials" (though saving the HTTP
password is messy).
### Update your git remote URL
Instead of trying to push to Forgejo, reconfigure your git remote URL to
interact with Gerrit directly.
Replace `$USER` with your `Username` shown in the Gerrit settings.
#### If using SSH authentication:
```console
$ git remote set-url origin "ssh://$USER@cl.snix.dev:29418/snix"
```
#### If using HTTP authentication:
```console
$ git remote set-url origin "https://$USER@cl.snix.dev/a/snix"
```
<!-- TODO: fix replication to include refs/changes/… etc, and ensure it
replicates fast enough, then update to --push only -->
### Install the commit-msg hook
Gerrit uses a `commit-msg` hook to add a `Change-Id: …` field to each commit
message if not present already. This allows Gerrit to identify new revisions /
updates of old commits, and track them as new revisions of the same "CL" [^3].
To install the commit-msg hook, run the following from the repo root:
```console
mkdir -p .git/hooks
curl -Lo .git/hooks/commit-msg https://cl.snix.dev/tools/hooks/commit-msg
chmod +x .git/hooks/commit-msg
```
{{< callout context="tip" title="Did you know?" icon="outline/rocket" >}}
Gerrit refuses receiving commits without these `Change-Id: …` fields.
If you already have some local commits without `Change-Id` field, `git commit
--amend` them after installing the `commit-msg` hook to add them.
{{< /callout >}}
### Push your changes
Do some local changes, and push them to Gerrit as follows:
```console
$ git push origin HEAD:refs/for/canon
```
Gerrit will print links to newly created CLs to your terminal.
If you want to update/edit your CL, simply squash these changes into your local
commit and push again.
### The Gerrit model
If do not have experience with the Gerrit, consider reading the
[<cite>Working with Gerrit: An example</cite>][Gerrit Walkthrough] or
[<cite>Basic Gerrit WalkthroughFor GitHub Users</cite>][gerrit-for-github-users].
Some more tips:
* Assign a reviewer to review your changes.
* React on comments and mark them as resolved once you did.
* Comments are only "Drafts" (stored server-side) until you send them off.
This can be done by the `Reply` button on the top, for example.
* Once CI is green, it's up to the *Author* of the CL to submit, not the
reviewer.
If you want a bot to automatically submit in this case, you can add the
`Autosubmit+1` label.
* Rebase on `origin/canon` regularly. You cannot push if you still have an old
version of a now-submitted CL in your git log.
{{< callout context="tip" title="Did you know?" icon="outline/rocket" >}}
You can immediately assign reviewers and other fields while pushing a
new/updated change, by adding it to the push URL.
```console
$ git push origin HEAD:refs/for/canon%r=alice,cc=bob,l=Autosubmit+1,publish-comments
```
* will set `alice` as a reviewer
* will set `bob` as CC
* adds the `Autosubmit+1` label
* publishes any outstanding draft comments
{{< /callout >}}
[snix-gerrit]: https://cl.snix.dev
[Gerrit walkthrough]: https://gerrit-review.googlesource.com/Documentation/intro-gerrit-walkthrough.html
[gerrit-for-github-users]: https://gerrit.wikimedia.org/r/Documentation/intro-gerrit-walkthrough-github.html
[^1]: more SSO providers to come
[^2]: currently, `ssh-*-sk` keytypes are not supported, so use an `ssh-ed25519` key.
[^3]: abbreviation for "change list", and the review unit in Gerrit.

View file

@ -0,0 +1,37 @@
---
title: "Use as a library"
slug: use-as-library
description: ""
summary: ""
date: 2025-03-14T14:14:35+01:00
lastmod: 2025-03-14T14:14:35+01:00
draft: false
weight: 13
toc: true
---
If you want to use (parts of) Snix in your own project, you can simply refer to
it using cargo and specifying the git sources. `cargo` will pin the exact rev
in `Cargo.lock`. See [The Cargo Book](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories) for details.
We do not publish to crates.io yet, due to the interfaces still being a bit
in flux.
For example, to add `nix-compat`, exposing a lot of Nix data types and formats,
add the following line to your `Cargo.toml`'s `[dependencies]`':
```toml
nix-compat = { git = "https://git.snix.dev/snix/snix.git" }
```
{{<callout>}}
Keep in mind some crates have additional requirements on their environment.
For example, `snix-castore` and `snix-store` need to have access to a `protobuf`
compiler and the proto defintions (setting `PROTO_ROOT` usually).
`tvix-build` wants `TVIX_BUILD_SANDBOX_SHELL` to be set, etc.
Check each crates' `build.rs` scripts for details.
{{</callout>}}

View file

@ -0,0 +1,17 @@
---
title: "Reference"
description: ""
summary: ""
date: 2023-09-07T16:12:37+02:00
lastmod: 2023-09-07T16:12:37+02:00
draft: false
weight: 900
toc: true
sidebar:
collapsed: true
seo:
title: "" # custom title (optional)
description: "" # custom description (recommended)
canonical: "" # custom canonical URL (optional)
robots: "" # custom robot tags (optional)
---

View file

@ -0,0 +1,18 @@
---
title: "Component Overview"
slug: component-overview
description: ""
summary: ""
date: 2023-09-07T16:12:37+02:00
lastmod: 2023-09-07T16:12:37+02:00
draft: false
weight: 900
toc: true
sidebar:
collapsed: true
seo:
title: "" # custom title (optional)
description: "" # custom description (recommended)
canonical: "" # custom canonical URL (optional)
robots: "" # custom robot tags (optional)
---

View file

@ -0,0 +1,21 @@
---
title: "Example Reference"
description: "Reference pages are ideal for outlining how things work in terse and clear terms."
summary: ""
date: 2023-09-07T16:13:18+02:00
lastmod: 2023-09-07T16:13:18+02:00
draft: false
weight: 910
toc: true
seo:
title: "" # custom title (optional)
description: "" # custom description (recommended)
canonical: "" # custom canonical URL (optional)
robots: "" # custom robot tags (optional)
---
Reference pages are ideal for outlining how things work in terse and clear terms. Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what your documenting.
## Further reading
- Read [about reference](https://diataxis.fr/reference/) in the Diátaxis framework

View file

@ -0,0 +1,17 @@
---
title: "Resources"
description: ""
summary: ""
date: 2024-02-27T09:30:56+01:00
lastmod: 2024-02-27T09:30:56+01:00
draft: false
weight: 999
toc: true
seo:
title: "" # custom title (optional)
description: "" # custom description (recommended)
canonical: "" # custom canonical URL (optional)
robots: "" # custom robot tags (optional)
---
Link to valuable, relevant resources.

21
web/default.nix Normal file
View file

@ -0,0 +1,21 @@
{ pkgs, depot, ... }:
{
shell = pkgs.mkShell {
name = "tvix-website";
packages = [
pkgs.nodejs
pkgs.hugo
];
};
website = depot.third_party.npmlock2nix.v2.build {
pname = "snix-website";
version = "0.0.0";
src = depot.third_party.gitignoreSource ./.;
installPhase = "cp -r public/. $out";
buildCommands = [ "PATH=\"$PATH:${pkgs.hugo}/bin\" npm run build" ];
};
}

63
web/layouts/index.html Normal file
View file

@ -0,0 +1,63 @@
{{ define "main" }}
<section class="section container-fluid mt-n3 pb-3">
<div class="row justify-content-center">
<div class="col-lg-12 text-center">
<h1>{{ .Title }}</h1>
</div>
<div class="col-lg-9 col-xl-8 text-center">
<p class="lead">{{ .Params.lead | safeHTML }}</p>
<a class="btn btn-primary btn-cta rounded-pill btn-lg my-3" href="/about" role="button">Learn More</a>
{{ .Content }}
</div>
</div>
</section>
{{ end }}
{{ define "sidebar-prefooter" }}
{{ if site.Params.doks.backgroundDots -}}
<div class="d-flex justify-content-start">
<div class="bg-dots"></div>
</div>
{{ end -}}
{{ if eq $.Site.Language.LanguageName "English" }}
<section class="section section-md section-features">
<div class="container">
<div class="row justify-content-center text-center">
<div class="col-lg-5">
<h2 class="h4">Composable and Modular by Design</h2>
<p>Snix is architected with a focus on composability. Different components representing different aspects of Nix can be combined and extended freely, allowing it to be tailored to your usecase.</p>
</div>
<div class="col-lg-5">
<h2 class="h4">Library-first Approach</h2>
<p>Designed to be embedded in your project, it opens up the possibility to interact with Nix expressions and concepts more natively than conventional Nix CLI-based tools.</p>
</div>
<div class="col-lg-5">
<h2 class="h4">Robust Unit Test Coverage</h2>
<p>Snix has a strong commitment to reliability and compatibility with Nix' behaviour, resulting in an extensive test suite, documentation and regression testing.</p>
</div>
<div class="col-lg-5">
<h2 class="h4">Content-addressed Storage model</h2>
<p>With its own content-addressed storage engine, Snix can store and exchange store path contents in a much more granular fashion, while providing great deduplication, consistency and integrity across build artifacts and dependencies.</p>
</div>
<div class="col-lg-5">
<h2 class="h4">Interoperability with Nix</h2>
<p>While potentially doing thing differently underneath, it provides a "Nix-compatible surface". This results in nixpkgs compatibility, allowing to produce the same build expressions as Nix, bit-by-bit, and interoperability with existing Nix binary caches.</p>
</div>
</div>
</div>
</section>
{{ end }}
{{ end }}
{{ define "sidebar-footer" }}
{{ if site.Params.doks.sectionFooter -}}
<section class="section section-md container-fluid bg-light">
<div class="row justify-content-center text-center">
<div class="col-lg-7">
<h2 class="mt-2">Start building with Doks today</h2>
<a class="btn btn-primary rounded-pill px-4 my-2" href="/docs/{{ if site.Params.doks.docsVersioning }}{{ site.Params.doks.docsVersion }}/{{ end }}prologue/introduction/" role="button">{{ i18n "get-started" }}</a>
</div>
</div>
</section>
{{ end -}}
{{ end }}

View file

@ -0,0 +1,13 @@
{{/* Put your custom <script></script> tags here */}}
{{/* EXAMPLE - only load script for production
{{ if eq (hugo.Environment) "production" -}}
{{ partial "footer/esbuild" (dict "src" "js/instantpage.js" "load" "async" "transpile" false) -}}
{{ end -}}
*/}}
{{/* EXAMPLE - only load script for a page type e.g. contact or gallery
{{ if eq .Type "gallery" -}}
{{ partial "footer/esbuild" (dict "src" "js/gallery.js" "load" "async" "transpile" false) -}}
{{ end -}}
*/}}

View file

@ -0,0 +1 @@
<!-- Custom head -->

View file

@ -0,0 +1 @@
<!-- Insert scripts NOT needed by stylesheets here -->

49
web/netlify.toml Normal file
View file

@ -0,0 +1,49 @@
[build]
publish = "public"
functions = "functions"
[build.environment]
NODE_VERSION = "20.11.0"
NPM_VERSION = "10.2.4"
HUGO_VERSION = "0.125.1"
[context.production]
command = "npm run build"
[context.deploy-preview]
command = "npm run build"
[context.branch-deploy]
command = "npm run build"
[context.next]
command = "npm run build"
[context.next.environment]
HUGO_ENV = "next"
[dev]
framework = "#custom"
command = "npm run dev"
targetPort = 1313
port = 8888
publish = "public"
autoLaunch = false
# Redirects and rewrites — https://docs.netlify.com/routing/redirects/#syntax-for-the-netlify-configuration-file
# Custom headers — https://docs.netlify.com/routing/headers/#syntax-for-the-netlify-configuration-file
[[headers]]
for = "/*"
[headers.values]
Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options = "nosniff"
X-XSS-Protection = "1; mode=block"
Content-Security-Policy = "default-src 'self'; manifest-src 'self'; connect-src 'self'; font-src 'self'; img-src 'self' https://avatars.githubusercontent.com data:; script-src 'self' 'nonce-dXNlcj0iaGVsbG8iLGRvbWFpbj0iaGVua3ZlcmxpbmRlLmNvbSIsZG9jdW1lbnQud3JpdGUodXNlcisiQCIrZG9tYWluKTs=' 'sha256-aWZ3y/RxbBYKHXH0z8+8ljrHG1mSBvyzSfxSMjBSaXk='; style-src 'self'"
X-Frame-Options = "SAMEORIGIN"
Referrer-Policy = "strict-origin"
Permissions-Policy = "geolocation=(self), microphone=(), camera=()"
Cache-Control= '''
public,
max-age=31536000'''
Access-Control-Allow-Origin = "*"

4679
web/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

28
web/package.json Normal file
View file

@ -0,0 +1,28 @@
{
"name": "snix-website",
"version": "0.0.0",
"description": "The Snix Website",
"author": "The Snix Project",
"scripts": {
"create": "hugo new",
"dev": "hugo server --disableFastRender --noHTTPCache",
"format": "prettier **/** -w -c",
"build": "hugo --minify --gc",
"preview": "vite preview --outDir public"
},
"dependencies": {
"@thulite/doks-core": "^1.8.0",
"@thulite/images": "^3.3.0",
"@thulite/inline-svg": "^1.1.0",
"@thulite/seo": "^2.4.1",
"@tabler/icons": "^3.12.0",
"thulite": "^2.5.0"
},
"devDependencies": {
"prettier": "^3.3.3",
"vite": "^5.4.2"
},
"engines": {
"node": ">=20.11.0"
}
}

0
web/static/.gitkeep Normal file
View file

View file

@ -0,0 +1,25 @@
---
title: "Example Post"
description: "Just an example post."
summary: "You can use blog posts for announcing product updates and features."
date: 2023-09-07T16:27:22+02:00
lastmod: 2023-09-07T16:27:22+02:00
draft: true
weight: 50
categories: []
tags: []
contributors: []
pinned: false
homepage: false
seo:
title: "" # custom title (optional)
description: "" # custom description (recommended)
canonical: "" # custom canonical URL (optional)
robots: "" # custom robot tags (optional)
---
Well-thought-through product announcements will help increase feature awareness and engage users with new functionality. Just like [sharing your public roadmap](https://canny.io/blog/should-you-have-a-public-roadmap/), it's also a great way to let potential customers see that you're constantly improving.
## Further reading
- Read [How to announce product updates and features](https://canny.io/blog/announce-product-updates-features/)