diff --git a/docker-compose.yml b/docker-compose.yml
index bbef596..f542870 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -10,4 +10,4 @@ services:
ports:
- "2101:3000"
volumes:
- - ./docs.vxserver.dev:/app
+ - ./docs.vxserver.dev:/app
diff --git a/docs.vxserver.dev/Dockerfile b/docs.vxserver.dev/Dockerfile
deleted file mode 100644
index a64443c..0000000
--- a/docs.vxserver.dev/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM fes:latest
-
-COPY . /app
-
-WORKDIR /app
-
-CMD ["fes", "-p", "2101", "run", "/app"]
diff --git a/fsd.vxserver.dev/Dockerfile b/fsd.vxserver.dev/Dockerfile
deleted file mode 100644
index c0168a8..0000000
--- a/fsd.vxserver.dev/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM fes:latest
-
-COPY . /app
-
-WORKDIR /app
-
-CMD ["fes", "-p", "2100", "run", "/app"]
diff --git a/fsd.vxserver.dev/archive/fes-0.1.0.tar.gz b/fsd.vxserver.dev/archive/fes/fes-0.1.0.tar.gz
similarity index 100%
rename from fsd.vxserver.dev/archive/fes-0.1.0.tar.gz
rename to fsd.vxserver.dev/archive/fes/fes-0.1.0.tar.gz
diff --git a/fsd.vxserver.dev/archive/fes-0.2.0.tar.gz b/fsd.vxserver.dev/archive/fes/fes-0.2.0.tar.gz
similarity index 100%
rename from fsd.vxserver.dev/archive/fes-0.2.0.tar.gz
rename to fsd.vxserver.dev/archive/fes/fes-0.2.0.tar.gz
diff --git a/fsd.vxserver.dev/archive/tools/yait-0.3.tar.gz b/fsd.vxserver.dev/archive/tools/yait-0.3.tar.gz
new file mode 100644
index 0000000..6f0ff65
Binary files /dev/null and b/fsd.vxserver.dev/archive/tools/yait-0.3.tar.gz differ
diff --git a/fsd.vxserver.dev/archive/yait-1.0.tar.gz b/fsd.vxserver.dev/archive/yait-1.0.tar.gz
deleted file mode 100644
index 9501400..0000000
Binary files a/fsd.vxserver.dev/archive/yait-1.0.tar.gz and /dev/null differ
diff --git a/fsd.vxserver.dev/article/Versioning.md b/fsd.vxserver.dev/article/Versioning.md
deleted file mode 100644
index fef6601..0000000
--- a/fsd.vxserver.dev/article/Versioning.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Versioning
-
-### Summary
-
-Given a version number MAJOR.MINOR.PATCH, increment the:
-
-* MAJOR version when you make incompatible API changes
-* MINOR version when you add functionality in a backward compatible manner
-* PATCH version when you make backward compatible bug fixes
-
-Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
-
-***EXCEPT*** when the MAJOR version is zero, then MINOR versions are treated the same as MAJOR versions.
-
-### Semantic Versioning Specification (SemVer)
-
-The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
-
-Software using Semantic Versioning MUST declare a public API. This API could be declared in the code itself or exist strictly in documentation. However it is done, it SHOULD be precise and comprehensive.
-
-A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes. X is the major version, Y is the minor version, and Z is the patch version. Each element MUST increase numerically. For instance: 1.9.0 -> 1.10.0 -> 1.11.0.
-
-Once a versioned package has been released, the contents of that version MUST NOT be modified. Any modifications MUST be released as a new version.
-
-Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.
-
-Version 1.0.0 defines the public API. The way in which the version number is incremented after this release is dependent on this public API and how it changes.
-
-Patch version Z (x.y.Z | x > 0) MUST be incremented if only backward compatible bug fixes are introduced. A bug fix is defined as an internal change that fixes incorrect behavior.
-
-Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backward compatible functionality is introduced to the public API. It MUST be incremented if any public API functionality is marked as deprecated. It MAY be incremented if substantial new functionality or improvements are introduced within the private code. It MAY include patch level changes. Patch version MUST be reset to 0 when minor version is incremented.
-
-Major version X (X.y.z | X > 0) MUST be incremented if any backward incompatible changes are introduced to the public API. It MAY also include minor and patch level changes. Patch and minor versions MUST be reset to 0 when major version is incremented.
-
-A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
-
-Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.
-
-Precedence refers to how versions are compared to each other when ordered.
-
-Precedence MUST be calculated by separating the version into major, minor, patch and pre-release identifiers in that order (Build metadata does not figure into precedence).
-
-Precedence is determined by the first difference when comparing each of these identifiers from left to right as follows: Major, minor, and patch versions are always compared numerically.
-
-Example: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1.
-
-When major, minor, and patch are equal, a pre-release version has lower precedence than a normal version:
-
-Example: 1.0.0-alpha < 1.0.0.
-
-Precedence for two pre-release versions with the same major, minor, and patch version MUST be determined by comparing each dot separated identifier from left to right until a difference is found as follows:
-
-Identifiers consisting of only digits are compared numerically.
-
-Identifiers with letters or hyphens are compared lexically in ASCII sort order.
-
-Numeric identifiers always have lower precedence than non-numeric identifiers.
-
-A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.
-
-Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.
-
-### Attributions
-
-The summary of Semantic Versioning 2.0.0 is based on the offical specification at [semver.org](https://semver.org/spec/v2.0.0.html) and is published under a [Creative Commons -- CC BY 3.0](https://creativecommons.org/licenses/by/3.0/) license.
-
-The specification of Semantic Versioning 2.0.0 is based on the offical specification at [semver.org](https://semver.org/spec/v2.0.0.html) and is published under a [Creative Commons -- CC BY 3.0](https://creativecommons.org/licenses/by/3.0/) license.
diff --git a/fsd.vxserver.dev/include/global.lua b/fsd.vxserver.dev/include/global.lua
new file mode 100644
index 0000000..97d03ad
--- /dev/null
+++ b/fsd.vxserver.dev/include/global.lua
@@ -0,0 +1,34 @@
+local global = {}
+
+global.start = function(fes, site, title)
+ if title and title ~= "" then
+ title = title .. " - "
+ else
+ title = ""
+ end
+ site.title = title .. "Free Software Distributions "
+ site.copyright = fes.util.copyright("https://fsdproject.org", "fSD")
+ site.favicon = "/static/favicon.ico"
+ site:banner(fes.util.cc {
+ fes.std.center(fes.std.ha("/", fes.std.h1("Free Software Distributions"))),
+ fes.std.center(fes.util.cc {
+ fes.std.nav("/about", "About"),
+ fes.std.nav("/community", "Community"),
+ fes.std.nav("/releases", "Releases"),
+ fes.std.nav("/hacking", "Hacking"),
+ })
+ })
+end
+
+global.finish = function(fes, site)
+ site:note(fes.util.cc {
+ fes.std.h2("Other resources"),
+ fes.std.tl({
+ fes.std.external("https://git.vxserver.dev", "Git Trees"),
+ fes.std.external("https://docs.fsdproject.org", "Documentation"),
+ }),
+
+ })
+end
+
+return global
diff --git a/fsd.vxserver.dev/include/header.lua b/fsd.vxserver.dev/include/header.lua
deleted file mode 100644
index d67a981..0000000
--- a/fsd.vxserver.dev/include/header.lua
+++ /dev/null
@@ -1,15 +0,0 @@
-local header = {}
-
-header.render = function(std)
- return table.concat({
- std.center(std.ha("/", std.h1("Free Software Distributions"))),
- std.center(table.concat({
- std.nav("/about", "About"),
- std.nav("/faq", "FAQ"),
- std.nav("/release", "Releases"),
- std.nav("/article", "Articles"),
- }))
- })
-end
-
-return header
diff --git a/fsd.vxserver.dev/www/about.lua b/fsd.vxserver.dev/www/about.lua
index ebbc2c4..99b3d8c 100644
--- a/fsd.vxserver.dev/www/about.lua
+++ b/fsd.vxserver.dev/www/about.lua
@@ -4,13 +4,7 @@ local u = fes.util
local site = fes.fes()
-local title = "Free Software Distributions"
-
-site.title = title .. "- About"
-site.copyright = u.copyright("https://git.vxserver.dev/fSD", "fSD")
-site.favicon = "/static/favicon.ico"
-
-site:banner(fes.app.header.render(std))
+fes.app.global.start(fes, site, "About")
site:note(u.cc({
std.h2("Free Software Distributions"),
@@ -50,6 +44,6 @@ site:note(u.cc({
std.p("Except where otherwise stated, content on this site is copyright (C) 2025 by fSD and is made avaliable to you under the " .. fes.std.a("https://creativecommons.org/licenses/by-nc/4.0/", "Creative Commons Attribtuion-NonCommerical 4.0 International"))
}))
-site:note(fes.app.footer.render(std))
+fes.app.global.finish(fes, site)
return site
diff --git a/fsd.vxserver.dev/www/article.lua b/fsd.vxserver.dev/www/article.lua
deleted file mode 100644
index b8475b7..0000000
--- a/fsd.vxserver.dev/www/article.lua
+++ /dev/null
@@ -1,81 +0,0 @@
-local fes = require("fes")
-local std = fes.std
-local u = fes.util
-
-local site = fes.fes()
-
-local title = "Free Software Distributions"
-
-site.title = title .. " - Site articles"
-site.copyright = u.copyright("[https://git.vxserver.dev/fSD](https://git.vxserver.dev/fSD)", "fSD")
-site.favicon = "/static/favicon.ico"
-site:banner(fes.app.header.render(std))
-
-local function url_encode(s)
- if not s then return "" end
- s = s:gsub("([^%w%-_.~])", function(c) return string.format("%%%02X", string.byte(c)) end)
- return s
-end
-
-local function read_file(path)
- local f = io.open(path, "r")
- if not f then return nil end
- local data = f:read("*a")
- f:close()
- return data
-end
-
-local dir = "article"
-local files = u.ls(dir)
-
-local params = fes.bus.params or {}
-local article = params.article
-if type(article) == "table" then
- article = article[1]
-end
-
-if article then
- local candidates = { article, article .. ".txt", article .. ".md", article .. ".html" }
- local body
- for _, c in ipairs(candidates) do
- local p = dir .. "/" .. c
- body = read_file(p)
- if body then break end
- end
- site.title = article
- if body then
- site:g("")
- site:g(fes.markdown_to_html(body))
- else
- site:note(u.cc {
- std.h1(article),
- std.p("article not found"),
- })
- end
- site:note(fes.app.footer.render(std))
- return site
-end
-
-local articles = {}
-local n = 0
-for _, v in ipairs(files) do
- local display = v:gsub("%.[^%.]+$", "")
- local link = "/article?article=" .. url_encode(display)
- table.insert(articles, std.a(link, display))
- n = n + 1
-end
-
-table.sort(articles, function (x, y)
- return x > y
-end)
-
-if n > 0 then
- site:h1("Articles")
- site:note(std.ul(articles))
-else
- site:h1("No articles")
-end
-
-site:note(fes.app.footer.render(std))
-
-return site
diff --git a/fsd.vxserver.dev/www/community.lua b/fsd.vxserver.dev/www/community.lua
new file mode 100644
index 0000000..81e2db9
--- /dev/null
+++ b/fsd.vxserver.dev/www/community.lua
@@ -0,0 +1,21 @@
+local fes = require("fes")
+
+local std = fes.std
+
+local site = fes.fes()
+
+fes.app.global.start(fes, site, "Community")
+
+site:h1("Community")
+
+site:h2("Mailing lists")
+site:ul {
+ std.element("code", nil, "hackers@fsdproject.org") .. " - " .. std.strong("only for patches") .. "Commit messages and diffs for all fSD projects can be sent here for review.",
+}
+
+site:h2("Discord")
+site:p("Offical " .. std.a("https://discord.gg/A7QBvK5jhd", "discord") .. " server of the fSD project:")
+
+fes.app.global.finish(fes, site)
+
+return site
diff --git a/fsd.vxserver.dev/www/faq.lua b/fsd.vxserver.dev/www/faq.lua
deleted file mode 100644
index 36248b7..0000000
--- a/fsd.vxserver.dev/www/faq.lua
+++ /dev/null
@@ -1,28 +0,0 @@
-local fes = require("fes")
-local std = fes.std
-local u = fes.util
-
-local site = fes.fes()
-
-local title = "Free Software Distributions"
-
-site.title = title .. "- FAQ"
-site.copyright = u.copyright("https://git.vxserver.dev/fSD", "fSD")
-site.favicon = "/static/favicon.ico"
-
-site:banner(fes.app.header.render(std))
-
-site:note(u.cc({
- std.h1("Frequently Asked Questions"),
- std.p("Welcome to the world of fSD, come here ye before thou ask thy stupid questions."),
- std.h2("Why is it called fSD?"),
- std.p([[
- The name "Free Software Distributions" is dervided from exactly what we do, we distribute free software.
- This name stems from the Berkeley Software Distribution (BSD) specifically the Software Distribution part.
- ]]),
- std.p('It is worth pointing out that the word "free" is being used in two ways here: one meaning "at no cost" and the other meaning "do whatever you like".'),
-}))
-
-site:note(fes.app.footer.render(std))
-
-return site
diff --git a/fsd.vxserver.dev/www/hacking.lua b/fsd.vxserver.dev/www/hacking.lua
new file mode 100644
index 0000000..fafce86
--- /dev/null
+++ b/fsd.vxserver.dev/www/hacking.lua
@@ -0,0 +1,45 @@
+local fes = require("fes")
+
+local site = fes.fes()
+
+fes.app.global.start(fes, site)
+
+site:h1("Hacking")
+
+site:h2("Copying/license")
+site:p("We only accept contributions from individuals, not corporate entities. See the project LICENSE or equivalent file you're contributing to.")
+
+site:h2("Patches")
+site:p("Please provide a clear and concise \"commit message\" for your patches.")
+
+site:h3("patch filename format")
+site:p("The expected format for patches is:")
+site:p("For git revisions:")
+site:code([[
+toolname-patchname-YYYDDMM-SHORTHASH.patch
+yait-updatething-19300101-1234abc.patch
+]])
+site:p([[
+The YYYYMMDD date should correspond to the last time the patch has been
+modified. The SHORTHASH here is the seven chars git commit short hash
+corresponding to the last commit of the tool on which the patch can be applied
+correctly and is working with. You can get it by taking the first seven chars
+of the full hash or for example:
+]])
+site:code("git rev-parse --short (with commit-id: HEAD, commit hash, etc.)")
+
+site:h2("patch generation")
+site:p("For git:")
+site:code([[
+git format-patch --stdout origin/main >toolname-patchname-YYYYDDMM-SHORTHASH.patch
+]])
+
+site:h2("patch program")
+site:p("For git users:")
+site:code([[
+git apply toolname-patchname-YYYYDDMM-SHORTHASH.patch
+]])
+
+fes.app.global.finish(fes, site)
+
+return site
diff --git a/fsd.vxserver.dev/www/index.lua b/fsd.vxserver.dev/www/index.lua
index 12904ff..daac631 100644
--- a/fsd.vxserver.dev/www/index.lua
+++ b/fsd.vxserver.dev/www/index.lua
@@ -1,59 +1,17 @@
local fes = require("fes")
+
local std = fes.std
local u = fes.util
local site = fes.fes()
-local title = "Free Software Distributions"
+fes.app.global.start(fes, site)
-site.title = title
-site.copyright = u.copyright("https://git.vxserver.dev/fSD", "fSD")
-site.favicon = "/static/favicon.ico"
+site:h1("Home")
+site:p(u.cc {
+ std.p("Welcome to the " .. std.em("Free Software Distributions Project") .. ". This place is home to various free software."),
+})
-site:banner(fes.app.header.render(std))
-
-site:g(fes.markdown_to_html([[
-News
-===
-2026-03-01
-----------
-[fes-0.3.0](/releases/fes) released: [download](/archive/fes/fes-0.3.0.tar.gz)
-
-2026-03-01
-----------
-[fes-0.2.1](/releases/fes) released: [download](/archive/fes/fes-0.2.1.tar.gz)
-
-2026-03-01
-----------
-[fes-0.2.0](/releases/fes) released: [download](/archive/fes/fes-0.2.0.tar.gz)
-
-2026-01-02
-----------
-Some changes were made to this site.
-[sites](https://git.vxserver.dev/fSD/sites)
-* Update fes's release page
-* Update release archive structure
-* Add way to get to archive fromr release
-
-2026-01-01
-----------
-[fes-0.1.0](/releases/fes) released: [download](/archive/fes/fes-0.1.0.tar.gz)
-
-2025-31-12
-----------
-Some changes were made to this site.
-[sites](https://git.vxserver.dev/fSD/sites)
-* New article
-* Update release pages
-
-2025-17-12
-----------
-Some changes were made to this site.
-[sites](https://git.vxserver.dev/fSD/sites)
-* General improvments and fixes
-* Moving the news page to here.
-]]))
-
-site:note(fes.app.footer.render(std))
+fes.app.global.finish(fes, site)
return site
diff --git a/fsd.vxserver.dev/www/release.lua b/fsd.vxserver.dev/www/releases.lua
similarity index 60%
rename from fsd.vxserver.dev/www/release.lua
rename to fsd.vxserver.dev/www/releases.lua
index d47584a..0967f6b 100644
--- a/fsd.vxserver.dev/www/release.lua
+++ b/fsd.vxserver.dev/www/releases.lua
@@ -1,16 +1,9 @@
local fes = require("fes")
local std = fes.std
-local u = fes.util
local site = fes.fes()
-local title = "Free Software Distributions"
-
-site.title = title .. " - Release"
-site.copyright = u.copyright("https://git.vxserver.dev/fSD", "fSD")
-site.favicon = "/static/favicon.ico"
-
-site:banner(fes.app.header.render(std))
+fes.app.global.start(fes, site, "Releases")
local pkgs = {
"yait",
@@ -27,6 +20,6 @@ end
site:p("This directory contains the tools which have been created or maintained by the Free Software Distributions Project.")
site:tl(directory_packages)
-site:note(fes.app.footer.render(std))
+fes.app.global.finish(fes, site)
return site
diff --git a/fsd.vxserver.dev/www/releases/fes.lua b/fsd.vxserver.dev/www/releases/fes.lua
index ac93e9d..3b8cd0e 100644
--- a/fsd.vxserver.dev/www/releases/fes.lua
+++ b/fsd.vxserver.dev/www/releases/fes.lua
@@ -4,11 +4,7 @@ local u = fes.util
local site = fes.fes()
-site.title = "fes - Free Easy Site"
-site.copyright = u.copyright("https://git.vxserver.dev/fSD", "fSD")
-site.favicon = "/static/favicon.ico"
-
-site:banner(fes.app.header.render(std))
+fes.app.global.start(fes, site, "fes")
site:h2("Fes")
site:muted("fes is a lightweight, static, and optionated microframework.")
@@ -24,7 +20,7 @@ site:p("You can deploy websites using the " ..
std.external("https://git.vxserver.dev/fSD/-/packages/container/fes/latest", "docker") .. " image:")
site:code("docker pull git.vxserver.dev/fsd/fes:latest")
-local tars = u.ls("archive")
+local tars = u.ls("archive/fes")
local function parseVersion(pkg)
local version = pkg:match("-(.+)$")
@@ -72,6 +68,6 @@ site:ul {
}
-site:note(fes.app.footer.render(std))
+fes.app.global.finish(fes, site)
return site
diff --git a/fsd.vxserver.dev/www/releases/yait.lua b/fsd.vxserver.dev/www/releases/yait.lua
index 5227ef1..42fb6f8 100644
--- a/fsd.vxserver.dev/www/releases/yait.lua
+++ b/fsd.vxserver.dev/www/releases/yait.lua
@@ -4,11 +4,7 @@ local u = fes.util
local site = fes.fes()
-site.title = "yait - Yet Another Init Tool"
-site.copyright = u.copyright("https://git.vxserver.dev/fSD", "fSD")
-site.favicon = "/static/favicon.ico"
-
-site:banner(fes.app.header.render(std))
+fes.app.global.start(fes, site, "yait")
site:h2("Yait")
site:muted("Yait is a highly opinionated C and SH project generator.")
@@ -20,9 +16,9 @@ site:code("git clone https://git.vxserver.dev/fSD/yait")
site:h2("Download")
site:ul {
std.p(std.a("/archive/yait/yait-1.0.tar.gz", "yait-1.0") .. " (2025-31-12)"),
- std.a("/archive/yait", "Looking for specific version?")
+ std.a("/archive/tools", "Looking for specific version?")
}
-site:note(fes.app.footer.render(std))
+fes.app.global.finish(fes, site)
return site