diff --git a/mkdocs/.cache/plugin/social/0bb26570b1971d8fad2883fbe816588f.png b/mkdocs/.cache/plugin/social/0bb26570b1971d8fad2883fbe816588f.png
new file mode 100644
index 0000000..9678544
Binary files /dev/null and b/mkdocs/.cache/plugin/social/0bb26570b1971d8fad2883fbe816588f.png differ
diff --git a/mkdocs/.cache/plugin/social/10a5546a448a8a0b16de3eb978f8a68f.png b/mkdocs/.cache/plugin/social/10a5546a448a8a0b16de3eb978f8a68f.png
new file mode 100644
index 0000000..bfb5e64
Binary files /dev/null and b/mkdocs/.cache/plugin/social/10a5546a448a8a0b16de3eb978f8a68f.png differ
diff --git a/mkdocs/.cache/plugin/social/29555bf533763ae8eb2a49b8d7625632.png b/mkdocs/.cache/plugin/social/29555bf533763ae8eb2a49b8d7625632.png
new file mode 100644
index 0000000..332440b
Binary files /dev/null and b/mkdocs/.cache/plugin/social/29555bf533763ae8eb2a49b8d7625632.png differ
diff --git a/mkdocs/.cache/plugin/social/33611a3592836152c371702e7667700b.png b/mkdocs/.cache/plugin/social/33611a3592836152c371702e7667700b.png
new file mode 100644
index 0000000..4af557d
Binary files /dev/null and b/mkdocs/.cache/plugin/social/33611a3592836152c371702e7667700b.png differ
diff --git a/mkdocs/.cache/plugin/social/5de16fced5aba77a2bd09132eb5fda0d.png b/mkdocs/.cache/plugin/social/5de16fced5aba77a2bd09132eb5fda0d.png
new file mode 100644
index 0000000..1dfe0d5
Binary files /dev/null and b/mkdocs/.cache/plugin/social/5de16fced5aba77a2bd09132eb5fda0d.png differ
diff --git a/mkdocs/.cache/plugin/social/6721c84d438859307b9b7082ea394f26.png b/mkdocs/.cache/plugin/social/6721c84d438859307b9b7082ea394f26.png
new file mode 100644
index 0000000..9216ea5
Binary files /dev/null and b/mkdocs/.cache/plugin/social/6721c84d438859307b9b7082ea394f26.png differ
diff --git a/mkdocs/.cache/plugin/social/74ba9b753bb76229ba95a19f832f65f7.png b/mkdocs/.cache/plugin/social/74ba9b753bb76229ba95a19f832f65f7.png
new file mode 100644
index 0000000..285cbbd
Binary files /dev/null and b/mkdocs/.cache/plugin/social/74ba9b753bb76229ba95a19f832f65f7.png differ
diff --git a/mkdocs/.cache/plugin/social/7e31098fbf39b20bb38d3f1e683c5e05.png b/mkdocs/.cache/plugin/social/7e31098fbf39b20bb38d3f1e683c5e05.png
new file mode 100644
index 0000000..44beaa9
Binary files /dev/null and b/mkdocs/.cache/plugin/social/7e31098fbf39b20bb38d3f1e683c5e05.png differ
diff --git a/mkdocs/.cache/plugin/social/7e8c377901c50a398db9288363ecd8be.png b/mkdocs/.cache/plugin/social/7e8c377901c50a398db9288363ecd8be.png
new file mode 100644
index 0000000..439136b
Binary files /dev/null and b/mkdocs/.cache/plugin/social/7e8c377901c50a398db9288363ecd8be.png differ
diff --git a/mkdocs/.cache/plugin/social/cffa905c80eff784b883e05e89cc8e46.png b/mkdocs/.cache/plugin/social/cffa905c80eff784b883e05e89cc8e46.png
new file mode 100644
index 0000000..eebe859
Binary files /dev/null and b/mkdocs/.cache/plugin/social/cffa905c80eff784b883e05e89cc8e46.png differ
diff --git a/mkdocs/.cache/plugin/social/e323ce43d557f92ed3a43f83a2c99c85.png b/mkdocs/.cache/plugin/social/e323ce43d557f92ed3a43f83a2c99c85.png
new file mode 100644
index 0000000..7a0819e
Binary files /dev/null and b/mkdocs/.cache/plugin/social/e323ce43d557f92ed3a43f83a2c99c85.png differ
diff --git a/mkdocs/.cache/plugin/social/e66117191f6f452004c243553237c2ee.png b/mkdocs/.cache/plugin/social/e66117191f6f452004c243553237c2ee.png
new file mode 100644
index 0000000..fb5de1a
Binary files /dev/null and b/mkdocs/.cache/plugin/social/e66117191f6f452004c243553237c2ee.png differ
diff --git a/mkdocs/.cache/plugin/social/f3cbac41242a5f4062687e6ebf8b69a9.png b/mkdocs/.cache/plugin/social/f3cbac41242a5f4062687e6ebf8b69a9.png
new file mode 100644
index 0000000..a5d2f7c
Binary files /dev/null and b/mkdocs/.cache/plugin/social/f3cbac41242a5f4062687e6ebf8b69a9.png differ
diff --git a/mkdocs/.cache/plugin/social/fbde04cce7c404b3322bd153c6e57a38.png b/mkdocs/.cache/plugin/social/fbde04cce7c404b3322bd153c6e57a38.png
new file mode 100644
index 0000000..914f854
Binary files /dev/null and b/mkdocs/.cache/plugin/social/fbde04cce7c404b3322bd153c6e57a38.png differ
diff --git a/mkdocs/.cache/plugin/social/fd3474c8ee7ae0ad5529def83d0c8857.png b/mkdocs/.cache/plugin/social/fd3474c8ee7ae0ad5529def83d0c8857.png
new file mode 100644
index 0000000..11839b0
Binary files /dev/null and b/mkdocs/.cache/plugin/social/fd3474c8ee7ae0ad5529def83d0c8857.png differ
diff --git a/mkdocs/core b/mkdocs/core
new file mode 100644
index 0000000..ade3959
Binary files /dev/null and b/mkdocs/core differ
diff --git a/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json b/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json
new file mode 100644
index 0000000..bce32ea
--- /dev/null
+++ b/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json
@@ -0,0 +1,16 @@
+{
+ "full_name": "admin/changemaker.lite",
+ "name": "changemaker.lite",
+ "description": "Changemaker-lite is the current active development branch of Changemaker, focused on streamlining core services. These improvements will be merged into the master branch once ready.",
+ "html_url": "https://gitea.bnkops.com/admin/changemaker.lite",
+ "language": "HTML",
+ "stars_count": 0,
+ "forks_count": 0,
+ "open_issues_count": 0,
+ "updated_at": "2025-06-30T10:01:47-06:00",
+ "created_at": "2025-05-28T14:54:59-06:00",
+ "clone_url": "https://gitea.bnkops.com/admin/changemaker.lite.git",
+ "ssh_url": "git@gitea.bnkops.com:admin/changemaker.lite.git",
+ "default_branch": "main",
+ "last_build_update": "2025-06-30T10:01:47-06:00"
+}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/coder-code-server.json b/mkdocs/docs/assets/repo-data/coder-code-server.json
new file mode 100644
index 0000000..13512fa
--- /dev/null
+++ b/mkdocs/docs/assets/repo-data/coder-code-server.json
@@ -0,0 +1,16 @@
+{
+ "full_name": "coder/code-server",
+ "name": "code-server",
+ "description": "VS Code in the browser",
+ "html_url": "https://github.com/coder/code-server",
+ "language": "TypeScript",
+ "stars_count": 72491,
+ "forks_count": 6060,
+ "open_issues_count": 132,
+ "updated_at": "2025-06-30T21:31:29Z",
+ "created_at": "2019-02-27T16:50:41Z",
+ "clone_url": "https://github.com/coder/code-server.git",
+ "ssh_url": "git@github.com:coder/code-server.git",
+ "default_branch": "main",
+ "last_build_update": "2025-06-25T21:18:52Z"
+}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/gethomepage-homepage.json b/mkdocs/docs/assets/repo-data/gethomepage-homepage.json
new file mode 100644
index 0000000..6476e32
--- /dev/null
+++ b/mkdocs/docs/assets/repo-data/gethomepage-homepage.json
@@ -0,0 +1,16 @@
+{
+ "full_name": "gethomepage/homepage",
+ "name": "homepage",
+ "description": "A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.",
+ "html_url": "https://github.com/gethomepage/homepage",
+ "language": "JavaScript",
+ "stars_count": 24565,
+ "forks_count": 1519,
+ "open_issues_count": 1,
+ "updated_at": "2025-06-30T20:44:09Z",
+ "created_at": "2022-08-24T07:29:42Z",
+ "clone_url": "https://github.com/gethomepage/homepage.git",
+ "ssh_url": "git@github.com:gethomepage/homepage.git",
+ "default_branch": "dev",
+ "last_build_update": "2025-06-30T12:13:58Z"
+}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/knadh-listmonk.json b/mkdocs/docs/assets/repo-data/knadh-listmonk.json
new file mode 100644
index 0000000..c1a4564
--- /dev/null
+++ b/mkdocs/docs/assets/repo-data/knadh-listmonk.json
@@ -0,0 +1,16 @@
+{
+ "full_name": "knadh/listmonk",
+ "name": "listmonk",
+ "description": "High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.",
+ "html_url": "https://github.com/knadh/listmonk",
+ "language": "Go",
+ "stars_count": 17238,
+ "forks_count": 1656,
+ "open_issues_count": 103,
+ "updated_at": "2025-06-30T20:57:12Z",
+ "created_at": "2019-06-26T05:08:39Z",
+ "clone_url": "https://github.com/knadh/listmonk.git",
+ "ssh_url": "git@github.com:knadh/listmonk.git",
+ "default_branch": "master",
+ "last_build_update": "2025-06-30T10:45:51Z"
+}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/n8n-io-n8n.json b/mkdocs/docs/assets/repo-data/n8n-io-n8n.json
new file mode 100644
index 0000000..c99c2cb
--- /dev/null
+++ b/mkdocs/docs/assets/repo-data/n8n-io-n8n.json
@@ -0,0 +1,16 @@
+{
+ "full_name": "n8n-io/n8n",
+ "name": "n8n",
+ "description": "Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.",
+ "html_url": "https://github.com/n8n-io/n8n",
+ "language": "TypeScript",
+ "stars_count": 113623,
+ "forks_count": 33244,
+ "open_issues_count": 1061,
+ "updated_at": "2025-06-30T21:38:07Z",
+ "created_at": "2019-06-22T09:24:21Z",
+ "clone_url": "https://github.com/n8n-io/n8n.git",
+ "ssh_url": "git@github.com:n8n-io/n8n.git",
+ "default_branch": "master",
+ "last_build_update": "2025-06-30T20:59:49Z"
+}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/nocodb-nocodb.json b/mkdocs/docs/assets/repo-data/nocodb-nocodb.json
new file mode 100644
index 0000000..3a2b7c2
--- /dev/null
+++ b/mkdocs/docs/assets/repo-data/nocodb-nocodb.json
@@ -0,0 +1,16 @@
+{
+ "full_name": "nocodb/nocodb",
+ "name": "nocodb",
+ "description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 Open Source Airtable Alternative",
+ "html_url": "https://github.com/nocodb/nocodb",
+ "language": "TypeScript",
+ "stars_count": 55465,
+ "forks_count": 3980,
+ "open_issues_count": 714,
+ "updated_at": "2025-06-30T21:39:01Z",
+ "created_at": "2017-10-29T18:51:48Z",
+ "clone_url": "https://github.com/nocodb/nocodb.git",
+ "ssh_url": "git@github.com:nocodb/nocodb.git",
+ "default_branch": "develop",
+ "last_build_update": "2025-06-30T20:21:14Z"
+}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json b/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json
new file mode 100644
index 0000000..6e46b4d
--- /dev/null
+++ b/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json
@@ -0,0 +1,16 @@
+{
+ "full_name": "squidfunk/mkdocs-material",
+ "name": "mkdocs-material",
+ "description": "Documentation that simply works",
+ "html_url": "https://github.com/squidfunk/mkdocs-material",
+ "language": "Python",
+ "stars_count": 23757,
+ "forks_count": 3783,
+ "open_issues_count": 4,
+ "updated_at": "2025-06-30T21:37:52Z",
+ "created_at": "2016-01-28T22:09:23Z",
+ "clone_url": "https://github.com/squidfunk/mkdocs-material.git",
+ "ssh_url": "git@github.com:squidfunk/mkdocs-material.git",
+ "default_branch": "master",
+ "last_build_update": "2025-06-29T16:43:26Z"
+}
\ No newline at end of file
diff --git a/mkdocs/docs/build/build-server.md b/mkdocs/docs/build/build-server.md
new file mode 100644
index 0000000..1cf5fb4
--- /dev/null
+++ b/mkdocs/docs/build/build-server.md
@@ -0,0 +1,147 @@
+# BNKops Server Build
+
+Purpose: a Ubuntu server build-out for general application
+
+---
+
+
+This documentation is a overview of the full build out for a server OS and baseline for running Changemaker-lite. It is a manual to re-install this server on any machine.
+
+All of the following systems are free and the majority are open source.
+## [Ubuntu](https://ubuntu.com/) OS
+_Ubuntu_ is a Linux distribution derived from Debian and composed mostly of free and open-source software.
+### [Install Ubuntu](https://ubuntu.com/tutorials/install-ubuntu-desktop#1-overview)
+### Post Install
+Post installation, run update:
+```
+sudo apt update
+```
+
+```
+sudo apt upgrade
+```
+### Configuration
+Further configurations:
+
+- User profile was updated to Automatically Login
+- Remote Desktop, Sharing, and Login have all been enabled.
+- Default system settings have been set to dark mode.
+
+## [VSCode Insiders](https://code.visualstudio.com/insiders/)
+Visual Studio Code is a new choice of tool that combines the simplicity of a code editor with what developers need for the core edit-build-debug cycle.
+### Install Using App Centre
+
+## [Obsidian](https://obsidian.md/)
+The free and flexible app for your privateΒ thoughts.
+### Install Using App Center
+
+## [Curl](https://curl.se/)
+command line tool and library for transferring data with URLs (since 1998)
+### Install
+```
+sudo apt install curl
+```
+## [Glances](https://github.com/nicolargo/glances)
+ Glances an Eye on your system. A top/htop alternative for GNU/Linux, BSD, Mac OS and Windows operating systems.
+### Install
+```
+sudo snap install glances
+```
+## [Syncthing](https://syncthing.net/)
+Syncthing is a continuous file synchronization program. It synchronizes files between two or more computers in real time, safely protected from prying eyes. Your data is your data alone and you deserve to choose where it is stored, whether it is shared with some third party, and how itβs transmitted over the internet.
+### Install
+```
+# Add the release PGP keys:
+sudo mkdir -p /etc/apt/keyrings
+sudo curl -L -o /etc/apt/keyrings/syncthing-archive-keyring.gpg https://syncthing.net/release-key.gpg
+```
+
+```
+# Add the "stable" channel to your APT sources:
+echo "deb [signed-by=/etc/apt/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable" | sudo tee /etc/apt/sources.list.d/syncthing.list
+```
+
+```
+# Update and install syncthing:
+sudo apt-get update
+sudo apt-get install syncthing
+```
+### Post Install
+Run syncthing as a system service.
+```
+sudo systemctl start syncthing@yourusername
+```
+
+```
+sudo systemctl enable syncthing@yourusername
+```
+## [Docker](https://www.docker.com/)
+Docker helps developers build, share, run, and verify applications anywhere β without tedious environment configuration or management.
+```
+# Add Docker's official GPG key:
+sudo apt-get update
+sudo apt-get install ca-certificates curl
+sudo install -m 0755 -d /etc/apt/keyrings
+sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
+sudo chmod a+r /etc/apt/keyrings/docker.asc
+
+# Add the repository to Apt sources:
+echo \
+ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
+ $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
+ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
+sudo apt-get update
+```
+
+```
+sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+```
+
+### Update Users
+```
+sudo groupadd docker
+```
+
+```
+sudo usermod -aG docker $USER
+```
+
+```
+newgrp docker
+```
+
+### Enable on Boot
+```
+sudo systemctl enable docker.service
+sudo systemctl enable containerd.service
+```
+## [Cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)
+Connect, protect, and build everywhere. We make websites, apps, and networks faster and more secure. Our developer platform is the best place to build modern apps and deliver AI initiatives.
+
+```
+sudo mkdir -p --mode=0755 /usr/share/keyrings
+curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
+```
+
+```
+echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
+```
+
+```
+sudo apt-get update && sudo apt-get install cloudflared
+```
+### Post Install
+Login to Cloudflare
+```
+cloudflared login
+```
+### Configuration
+- Setting up the [[service.cloudflared]] enables your cloudflared tunnel to automatically run on reboot
+## [Pandoc](https://pandoc.org/)
+If you need to convert files from one markup format into another, pandoc is your swiss-army knife.
+
+```
+sudo apt install pandoc
+```
+## [Changemaker (V3.9.9.1)](https://changemaker.bnkops.com)
+
diff --git a/mkdocs/docs/getting-started.md b/mkdocs/docs/build/index.md
similarity index 75%
rename from mkdocs/docs/getting-started.md
rename to mkdocs/docs/build/index.md
index 09605ee..25f1eab 100644
--- a/mkdocs/docs/getting-started.md
+++ b/mkdocs/docs/build/index.md
@@ -1,6 +1,42 @@
-# Getting Started with Digital Liberation π³οΈββ§οΈ
+# Getting Started with Digital Liberation
+
+Welcome to Changemaker-Lite! You're about to reclaim your digital sovereignty and stop feeding your secrets to corporations. This guide will help you set up your own political infrastructure that you actually own and control.
+
+## Quick Start
+
+### Build Changemkaer-Lite
+
+```bash
+# Clone the repository
+git clone https://gitea.bnkops.com/admin/changemaker.lite
+cd changemaker.lite
+```
+
+!!! warning "Cloudflare Credentials"
+ The config.sh script will ask you for your Cloudflare credentials to get started. You can find more information on how to find this in the [Cloudlflare Configuration](./config/cloudflare-config.md)
+
+
+```
+# Configure environment (creates .env file)
+./config.sh
+```
+
+```
+# Start all services
+docker compose up -d
+```
+
+### Deploy
+
+!!! note "Cloudflare"
+ Right now, we suggest deploying using Cloudflare for simplicity and protections against 99% of surface level attacks to digital infrastructure. If you want to avoid using this service, we recommend checking out [Pagolin](https://github.com/fosrl/pangolin) as a drop in replacement.
+
+For secure public access, use the production deployment script:
+
+```bash
+./start-production.sh
+```
-Welcome to Changemaker Lite! You're about to reclaim your digital sovereignty and stop feeding your secrets to corporations. This guide will help you set up your own political infrastructure that you actually own and control.
## Why Changemaker Lite?
@@ -30,8 +66,13 @@ Before we dive into the technical setup, let's be clear about what you're doing
### Operating System
- **Ubuntu 24.04 LTS (Noble Numbat)** - Recommended and tested
+
+!!! note "Getting Started on Ubunut"
+ Want some help getting started with a baseline buildout for a Ubunut server? You can use our [BNKops Server Build Script](./build-server.md)
+
- Other Linux distributions with systemd support
- WSL2 on Windows (limited functionality)
+- Mac OS
!!! tip "New to Linux?"
Consider [Linux Mint](https://www.linuxmint.com/) - it looks like Windows but opens the door to true digital freedom.
@@ -44,10 +85,13 @@ Before we dive into the technical setup, let's be clear about what you're doing
- **Network**: Stable internet connection
!!! info "Cloud Hosting"
- You can run this on a VPS from providers like Hetzner, DigitalOcean, or Linode for $20-50/month.
+ You can run this on a VPS from providers like Hetzner, DigitalOcean, or Linode for ~$20/month.
### Software Prerequisites
+!!! tip "Getting Started on Docker"
+ Want some help getting started with a baseline buildout for a Ubunutu server? You can use our [BNKops Server Build Script](./build-server.md) to roll out a configured server in about 20 mins!
+
1. **Docker Engine** (24.0+)
```bash
@@ -159,34 +203,29 @@ Expected output should show all services as "Up":
Once services are running, access them locally:
-### π Homepage Dashboard
-
-- **URL**: http://localhost:3010
-- **Purpose**: Central hub for all services
+### π Homepage Dashboard
+- **URL**: [http://localhost:3010](http://localhost:3010)
+- **Purpose**: Central hub for all services
- **Features**: Service status, quick links, monitoring
-### π» Development Tools
+### π» Development Tools
+- **Code Server**: [http://localhost:8888](http://localhost:8888) β VS Code in browser
+- **Gitea**: [http://localhost:3030](http://localhost:3030) β Git repository management
+- **MkDocs Dev**: [http://localhost:4000](http://localhost:4000) β Live documentation preview
+- **MkDocs Prod**: [http://localhost:4001](http://localhost:4001) β Built documentation
-- **Code Server**: http://localhost:8888 - VS Code in browser
-- **Gitea**: http://localhost:3030 - Git repository management
-- **MkDocs Dev**: http://localhost:4000 - Live documentation preview
-- **MkDocs Prod**: http://localhost:4001 - Built documentation
+### π§ Communication
+- **Listmonk**: [http://localhost:9000](http://localhost:9000) β Email campaigns
+ _Login with credentials set during configuration_
-### π§ Communication
+### π Automation & Data
+- **n8n**: [http://localhost:5678](http://localhost:5678) β Workflow automation
+ _Login with credentials set during configuration_
+- **NocoDB**: [http://localhost:8090](http://localhost:8090) β No-code database
-- **Listmonk**: http://localhost:9000 - Email campaigns
- - Login with credentials set during configuration
-
-### π Automation & Data
-
-- **n8n**: http://localhost:5678 - Workflow automation
- - Login with credentials set during configuration
-- **NocoDB**: http://localhost:8090 - No-code database
-
-### π οΈ Interactive Tools
-
-- **Map Viewer**: http://localhost:3000 - Geographic data visualization
-- **Mini QR**: http://localhost:8089 - QR code generator
+### π οΈ Interactive Tools
+- **Map Viewer**: [http://localhost:3000](http://localhost:3000) β Geographic data visualization
+- **Mini QR**: [http://localhost:8089](http://localhost:8089) β QR code generator
## Production Deployment
diff --git a/mkdocs/docs/cloudflare/index.md b/mkdocs/docs/cloudflare/index.md
deleted file mode 100644
index 3601fdf..0000000
--- a/mkdocs/docs/cloudflare/index.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Cloudflare
-
-In this section, you will find instructions on how to properly set up Cloudflare for managing a Changemaker-lite.
-
-## Config
-
-When you first run the `./config.sh` it will prompt you for the a api token, zone id, and a tunnel id. A
\ No newline at end of file
diff --git a/mkdocs/docs/config/cloudflare-config.md b/mkdocs/docs/config/cloudflare-config.md
new file mode 100644
index 0000000..cd487f0
--- /dev/null
+++ b/mkdocs/docs/config/cloudflare-config.md
@@ -0,0 +1,57 @@
+# Configure Cloudflare
+
+Cloudflare is the largest DNS routing service on the planet. We use their free service tier to provide Changemaker users with a fast, secure, and reliable way to get online that blocks 99% of surface level attacks and has built in user authenticaion (if you so choose to use it)
+
+## Credentials
+
+The `config.sh` and `start-production.sh` scripts require the following Cloudflare credentials to function properly:
+
+### 1. **Cloudflare API Token**
+
+ - **Purpose**: Used to authenticate API requests to Cloudflare for managing DNS records, tunnels, and access policies.
+ - **Required Permissions**:
+ - `Zone.DNS` (Read/Write)
+ - `Account.Cloudflare Tunnel` (Read/Write)
+ - **How to Obtain**:
+ - Log in to your Cloudflare account.
+ - Go to **My Profile** > **API Tokens** > **Create Token**.
+ - Use the **Edit zone DNS** template and add **Cloudflare Tunnel** permissions.
+
+### 2. **Cloudflare Zone ID**
+
+ - **Purpose**: Identifies the specific DNS zone (domain) in Cloudflare where DNS records will be created.
+ - **How to Obtain**:
+ - Log in to your Cloudflare account.
+ - Select the domain you want to use.
+ - The Zone ID is displayed in the **Overview** section under **API**.
+
+### 3. **Cloudflare Account ID**
+
+ - **Purpose**: Identifies your Cloudflare account for tunnel creation and management.
+ - **How to Obtain**:
+ - Log in to your Cloudflare account.
+ - Go to **My Profile** > **API Tokens**.
+ - The Account ID is displayed at the top of the page.
+
+### 4. **Cloudflare Tunnel ID** (Optional in config.sh, Required in start-production.sh)
+
+ - **Purpose**: Identifies the specific Cloudflare Tunnel that will be used to route traffic to your services.
+ - **How to Obtain**:
+ - This is automatically generated when you create a tunnel using `cloudflared tunnel create` or via the Cloudflare dashboard.
+ - The start-production.sh script will create this for you if it doesn't exist.
+
+### Summary of Required Credentials:
+
+```bash
+# In .env file
+CF_API_TOKEN=your_cloudflare_api_token
+CF_ZONE_ID=your_cloudflare_zone_id
+CF_ACCOUNT_ID=your_cloudflare_account_id
+CF_TUNNEL_ID=will_be_set_by_start_production # This will be set by start-production.sh
+```
+
+### Notes:
+
+- The config.sh script will prompt you for these credentials during setup.
+- The start-production.sh script will verify these credentials and use them to configure DNS records, create tunnels, and set up access policies.
+- Ensure that the API token has the correct permissions, or the scripts will fail to configure Cloudflare services.
\ No newline at end of file
diff --git a/mkdocs/docs/config/index.md b/mkdocs/docs/config/index.md
new file mode 100644
index 0000000..4a34e45
--- /dev/null
+++ b/mkdocs/docs/config/index.md
@@ -0,0 +1,6 @@
+# Configuration
+
+There are several configuration steps to building a production ready Changemaker-Lite.
+
+In the order we suggest doing them:
+
diff --git a/mkdocs/docs/hooks/__pycache__/repo_widget_hook.cpython-311.pyc b/mkdocs/docs/hooks/__pycache__/repo_widget_hook.cpython-311.pyc
new file mode 100644
index 0000000..516ce79
Binary files /dev/null and b/mkdocs/docs/hooks/__pycache__/repo_widget_hook.cpython-311.pyc differ
diff --git a/mkdocs/docs/hooks/repo_widget_hook.py b/mkdocs/docs/hooks/repo_widget_hook.py
new file mode 100644
index 0000000..f8cb95d
--- /dev/null
+++ b/mkdocs/docs/hooks/repo_widget_hook.py
@@ -0,0 +1,132 @@
+"""
+MkDocs Hook for Repository Widget Data Generation
+Fetches repository data and generates JSON files during build
+"""
+
+import json
+import os
+import requests
+from pathlib import Path
+from typing import Dict, Any
+import logging
+
+# Configure logging
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+def on_pre_build(config: Dict[str, Any]) -> None:
+ """
+ Hook that runs before MkDocs builds the site
+ Generates repository JSON data files
+ """
+ logger.info("Generating repository widget data...")
+
+ # Define repositories to fetch - all repos from services.md
+ repositories = [
+ # Gitea repositories
+ {
+ "repo": "admin/changemaker.lite",
+ "gitea_url": "https://gitea.bnkops.com",
+ "token": os.getenv("GITEA_TOKEN")
+ },
+ # GitHub repositories
+ {
+ "repo": "coder/code-server",
+ "github": True
+ },
+ {
+ "repo": "n8n-io/n8n",
+ "github": True
+ },
+ {
+ "repo": "knadh/listmonk",
+ "github": True
+ },
+ {
+ "repo": "nocodb/nocodb",
+ "github": True
+ },
+ { "repo": "squidfunk/mkdocs-material",
+ "github": True
+ },
+ {
+ "repo": "gethomepage/homepage",
+ "github": True
+ }
+ ]
+
+ # Create output directory
+ docs_dir = config.get('docs_dir', 'docs')
+ output_dir = Path(docs_dir) / 'assets' / 'repo-data'
+ output_dir.mkdir(parents=True, exist_ok=True)
+
+ # Generate data for each repository
+ for repo_config in repositories:
+ try:
+ generate_repo_data(repo_config, output_dir)
+ except Exception as e:
+ logger.error(f"Failed to generate data for {repo_config['repo']}: {e}")
+
+def generate_repo_data(repo_config: Dict[str, Any], output_dir: Path) -> None:
+ """Generate JSON data file for a single repository"""
+
+ repo = repo_config['repo']
+ logger.info(f"Fetching data for {repo}")
+
+ # Determine API URL and headers
+ if repo_config.get('github'):
+ api_url = f"https://api.github.com/repos/{repo}"
+ headers = {'Accept': 'application/vnd.github.v3+json'}
+ github_token = os.getenv('GITHUB_TOKEN')
+ if github_token:
+ headers['Authorization'] = f'token {github_token}'
+ else:
+ gitea_url = repo_config.get('gitea_url', 'https://gitea.bnkops.com')
+ api_url = f"{gitea_url}/api/v1/repos/{repo}"
+ headers = {'Accept': 'application/json'}
+ token = repo_config.get('token') or os.getenv('GITEA_TOKEN')
+ if token:
+ headers['Authorization'] = f'token {token}'
+
+ # Fetch repository data
+ try:
+ response = requests.get(api_url, headers=headers, timeout=10)
+ response.raise_for_status()
+ data = response.json()
+ except requests.RequestException as e:
+ logger.error(f"Failed to fetch {repo}: {e}")
+ return
+
+ # Extract widget data
+ widget_data = {
+ 'full_name': data.get('full_name'),
+ 'name': data.get('name'),
+ 'description': data.get('description'),
+ 'html_url': data.get('html_url'),
+ 'language': data.get('language'),
+ 'stars_count': data.get('stargazers_count') or data.get('stars_count', 0),
+ 'forks_count': data.get('forks_count', 0),
+ 'open_issues_count': data.get('open_issues_count', 0),
+ 'updated_at': data.get('updated_at'),
+ 'created_at': data.get('created_at'),
+ 'clone_url': data.get('clone_url'),
+ 'ssh_url': data.get('ssh_url'),
+ 'default_branch': data.get('default_branch', 'main'),
+ 'last_build_update': data.get('pushed_at') or data.get('updated_at')
+ }
+
+ # Generate filename
+ filename = f"{repo.replace('/', '-')}.json"
+ file_path = output_dir / filename
+
+ # Write JSON file
+ try:
+ with open(file_path, 'w') as f:
+ json.dump(widget_data, f, indent=2)
+ logger.info(f"Generated: {filename}")
+ except Exception as e:
+ logger.error(f"Failed to write {filename}: {e}")
+
+def on_post_build(config: Dict[str, Any]) -> None:
+ """Hook that runs after MkDocs builds the site"""
+ logger.info("Repository widget data generation complete")
\ No newline at end of file
diff --git a/mkdocs/docs/javascripts/gitea-widget.js b/mkdocs/docs/javascripts/gitea-widget.js
new file mode 100644
index 0000000..74b7fac
--- /dev/null
+++ b/mkdocs/docs/javascripts/gitea-widget.js
@@ -0,0 +1,132 @@
+document.addEventListener('DOMContentLoaded', function() {
+ const widgets = document.querySelectorAll('.gitea-widget');
+
+ widgets.forEach(widget => {
+ const repo = widget.dataset.repo;
+
+ // Auto-generate data file path from repo name
+ const dataFile = `/assets/repo-data/${repo.replace('/', '-')}.json`;
+ const showDescription = widget.dataset.showDescription !== 'false';
+ const showLanguage = widget.dataset.showLanguage !== 'false';
+ const showLastUpdate = widget.dataset.showLastUpdate !== 'false';
+
+ // Show loading state
+ widget.innerHTML = `
+
+ `;
+
+ // Fetch repository data
+ fetch(dataFile)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`Could not load data for ${repo}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ renderWidget(widget, data, { showDescription, showLanguage, showLastUpdate });
+ })
+ .catch(error => {
+ renderError(widget, repo, error.message);
+ });
+ });
+});
+
+function renderWidget(widget, data, options) {
+ const lastUpdate = new Date(data.updated_at).toLocaleDateString();
+ const language = data.language || 'Not specified';
+
+ widget.innerHTML = `
+
+ `;
+}
+
+function renderError(widget, repo, error) {
+ widget.innerHTML = `
+
+ `;
+}
+
+function getLanguageColor(language) {
+ const colors = {
+ 'JavaScript': '#f1e05a',
+ 'TypeScript': '#2b7489',
+ 'Python': '#3572A5',
+ 'Java': '#b07219',
+ 'C++': '#f34b7d',
+ 'C': '#555555',
+ 'C#': '#239120',
+ 'PHP': '#4F5D95',
+ 'Ruby': '#701516',
+ 'Go': '#00ADD8',
+ 'Rust': '#dea584',
+ 'Swift': '#ffac45',
+ 'Kotlin': '#F18E33',
+ 'Scala': '#c22d40',
+ 'Shell': '#89e051',
+ 'HTML': '#e34c26',
+ 'CSS': '#563d7c',
+ 'Vue': '#2c3e50',
+ 'React': '#61dafb',
+ 'Dockerfile': '#384d54',
+ 'Markdown': '#083fa1'
+ };
+ return colors[language] || '#586069';
+}
\ No newline at end of file
diff --git a/mkdocs/docs/javascripts/github-widget.js b/mkdocs/docs/javascripts/github-widget.js
new file mode 100644
index 0000000..c4a69df
--- /dev/null
+++ b/mkdocs/docs/javascripts/github-widget.js
@@ -0,0 +1,167 @@
+let widgetsInitialized = new Set();
+
+function initializeGitHubWidgets() {
+ const widgets = document.querySelectorAll('.github-widget');
+
+ widgets.forEach(widget => {
+ // Skip if already initialized
+ const widgetId = widget.dataset.repo + '-' + Math.random().toString(36).substr(2, 9);
+ if (widget.dataset.initialized) return;
+
+ widget.dataset.initialized = 'true';
+ const repo = widget.dataset.repo;
+
+ // Auto-generate data file path from repo name
+ const dataFile = `/assets/repo-data/${repo.replace('/', '-')}.json`;
+ const showDescription = widget.dataset.showDescription !== 'false';
+ const showLanguage = widget.dataset.showLanguage !== 'false';
+ const showLastUpdate = widget.dataset.showLastUpdate !== 'false';
+
+ // Show loading state
+ widget.innerHTML = `
+
+ `;
+
+ // Fetch repository data from pre-generated JSON file
+ fetch(dataFile)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`Could not load data for ${repo}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ const lastUpdate = new Date(data.updated_at).toLocaleDateString();
+ const language = data.language || 'Not specified';
+
+ widget.innerHTML = `
+
+ `;
+ })
+ .catch(error => {
+ console.error('Error loading repository data:', error);
+ widget.innerHTML = `
+
+ `;
+ });
+ });
+}
+
+// Initialize on DOM ready
+document.addEventListener('DOMContentLoaded', initializeGitHubWidgets);
+
+// Watch for DOM changes (MkDocs Material dynamic content)
+const observer = new MutationObserver((mutations) => {
+ let shouldReinitialize = false;
+
+ mutations.forEach((mutation) => {
+ if (mutation.type === 'childList') {
+ // Check if any github-widget elements were added
+ mutation.addedNodes.forEach((node) => {
+ if (node.nodeType === 1 && // Element node
+ (node.classList?.contains('github-widget') ||
+ node.querySelector?.('.github-widget'))) {
+ shouldReinitialize = true;
+ }
+ });
+ }
+ });
+
+ if (shouldReinitialize) {
+ // Small delay to ensure DOM is stable
+ setTimeout(initializeGitHubWidgets, 100);
+ }
+});
+
+// Start observing
+observer.observe(document.body, {
+ childList: true,
+ subtree: true
+});
+
+// Language color mapping (simplified version)
+function getLanguageColor(language) {
+ const colors = {
+ 'JavaScript': '#f1e05a',
+ 'TypeScript': '#2b7489',
+ 'Python': '#3572A5',
+ 'Java': '#b07219',
+ 'C++': '#f34b7d',
+ 'C': '#555555',
+ 'C#': '#239120',
+ 'PHP': '#4F5D95',
+ 'Ruby': '#701516',
+ 'Go': '#00ADD8',
+ 'Rust': '#dea584',
+ 'Swift': '#ffac45',
+ 'Kotlin': '#F18E33',
+ 'Scala': '#c22d40',
+ 'Shell': '#89e051',
+ 'HTML': '#e34c26',
+ 'CSS': '#563d7c',
+ 'Vue': '#2c3e50',
+ 'React': '#61dafb',
+ 'Dockerfile': '#384d54'
+ };
+ return colors[language] || '#586069';
+}
diff --git a/mkdocs/docs/overrides/home.html b/mkdocs/docs/overrides/home.html
index 383b702..7508dcb 100644
--- a/mkdocs/docs/overrides/home.html
+++ b/mkdocs/docs/overrides/home.html
@@ -1,339 +1,369 @@
{% extends "main.html" %}
{% block extrahead %}
- {{ super() }}
-
+
{% endblock %}
{% block content %}
-
-
-
-
-
-
π€― This Site Runs On Changemaker Lite
-
The Only FOSS Political Campaign Stack
-
Stop paying $1,200/month to corporate platforms. Run your entire political campaign on $200 hardware with fewer corporate dependencies every day.
-
-
-
-
-
-
-
The Problem
-
-
πΈ NGP VAN: $1,000+/mo
-
π§ Mailchimp: $200+/mo
-
π Your data: Their servers
-
ποΈ Surveillance: Always on
-
-
-
-
-
-
The Solution
-
-
-
-
-
-
β
-
Fewer corporate deps every day
-
-
-
-
-
-
-
Proven By
-
-
- β‘
- Powers BNKops.com
-
-
- π³οΈββ§οΈ
- Trans liberation tech
-
-
- π‘οΈ
- Zero surveillance
-
-
- π
- 30-min setup
-
-
-
-
-
+
+
+
+
+
+
π€― This Site Runs On Changemaker Lite
+
The Only Free and Open Source Political Campaign Stack
+
Stop paying thousands of dollars a month to corporate platforms just to be surveilled and your supports data sold to the highest bidder. Run your entire political campaign on ~$200 hardware and
+ with fewer corporate dependencies every day.
-
-
-
-
-
-
-
-
-
π»
-
Code Server
-
Replaces: VS Code
-
- - Browser-based IDE
- - Customizable workspace
- - Live collaboration
-
-
Code Server
+
-
-
-
π
-
Documentation
-
Replaces: Confluence
-
- - Markdown-based
- - Live preview
- - Static site generation
-
-
MkDocs
-
-
-
-
-
π§
-
Email Campaigns
-
Replaces: Mailchimp
-
- - Unlimited subscribers
- - A/B testing
- - Analytics
-
-
Listmonk
-
-
-
-
-
π
-
Database & Canvassing
-
Replaces: Airtable
-
- - Contact management
- - Custom fields
- - Canvassing support
-
-
NocoDB
-
-
-
-
-
πΊοΈ
-
Interactive Maps
-
Replaces: Google Maps
-
- - Real-time geolocation
- - Custom map layers
- - Location management
-
-
Map Viewer
-
-
-
-
-
π
-
Workflow Automation
-
Replaces: Zapier
-
- - Workflow builder
- - API connections
- - Event triggers
-
-
n8n
-
-
-
-
-
π±
-
QR Code Generator
-
Replaces: QR Code SaaS
-
- - Customizable codes
- - Batch generation
- - Static and dynamic codes
-
-
Mini QR
-
-
-
-
-
π§
-
Version Control
-
Replaces: GitHub
-
- - Self-hosted Git
- - Collaborative development
- - Issue tracking
-
-
Gitea
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Monthly Cost
-
$1,200+
-
$50 hosting
-
-
-
-
Data Ownership
-
Their servers
-
100% yours
-
-
-
-
Surveillance
-
Always tracked
-
Zero tracking
-
-
-
-
Vendor Lock-in
-
Trapped forever
-
Export anytime
-
-
-
-
Customization
-
Limited options
-
Full control
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Most Popular
-
π
-
Plug & Play
-
$200
-
-
β Pre-configured hardware
-
β 30-minute setup
-
β All 11 services ready
-
β Priority support
-
β Ships on request
+
+
+
The Problem
+
+
πΈ Canvassing: $100+/mo
+
π Nationbuilder: $500+/mo
+
π§ Mailchimp: $200+/mo
+
ποΈ Surveillance: Always on
+
π Vendor lock-in: Trapped forever
+
π Data ownership: Not yours
+
π Implicitly Supporting Evil Corporations
-
Order Hardware
-
-
-
-
π οΈ
-
DIY Install
-
Free
-
-
β Use your hardware
-
β Docker compose
-
β Full documentation
-
β Community support
-
β Learn the system
+
+
+
+
The Solution
+
+
+
Runs on ~$200 Hardware
+
One-time cost
+
+
+
+
Your Data
+
Localized & Secure
+
+
+
β
+
Fewer corporate deps every day
+
-
Install Guide
-
-
-
-
βοΈ
-
Managed Hosting
-
$???/mo
-
-
β We manage everything
-
β Your domain
-
β Daily backups
-
β 24/7 monitoring
-
β Still your data
+
+
+
+
Proven By
+
+
+ β‘
+ Powers BNKops.com
+
+
+ π
+ Liberation tech
+
+
+ π‘οΈ
+ Zero surveillance
+
+
+ π
+ 30-min setup
+
-
Learn More
-
-
-
-
Join the Movement
-
Some of the biggest players in local politics are already using it; maybe give it a try?
-
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/mkdocs/docs/philosophy.md b/mkdocs/docs/phil/index.md
similarity index 96%
rename from mkdocs/docs/philosophy.md
rename to mkdocs/docs/phil/index.md
index 29c2652..439ed0c 100644
--- a/mkdocs/docs/philosophy.md
+++ b/mkdocs/docs/phil/index.md
@@ -104,6 +104,8 @@ The tools we use shape the movements we build. Corporate tools create corporate
**No.** We specifically designed Changemaker Lite for organizers, activists, and movement builders who may not have technical backgrounds. Our philosophy is that everyone deserves digital sovereignty, not just people with computer science degrees.
+This is not to say that you won't need to learn! These tools are just that; tools. They have no fancy or white-labeled marketing and are technical in nature. You will need to learn to use them, just as any worker needs to learn the power tools they use on the job.
+
### "What about convenience?"
Corporate platforms are convenient because they've extracted billions of dollars from users to fund that convenience. When you own your tools, there's a learning curveβbut it's the same learning curve as learning to organize, learning to build power, learning to create change.
diff --git a/mkdocs/docs/services/code-server.md b/mkdocs/docs/services/code-server.md
index 82bd67c..57bafd0 100644
--- a/mkdocs/docs/services/code-server.md
+++ b/mkdocs/docs/services/code-server.md
@@ -1,6 +1,6 @@
# Code Server
-Visual Studio Code in your browser for remote development.
+
## Overview
diff --git a/mkdocs/docs/services/index.md b/mkdocs/docs/services/index.md
index 9bfc21b..134bfc4 100644
--- a/mkdocs/docs/services/index.md
+++ b/mkdocs/docs/services/index.md
@@ -6,6 +6,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [Code Server](code-server.md)
**Port: 8888** | Visual Studio Code in your browser for remote development
+
- Full IDE experience
- Extensions support
- Git integration
@@ -13,6 +14,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [Listmonk](listmonk.md)
**Port: 9000** | Self-hosted newsletter and mailing list manager
+
- Email campaigns
- Subscriber management
- Analytics
@@ -27,6 +29,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [MkDocs Material](mkdocs.md)
**Port: 4000** | Documentation site generator with live preview
+
- Material Design theme
- Live reload
- Search functionality
@@ -41,6 +44,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [n8n](n8n.md)
**Port: 5678** | Workflow automation tool
+
- Visual workflow editor
- 400+ integrations
- Custom code execution
@@ -48,6 +52,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [NocoDB](nocodb.md)
**Port: 8090** | No-code database platform
+
- Smart spreadsheet interface
- Form builder and API generation
- Real-time collaboration
@@ -55,6 +60,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [Homepage](homepage.md)
**Port: 3010** | Modern dashboard for all services
+
- Service dashboard and monitoring
- Docker integration
- Customizable layout
diff --git a/mkdocs/docs/services/n8n.md b/mkdocs/docs/services/n8n.md
index 28b6fe3..25df825 100644
--- a/mkdocs/docs/services/n8n.md
+++ b/mkdocs/docs/services/n8n.md
@@ -1,5 +1,7 @@
# n8n
+
+
Workflow automation tool for connecting services and automating tasks.
## Overview
diff --git a/mkdocs/docs/stylesheets/extra.css b/mkdocs/docs/stylesheets/extra.css
index e69de29..5599aae 100644
--- a/mkdocs/docs/stylesheets/extra.css
+++ b/mkdocs/docs/stylesheets/extra.css
@@ -0,0 +1,554 @@
+.login-button {
+ display: inline-block;
+ padding: 2px 10px;
+ margin-left: auto; /* Push the button to the right */
+ margin-right: 10px;
+ background-color: hsl(315, 80%, 42%); /* Use a solid, high-contrast color */
+ color: #fff; /* Ensure text is white */
+ text-decoration: none;
+ border-radius: 4px;
+ font-weight: bold;
+ transition: background-color 0.2s ease;
+ font-size: 0.9em;
+ vertical-align: middle;
+}
+
+.login-button:hover {
+ background-color: #003c8f; /* Darker shade for hover */
+ text-decoration: none;
+}
+
+.git-code-button {
+ display: inline-block;
+ background: #30363d;
+ color: white !important;
+ padding: 0.6rem 1.2rem;
+ border-radius: 20px;
+ text-decoration: none;
+ font-size: 0.95rem;
+ font-weight: bold;
+ margin-left: 1rem;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
+}
+
+.git-code-button:hover {
+ background: #444d56;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 8px rgba(0,0,0,0.3);
+ text-decoration: none;
+}
+
+.git-code-button .material-icons {
+ font-size: 1rem;
+ vertical-align: middle;
+ margin-right: 4px;
+}
+
+/* GitHub Widget Styles */
+.github-widget {
+ margin: 1.5rem 0;
+ display: block;
+}
+
+.github-widget-container {
+ border: 1px solid rgba(var(--md-primary-fg-color--rgb), 0.15);
+ border-radius: 12px;
+ padding: 20px;
+ background: linear-gradient(135deg, var(--md-code-bg-color) 0%, rgba(var(--md-primary-fg-color--rgb), 0.03) 100%);
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.6;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ position: relative;
+ overflow: hidden;
+}
+
+.github-widget-container::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: linear-gradient(90deg, var(--md-primary-fg-color), var(--md-accent-fg-color));
+ border-radius: 12px 12px 0 0;
+}
+
+.github-widget-container:hover {
+ border-color: var(--md-accent-fg-color);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+}
+
+.github-widget-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 16px;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.github-widget-title {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex: 1;
+ min-width: 0;
+}
+
+.github-icon {
+ color: var(--md-default-fg-color--light);
+ flex-shrink: 0;
+ width: 20px;
+ height: 20px;
+}
+
+.github-widget .repo-link {
+ color: var(--md-accent-fg-color);
+ text-decoration: none;
+ font-weight: 600;
+ font-size: 16px;
+ transition: color 0.2s ease;
+ word-break: break-word;
+}
+
+.github-widget .repo-link:hover {
+ color: var(--md-primary-fg-color);
+ text-decoration: none;
+}
+
+.github-widget-stats {
+ display: flex;
+ gap: 20px;
+ align-items: center;
+ flex-wrap: wrap;
+}
+
+.stat-item {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ color: var(--md-default-fg-color);
+ font-size: 13px;
+ font-weight: 600;
+ background: rgba(var(--md-primary-fg-color--rgb), 0.08);
+ padding: 4px 8px;
+ border-radius: 16px;
+ transition: all 0.2s ease;
+}
+
+.stat-item:hover {
+ background: rgba(var(--md-accent-fg-color--rgb), 0.15);
+ transform: scale(1.05);
+}
+
+.stat-item svg {
+ color: var(--md-accent-fg-color);
+ width: 14px;
+ height: 14px;
+}
+
+.github-widget-description {
+ color: var(--md-default-fg-color--light);
+ margin-bottom: 16px;
+ line-height: 1.5;
+ font-size: 14px;
+ font-style: italic;
+ padding: 12px;
+ background: rgba(var(--md-default-fg-color--rgb), 0.03);
+ border-radius: 8px;
+ border-left: 3px solid var(--md-accent-fg-color);
+}
+
+.github-widget-footer {
+ display: flex;
+ gap: 20px;
+ align-items: center;
+ font-size: 12px;
+ color: var(--md-default-fg-color--lighter);
+ border-top: 1px solid rgba(var(--md-default-fg-color--rgb), 0.1);
+ padding-top: 16px;
+ margin-top: 16px;
+ flex-wrap: wrap;
+}
+
+.language-info {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.language-dot {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ display: inline-block;
+}
+
+.last-update,
+.license-info {
+ color: var(--md-default-fg-color--lighter);
+}
+
+/* Loading State */
+.github-widget-loading {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 20px;
+ color: var(--md-default-fg-color--light);
+ justify-content: center;
+}
+
+.loading-spinner {
+ width: 20px;
+ height: 20px;
+ border: 2px solid var(--md-default-fg-color--lightest);
+ border-top: 2px solid var(--md-accent-fg-color);
+ border-radius: 50%;
+ animation: github-widget-spin 1s linear infinite;
+}
+
+@keyframes github-widget-spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Error State */
+.github-widget-error {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+ padding: 20px;
+ color: var(--md-typeset-color);
+ text-align: center;
+ background: var(--md-code-bg-color);
+ border: 1px solid #f85149;
+ border-radius: 6px;
+}
+
+.github-widget-error svg {
+ color: #f85149;
+}
+
+.github-widget-error small {
+ color: var(--md-default-fg-color--lighter);
+ font-size: 11px;
+}
+
+/* Dark mode specific adjustments */
+[data-md-color-scheme="slate"] .github-widget-container {
+ background: var(--md-code-bg-color);
+ border-color: #30363d;
+}
+
+[data-md-color-scheme="slate"] .github-widget-container:hover {
+ border-color: var(--md-accent-fg-color);
+}
+
+/* Multiple widgets in a row */
+.github-widgets-row {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ gap: 1rem;
+ margin: 1rem 0;
+}
+
+.github-widgets-row .github-widget {
+ margin: 0;
+}
+
+/* Compact widget variant */
+.github-widget.compact .github-widget-container {
+ padding: 12px;
+}
+
+.github-widget.compact .github-widget-header {
+ margin-bottom: 8px;
+}
+
+.github-widget.compact .github-widget-description {
+ display: none;
+}
+
+.github-widget.compact .github-widget-footer {
+ margin-top: 8px;
+ padding-top: 8px;
+}
+
+/* GitHub Widget Responsive - placed after existing mobile styles */
+@media (max-width: 768px) {
+ .github-widget-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+ }
+
+ .github-widget-stats {
+ gap: 12px;
+ }
+
+ .github-widget-footer {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+ }
+}
+
+/* Gitea Widget Styles */
+.gitea-widget {
+ margin: 1.5rem 0;
+ display: block;
+}
+
+.gitea-widget-container {
+ border: 1px solid rgba(var(--md-primary-fg-color--rgb), 0.15);
+ border-radius: 12px;
+ padding: 20px;
+ background: linear-gradient(135deg, var(--md-code-bg-color) 0%, rgba(var(--md-primary-fg-color--rgb), 0.03) 100%);
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.6;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ position: relative;
+ overflow: hidden;
+}
+
+.gitea-widget-container::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: linear-gradient(90deg, #609926, #89c442);
+ border-radius: 12px 12px 0 0;
+}
+
+.gitea-widget-container:hover {
+ border-color: #89c442;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+}
+
+.gitea-widget-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 16px;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.gitea-widget-title {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex: 1;
+ min-width: 0;
+}
+
+.gitea-icon {
+ color: #89c442;
+ flex-shrink: 0;
+ width: 20px;
+ height: 20px;
+}
+
+.gitea-widget .repo-link {
+ color: #89c442;
+ text-decoration: none;
+ font-weight: 600;
+ font-size: 16px;
+ transition: color 0.2s ease;
+ word-break: break-word;
+}
+
+.gitea-widget .repo-link:hover {
+ color: #609926;
+ text-decoration: none;
+}
+
+.gitea-widget-stats {
+ display: flex;
+ gap: 20px;
+ align-items: center;
+ flex-wrap: wrap;
+}
+
+.gitea-widget .stat-item {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ color: var(--md-default-fg-color);
+ font-size: 13px;
+ font-weight: 600;
+ background: rgba(137, 196, 66, 0.1);
+ padding: 4px 8px;
+ border-radius: 16px;
+ transition: all 0.2s ease;
+}
+
+.gitea-widget .stat-item:hover {
+ background: rgba(137, 196, 66, 0.2);
+ transform: scale(1.05);
+}
+
+.gitea-widget .stat-item svg {
+ color: #89c442;
+ width: 14px;
+ height: 14px;
+}
+
+.gitea-widget-description {
+ color: var(--md-default-fg-color--light);
+ margin-bottom: 16px;
+ line-height: 1.5;
+ font-size: 14px;
+ font-style: italic;
+ padding: 12px;
+ background: rgba(var(--md-default-fg-color--rgb), 0.03);
+ border-radius: 8px;
+ border-left: 3px solid #89c442;
+}
+
+.gitea-widget-footer {
+ display: flex;
+ gap: 20px;
+ align-items: center;
+ font-size: 12px;
+ color: var(--md-default-fg-color--lighter);
+ border-top: 1px solid rgba(var(--md-default-fg-color--rgb), 0.1);
+ padding-top: 16px;
+ margin-top: 16px;
+ flex-wrap: wrap;
+}
+
+.gitea-widget .language-info {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.gitea-widget .language-dot {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ display: inline-block;
+}
+
+.gitea-widget .last-update,
+.gitea-widget .license-info {
+ color: var(--md-default-fg-color--lighter);
+}
+
+/* Gitea Loading State */
+.gitea-widget-loading {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 20px;
+ color: var(--md-default-fg-color--light);
+ justify-content: center;
+}
+
+.gitea-widget-loading .loading-spinner {
+ width: 20px;
+ height: 20px;
+ border: 2px solid var(--md-default-fg-color--lightest);
+ border-top: 2px solid #89c442;
+ border-radius: 50%;
+ animation: gitea-widget-spin 1s linear infinite;
+}
+
+@keyframes gitea-widget-spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Gitea Error State */
+.gitea-widget-error {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+ padding: 20px;
+ color: var(--md-typeset-color);
+ text-align: center;
+ background: var(--md-code-bg-color);
+ border: 1px solid #f85149;
+ border-radius: 6px;
+}
+
+.gitea-widget-error svg {
+ color: #f85149;
+}
+
+.gitea-widget-error small {
+ color: var(--md-default-fg-color--lighter);
+ font-size: 11px;
+}
+
+/* Dark mode specific adjustments for Gitea */
+[data-md-color-scheme="slate"] .gitea-widget-container {
+ background: var(--md-code-bg-color);
+ border-color: #30363d;
+}
+
+[data-md-color-scheme="slate"] .gitea-widget-container:hover {
+ border-color: #89c442;
+}
+
+/* Multiple Gitea widgets in a row */
+.gitea-widgets-row {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ gap: 1rem;
+ margin: 1rem 0;
+}
+
+.gitea-widgets-row .gitea-widget {
+ margin: 0;
+}
+
+/* Compact Gitea widget variant */
+.gitea-widget.compact .gitea-widget-container {
+ padding: 12px;
+}
+
+.gitea-widget.compact .gitea-widget-header {
+ margin-bottom: 8px;
+}
+
+.gitea-widget.compact .gitea-widget-description {
+ display: none;
+}
+
+.gitea-widget.compact .gitea-widget-footer {
+ margin-top: 8px;
+ padding-top: 8px;
+}
+
+/* Gitea Widget Responsive */
+@media (max-width: 768px) {
+ .gitea-widget-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+ }
+
+ .gitea-widget-stats {
+ gap: 12px;
+ }
+
+ .gitea-widget-footer {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+ }
+}
diff --git a/mkdocs/docs/stylesheets/home.css b/mkdocs/docs/stylesheets/home.css
index a64b72d..4c72fcb 100644
--- a/mkdocs/docs/stylesheets/home.css
+++ b/mkdocs/docs/stylesheets/home.css
@@ -265,7 +265,7 @@ body[data-md-template="home"] .md-main__inner {
.stat-number {
font-size: 1.2rem;
font-weight: 700;
- color: var(--trans-blue);
+ color: var(--trans-pink);
margin: 0;
animation: number-glow 4s ease-in-out infinite;
}
@@ -309,6 +309,8 @@ body[data-md-template="home"] .md-main__inner {
.section-header {
text-align: center;
margin-bottom: var(--space-lg);
+ position: relative;
+ z-index: 10;
}
.section-header h2 {
@@ -672,6 +674,21 @@ body[data-md-template="home"] .md-main__inner {
}
}
+/* Row cards at bottom: two cards in a row on desktop, stack on mobile */
+.row-cards {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: var(--space-sm);
+ margin-top: var(--space-lg);
+}
+
+@media (max-width: 768px) {
+ .row-cards {
+ grid-template-columns: 1fr;
+ gap: var(--space-xs);
+ }
+}
+
/* =================================
PERFORMANCE
================================= */
diff --git a/mkdocs/mkdocs.yml b/mkdocs/mkdocs.yml
index 2368878..5dd1171 100644
--- a/mkdocs/mkdocs.yml
+++ b/mkdocs/mkdocs.yml
@@ -79,6 +79,11 @@ extra_css:
extra_javascript:
- javascripts/home.js
+ - javascripts/github-widget.js
+ - javascripts/gitea-widget.js
+
+hooks:
+ - docs/hooks/repo_widget_hook.py
# Markdown Extensions
markdown_extensions:
@@ -131,14 +136,6 @@ extra:
- icon: fontawesome/solid/paper-plane
link: https://listmonk.bnkops.com/subscription/form
name: Newsletter
- # Removed analytics as plausible is not built-in
- consent:
- title: Cookie consent
- description: >-
- We use cookies to recognize your repeated visits and preferences, as well
- as to measure the effectiveness of our documentation and whether users
- find what they're searching for. With your consent, you're helping us to
- make our documentation better.
# Copyright
copyright: >
@@ -148,22 +145,31 @@ copyright: >
# Navigation - Updated to match existing files
nav:
- Home: index.md
- - Getting Started: getting-started.md
- - Philosophy: philosophy.md
+ - Philosophy:
+ - phil/index.md
+ - Who Reads Your Secrets: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/If%20you%20do%20politics%20who%20is%20reading%20your%20secrets%20-%20why%20you%20should%20de-corp%20your%20software%20stack/
+ - How To Not Get Got Making Content: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/How%20not%20to%20get%20got%20making%20content%20v2/
+ - Digital Organizing: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/Distributed%20Digital%20Organizing%20is%20The%20Way%20Out/#why-not-give-it-a-shot
+ - What is Security Culture: https://docs.bnkops.com/archive/repo.archive/Zines%20We%20Like%20%F0%9F%98%8E/What%20Is%20Security%20Culture%20%E2%98%A0/#what-is-security-culture
+ - Getting Started:
+ - build/index.md
+ - Build Server: build/build-server.md
+ - Services:
+ - services/index.md
+ - Homepage: services/homepage.md
+ - Code Server: services/code-server.md
+ - MkDocs: services/mkdocs.md
+ - Static Server: services/static-server.md
+ - Listmonk: services/listmonk.md
+ - PostgreSQL: services/postgresql.md
+ - n8n: services/n8n.md
+ - NocoDB: services/nocodb.md
+ - Gitea: services/gitea.md
+ - Map Viewer: services/map.md
+ - Mini QR: services/mini-qr.md
+ - Configuration:
+ - config/index.md
+ - Cloudflare: config/cloudflare-config.md
- Cost Comparison: cost-comparison.md
- - Services:
- - services/index.md
- - Homepage: services/homepage.md
- - Code Server: services/code-server.md
- - MkDocs: services/mkdocs.md
- - Static Server: services/static-server.md
- - Listmonk: services/listmonk.md
- - PostgreSQL: services/postgresql.md
- - n8n: services/n8n.md
- - NocoDB: services/nocodb.md
- - Gitea: services/gitea.md
- - Map Viewer: services/map.md
- - Mini QR: services/mini-qr.md
- - Cloudflare Tunnels: cloudflare/index.md
- Blog:
- - blog/index.md
+ - blog/index.md
diff --git a/mkdocs/site/404.html b/mkdocs/site/404.html
index e7f8a05..3760699 100644
--- a/mkdocs/site/404.html
+++ b/mkdocs/site/404.html
@@ -258,17 +258,20 @@ Changemaker Archive.
Learn more
-
-
-
+
+
+
+
+
- Getting Started
+ Philosophy
-
-
+
+
+
@@ -277,17 +280,20 @@ Changemaker Archive.
Learn more
-
-
-
+
+
+
+
+
- Philosophy
+ Getting Started
-
-
+
+
+
@@ -317,47 +323,6 @@ Changemaker Archive.
Learn more
-
-
-
-
-
-
-
- Services
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cloudflare Tunnels
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -452,72 +417,6 @@ Changemaker Archive. Learn more
-
-
-
-
-
-
- Getting Started
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Philosophy
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cost Comparison
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -526,20 +425,6 @@ Changemaker Archive.
Learn more
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -567,12 +452,72 @@ Changemaker Archive.
Learn more
-
+
- Services
+ Philosophy
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Getting Started
@@ -595,12 +540,12 @@ Changemaker Archive. Learn more
-
+
- Cloudflare Tunnels
+ Cost Comparison
@@ -761,51 +706,6 @@ Changemaker Archive. Learn more
-
-
-
@@ -815,6 +715,10 @@ Changemaker Archive. Learn more
+
+
+
+