a tonne of improvements! We got maps updaTed, a tonne of documentaiton done, and several small upgrades to hook logic and other things. Fixed the looping problem for mkdocs and claude is not integrated with coder; if people wanna have a ai anyway

This commit is contained in:
admin 2025-07-02 11:49:22 -06:00
parent 9963c57b9b
commit ea6e5f17b2
94 changed files with 19491 additions and 360 deletions

View File

@ -83,7 +83,7 @@ services:
- "${MKDOCS_PORT:-4000}:8000"
environment:
- SITE_URL=${BASE_DOMAIN:-https://changeme.org}
command: serve --dev-addr=0.0.0.0:8000 --watch-theme --livereload --dirty
command: serve --dev-addr=0.0.0.0:8000 --watch-theme --livereload
networks:
- changemaker-lite
restart: unless-stopped

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

509
mkdocs/docs/adv/ansible.md Normal file
View File

@ -0,0 +1,509 @@
# Setting Up Ansible with Tailscale for Remote Server Management
## Overview
This guide walks you through setting up Ansible to manage remote servers (like ThinkCentre units) using Tailscale for secure networking. This approach provides reliable remote access without complex port forwarding or VPN configurations.
In plainer language; this allows you to manage several Changemaker nodes remotely. If you are a full time campaigner, this can enable you to manage several campaigns infrastructure from a central location while each user gets their own Changemaker box.
## What You'll Learn
- How to set up Ansible for infrastructure automation
- How to configure secure remote access using Tailscale
- How to troubleshoot common SSH and networking issues
- Why this approach is better than alternatives like Cloudflare Tunnels for simple SSH access
## Prerequisites
- **Master Node**: Your main computer running Ubuntu/Linux (control machine)
- **Target Nodes**: Remote servers/ThinkCentres running Ubuntu/Linux
- **Both machines**: Must have internet access
- **User Account**: Same username on all machines (recommended)
## Part 1: Initial Setup on Master Node
### 1. Create Ansible Directory Structure
```bash
# Create project directory
mkdir ~/ansible_quickstart
cd ~/ansible_quickstart
# Create directory structure
mkdir -p group_vars host_vars roles playbooks
```
### 2. Install Ansible
```bash
sudo apt update
sudo apt install ansible
```
### 3. Generate SSH Keys (if not already done)
```bash
# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
# Display public key (save this for later)
cat ~/.ssh/id_rsa.pub
```
## Part 2: Target Node Setup (Physical Access Required Initially)
### 1. Enable SSH on Target Node
Access each target node physically (monitor + keyboard):
```bash
# Update system
sudo apt update && sudo apt upgrade -y
# Install and enable SSH
sudo apt install openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh
# Check SSH status
sudo systemctl status ssh
```
### 2. Configure SSH Key Authentication
```bash
# Create .ssh directory
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Create authorized_keys file
nano ~/.ssh/authorized_keys
```
Paste your public key from the master node, then:
```bash
# Set proper permissions
chmod 600 ~/.ssh/authorized_keys
```
### 3. Configure SSH Security
```bash
# Edit SSH config
sudo nano /etc/ssh/sshd_config
```
Ensure these lines are uncommented:
```
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
```
```bash
# Restart SSH service
sudo systemctl restart ssh
```
### 4. Configure Firewall
```bash
# Check firewall status
sudo ufw status
# Allow SSH through firewall
sudo ufw allow ssh
# Fix home directory permissions (required for SSH keys)
chmod 755 ~/
```
## Part 3: Test Local SSH Connection
Before proceeding with remote access, test SSH connectivity locally:
```bash
# From master node, test SSH to target
ssh username@<target-local-ip>
```
**Common Issues and Solutions:**
- **Connection hangs**: Check firewall rules (`sudo ufw allow ssh`)
- **Permission denied**: Verify SSH keys and file permissions
- **SSH config errors**: Ensure `PubkeyAuthentication yes` is set
## Part 4: Set Up Tailscale for Remote Access
### Why Tailscale Over Alternatives
We initially tried Cloudflare Tunnels but encountered complexity with:
- DNS routing issues
- Complex configuration for SSH
- Same-network testing problems
- Multiple configuration approaches with varying success
**Tailscale is superior because:**
- Zero configuration mesh networking
- Works from any network
- Persistent IP addresses
- No port forwarding needed
- Free for personal use
### 1. Install Tailscale on Master Node
```bash
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Connect to Tailscale network
sudo tailscale up
```
Follow the authentication URL to connect with your Google/Microsoft/GitHub account.
### 2. Install Tailscale on Target Nodes
**On each target node:**
```bash
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Connect to Tailscale network
sudo tailscale up
```
Authenticate each device through the provided URL.
### 3. Get Tailscale IP Addresses
**On each machine:**
```bash
# Get your Tailscale IP
tailscale ip -4
```
Each device receives a persistent IP like `100.x.x.x`.
## Part 5: Configure Ansible
### 1. Create Inventory File
```bash
# Create inventory.ini
cd ~/ansible_quickstart
nano inventory.ini
```
**Content:**
```ini
[thinkcenter]
tc-node1 ansible_host=100.x.x.x ansible_user=your-username
tc-node2 ansible_host=100.x.x.x ansible_user=your-username
[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_host_key_checking=False
```
Replace:
- `100.x.x.x` with actual Tailscale IPs
- `your-username` with your actual username
### 2. Test Ansible Connectivity
```bash
# Test connection to all nodes
ansible all -i inventory.ini -m ping
```
**Expected output:**
```
tc-node1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
```
## Part 6: Create and Run Playbooks
### 1. Simple Information Gathering Playbook
```bash
mkdir -p playbooks
nano playbooks/info-playbook.yml
```
**Content:**
```yaml
---
- name: Gather Node Information
hosts: all
tasks:
- name: Get system information
setup:
- name: Display basic system info
debug:
msg: |
Hostname: {{ ansible_hostname }}
Operating System: {{ ansible_distribution }} {{ ansible_distribution_version }}
Architecture: {{ ansible_architecture }}
Memory: {{ ansible_memtotal_mb }}MB
CPU Cores: {{ ansible_processor_vcpus }}
- name: Show disk usage
command: df -h /
register: disk_info
- name: Display disk usage
debug:
msg: "Root filesystem usage: {{ disk_info.stdout_lines[1] }}"
- name: Check uptime
command: uptime
register: uptime_info
- name: Display uptime
debug:
msg: "System uptime: {{ uptime_info.stdout }}"
```
### 2. Run the Playbook
```bash
ansible-playbook -i inventory.ini playbooks/info-playbook.yml
```
## Part 7: Advanced Playbook Example
### System Setup Playbook
```bash
nano playbooks/setup-node.yml
```
**Content:**
```yaml
---
- name: Setup ThinkCentre Node
hosts: all
become: yes
tasks:
- name: Update package cache
apt:
update_cache: yes
- name: Install essential packages
package:
name:
- htop
- vim
- curl
- git
- docker.io
state: present
- name: Add user to docker group
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
- name: Create management directory
file:
path: /opt/management
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
```
## Troubleshooting Guide
### SSH Issues
**Problem: SSH connection hangs**
- Check firewall: `sudo ufw status` and `sudo ufw allow ssh`
- Verify SSH service: `sudo systemctl status ssh`
- Test local connectivity first
**Problem: Permission denied (publickey)**
- Check SSH key permissions: `chmod 600 ~/.ssh/authorized_keys`
- Verify home directory permissions: `chmod 755 ~/`
- Ensure SSH config allows key auth: `PubkeyAuthentication yes`
**Problem: Bad owner or permissions on SSH config**
```bash
chmod 600 ~/.ssh/config
```
### Ansible Issues
**Problem: Host key verification failed**
- Add to inventory: `ansible_host_key_checking=False`
**Problem: Ansible command not found**
```bash
sudo apt install ansible
```
**Problem: Connection timeouts**
- Verify Tailscale connectivity: `ping <tailscale-ip>`
- Check if both nodes are connected: `tailscale status`
### Tailscale Issues
**Problem: Can't connect to Tailscale IP**
- Verify both devices are authenticated: `tailscale status`
- Check Tailscale is running: `sudo systemctl status tailscaled`
- Restart Tailscale: `sudo tailscale up`
## Scaling to Multiple Nodes
### Adding New Nodes
1. **Install Tailscale on new node**
2. **Set up SSH access** (repeat Part 2)
3. **Add to inventory.ini:**
```ini
[thinkcenter]
tc-node1 ansible_host=100.125.148.60 ansible_user=bunker-admin
tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin
tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin
```
### Group Management
```ini
[webservers]
tc-node1 ansible_host=100.x.x.x ansible_user=bunker-admin
tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin
[databases]
tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin
[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_host_key_checking=False
```
Run playbooks on specific groups:
```bash
ansible-playbook -i inventory.ini -l webservers playbook.yml
```
## Best Practices
### Security
- Use SSH keys, not passwords
- Keep Tailscale client updated
- Regular security updates via Ansible
- Use `become: yes` only when necessary
### Organization
```
ansible_quickstart/
├── inventory.ini
├── group_vars/
├── host_vars/
├── roles/
└── playbooks/
├── info-playbook.yml
├── setup-node.yml
└── maintenance.yml
```
### Monitoring and Maintenance
Create regular maintenance playbooks:
```yaml
- name: System maintenance
hosts: all
become: yes
tasks:
- name: Update all packages
apt:
upgrade: dist
update_cache: yes
- name: Clean package cache
apt:
autoclean: yes
autoremove: yes
```
## Alternative Approaches We Considered
### Cloudflare Tunnels
- **Pros**: Good for web services, handles NAT traversal
- **Cons**: Complex SSH setup, DNS routing issues, same-network problems
- **Use case**: Better for web applications than SSH access
### Traditional VPN
- **Pros**: Full network access
- **Cons**: Complex setup, port forwarding required, router configuration
- **Use case**: When you control the network infrastructure
### SSH Reverse Tunnels
- **Pros**: Simple concept
- **Cons**: Requires VPS, single point of failure, manual setup
- **Use case**: Temporary access or when other methods fail
## Conclusion
This setup provides:
- **Reliable remote access** from anywhere
- **Secure mesh networking** with Tailscale
- **Infrastructure automation** with Ansible
- **Easy scaling** to multiple nodes
- **No complex networking** required
The combination of Ansible + Tailscale is ideal for managing distributed infrastructure without the complexity of traditional VPN setups or the limitations of cloud-specific solutions.
## Quick Reference Commands
```bash
# Check Tailscale status
tailscale status
# Test Ansible connectivity
ansible all -i inventory.ini -m ping
# Run playbook on all hosts
ansible-playbook -i inventory.ini playbook.yml
# Run playbook on specific group
ansible-playbook -i inventory.ini -l groupname playbook.yml
# Run single command on all hosts
ansible all -i inventory.ini -m command -a "uptime"
# SSH to node via Tailscale
ssh username@100.x.x.x
```

3
mkdocs/docs/adv/index.md Normal file
View File

@ -0,0 +1,3 @@
# Advanced Configurations
We are also publishing how BNKops does several advanced workflows. These include things like assembling hardware, how to manage a network, how to manage several changemakers simultaneously, and integrating AI.

View File

@ -0,0 +1,676 @@
# Remote Development with VSCode over Tailscale
## Overview
This guide shows you how to set up Visual Studio Code for remote development on your servers using the Tailscale network. This allows you to develop directly on your remote ThinkCentre units as if they were local machines, with full access to files, terminals, and debugging capabilities.
## What You'll Learn
- How to configure VSCode for remote SSH connections
- How to set up remote development environments
- How to manage multiple remote servers efficiently
- How to troubleshoot common remote development issues
- Best practices for remote development workflows
## Prerequisites
- **Completed the Ansible + Tailscale setup** from the previous guide
- **VSCode installed** on your local machine (master node)
- **Working SSH access** to remote servers via Tailscale
- **Tailscale running** on both local and remote machines
## Verify Prerequisites
Before starting, ensure your setup is working:
```bash
# Check Tailscale connectivity
tailscale status
# Test SSH access
ssh bunker-admin@100.125.148.60
# Check VSCode is installed
code --version
```
## Part 1: Install and Configure Remote-SSH Extension
### 1. Install the Remote Development Extensions
**Option A: Install Remote Development Pack (Recommended)**
1. Open VSCode
2. Press **Ctrl+Shift+X** (or **Cmd+Shift+X** on Mac)
3. Search for **"Remote Development"**
4. Install the **Remote Development extension pack** by Microsoft
This pack includes:
- Remote - SSH
- Remote - SSH: Editing Configuration Files
- Remote - Containers
- Remote - WSL (Windows only)
**Option B: Install Individual Extension**
1. Search for **"Remote - SSH"**
2. Install **Remote - SSH** by Microsoft
### 2. Verify Installation
After installation, you should see:
- Remote Explorer icon in the Activity Bar (left sidebar)
- "Remote-SSH" commands in Command Palette (Ctrl+Shift+P)
## Part 2: Configure SSH Connections
### 1. Access SSH Configuration
**Method A: Through VSCode**
1. Press **Ctrl+Shift+P** to open Command Palette
2. Type **"Remote-SSH: Open SSH Configuration File..."**
3. Select your SSH config file (usually the first option)
**Method B: Direct File Editing**
```bash
# Edit SSH config file directly
nano ~/.ssh/config
```
### 2. Add Server Configurations
Add your servers to the SSH config file:
```
# Primary ThinkCentre Node
Host tc-node1
HostName 100.125.148.60
User bunker-admin
IdentityFile ~/.ssh/id_rsa
ForwardAgent yes
ServerAliveInterval 60
ServerAliveCountMax 3
# Additional nodes (add as needed)
Host tc-node2
HostName 100.x.x.x
User bunker-admin
IdentityFile ~/.ssh/id_rsa
ForwardAgent yes
ServerAliveInterval 60
ServerAliveCountMax 3
Host tc-node3
HostName 100.x.x.x
User bunker-admin
IdentityFile ~/.ssh/id_rsa
ForwardAgent yes
ServerAliveInterval 60
ServerAliveCountMax 3
```
**Configuration Options Explained:**
- `Host`: Friendly name for the connection
- `HostName`: Tailscale IP address
- `User`: Username on the remote server
- `IdentityFile`: Path to your SSH private key
- `ForwardAgent`: Enables SSH agent forwarding for Git operations
- `ServerAliveInterval`: Keeps connection alive (prevents timeouts)
- `ServerAliveCountMax`: Number of keepalive attempts
### 3. Set Proper SSH Key Permissions
```bash
# Ensure SSH config has correct permissions
chmod 600 ~/.ssh/config
# Verify SSH key permissions
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
```
## Part 3: Connect to Remote Servers
### 1. Connect via Command Palette
1. Press **Ctrl+Shift+P**
2. Type **"Remote-SSH: Connect to Host..."**
3. Select your server (e.g., `tc-node1`)
4. VSCode will open a new window connected to the remote server
### 2. Connect via Remote Explorer
1. Click the **Remote Explorer** icon in Activity Bar
2. Expand **SSH Targets**
3. Click the **connect** icon next to your server name
### 3. Connect via Quick Menu
1. Click the **remote indicator** in bottom-left corner (looks like ><)
2. Select **"Connect to Host..."**
3. Choose your server from the list
### 4. First Connection Process
On first connection, VSCode will:
1. **Verify the host key** (click "Continue" if prompted)
2. **Install VSCode Server** on the remote machine (automatic)
3. **Open a remote window** with access to the remote file system
**Expected Timeline:**
- First connection: 1-3 minutes (installs VSCode Server)
- Subsequent connections: 10-30 seconds
## Part 4: Remote Development Environment Setup
### 1. Open Remote Workspace
Once connected:
```bash
# In the VSCode terminal (now running on remote server)
# Navigate to your project
cd /home/bunker-admin/projects
# Open current directory in VSCode
code .
# Or open a specific project
code /opt/myproject
```
### 2. Install Extensions on Remote Server
Extensions need to be installed separately on the remote server:
**Essential Development Extensions:**
1. **Python** (Microsoft) - Python development
2. **GitLens** (GitKraken) - Enhanced Git capabilities
3. **Docker** (Microsoft) - Container development
4. **Prettier** - Code formatting
5. **ESLint** - JavaScript linting
6. **Auto Rename Tag** - HTML/XML tag editing
**To Install:**
1. Go to Extensions (Ctrl+Shift+X)
2. Find your desired extension
3. Click **"Install in SSH: tc-node1"** (not local install)
### 3. Configure Git on Remote Server
```bash
# In VSCode terminal (remote)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# Test Git connectivity
git clone https://github.com/yourusername/yourrepo.git
```
## Part 5: Remote Development Workflows
### 1. File Management
**File Explorer:**
- Shows remote server's file system
- Create, edit, delete files directly
- Drag and drop between local and remote (limited)
**File Transfer:**
```bash
# Upload files to remote (from local terminal)
scp localfile.txt bunker-admin@100.125.148.60:/home/bunker-admin/
# Download files from remote
scp bunker-admin@100.125.148.60:/remote/path/file.txt ./local/path/
```
### 2. Terminal Usage
**Integrated Terminal:**
- Press **Ctrl+`** to open terminal
- Runs directly on remote server
- Multiple terminals supported
- Full shell access (bash, zsh, etc.)
**Common Remote Terminal Commands:**
```bash
# Check system resources
htop
df -h
free -h
# Install packages
sudo apt update
sudo apt install nodejs npm
# Start services
sudo systemctl start nginx
sudo docker-compose up -d
```
### 3. Port Forwarding
**Automatic Port Forwarding:**
VSCode automatically detects and forwards common development ports.
**Manual Port Forwarding:**
1. Open **Ports** tab in terminal panel
2. Click **"Forward a Port"**
3. Enter port number (e.g., 3000, 8080, 5000)
4. Access via `http://localhost:port` on local machine
**Example: Web Development**
```bash
# Start a web server on remote (port 3000)
npm start
# VSCode automatically suggests forwarding port 3000
# Access at http://localhost:3000 on your local machine
```
### 4. Debugging Remote Applications
**Python Debugging:**
```json
// .vscode/launch.json on remote server
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}
```
**Node.js Debugging:**
```json
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Program",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/app.js"
}
]
}
```
## Part 6: Advanced Configuration
### 1. Workspace Settings
Create remote-specific settings:
```json
// .vscode/settings.json (on remote server)
{
"python.defaultInterpreterPath": "/usr/bin/python3",
"terminal.integrated.shell.linux": "/bin/bash",
"files.autoSave": "afterDelay",
"editor.formatOnSave": true,
"remote.SSH.remotePlatform": {
"tc-node1": "linux"
}
}
```
### 2. Multi-Server Management
**Switch Between Servers:**
1. Click remote indicator (bottom-left)
2. Select **"Connect to Host..."**
3. Choose different server
**Compare Files Across Servers:**
1. Open file from server A
2. Connect to server B in new window
3. Open corresponding file
4. Use **"Compare with..."** command
### 3. Sync Configuration
**Settings Sync:**
1. Enable Settings Sync in VSCode
2. Settings, extensions, and keybindings sync to remote
3. Consistent experience across all servers
## Part 7: Project-Specific Setups
### 1. Python Development
```bash
# On remote server
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install packages
pip install flask django requests
# VSCode automatically detects Python interpreter
```
**VSCode Python Configuration:**
```json
// .vscode/settings.json
{
"python.defaultInterpreterPath": "./venv/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true
}
```
### 2. Node.js Development
```bash
# On remote server
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Create project
mkdir myapp && cd myapp
npm init -y
npm install express
```
### 3. Docker Development
```bash
# On remote server
# Install Docker (if not already done via Ansible)
sudo apt install docker.io docker-compose
sudo usermod -aG docker $USER
# Create Dockerfile
cat > Dockerfile << EOF
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
EOF
```
**VSCode Docker Integration:**
- Install Docker extension on remote
- Right-click Dockerfile → "Build Image"
- Manage containers from VSCode interface
## Part 8: Troubleshooting Guide
### Common Connection Issues
**Problem: "Could not establish connection to remote host"**
**Solutions:**
```bash
# Check Tailscale connectivity
tailscale status
ping 100.125.148.60
# Test SSH manually
ssh bunker-admin@100.125.148.60
# Check SSH config syntax
ssh -T tc-node1
```
**Problem: "Permission denied (publickey)"**
**Solutions:**
```bash
# Check SSH key permissions
chmod 600 ~/.ssh/id_rsa
chmod 600 ~/.ssh/config
# Verify SSH agent
ssh-add ~/.ssh/id_rsa
ssh-add -l
# Test SSH connection verbosely
ssh -v bunker-admin@100.125.148.60
```
**Problem: "Host key verification failed"**
**Solutions:**
```bash
# Remove old host key
ssh-keygen -R 100.125.148.60
# Or disable host key checking (less secure)
# Add to SSH config:
# StrictHostKeyChecking no
```
### VSCode-Specific Issues
**Problem: Extensions not working on remote**
**Solutions:**
1. Install extensions specifically for remote server
2. Check extension compatibility with remote development
3. Reload VSCode window: Ctrl+Shift+P → "Developer: Reload Window"
**Problem: Slow performance**
**Solutions:**
- Use `.vscode/settings.json` to exclude large directories:
```json
{
"files.watcherExclude": {
"**/node_modules/**": true,
"**/.git/objects/**": true,
"**/dist/**": true
}
}
```
**Problem: Terminal not starting**
**Solutions:**
```bash
# Check shell path in remote settings
"terminal.integrated.shell.linux": "/bin/bash"
# Or let VSCode auto-detect
"terminal.integrated.defaultProfile.linux": "bash"
```
### Network and Performance Issues
**Problem: Connection timeouts**
**Solutions:**
Add to SSH config:
```
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
```
**Problem: File transfer slow**
**Solutions:**
- Use `.vscodeignore` to exclude unnecessary files
- Compress large files before transfer
- Use `rsync` for large file operations:
```bash
rsync -avz --progress localdir/ bunker-admin@100.125.148.60:remotedir/
```
## Part 9: Best Practices
### Security Best Practices
1. **Use SSH keys, never passwords**
2. **Keep SSH agent secure**
3. **Regular security updates on remote servers**
4. **Use VSCode's secure connection verification**
### Performance Optimization
1. **Exclude unnecessary files**:
```json
// .vscode/settings.json
{
"files.watcherExclude": {
"**/node_modules/**": true,
"**/.git/**": true,
"**/dist/**": true,
"**/build/**": true
},
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true
}
}
```
2. **Use remote workspace for large projects**
3. **Close unnecessary windows and extensions**
4. **Use efficient development workflows**
### Development Workflow
1. **Use version control effectively**:
```bash
# Always work in Git repositories
git status
git add .
git commit -m "feature: add new functionality"
git push origin main
```
2. **Environment separation**:
```bash
# Development
ssh tc-node1
cd /home/bunker-admin/dev-projects
# Production
ssh tc-node2
cd /opt/production-apps
```
3. **Backup important work**:
```bash
# Regular backups via Git
git push origin main
# Or manual backup
scp -r bunker-admin@100.125.148.60:/important/project ./backup/
```
## Part 10: Team Collaboration
### Shared Development Servers
**SSH Config for Team:**
```
# Shared development server
Host team-dev
HostName 100.x.x.x
User dev-user
IdentityFile ~/.ssh/team_dev_key
ForwardAgent yes
# Personal development
Host my-dev
HostName 100.125.148.60
User bunker-admin
IdentityFile ~/.ssh/id_rsa
```
### Project Structure
```
/opt/projects/
├── project-a/
│ ├── dev/ # Development branch
│ ├── staging/ # Staging environment
│ └── docs/ # Documentation
├── project-b/
└── shared-tools/ # Common utilities
```
### Access Management
```bash
# Create shared project directory
sudo mkdir -p /opt/projects
sudo chown -R :developers /opt/projects
sudo chmod -R g+w /opt/projects
# Add users to developers group
sudo usermod -a -G developers bunker-admin
```
## Quick Reference
### Essential VSCode Remote Commands
```bash
# Command Palette shortcuts
Ctrl+Shift+P → "Remote-SSH: Connect to Host..."
Ctrl+Shift+P → "Remote-SSH: Open SSH Configuration File..."
Ctrl+Shift+P → "Remote-SSH: Kill VS Code Server on Host..."
# Terminal
Ctrl+` → Open integrated terminal
Ctrl+Shift+` → Create new terminal
# File operations
Ctrl+O → Open file
Ctrl+S → Save file
Ctrl+Shift+E → Focus file explorer
```
### SSH Connection Quick Test
```bash
# Test connectivity
ssh -T tc-node1
# Connect with verbose output
ssh -v bunker-admin@100.125.148.60
# Check SSH config
ssh -F ~/.ssh/config tc-node1
```
### Port Forwarding Commands
```bash
# Manual port forwarding
ssh -L 3000:localhost:3000 bunker-admin@100.125.148.60
# Background tunnel
ssh -f -N -L 8080:localhost:80 bunker-admin@100.125.148.60
```
## Conclusion
This remote development setup provides:
- **Full development environment** on remote servers
- **Seamless file access** and editing capabilities
- **Integrated debugging** and terminal access
- **Port forwarding** for web development
- **Extension ecosystem** available remotely
- **Secure connections** through Tailscale network
The combination of VSCode Remote Development with Tailscale networking creates a powerful, flexible development environment that works from anywhere while maintaining security and performance.
Whether you're developing Python applications, Node.js services, or managing Docker containers, this setup provides a professional remote development experience that rivals local development while leveraging the power and resources of your remote servers.

View File

@ -6,11 +6,11 @@
"language": "HTML",
"stars_count": 0,
"forks_count": 0,
"open_issues_count": 0,
"updated_at": "2025-06-30T21:38:32-06:00",
"open_issues_count": 1,
"updated_at": "2025-07-01T09:33:43-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-30T21:38:32-06:00"
"last_build_update": "2025-07-01T09:33:43-06:00"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "anthropics/claude-code",
"name": "claude-code",
"description": "Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.",
"html_url": "https://github.com/anthropics/claude-code",
"language": "Shell",
"stars_count": 16934,
"forks_count": 929,
"open_issues_count": 1495,
"updated_at": "2025-07-02T17:38:19Z",
"created_at": "2025-02-22T17:41:21Z",
"clone_url": "https://github.com/anthropics/claude-code.git",
"ssh_url": "git@github.com:anthropics/claude-code.git",
"default_branch": "main",
"last_build_update": "2025-07-02T16:32:38Z"
}

View File

@ -4,10 +4,10 @@
"description": "VS Code in the browser",
"html_url": "https://github.com/coder/code-server",
"language": "TypeScript",
"stars_count": 72508,
"forks_count": 6062,
"open_issues_count": 142,
"updated_at": "2025-07-01T15:16:52Z",
"stars_count": 72530,
"forks_count": 6064,
"open_issues_count": 143,
"updated_at": "2025-07-02T17:11:14Z",
"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",

View File

@ -4,13 +4,13 @@
"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": 24583,
"forks_count": 1519,
"stars_count": 24608,
"forks_count": 1520,
"open_issues_count": 1,
"updated_at": "2025-07-01T15:20:04Z",
"updated_at": "2025-07-02T17:20:41Z",
"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-07-01T12:14:06Z"
"last_build_update": "2025-07-02T12:13:57Z"
}

View File

@ -4,13 +4,13 @@
"description": "Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD",
"html_url": "https://github.com/go-gitea/gitea",
"language": "Go",
"stars_count": 49327,
"forks_count": 5887,
"open_issues_count": 2706,
"updated_at": "2025-07-01T14:28:19Z",
"stars_count": 49339,
"forks_count": 5891,
"open_issues_count": 2711,
"updated_at": "2025-07-02T16:36:32Z",
"created_at": "2016-11-01T02:13:26Z",
"clone_url": "https://github.com/go-gitea/gitea.git",
"ssh_url": "git@github.com:go-gitea/gitea.git",
"default_branch": "main",
"last_build_update": "2025-07-01T13:44:05Z"
"last_build_update": "2025-07-02T00:37:56Z"
}

View File

@ -4,10 +4,10 @@
"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": 17242,
"forks_count": 1657,
"open_issues_count": 104,
"updated_at": "2025-07-01T14:26:50Z",
"stars_count": 17248,
"forks_count": 1658,
"open_issues_count": 105,
"updated_at": "2025-07-02T10:32:44Z",
"created_at": "2019-06-26T05:08:39Z",
"clone_url": "https://github.com/knadh/listmonk.git",
"ssh_url": "git@github.com:knadh/listmonk.git",

View File

@ -4,13 +4,13 @@
"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": 113903,
"forks_count": 33364,
"open_issues_count": 1058,
"updated_at": "2025-07-01T15:22:32Z",
"stars_count": 114294,
"forks_count": 33577,
"open_issues_count": 1070,
"updated_at": "2025-07-02T17:42:44Z",
"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-07-01T15:23:16Z"
"last_build_update": "2025-07-02T17:17:32Z"
}

View File

@ -4,13 +4,13 @@
"description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 Open Source Airtable Alternative",
"html_url": "https://github.com/nocodb/nocodb",
"language": "TypeScript",
"stars_count": 55480,
"forks_count": 3987,
"open_issues_count": 714,
"updated_at": "2025-07-01T14:03:05Z",
"stars_count": 55505,
"forks_count": 3994,
"open_issues_count": 718,
"updated_at": "2025-07-02T17:05:35Z",
"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-07-01T14:26:19Z"
"last_build_update": "2025-07-02T16:01:20Z"
}

View File

@ -4,13 +4,13 @@
"description": "Documentation that simply works",
"html_url": "https://github.com/squidfunk/mkdocs-material",
"language": "Python",
"stars_count": 23763,
"forks_count": 3786,
"open_issues_count": 4,
"updated_at": "2025-07-01T13:38:53Z",
"stars_count": 23785,
"forks_count": 3787,
"open_issues_count": 5,
"updated_at": "2025-07-02T17:21:29Z",
"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-07-01T12:56:28Z"
"last_build_update": "2025-07-02T16:12:25Z"
}

View File

@ -68,7 +68,7 @@ Before we dive into the technical setup, let's be clear about what you're doing
- **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)
Want some help getting started with a baseline buildout for a Ubunut server? You can use our [BNKops Server Build Script](./server.md)
- Other Linux distributions with systemd support
- WSL2 on Windows (limited functionality)
@ -90,7 +90,7 @@ Before we dive into the technical setup, let's be clear about what you're doing
### 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!
Want some help getting started with a baseline buildout for a Ubunutu server? You can use our [BNKops Server Build Script](./server.md) to roll out a configured server in about 20 mins!
1. **Docker Engine** (24.0+)

View File

@ -10,9 +10,13 @@ Map is BNKops canvassing application. It is built from the ground up to serve ou
## NocoDB Table Setup
### Required Columns
!!! warning "Case Sensitive"
When entering in the required columns, make sure that you enter in exact information. Case sensitivity matters for mapping the values to the map itself.
Create a table in NocoDB with these required columns. The format here is the `Name of the column - column type - details`:
1. **Geo Location** (geo-data) - Format: "latitude;longitude"
1. **Geo-Location** (geo-data) - Format: "latitude;longitude"
2. **latitude** (Decimal) - Precision: 10, Scale: 8
3. **longitude** (Decimal) - Precision: 11, Scale: 8

View File

@ -136,7 +136,9 @@ Login to Cloudflare
cloudflared login
```
### Configuration
- Setting up the [[service.cloudflared]] enables your cloudflared tunnel to automatically run on reboot
The `./config.sh` and `./start-production.sh` scripts will properly configure a Cloudflare tunnel and service to put your system online. More info in the [Cloudflare Configuration.](../config/cloudflare-config.md)
## [Pandoc](https://pandoc.org/)
If you need to convert files from one markup format into another, pandoc is your swiss-army knife.

98
mkdocs/docs/build/site.md vendored Normal file
View File

@ -0,0 +1,98 @@
# Building the Site with MkDocs Material
Welcome! This guide will help you get started building and customizing your site using [MkDocs Material](https://squidfunk.github.io/mkdocs-material/).
---
## 🚀 How to Build Your Site (Step by Step)
1. **Open your Coder instance.**
For example: coder.yourdomain.com
2. **Go to the mkdocs folder:**
In the terminal (for a new terminal press Crtl - Shift - ~), type:
```sh
cd mkdocs
```
3. **Build the site:**
Type:
```sh
mkdocs build
```
This creates the static website from your documents and places them in the `mkdocs/site` directory.
**Preview your site locally:**
Visit [localhost:4000](localhost:4000) for local development or `live.youdomain.com` to see a public live load.
- All documentation in the `mkdocs/docs` folder is included automatically.
- The site uses the beautiful and easy-to-use Material for MkDocs theme.
[Material for MkDocs Documentation :material-arrow-right:](https://squidfunk.github.io/mkdocs-material/){ .md-button }
!!! note "Build vs Serve"
Your website is built in stages. Any edits to documents in the mkdocs directory are instantly served and visible at [localhost:4000](localhost:4000) or if in production mode live.yourdomain.com. **The live site is not meant as a public access point and will crash if too many requests are made to it**.
Running `mkdocs build` pushes any changes to the `site` directory, which then a ngnix server pushes them to the production server for public access at your root domain (yourdomain.com).
You can think of it as serve/live = draft for personal review and build = save/push to production for the public.
This combination allows for rapid development of documentation while ensuring your live site does not get updated until your content is ready.
---
## 🧹 Resetting the Site
If you want to start fresh:
1. **Delete all folders EXCEPT these folders:**
- `/blog`
- `/javascripts`
- `/hooks`
- `/assets`
- `/stylesheets`
- `/overrides`
2. **Reset the landing page:**
- Open the main `index.md` file and remove everything at the very top (the "front matter").
- *Or* edit `/overrides/home.html` to change the landing page.
3. **Reset the `mkdocs.yml`**
- Open `mkdocs.yml` and delete the `nav` section entirely.
- This action will enable mkdocs to build your site navigation based on file names in the root directory.
---
## 🤖 Using AI to Help Build Your Site
- If you have a [claude.ai](https://claude.ai/) subscription, you can use powerful AI in your Coder terminal to write or rewrite pages, including a new `home.html`.
- All you need to do is open the terminal and type:
```sh
claude
```
- You can also try local AI tools like [Ollama](https://ollama.com/) for on-demand help.
---
## 🛠️ First-Time Setup Tips
- **Navigation:**
Open `mkdocs.yml` and remove the `nav` section to start with a blank menu. Add your own pages as you go.
- **Customize the look:**
Check out the [Material for MkDocs customization guide](https://squidfunk.github.io/mkdocs-material/setup/changing-the-theme/).
- **Live preview:**
Use `mkdocs serve` (see above) to see changes instantly as you edit.
- **Custom files:**
Put your own CSS, JavaScript, or HTML in `/assets`, `/stylesheets`, `/javascripts`, or `/overrides`.
[Quick Start Guide :material-arrow-right:](https://squidfunk.github.io/mkdocs-material/creating-your-site/){ .md-button }
---
## 📚 More Resources
- [MkDocs User Guide :material-arrow-right:](https://www.mkdocs.org/user-guide/){ .md-button }
- [Material for MkDocs Features :material-arrow-right:](https://squidfunk.github.io/mkdocs-material/setup/){ .md-button }
- [BNKops MKdocs Configuration & Customization](../config/mkdocs.md){ .md-button }
---
Happy building!

113
mkdocs/docs/config/coder.md Normal file
View File

@ -0,0 +1,113 @@
# Coder Configuration
This section describes the configuration and features of the code-server environment.
## Accessing Code Server
- **URL:** `http://localhost:8080`
- **Authentication:** Password-based (see below for password retrieval)
### Retrieving the Code Server Password
After the first build, the code-server password is stored in:
```
configs/code-server/.config/code-server/config.yaml
```
Look for the `password:` field in that file. For example:
```yaml
password: 0c0dca951a2d12eff1665817
```
> **Note:** It is recommended **not** to change this password manually, as it is securely generated.
## Main Configuration Options
- `bind-addr`: The address and port code-server listens on (default: `127.0.0.1:8080`)
- `auth`: Authentication method (default: `password`)
- `password`: The login password (see above)
- `cert`: Whether to use HTTPS (default: `false`)
## Installed Tools and Features
The code-server environment includes:
- **Node.js 18+** and **npm**
- **Claude Code** (`@anthropic-ai/claude-code`) globally installed
- **Python 3** and tools:
- `python3-pip`, `python3-venv`, `python3-full`, `pipx`
- **Image and PDF processing libraries**:
- `CairoSVG`, `Pillow`, `libcairo2-dev`, `libfreetype6-dev`, `libjpeg-dev`, `libpng-dev`, `libwebp-dev`, `libtiff5-dev`, `libopenjp2-7-dev`, `liblcms2-dev`
- `weasyprint`, `fonts-roboto`
- **Git** for version control and plugin management
- **Build tools**: `build-essential`, `pkg-config`, `python3-dev`, `zlib1g-dev`
- **MkDocs Material** and a wide range of MkDocs plugins, installed in a dedicated Python virtual environment at `/home/coder/.venv/mkdocs`
- **Convenience script**: `run-mkdocs` for running MkDocs commands easily
### Using MkDocs
The virtual environment for MkDocs is automatically added to your `PATH`. You can run MkDocs commands directly, or use the provided script. For example, to build the site, from a clean terminal we would rung:
```bash
cd mkdocs
mkdocs build
```
## Claude Code Integration
<div class="github-widget" data-repo="anthropics/claude-code"></div>
The code-server environment comes with **Claude Code** (`@anthropic-ai/claude-code`) globally installed via npm.
### What is Claude Code?
Claude Code is an AI-powered coding assistant by Anthropic, designed to help you write, refactor, and understand code directly within your development environment.
### Usage
- Access Claude Code features through the command palette or sidebar in code-server.
- Use Claude Code to generate code, explain code snippets, or assist with documentation and refactoring tasks.
- For more information, refer to the [Claude Code documentation](https://docs.anthropic.com/claude/docs/claude-code).
> **Note:** Claude Code requires an API key or account with Anthropic for full functionality. Refer to the extension settings for configuration.
### Call Claude
To use claude simply type claude into the terminal and follow instructions.
```bash
claude
```
## Shell Environment
The `.bashrc` is configured to include the MkDocs virtual environment and user-local binaries in your `PATH` for convenience.
## Code Navigation and Editing Features
The code-server environment provides robust code navigation and editing features, including:
- **IntelliSense**: Smart code completions based on variable types, function definitions, and imported modules.
- **Code Navigation**: Easily navigate to definitions, references, and symbol searches within your codebase.
- **Debugging Support**: Integrated debugging support for Node.js and Python, with breakpoints, call stacks, and interactive consoles.
- **Terminal Access**: Built-in terminal access to run commands, scripts, and version control operations.
## Collaboration Features
Code-server includes features to support collaboration:
- **Live Share**: Collaborate in real-time with others, sharing your code and terminal sessions.
- **ChatGPT Integration**: AI-powered code assistance and chat-based collaboration.
## Security Considerations
When using code-server, consider the following security aspects:
- **Password Management**: The default password is securely generated. Do not share it or expose it in public repositories.
- **Network Security**: Ensure that your firewall settings allow access to the code-server port (default: 8080) only from trusted networks.
- **Data Privacy**: Be cautious when uploading sensitive data or code to the server. Use environment variables or secure vaults for sensitive information.
For more detailed information on configuring and using code-server, refer to the official [code-server documentation](https://coder.com/docs/).

View File

@ -0,0 +1,143 @@
# MkDocs Customization & Features Overview
BNKops has been building our own features, widgets, and css styles for MKdocs material theme.
This document explains the custom styling, repository widgets, and key features enabled in this MkDocs site.
For more info on how to build your site see [Site Build](../build/site.md)
---
## Using the Repository Widget in Documentation
You can embed repository widgets directly in your Markdown documentation to display live repository stats and metadata.
To do this, add a `div` with the appropriate class and `data-repo` attribute for the repository you want to display.
**Example (for a Gitea repository):**
```html
<div class="gitea-widget" data-repo="admin/changemaker.lite"></div>
```
This will render a styled card with information about the `admin/changemaker.lite` repository:
<div class="gitea-widget" data-repo="admin/changemaker.lite"></div>
**Options:**
You can control the widget display with additional data attributes:
- `data-show-description="false"` — Hide the description
- `data-show-language="false"` — Hide the language
- `data-show-last-update="false"` — Hide the last update date
**Example with options:**
```html
<div class="gitea-widget" data-repo="admin/changemaker.lite" data-show-description="false"></div>
```
For GitHub repositories, use the `github-widget` class:
```html
<div class="github-widget" data-repo="lyqht/mini-qr"></div>
```
---
## Custom CSS Styling (`stylesheets/extra.css`)
The `extra.css` file provides extensive custom styling for the site, including:
- **Login and Git Code Buttons**:
Custom styles for `.login-button` and `.git-code-button` to create visually distinct, modern buttons with hover effects.
- **Code Block Improvements**:
Forces code blocks to wrap text (`white-space: pre-wrap`) and ensures inline code and tables with code display correctly on all devices.
- **GitHub Widget Styles**:
Styles for `.github-widget` and its subcomponents, including:
- Card-like container with gradient backgrounds and subtle box-shadows.
- Header with icon, repo link, and stats (stars, forks, issues).
- Description area with accent border.
- Footer with language, last update, and license info.
- Loading and error states with spinners and error messages.
- Responsive grid layout for multiple widgets.
- Compact variant for smaller displays.
- Dark mode adjustments.
- **Gitea Widget Styles**:
Similar to GitHub widget, but with Gitea branding (green accents).
Includes `.gitea-widget`, `.gitea-widget-container`, and related classes for header, stats, description, footer, loading, and error states.
- **Responsive Design**:
Media queries ensure widgets and tables look good on mobile devices.
---
## Repository Widgets
### Data Generation (`hooks/repo_widget_hook.py`)
- **Purpose**:
During the MkDocs build, this hook fetches metadata for a list of GitHub and Gitea repositories and writes JSON files to `docs/assets/repo-data/`.
- **How it works**:
- Runs before build (unless in `serve` mode).
- Fetches repo data (stars, forks, issues, language, etc.) via GitHub/Gitea APIs.
- Outputs a JSON file per repo (e.g., `lyqht-mini-qr.json`).
- Used by frontend widgets for fast, client-side rendering.
### GitHub Widget (`javascripts/github-widget.js`)
- **Purpose**:
Renders a card for each GitHub repository using the pre-generated JSON data.
- **Features**:
- Displays repo name, link, stars, forks, open issues, language, last update, and license.
- Shows loading spinner while fetching data.
- Handles errors gracefully.
- Supports dynamic content (re-initializes on DOM changes).
- Language color coding for popular languages.
### Gitea Widget (`javascripts/gitea-widget.js`)
- **Purpose**:
Renders a card for each Gitea repository using the pre-generated JSON data.
- **Features**:
- Similar to GitHub widget, but styled for Gitea.
- Shows repo name, link, stars, forks, open issues, language, last update.
- Loading and error states.
- Language color coding.
---
## MkDocs Features (`mkdocs.yml`)
Key features and plugins enabled:
- **Material Theme**:
Modern, responsive UI with dark/light mode toggle, custom fonts, and accent colors.
- **Navigation Enhancements**:
- Tabs, sticky navigation, instant loading, breadcrumbs, and sectioned navigation.
- Table of contents with permalinks.
- **Content Features**:
- Code annotation, copy buttons, tooltips, and improved code highlighting.
- Admonitions, tabbed content, task lists, and emoji support.
- **Plugins**:
- **Search**: Advanced search with custom tokenization.
- **Social**: OpenGraph/social card generation.
- **Blog**: Blogging support with archives and categories.
- **Tags**: Tagging for content organization.
- **Custom Hooks**:
- `repo_widget_hook.py` for repository widget data.
- **Extra CSS/JS**:
- Custom styles and scripts for widgets and homepage.
- **Extra Configuration**:
- Social links, copyright.
---
## Summary
This MkDocs site is highly customized for developer documentation, with visually rich repository widgets, improved code and table rendering, and a modern, responsive UI.
All repository stats are fetched at build time for performance and reliability.

View File

@ -6,6 +6,7 @@ Fetches repository data and generates JSON files during build
import json
import os
import requests
import sys
from pathlib import Path
from typing import Dict, Any
import logging
@ -19,6 +20,11 @@ def on_pre_build(config: Dict[str, Any]) -> None:
Hook that runs before MkDocs builds the site
Generates repository JSON data files
"""
# Skip during serve mode to prevent infinite loops
if _is_serve_mode():
logger.info("Serve mode detected, skipping repository widget data generation")
return
logger.info("Generating repository widget data...")
# Define repositories to fetch - all repos from services.md
@ -60,6 +66,10 @@ def on_pre_build(config: Dict[str, Any]) -> None:
{
"repo": "gethomepage/homepage",
"github": True
},
{
"repo": "anthropics/claude-code",
"github": True
}
]
@ -137,4 +147,9 @@ def generate_repo_data(repo_config: Dict[str, Any], output_dir: Path) -> None:
def on_post_build(config: Dict[str, Any]) -> None:
"""Hook that runs after MkDocs builds the site"""
logger.info("Repository widget data generation complete")
logger.info("Repository widget data generation complete")
def _is_serve_mode() -> bool:
"""Check if MkDocs is running in serve mode"""
# Check command line arguments
return 'serve' in sys.argv

View File

@ -68,8 +68,8 @@ document.addEventListener('DOMContentLoaded', function() {
});
}, observerOptions);
// Observe all grid cards
document.querySelectorAll('.grid-card').forEach((card, index) => {
// Observe all grid cards (exclude site-card and stat-card which have their own observer)
document.querySelectorAll('.grid-card:not(.site-card):not(.stat-card)').forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
@ -109,7 +109,7 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
// Animated counter for stats
// Animated counter for hero stats (the smaller stat grid)
const animateValue = (element, start, end, duration) => {
const range = end - start;
const increment = range / (duration / 16);
@ -125,8 +125,8 @@ document.addEventListener('DOMContentLoaded', function() {
}, 16);
};
// Animate stat numbers on scroll
const statObserver = new IntersectionObserver((entries) => {
// Animate hero stat numbers on scroll (only for .stat-item, not .stat-card)
const heroStatObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const statNumber = entry.target.querySelector('.stat-number');
@ -138,13 +138,129 @@ document.addEventListener('DOMContentLoaded', function() {
animateValue(statNumber, 0, value, 1000);
}
}
statObserver.unobserve(entry.target);
heroStatObserver.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll('.stat-item').forEach(stat => {
statObserver.observe(stat);
heroStatObserver.observe(stat);
});
// Animated counter for proof stats - improved version
const proofStatObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const statCard = entry.target;
const counter = statCard.querySelector('.stat-counter');
const statValue = statCard.getAttribute('data-stat');
if (counter && statValue && !counter.hasAttribute('data-animated')) {
counter.setAttribute('data-animated', 'true');
// Add counting class for visual effect
counter.classList.add('counting');
// Special handling for different stat types
if (statValue === '1') {
// AI Ready - just animate the text
counter.style.opacity = '0';
counter.style.transform = 'scale(0.5)';
setTimeout(() => {
counter.style.transition = 'all 0.8s ease';
counter.style.opacity = '1';
counter.style.transform = 'scale(1)';
}, 200);
} else if (statValue === '30' || statValue === '2') {
// Time values like "30min", "2hr"
const originalText = counter.textContent;
counter.textContent = '0';
counter.style.opacity = '0';
setTimeout(() => {
counter.style.transition = 'all 0.8s ease';
counter.style.opacity = '1';
counter.textContent = originalText;
}, 200);
} else {
// Numeric values - animate the counting
const value = parseInt(statValue);
const originalText = counter.textContent;
counter.textContent = '0';
// Simple counting animation
let current = 0;
const increment = value / 30; // 30 steps
const timer = setInterval(() => {
current += increment;
if (current >= value) {
current = value;
clearInterval(timer);
// Restore original formatted text
setTimeout(() => {
counter.textContent = originalText;
}, 200);
} else {
counter.textContent = Math.floor(current).toLocaleString();
}
}, 50);
}
}
proofStatObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.3,
rootMargin: '0px 0px -20px 0px'
});
// Observe proof stat cards (only those with data-stat attribute)
document.querySelectorAll('.stat-card[data-stat]').forEach(stat => {
proofStatObserver.observe(stat);
});
// Site card hover effects
document.querySelectorAll('.site-card').forEach(card => {
card.addEventListener('mouseenter', function() {
const icon = this.querySelector('.site-icon');
if (icon) {
icon.style.animation = 'none';
setTimeout(() => {
icon.style.animation = 'site-float 3s ease-in-out infinite';
}, 10);
}
});
});
// Staggered animation for proof cards - improved
const proofCardObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const container = entry.target.closest('.sites-grid, .stats-grid');
if (container) {
const allCards = Array.from(container.children);
const index = allCards.indexOf(entry.target);
setTimeout(() => {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}, index * 150); // Slightly longer delay for better effect
}
proofCardObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.2,
rootMargin: '0px 0px -30px 0px'
});
// Observe site cards and stat cards for stagger animation
document.querySelectorAll('.site-card, .stat-card').forEach((card) => {
// Set initial state
card.style.opacity = '0';
card.style.transform = 'translateY(30px)';
card.style.transition = 'opacity 0.8s ease, transform 0.8s ease';
proofCardObserver.observe(card);
});
// Add parallax effect to hero section

View File

@ -18,12 +18,13 @@
<div class="hero-main grid-card">
<div class="meta-badge">🤯 This Site Runs On Changemaker Lite</div>
<h1>The Only Free and Open Source Political Campaign Platform</h1>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on ~$200 hardware and
with fewer corporate dependencies every day.</p>
<p>The medium is the message; if your competition is using the same platform, who is profiting? If your campaign is not self-hosted, who is control of your data? If you are not in control of your data, who has access to it? </p>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on your own hardware for free or work with BNKops to get a pre-configured server.</p>
</p>
<div class="hero-ctas">
<a href="#solution" class="btn btn-primary">See The Solution</a>
<a href="#get-started" class="btn btn-secondary">Get Started</a>
<a href="https://cmlite.org/build/" class="btn btn-secondary">Get Started</a>
</div>
</div>
@ -31,6 +32,7 @@
<div class="hero-problem grid-card">
<h3>The Problem</h3>
<div class="problem-list">
<div class="problem-item">💻 Website $100+/mo</div>
<div class="problem-item">💸 Canvassing: $100+/mo</div>
<div class="problem-item">📊 Nationbuilder: $500+/mo</div>
<div class="problem-item">📧 Mailchimp: $200+/mo</div>
@ -228,6 +230,87 @@
</div>
</section>
<!-- Proofs Section -->
<section class="proofs-grid" id="proofs">
<div class="grid-container">
<div class="section-header">
<h2>Real Sites, Real Results</h2>
<p>Live sites powered by Changemaker Lite and integrated into our network</p>
</div>
<!-- Example Sites -->
<div class="proof-sites">
<h3>Sites Built With Changemaker Lite</h3>
<div class="sites-grid">
<a href="https://pridecorner.ca/" target="_blank" class="site-card grid-card">
<div class="site-icon">🏳️‍🌈</div>
<div class="site-name">Pride Corner</div>
<div class="site-desc">Community hub</div>
</a>
<a href="https://publicinterestalberta.org/" target="_blank" class="site-card grid-card">
<div class="site-icon">🏛️</div>
<div class="site-name">Public Interest Alberta</div>
<div class="site-desc">Policy advocacy</div>
</a>
<a href="https://lindalindsay.org/" target="_blank" class="site-card grid-card">
<div class="site-icon">🗳️</div>
<div class="site-name">Linda Lindsay</div>
<div class="site-desc">Political campaign</div>
</a>
<a href="https://bnkops.com/" target="_blank" class="site-card grid-card featured">
<div class="site-badge">Platform Provider</div>
<div class="site-icon"></div>
<div class="site-name">BNKops</div>
<div class="site-desc">Liberation tech</div>
</a>
</div>
</div>
<!-- Live Stats -->
<div class="proof-stats">
<h3>Live Performance Metrics</h3>
<div class="stats-grid">
<div class="stat-card grid-card" data-stat="100000">
<div class="stat-icon">👀</div>
<div class="stat-counter">100,000+</div>
<div class="stat-label">Website visits daily</div>
<div class="stat-detail">Across BNKops managed sites</div>
</div>
<div class="stat-card grid-card" data-stat="500">
<div class="stat-icon">📧</div>
<div class="stat-counter">500+</div>
<div class="stat-label">Emails sent daily</div>
<div class="stat-detail">Newsletter & automation</div>
</div>
<div class="stat-card grid-card" data-stat="24">
<div class="stat-icon">🤖</div>
<div class="stat-counter">24+</div>
<div class="stat-label">Tasks automated</div>
<div class="stat-detail">Running continuously</div>
</div>
<div class="stat-card grid-card" data-stat="30">
<div class="stat-icon"></div>
<div class="stat-counter">30min</div>
<div class="stat-label">Setup time</div>
<div class="stat-detail">From zero to production</div>
</div>
<div class="stat-card grid-card" data-stat="2">
<div class="stat-icon">⏱️</div>
<div class="stat-counter">2hr</div>
<div class="stat-label">Configuration</div>
<div class="stat-detail">Full customization</div>
</div>
<div class="stat-card grid-card" data-stat="1">
<div class="stat-icon">🧠</div>
<div class="stat-counter">AI Ready</div>
<div class="stat-label">Local AI Integrations Available</div>
<div class="stat-detail">Build With Plain Language</div>
</div>
</div>
</div>
</div>
</section>
<!-- Comparison Grid -->
<section class="comparison-grid">
<div class="grid-container">
@ -313,7 +396,7 @@
<div class="feature">✓ Community support</div>
<div class="feature">✓ Learn the system</div>
</div>
<a href="/getting-started" class="btn btn-secondary">Install Guide</a>
<a href="/build/getting-started" class="btn btn-secondary">Install Guide</a>
</div>
<!-- Managed -->

View File

@ -1,8 +1,14 @@
# MkDocs Material
<div class="github-widget" data-repo="squidfunk/mkdocs-material"></div>
Modern documentation site generator with live preview.
Modern documentation site generator with live preview.
Looking for more info on BNKops code-server integration?
[→ Code Server Configuration](../config/coder.md)
## Overview

View File

@ -10,13 +10,13 @@
--trans-white: #FFFFFF;
--trans-white-dim: #E0E0E0;
/* Dark theme colors */
/* Dark theme colors - updated for consistent slate */
--home-dark-bg: #0a0a0a;
--home-dark-surface: #151515;
--home-dark-card: #1a1a1a;
--home-dark-border: #2a2a2a;
--home-dark-text: #e0e0e0;
--home-dark-text-muted: #999;
--home-dark-surface: #1e293b; /* slate-800 */
--home-dark-card: #334155; /* slate-700 */
--home-dark-border: #475569; /* slate-600 */
--home-dark-text: #e2e8f0; /* slate-200 */
--home-dark-text-muted: #94a3b8; /* slate-400 */
/* Grid colors */
--grid-primary: var(--trans-blue);
@ -104,13 +104,14 @@ body[data-md-template="home"] .md-main__inner {
}
.grid-card {
background: var(--md-default-bg-color);
border: 1px solid var(--grid-border);
background: var(--home-dark-card);
border: 1px solid var(--home-dark-border);
border-radius: 4px;
padding: var(--space-md);
transition: all 0.2s ease;
position: relative;
overflow: hidden;
color: var(--home-dark-text);
}
.grid-card::before {
@ -307,20 +308,21 @@ body[data-md-template="home"] .md-main__inner {
.section-header {
text-align: center;
margin-bottom: var(--space-lg);
padding: var(--space-sm) 0;
background: linear-gradient(to bottom,
rgba(10, 10, 10, 0.9) 0%,
rgba(10, 10, 10, 0.7) 70%,
transparent 100%);
backdrop-filter: blur(4px);
border-bottom: 1px solid var(--grid-border);
padding: var(--space-lg) var(--space-md);
background: #2d1b69; /* Deep purple solid background */
border-radius: var(--home-radius);
border: 1px solid var(--mkdocs-purple);
box-shadow: 0 0 20px rgba(111, 66, 193, 0.3);
position: relative;
z-index: 10; /* Ensure it stays above other content */
overflow: hidden; /* Prevent any content bleeding */
}
.section-header h2 {
font-size: 1.8rem;
font-weight: 700;
margin: 0 0 var(--space-xs) 0;
color: var(--home-dark-text);
color: var(--trans-white);
position: relative;
display: inline-block;
}
@ -332,12 +334,12 @@ body[data-md-template="home"] .md-main__inner {
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, var(--trans-blue), transparent);
background: linear-gradient(90deg, transparent, var(--trans-pink), transparent);
}
.section-header p {
font-size: 0.9rem;
color: var(--home-dark-text-muted);
color: var(--trans-white-dim);
margin: 0;
}
@ -345,11 +347,23 @@ body[data-md-template="home"] .md-main__inner {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: var(--space-sm);
padding-top: var(--space-md); /* Add padding to accommodate service badges too */
}
.service-card {
text-decoration: none;
color: inherit;
text-align: center;
transition: all 0.3s ease;
position: relative;
cursor: pointer;
min-height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: var(--space-md); /* Reset to normal padding */
margin-top: 0; /* Remove margin, use grid padding instead */
}
.service-card:hover .service-icon {
@ -402,6 +416,204 @@ body[data-md-template="home"] .md-main__inner {
display: inline-block;
}
/* =================================
PROOFS SECTION - NEW
================================= */
.proofs-grid {
padding: var(--space-lg) 0;
border-top: 1px solid var(--grid-border);
}
/* Example Sites */
.proof-sites {
margin-bottom: var(--space-xl);
}
.proof-sites h3 {
font-size: 1.2rem;
margin: 0 0 var(--space-lg) 0;
color: var(--trans-blue);
text-align: center;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.sites-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--space-sm);
margin-bottom: var(--space-xl);
max-width: 900px;
margin-left: auto;
margin-right: auto;
padding-top: var(--space-md); /* Add padding to accommodate badges */
}
.site-card {
text-decoration: none;
color: inherit;
text-align: center;
transition: all 0.3s ease;
position: relative;
cursor: pointer;
min-height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: var(--space-md);
margin-top: 0; /* Remove margin, use grid padding instead */
}
.site-card:hover {
transform: translateY(-3px) scale(1.02);
box-shadow: 0 0 20px rgba(91, 206, 250, 0.4);
}
.site-card.featured {
border-color: var(--trans-blue);
box-shadow: 0 0 15px rgba(91, 206, 250, 0.3);
}
.site-badge {
position: absolute;
top: -4px; /* Bring badge even closer to card */
left: 50%;
transform: translateX(-50%);
background: var(--trans-blue);
color: #000;
padding: 0.1rem 0.6rem;
border-radius: 10px;
font-size: 0.65rem;
font-weight: 700;
z-index: 5;
white-space: nowrap; /* Prevent text wrapping */
}
.site-icon {
font-size: 2.5rem;
margin-bottom: var(--space-sm);
animation: site-float 3s ease-in-out infinite;
}
@keyframes site-float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
}
.site-name {
font-size: 1rem;
font-weight: 600;
margin-bottom: var(--space-xs);
color: var(--home-dark-text);
}
.site-desc {
font-size: 0.8rem;
color: var(--home-dark-text-muted);
}
/* Live Stats */
.proof-stats h3 {
font-size: 1.2rem;
margin: 0 0 var(--space-lg) 0;
color: var(--trans-pink);
text-align: center;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-sm);
max-width: 1000px;
margin: 0 auto;
}
.stat-card {
text-align: center;
position: relative;
overflow: hidden;
min-height: 160px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: var(--space-md);
}
.stat-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg,
var(--trans-blue),
var(--trans-pink),
var(--trans-blue));
animation: stat-glow 2s ease-in-out infinite;
}
@keyframes stat-glow {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
.stat-icon {
font-size: 2rem;
margin-bottom: var(--space-xs);
animation: stat-pulse 2s ease-in-out infinite;
}
@keyframes stat-pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.stat-counter {
font-size: 1.5rem;
font-weight: 700;
color: var(--trans-pink); /* Changed to pink to match section header */
margin-bottom: var(--space-xs);
/* Removed text-shadow and animation for better readability */
}
.stat-label {
font-size: 0.9rem;
font-weight: 600;
color: var(--home-dark-text);
margin-bottom: var(--space-xs);
}
.stat-detail {
font-size: 0.7rem;
color: var(--home-dark-text-muted);
}
/* Animated counter effect */
.stat-counter.counting {
animation: counter-count 1.2s ease-out;
}
@keyframes counter-count {
0% {
transform: scale(0.5) rotateY(-90deg);
opacity: 0;
}
50% {
transform: scale(1.2) rotateY(0deg);
opacity: 0.8;
}
100% {
transform: scale(1) rotateY(0deg);
opacity: 1;
}
}
/* =================================
COMPARISON TABLE - GRID STYLE
================================= */
@ -474,11 +686,14 @@ body[data-md-template="home"] .md-main__inner {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-sm);
margin-bottom: var(--space-lg);
padding-top: var(--space-md); /* Add padding to accommodate badges */
}
.option-card {
text-align: center;
position: relative;
padding-top: var(--space-md); /* Reduced padding since grid now has padding */
margin-top: 0; /* Remove margin, use grid padding instead */
}
.option-card.featured {
@ -499,7 +714,7 @@ body[data-md-template="home"] .md-main__inner {
.option-badge {
position: absolute;
top: -8px;
top: -4px; /* Bring badge even closer to card */
left: 50%;
transform: translateX(-50%);
background: var(--trans-blue);
@ -508,6 +723,8 @@ body[data-md-template="home"] .md-main__inner {
border-radius: 10px;
font-size: 0.65rem;
font-weight: 700;
z-index: 5;
white-space: nowrap; /* Prevent text wrapping */
}
.option-icon {
@ -582,7 +799,7 @@ body[data-md-template="home"] .md-main__inner {
min-width: 100px;
position: relative;
overflow: hidden;
color: var(--mkdocs-purple-dark);
color: var(--trans-white) !important; /* Force white text with higher specificity */
}
.btn::before {
@ -605,29 +822,52 @@ body[data-md-template="home"] .md-main__inner {
.btn-primary {
background: var(--mkdocs-purple);
color: var(--mkdocs-purple-dark);
color: var(--trans-white) !important; /* Force white text */
border-color: var(--mkdocs-purple);
}
.btn-primary:hover {
background: var(--mkdocs-purple-dark);
color: #000;
color: var(--trans-white) !important; /* Force white text on hover */
box-shadow: 0 0 15px var(--mkdocs-purple);
transform: translateY(-1px);
}
.btn-secondary {
background: transparent;
color: var(--mkdocs-purple);
color: var(--trans-white) !important; /* Force white text */
border-color: var(--mkdocs-purple);
}
.btn-secondary:hover {
background: var(--mkdocs-purple-dark);
color: #000;
color: var(--trans-white) !important; /* Force white text on hover */
box-shadow: 0 0 15px var(--mkdocs-purple);
}
/* Ensure all button variations have white text */
a.btn,
a.btn:visited,
a.btn:link,
a.btn:active {
color: var(--trans-white) !important;
text-decoration: none !important;
}
a.btn-primary,
a.btn-primary:visited,
a.btn-primary:link,
a.btn-primary:active {
color: var(--trans-white) !important;
}
a.btn-secondary,
a.btn-secondary:visited,
a.btn-secondary:link,
a.btn-secondary:active {
color: var(--trans-white) !important;
}
/* =================================
RESPONSIVE - ULTRA TIGHT
================================= */
@ -651,6 +891,16 @@ body[data-md-template="home"] .md-main__inner {
grid-template-columns: 1fr;
}
.sites-grid {
grid-template-columns: repeat(2, 1fr);
max-width: 500px;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
max-width: 500px;
}
.comparison-header,
.comparison-row {
font-size: 0.7rem;
@ -679,6 +929,16 @@ body[data-md-template="home"] .md-main__inner {
grid-template-columns: 1fr;
}
.sites-grid {
grid-template-columns: 1fr;
max-width: 350px;
}
.stats-grid {
grid-template-columns: 1fr;
max-width: 350px;
}
.service-card {
padding: var(--space-sm);
}
@ -686,6 +946,14 @@ body[data-md-template="home"] .md-main__inner {
.hero-main h1 {
font-size: 1.3rem;
}
.stat-counter {
font-size: 1.2rem;
}
.site-icon {
font-size: 2rem;
}
}
/* Row cards at bottom: two cards in a row on desktop, stack on mobile */
@ -734,4 +1002,72 @@ body[data-md-template="home"] .md-main__inner {
letter-spacing: 0.03em;
vertical-align: middle;
box-shadow: 0 0 6px var(--mkdocs-purple-dark);
}
/* Ensure all cards have consistent slate background */
.grid-card,
.site-card,
.stat-card,
.service-card,
.option-card,
.final-cta,
.subscribe-card {
background: var(--home-dark-card) !important;
color: var(--home-dark-text) !important;
}
/* Fix form elements in subscribe card */
.subscribe-card input[type="email"],
.subscribe-card input[type="text"] {
background: var(--home-dark-surface);
color: var(--home-dark-text);
border: 1px solid var(--home-dark-border);
border-radius: 4px;
padding: 0.5rem;
width: 100%;
box-sizing: border-box;
}
.subscribe-card input[type="email"]:focus,
.subscribe-card input[type="text"]:focus {
outline: none;
border-color: var(--trans-blue);
box-shadow: 0 0 0 2px rgba(91, 206, 250, 0.2);
}
.subscribe-card label {
color: var(--home-dark-text-muted);
font-size: 0.9rem;
}
.subscribe-card .action-btn {
background: var(--mkdocs-purple);
color: #000;
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.subscribe-card .action-btn:hover {
background: var(--mkdocs-purple-dark);
transform: translateY(-1px);
box-shadow: 0 0 10px rgba(111, 66, 193, 0.4);
}
/* Ensure all section content respects the header layering */
.solution-grid,
.proofs-grid,
.comparison-grid,
.get-started-grid {
position: relative;
z-index: 1; /* Lower than section headers */
}
/* Make sure grid cards don't interfere with section headers */
.grid-card {
position: relative;
z-index: 2; /* Higher than section content but lower than headers */
}

View File

@ -149,13 +149,14 @@ nav:
- 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
- Digital Organizing: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/Distributed%20Digital%20Organizing%20is%20The%20Way%20Out/
- 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
- Cost Comparison: phil/cost-comparison.md
- Getting Started:
- build/index.md
- Build Server: build/build-server.md
- Build Server: build/server.md
- Build Map: build/map.md
- Build Site: build/site.md
- Services:
- services/index.md
- Homepage: services/homepage.md
@ -172,5 +173,11 @@ nav:
- Configuration:
- config/index.md
- Cloudflare: config/cloudflare-config.md
- mkdocs: config/mkdocs.md
- Coder: config/coder.md
- Advanced Configuration:
- adv/index.md
- SSH + Tailscale + Ansible: adv/ansible.md
- SSH + VScode: adv/vscode-ssh.md
- Blog:
- blog/index.md

View File

@ -473,6 +473,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>

File diff suppressed because it is too large Load Diff

1496
mkdocs/site/adv/index.html Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -6,11 +6,11 @@
"language": "HTML",
"stars_count": 0,
"forks_count": 0,
"open_issues_count": 0,
"updated_at": "2025-06-30T21:38:32-06:00",
"open_issues_count": 1,
"updated_at": "2025-07-01T09:33:43-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-30T21:38:32-06:00"
"last_build_update": "2025-07-01T09:33:43-06:00"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "anthropics/claude-code",
"name": "claude-code",
"description": "Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.",
"html_url": "https://github.com/anthropics/claude-code",
"language": "Shell",
"stars_count": 16934,
"forks_count": 929,
"open_issues_count": 1495,
"updated_at": "2025-07-02T17:38:19Z",
"created_at": "2025-02-22T17:41:21Z",
"clone_url": "https://github.com/anthropics/claude-code.git",
"ssh_url": "git@github.com:anthropics/claude-code.git",
"default_branch": "main",
"last_build_update": "2025-07-02T16:32:38Z"
}

View File

@ -4,10 +4,10 @@
"description": "VS Code in the browser",
"html_url": "https://github.com/coder/code-server",
"language": "TypeScript",
"stars_count": 72508,
"forks_count": 6062,
"open_issues_count": 142,
"updated_at": "2025-07-01T15:16:52Z",
"stars_count": 72530,
"forks_count": 6064,
"open_issues_count": 143,
"updated_at": "2025-07-02T17:11:14Z",
"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",

View File

@ -4,13 +4,13 @@
"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": 24583,
"forks_count": 1519,
"stars_count": 24608,
"forks_count": 1520,
"open_issues_count": 1,
"updated_at": "2025-07-01T15:20:04Z",
"updated_at": "2025-07-02T17:20:41Z",
"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-07-01T12:14:06Z"
"last_build_update": "2025-07-02T12:13:57Z"
}

View File

@ -4,13 +4,13 @@
"description": "Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD",
"html_url": "https://github.com/go-gitea/gitea",
"language": "Go",
"stars_count": 49327,
"forks_count": 5887,
"open_issues_count": 2706,
"updated_at": "2025-07-01T14:28:19Z",
"stars_count": 49339,
"forks_count": 5891,
"open_issues_count": 2711,
"updated_at": "2025-07-02T16:36:32Z",
"created_at": "2016-11-01T02:13:26Z",
"clone_url": "https://github.com/go-gitea/gitea.git",
"ssh_url": "git@github.com:go-gitea/gitea.git",
"default_branch": "main",
"last_build_update": "2025-07-01T13:44:05Z"
"last_build_update": "2025-07-02T00:37:56Z"
}

View File

@ -4,10 +4,10 @@
"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": 17242,
"forks_count": 1657,
"open_issues_count": 104,
"updated_at": "2025-07-01T14:26:50Z",
"stars_count": 17248,
"forks_count": 1658,
"open_issues_count": 105,
"updated_at": "2025-07-02T10:32:44Z",
"created_at": "2019-06-26T05:08:39Z",
"clone_url": "https://github.com/knadh/listmonk.git",
"ssh_url": "git@github.com:knadh/listmonk.git",

View File

@ -4,13 +4,13 @@
"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": 113903,
"forks_count": 33364,
"open_issues_count": 1058,
"updated_at": "2025-07-01T15:22:32Z",
"stars_count": 114294,
"forks_count": 33577,
"open_issues_count": 1070,
"updated_at": "2025-07-02T17:42:44Z",
"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-07-01T15:23:16Z"
"last_build_update": "2025-07-02T17:17:32Z"
}

View File

@ -4,13 +4,13 @@
"description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 Open Source Airtable Alternative",
"html_url": "https://github.com/nocodb/nocodb",
"language": "TypeScript",
"stars_count": 55480,
"forks_count": 3987,
"open_issues_count": 714,
"updated_at": "2025-07-01T14:03:05Z",
"stars_count": 55505,
"forks_count": 3994,
"open_issues_count": 718,
"updated_at": "2025-07-02T17:05:35Z",
"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-07-01T14:26:19Z"
"last_build_update": "2025-07-02T16:01:20Z"
}

View File

@ -4,13 +4,13 @@
"description": "Documentation that simply works",
"html_url": "https://github.com/squidfunk/mkdocs-material",
"language": "Python",
"stars_count": 23763,
"forks_count": 3786,
"open_issues_count": 4,
"updated_at": "2025-07-01T13:38:53Z",
"stars_count": 23785,
"forks_count": 3787,
"open_issues_count": 5,
"updated_at": "2025-07-02T17:21:29Z",
"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-07-01T12:56:28Z"
"last_build_update": "2025-07-02T16:12:25Z"
}

View File

@ -15,7 +15,7 @@
<link rel="canonical" href="https://cmlite.org/blog/">
<link rel="prev" href="../config/cloudflare-config/">
<link rel="prev" href="../adv/vscode-ssh/">
@ -505,6 +505,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -703,7 +707,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../config/cloudflare-config/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Cloudflare">
<a href="../adv/vscode-ssh/" class="md-footer__link md-footer__link--prev" aria-label="Previous: SSH + VScode">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
@ -713,7 +717,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
Previous
</span>
<div class="md-ellipsis">
Cloudflare
SSH + VScode
</div>
</div>
</a>

View File

@ -18,7 +18,7 @@
<link rel="prev" href="../phil/cost-comparison/">
<link rel="next" href="build-server/">
<link rel="next" href="server/">
<link rel="icon" href="../assets/images/favicon.png">
@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="build-server/" class="md-nav__link">
<a href="server/" class="md-nav__link">
@ -620,6 +624,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_4" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -974,6 +1001,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -997,7 +1028,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1014,14 +1045,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1052,6 +1083,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>
@ -1665,7 +1865,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</ul>
<div class="admonition note">
<p class="admonition-title">Getting Started on Ubunut</p>
<p>Want some help getting started with a baseline buildout for a Ubunut server? You can use our <a href="build-server/">BNKops Server Build Script</a></p>
<p>Want some help getting started with a baseline buildout for a Ubunut server? You can use our <a href="server/">BNKops Server Build Script</a></p>
</div>
<ul>
<li>Other Linux distributions with systemd support</li>
@ -1690,7 +1890,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<h3 id="software-prerequisites">Software Prerequisites<a class="headerlink" href="#software-prerequisites" title="Permanent link">&para;</a></h3>
<div class="admonition tip">
<p class="admonition-title">Getting Started on Docker</p>
<p>Want some help getting started with a baseline buildout for a Ubunutu server? You can use our <a href="build-server/">BNKops Server Build Script</a> to roll out a configured server in about 20 mins! </p>
<p>Want some help getting started with a baseline buildout for a Ubunutu server? You can use our <a href="server/">BNKops Server Build Script</a> to roll out a configured server in about 20 mins! </p>
</div>
<ol>
<li><strong>Docker Engine</strong> (24.0+)</li>
@ -2040,7 +2240,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="build-server/" class="md-footer__link md-footer__link--next" aria-label="Next: Build Server">
<a href="server/" class="md-footer__link md-footer__link--next" aria-label="Next: Build Server">
<div class="md-footer__title">
<span class="md-footer__direction">
Next

View File

@ -15,10 +15,10 @@
<link rel="canonical" href="https://cmlite.org/build/map/">
<link rel="prev" href="../build-server/">
<link rel="prev" href="../server/">
<link rel="next" href="../../services/">
<link rel="next" href="../site/">
<link rel="icon" href="../../assets/images/favicon.png">
@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../build-server/" class="md-nav__link">
<a href="../server/" class="md-nav__link">
@ -811,6 +815,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -860,7 +887,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_4" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<div class="md-nav__link md-nav__container">
@ -877,14 +904,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1165,6 +1192,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1188,7 +1219,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1205,14 +1236,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1243,6 +1274,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>
@ -1515,9 +1715,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</ul>
<h2 id="nocodb-table-setup">NocoDB Table Setup<a class="headerlink" href="#nocodb-table-setup" title="Permanent link">&para;</a></h2>
<h3 id="required-columns">Required Columns<a class="headerlink" href="#required-columns" title="Permanent link">&para;</a></h3>
<div class="admonition warning">
<p class="admonition-title">Case Sensitive</p>
<p>When entering in the required columns, make sure that you enter in exact information. Case sensitivity matters for mapping the values to the map itself. </p>
</div>
<p>Create a table in NocoDB with these required columns. The format here is the <code>Name of the column - column type - details</code>:</p>
<ol>
<li><strong>Geo Location</strong> (geo-data) - Format: "latitude;longitude"</li>
<li><strong>Geo-Location</strong> (geo-data) - Format: "latitude;longitude"</li>
<li><strong>latitude</strong> (Decimal) - Precision: 10, Scale: 8</li>
<li><strong>longitude</strong> (Decimal) - Precision: 11, Scale: 8</li>
</ol>
@ -1677,7 +1881,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../build-server/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Build Server">
<a href="../server/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Build Server">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
@ -1694,13 +1898,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="../../services/" class="md-footer__link md-footer__link--next" aria-label="Next: Services">
<a href="../site/" class="md-footer__link md-footer__link--next" aria-label="Next: Build Site">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Services
Build Site
</div>
</div>
<div class="md-footer__button md-icon">

View File

@ -12,7 +12,7 @@
<meta name="author" content="Bunker Operations">
<link rel="canonical" href="https://cmlite.org/build/build-server/">
<link rel="canonical" href="https://cmlite.org/build/server/">
<link rel="prev" href="../">
@ -69,7 +69,7 @@
<meta property="og:description" content="Build Power. Not Rent It. Own your digital infrastructure." >
<meta property="og:image" content="https://cmlite.org/assets/images/social/build/build-server.png" >
<meta property="og:image" content="https://cmlite.org/assets/images/social/build/server.png" >
<meta property="og:image:type" content="image/png" >
@ -77,7 +77,7 @@
<meta property="og:image:height" content="630" >
<meta property="og:url" content="https://cmlite.org/build/build-server/" >
<meta property="og:url" content="https://cmlite.org/build/server/" >
<meta name="twitter:card" content="summary_large_image" >
@ -85,7 +85,7 @@
<meta name="twitter:description" content="Build Power. Not Rent It. Own your digital infrastructure." >
<meta name="twitter:image" content="https://cmlite.org/assets/images/social/build/build-server.png" >
<meta name="twitter:image" content="https://cmlite.org/assets/images/social/build/server.png" >
@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -910,6 +914,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -959,7 +986,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_4" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<div class="md-nav__link md-nav__container">
@ -976,14 +1003,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1264,6 +1291,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1287,7 +1318,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1304,14 +1335,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1342,6 +1373,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>
@ -1803,9 +2003,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="language-text highlight"><pre><span></span><code><span id="__span-18-1"><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a>cloudflared login
</span></code></pre></div></p>
<h3 id="configuration_1">Configuration<a class="headerlink" href="#configuration_1" title="Permanent link">&para;</a></h3>
<ul>
<li>Setting up the [[service.cloudflared]] enables your cloudflared tunnel to automatically run on reboot </li>
</ul>
<p>The <code>./config.sh</code> and <code>./start-production.sh</code> scripts will properly configure a Cloudflare tunnel and service to put your system online. More info in the <a href="../../config/cloudflare-config/">Cloudflare Configuration.</a></p>
<h2 id="pandoc"><a href="https://pandoc.org/">Pandoc</a><a class="headerlink" href="#pandoc" title="Permanent link">&para;</a></h2>
<p>If you need to convert files from one markup format into another, pandoc is your swiss-army knife. </p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-19-1"><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a>sudo apt install pandoc

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@
<link rel="prev" href="../">
<link rel="next" href="../../blog/">
<link rel="next" href="../mkdocs/">
<link rel="icon" href="../../assets/images/favicon.png">
@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -620,6 +624,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_4" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -976,6 +1003,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -997,7 +1028,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_6" checked>
<div class="md-nav__link md-nav__container">
@ -1014,14 +1045,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1165,6 +1196,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>
@ -1465,13 +1665,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="../../blog/" class="md-footer__link md-footer__link--next" aria-label="Next: Index">
<a href="../mkdocs/" class="md-footer__link md-footer__link--next" aria-label="Next: mkdocs">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Index
mkdocs
</div>
</div>
<div class="md-footer__button md-icon">

File diff suppressed because it is too large Load Diff

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../build/build-server/" class="md-nav__link">
<a href="../build/server/" class="md-nav__link">
@ -620,6 +624,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_4" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -976,6 +1003,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -997,7 +1028,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_6" checked>
<div class="md-nav__link md-nav__container">
@ -1014,14 +1045,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link md-nav__link--active" for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link md-nav__link--active" for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1052,6 +1083,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@ Fetches repository data and generates JSON files during build
import json
import os
import requests
import sys
from pathlib import Path
from typing import Dict, Any
import logging
@ -19,6 +20,11 @@ def on_pre_build(config: Dict[str, Any]) -> None:
Hook that runs before MkDocs builds the site
Generates repository JSON data files
"""
# Skip during serve mode to prevent infinite loops
if _is_serve_mode():
logger.info("Serve mode detected, skipping repository widget data generation")
return
logger.info("Generating repository widget data...")
# Define repositories to fetch - all repos from services.md
@ -60,6 +66,10 @@ def on_pre_build(config: Dict[str, Any]) -> None:
{
"repo": "gethomepage/homepage",
"github": True
},
{
"repo": "anthropics/claude-code",
"github": True
}
]
@ -137,4 +147,9 @@ def generate_repo_data(repo_config: Dict[str, Any], output_dir: Path) -> None:
def on_post_build(config: Dict[str, Any]) -> None:
"""Hook that runs after MkDocs builds the site"""
logger.info("Repository widget data generation complete")
logger.info("Repository widget data generation complete")
def _is_serve_mode() -> bool:
"""Check if MkDocs is running in serve mode"""
# Check command line arguments
return 'serve' in sys.argv

View File

@ -667,6 +667,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -924,12 +928,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="hero-main grid-card">
<div class="meta-badge">🤯 This Site Runs On Changemaker Lite</div>
<h1>The Only Free and Open Source Political Campaign Platform</h1>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on ~$200 hardware and
with fewer corporate dependencies every day.</p>
<p>The medium is the message; if your competition is using the same platform, who is profiting? If your campaign is not self-hosted, who is control of your data? If you are not in control of your data, who has access to it? </p>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on your own hardware for free or work with BNKops to get a pre-configured server.</p>
</p>
<div class="hero-ctas">
<a href="#solution" class="btn btn-primary">See The Solution</a>
<a href="#get-started" class="btn btn-secondary">Get Started</a>
<a href="https://cmlite.org/build/" class="btn btn-secondary">Get Started</a>
</div>
</div>
@ -937,6 +942,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="hero-problem grid-card">
<h3>The Problem</h3>
<div class="problem-list">
<div class="problem-item">💻 Website $100+/mo</div>
<div class="problem-item">💸 Canvassing: $100+/mo</div>
<div class="problem-item">📊 Nationbuilder: $500+/mo</div>
<div class="problem-item">📧 Mailchimp: $200+/mo</div>
@ -1134,6 +1140,87 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</div>
</section>
<!-- Proofs Section -->
<section class="proofs-grid" id="proofs">
<div class="grid-container">
<div class="section-header">
<h2>Real Sites, Real Results</h2>
<p>Live sites powered by Changemaker Lite and integrated into our network</p>
</div>
<!-- Example Sites -->
<div class="proof-sites">
<h3>Sites Built With Changemaker Lite</h3>
<div class="sites-grid">
<a href="https://pridecorner.ca/" target="_blank" class="site-card grid-card">
<div class="site-icon">🏳️‍🌈</div>
<div class="site-name">Pride Corner</div>
<div class="site-desc">Community hub</div>
</a>
<a href="https://publicinterestalberta.org/" target="_blank" class="site-card grid-card">
<div class="site-icon">🏛️</div>
<div class="site-name">Public Interest Alberta</div>
<div class="site-desc">Policy advocacy</div>
</a>
<a href="https://lindalindsay.org/" target="_blank" class="site-card grid-card">
<div class="site-icon">🗳️</div>
<div class="site-name">Linda Lindsay</div>
<div class="site-desc">Political campaign</div>
</a>
<a href="https://bnkops.com/" target="_blank" class="site-card grid-card featured">
<div class="site-badge">Platform Provider</div>
<div class="site-icon"></div>
<div class="site-name">BNKops</div>
<div class="site-desc">Liberation tech</div>
</a>
</div>
</div>
<!-- Live Stats -->
<div class="proof-stats">
<h3>Live Performance Metrics</h3>
<div class="stats-grid">
<div class="stat-card grid-card" data-stat="100000">
<div class="stat-icon">👀</div>
<div class="stat-counter">100,000+</div>
<div class="stat-label">Website visits daily</div>
<div class="stat-detail">Across BNKops managed sites</div>
</div>
<div class="stat-card grid-card" data-stat="500">
<div class="stat-icon">📧</div>
<div class="stat-counter">500+</div>
<div class="stat-label">Emails sent daily</div>
<div class="stat-detail">Newsletter & automation</div>
</div>
<div class="stat-card grid-card" data-stat="24">
<div class="stat-icon">🤖</div>
<div class="stat-counter">24+</div>
<div class="stat-label">Tasks automated</div>
<div class="stat-detail">Running continuously</div>
</div>
<div class="stat-card grid-card" data-stat="30">
<div class="stat-icon"></div>
<div class="stat-counter">30min</div>
<div class="stat-label">Setup time</div>
<div class="stat-detail">From zero to production</div>
</div>
<div class="stat-card grid-card" data-stat="2">
<div class="stat-icon">⏱️</div>
<div class="stat-counter">2hr</div>
<div class="stat-label">Configuration</div>
<div class="stat-detail">Full customization</div>
</div>
<div class="stat-card grid-card" data-stat="1">
<div class="stat-icon">🧠</div>
<div class="stat-counter">AI Ready</div>
<div class="stat-label">Local AI Integrations Available</div>
<div class="stat-detail">Build With Plain Language</div>
</div>
</div>
</div>
</div>
</section>
<!-- Comparison Grid -->
<section class="comparison-grid">
<div class="grid-container">
@ -1219,7 +1306,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="feature">✓ Community support</div>
<div class="feature">✓ Learn the system</div>
</div>
<a href="/getting-started" class="btn btn-secondary">Install Guide</a>
<a href="/build/getting-started" class="btn btn-secondary">Install Guide</a>
</div>
<!-- Managed -->

View File

@ -68,8 +68,8 @@ document.addEventListener('DOMContentLoaded', function() {
});
}, observerOptions);
// Observe all grid cards
document.querySelectorAll('.grid-card').forEach((card, index) => {
// Observe all grid cards (exclude site-card and stat-card which have their own observer)
document.querySelectorAll('.grid-card:not(.site-card):not(.stat-card)').forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
@ -109,7 +109,7 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
// Animated counter for stats
// Animated counter for hero stats (the smaller stat grid)
const animateValue = (element, start, end, duration) => {
const range = end - start;
const increment = range / (duration / 16);
@ -125,8 +125,8 @@ document.addEventListener('DOMContentLoaded', function() {
}, 16);
};
// Animate stat numbers on scroll
const statObserver = new IntersectionObserver((entries) => {
// Animate hero stat numbers on scroll (only for .stat-item, not .stat-card)
const heroStatObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const statNumber = entry.target.querySelector('.stat-number');
@ -138,13 +138,129 @@ document.addEventListener('DOMContentLoaded', function() {
animateValue(statNumber, 0, value, 1000);
}
}
statObserver.unobserve(entry.target);
heroStatObserver.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll('.stat-item').forEach(stat => {
statObserver.observe(stat);
heroStatObserver.observe(stat);
});
// Animated counter for proof stats - improved version
const proofStatObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const statCard = entry.target;
const counter = statCard.querySelector('.stat-counter');
const statValue = statCard.getAttribute('data-stat');
if (counter && statValue && !counter.hasAttribute('data-animated')) {
counter.setAttribute('data-animated', 'true');
// Add counting class for visual effect
counter.classList.add('counting');
// Special handling for different stat types
if (statValue === '1') {
// AI Ready - just animate the text
counter.style.opacity = '0';
counter.style.transform = 'scale(0.5)';
setTimeout(() => {
counter.style.transition = 'all 0.8s ease';
counter.style.opacity = '1';
counter.style.transform = 'scale(1)';
}, 200);
} else if (statValue === '30' || statValue === '2') {
// Time values like "30min", "2hr"
const originalText = counter.textContent;
counter.textContent = '0';
counter.style.opacity = '0';
setTimeout(() => {
counter.style.transition = 'all 0.8s ease';
counter.style.opacity = '1';
counter.textContent = originalText;
}, 200);
} else {
// Numeric values - animate the counting
const value = parseInt(statValue);
const originalText = counter.textContent;
counter.textContent = '0';
// Simple counting animation
let current = 0;
const increment = value / 30; // 30 steps
const timer = setInterval(() => {
current += increment;
if (current >= value) {
current = value;
clearInterval(timer);
// Restore original formatted text
setTimeout(() => {
counter.textContent = originalText;
}, 200);
} else {
counter.textContent = Math.floor(current).toLocaleString();
}
}, 50);
}
}
proofStatObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.3,
rootMargin: '0px 0px -20px 0px'
});
// Observe proof stat cards (only those with data-stat attribute)
document.querySelectorAll('.stat-card[data-stat]').forEach(stat => {
proofStatObserver.observe(stat);
});
// Site card hover effects
document.querySelectorAll('.site-card').forEach(card => {
card.addEventListener('mouseenter', function() {
const icon = this.querySelector('.site-icon');
if (icon) {
icon.style.animation = 'none';
setTimeout(() => {
icon.style.animation = 'site-float 3s ease-in-out infinite';
}, 10);
}
});
});
// Staggered animation for proof cards - improved
const proofCardObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const container = entry.target.closest('.sites-grid, .stats-grid');
if (container) {
const allCards = Array.from(container.children);
const index = allCards.indexOf(entry.target);
setTimeout(() => {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}, index * 150); // Slightly longer delay for better effect
}
proofCardObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.2,
rootMargin: '0px 0px -30px 0px'
});
// Observe site cards and stat cards for stagger animation
document.querySelectorAll('.site-card, .stat-card').forEach((card) => {
// Set initial state
card.style.opacity = '0';
card.style.transform = 'translateY(30px)';
card.style.transition = 'opacity 0.8s ease, transform 0.8s ease';
proofCardObserver.observe(card);
});
// Add parallax effect to hero section

View File

@ -18,12 +18,13 @@
<div class="hero-main grid-card">
<div class="meta-badge">🤯 This Site Runs On Changemaker Lite</div>
<h1>The Only Free and Open Source Political Campaign Platform</h1>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on ~$200 hardware and
with fewer corporate dependencies every day.</p>
<p>The medium is the message; if your competition is using the same platform, who is profiting? If your campaign is not self-hosted, who is control of your data? If you are not in control of your data, who has access to it? </p>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on your own hardware for free or work with BNKops to get a pre-configured server.</p>
</p>
<div class="hero-ctas">
<a href="#solution" class="btn btn-primary">See The Solution</a>
<a href="#get-started" class="btn btn-secondary">Get Started</a>
<a href="https://cmlite.org/build/" class="btn btn-secondary">Get Started</a>
</div>
</div>
@ -31,6 +32,7 @@
<div class="hero-problem grid-card">
<h3>The Problem</h3>
<div class="problem-list">
<div class="problem-item">💻 Website $100+/mo</div>
<div class="problem-item">💸 Canvassing: $100+/mo</div>
<div class="problem-item">📊 Nationbuilder: $500+/mo</div>
<div class="problem-item">📧 Mailchimp: $200+/mo</div>
@ -228,6 +230,87 @@
</div>
</section>
<!-- Proofs Section -->
<section class="proofs-grid" id="proofs">
<div class="grid-container">
<div class="section-header">
<h2>Real Sites, Real Results</h2>
<p>Live sites powered by Changemaker Lite and integrated into our network</p>
</div>
<!-- Example Sites -->
<div class="proof-sites">
<h3>Sites Built With Changemaker Lite</h3>
<div class="sites-grid">
<a href="https://pridecorner.ca/" target="_blank" class="site-card grid-card">
<div class="site-icon">🏳️‍🌈</div>
<div class="site-name">Pride Corner</div>
<div class="site-desc">Community hub</div>
</a>
<a href="https://publicinterestalberta.org/" target="_blank" class="site-card grid-card">
<div class="site-icon">🏛️</div>
<div class="site-name">Public Interest Alberta</div>
<div class="site-desc">Policy advocacy</div>
</a>
<a href="https://lindalindsay.org/" target="_blank" class="site-card grid-card">
<div class="site-icon">🗳️</div>
<div class="site-name">Linda Lindsay</div>
<div class="site-desc">Political campaign</div>
</a>
<a href="https://bnkops.com/" target="_blank" class="site-card grid-card featured">
<div class="site-badge">Platform Provider</div>
<div class="site-icon"></div>
<div class="site-name">BNKops</div>
<div class="site-desc">Liberation tech</div>
</a>
</div>
</div>
<!-- Live Stats -->
<div class="proof-stats">
<h3>Live Performance Metrics</h3>
<div class="stats-grid">
<div class="stat-card grid-card" data-stat="100000">
<div class="stat-icon">👀</div>
<div class="stat-counter">100,000+</div>
<div class="stat-label">Website visits daily</div>
<div class="stat-detail">Across BNKops managed sites</div>
</div>
<div class="stat-card grid-card" data-stat="500">
<div class="stat-icon">📧</div>
<div class="stat-counter">500+</div>
<div class="stat-label">Emails sent daily</div>
<div class="stat-detail">Newsletter & automation</div>
</div>
<div class="stat-card grid-card" data-stat="24">
<div class="stat-icon">🤖</div>
<div class="stat-counter">24+</div>
<div class="stat-label">Tasks automated</div>
<div class="stat-detail">Running continuously</div>
</div>
<div class="stat-card grid-card" data-stat="30">
<div class="stat-icon"></div>
<div class="stat-counter">30min</div>
<div class="stat-label">Setup time</div>
<div class="stat-detail">From zero to production</div>
</div>
<div class="stat-card grid-card" data-stat="2">
<div class="stat-icon">⏱️</div>
<div class="stat-counter">2hr</div>
<div class="stat-label">Configuration</div>
<div class="stat-detail">Full customization</div>
</div>
<div class="stat-card grid-card" data-stat="1">
<div class="stat-icon">🧠</div>
<div class="stat-counter">AI Ready</div>
<div class="stat-label">Local AI Integrations Available</div>
<div class="stat-detail">Build With Plain Language</div>
</div>
</div>
</div>
</div>
</section>
<!-- Comparison Grid -->
<section class="comparison-grid">
<div class="grid-container">
@ -313,7 +396,7 @@
<div class="feature">✓ Community support</div>
<div class="feature">✓ Learn the system</div>
</div>
<a href="/getting-started" class="btn btn-secondary">Install Guide</a>
<a href="/build/getting-started" class="btn btn-secondary">Install Guide</a>
</div>
<!-- Managed -->

View File

@ -559,7 +559,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="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" class="md-nav__link">
<a href="https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/Distributed%20Digital%20Organizing%20is%20The%20Way%20Out/" class="md-nav__link">
@ -1001,6 +1001,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>

View File

@ -559,7 +559,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="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" class="md-nav__link">
<a href="https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/Distributed%20Digital%20Organizing%20is%20The%20Way%20Out/" class="md-nav__link">
@ -645,6 +645,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>

File diff suppressed because one or more lines are too long

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1105,6 +1132,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1128,7 +1159,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1145,14 +1176,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1183,6 +1214,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1096,6 +1123,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1119,7 +1150,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1136,14 +1167,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1174,6 +1205,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1273,6 +1300,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1296,7 +1327,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1313,14 +1344,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1351,6 +1382,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -15,7 +15,7 @@
<link rel="canonical" href="https://cmlite.org/services/">
<link rel="prev" href="../build/map/">
<link rel="prev" href="../build/site/">
<link rel="next" href="homepage/">
@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../build/build-server/" class="md-nav__link">
<a href="../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link md-nav__link--active" for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link md-nav__link--active" for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -974,6 +1001,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -997,7 +1028,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1014,14 +1045,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1052,6 +1083,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>
@ -1605,7 +1805,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../build/map/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Build Map">
<a href="../build/site/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Build Site">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
@ -1615,7 +1815,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
Previous
</span>
<div class="md-ellipsis">
Build Map
Build Site
</div>
</div>
</a>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1114,6 +1141,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1137,7 +1168,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1154,14 +1185,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1192,6 +1223,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1138,6 +1165,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1161,7 +1192,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1178,14 +1209,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1216,6 +1247,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1087,6 +1114,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1110,7 +1141,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1127,14 +1158,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1165,6 +1196,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1171,6 +1198,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1194,7 +1225,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1211,14 +1242,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1249,6 +1280,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>
@ -1520,7 +1720,9 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<h1 id="mkdocs-material">MkDocs Material<a class="headerlink" href="#mkdocs-material" title="Permanent link">&para;</a></h1>
<div class="github-widget" data-repo="squidfunk/mkdocs-material"></div>
<p>Modern documentation site generator with live preview.</p>
<p>Modern documentation site generator with live preview. </p>
<p>Looking for more info on BNKops code-server integration? </p>
<p><a href="../../config/coder/">→ Code Server Configuration</a></p>
<h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">&para;</a></h2>
<p>MkDocs Material is a powerful documentation framework built on top of MkDocs, providing a beautiful Material Design theme and advanced features for creating professional documentation sites.</p>
<h2 id="features">Features<a class="headerlink" href="#features" title="Permanent link">&para;</a></h2>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1249,6 +1276,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1272,7 +1303,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1289,14 +1320,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1327,6 +1358,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1240,6 +1267,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1263,7 +1294,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1280,14 +1311,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1318,6 +1349,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1180,6 +1207,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1203,7 +1234,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1220,14 +1251,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1258,6 +1289,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -513,6 +513,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -575,7 +579,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<a href="../../build/server/" class="md-nav__link">
@ -618,6 +622,29 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../build/site/" class="md-nav__link">
<span class="md-ellipsis">
Build Site
</span>
</a>
</li>
@ -669,7 +696,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" checked>
<div class="md-nav__link md-nav__container">
@ -686,14 +713,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_4">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1165,6 +1192,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -1188,7 +1219,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_5" >
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_6" >
<div class="md-nav__link md-nav__container">
@ -1205,14 +1236,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
@ -1243,6 +1274,175 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../config/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
mkdocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../config/coder/" class="md-nav__link">
<span class="md-ellipsis">
Coder
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3_7" >
<div class="md-nav__link md-nav__container">
<a href="../../adv/" class="md-nav__link ">
<span class="md-ellipsis">
Advanced Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Advanced Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../adv/ansible/" class="md-nav__link">
<span class="md-ellipsis">
SSH + Tailscale + Ansible
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../adv/vscode-ssh/" class="md-nav__link">
<span class="md-ellipsis">
SSH + VScode
</span>
</a>
</li>
</ul>
</nav>

View File

@ -2,86 +2,110 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://cmlite.org/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/adv/</loc>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/adv/ansible/</loc>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/adv/vscode-ssh/</loc>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/blog/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/build/</loc>
<lastmod>2025-07-01</lastmod>
</url>
<url>
<loc>https://cmlite.org/build/build-server/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/build/map/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/build/server/</loc>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/build/site/</loc>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/config/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/config/cloudflare-config/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/config/coder/</loc>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/config/mkdocs/</loc>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/phil/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/phil/cost-comparison/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/code-server/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/gitea/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/homepage/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/listmonk/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/map/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/mini-qr/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/mkdocs/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/n8n/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/nocodb/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/postgresql/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
<url>
<loc>https://cmlite.org/services/static-server/</loc>
<lastmod>2025-07-01</lastmod>
<lastmod>2025-07-02</lastmod>
</url>
</urlset>

Binary file not shown.

View File

@ -10,13 +10,13 @@
--trans-white: #FFFFFF;
--trans-white-dim: #E0E0E0;
/* Dark theme colors */
/* Dark theme colors - updated for consistent slate */
--home-dark-bg: #0a0a0a;
--home-dark-surface: #151515;
--home-dark-card: #1a1a1a;
--home-dark-border: #2a2a2a;
--home-dark-text: #e0e0e0;
--home-dark-text-muted: #999;
--home-dark-surface: #1e293b; /* slate-800 */
--home-dark-card: #334155; /* slate-700 */
--home-dark-border: #475569; /* slate-600 */
--home-dark-text: #e2e8f0; /* slate-200 */
--home-dark-text-muted: #94a3b8; /* slate-400 */
/* Grid colors */
--grid-primary: var(--trans-blue);
@ -104,13 +104,14 @@ body[data-md-template="home"] .md-main__inner {
}
.grid-card {
background: var(--md-default-bg-color);
border: 1px solid var(--grid-border);
background: var(--home-dark-card);
border: 1px solid var(--home-dark-border);
border-radius: 4px;
padding: var(--space-md);
transition: all 0.2s ease;
position: relative;
overflow: hidden;
color: var(--home-dark-text);
}
.grid-card::before {
@ -307,20 +308,21 @@ body[data-md-template="home"] .md-main__inner {
.section-header {
text-align: center;
margin-bottom: var(--space-lg);
padding: var(--space-sm) 0;
background: linear-gradient(to bottom,
rgba(10, 10, 10, 0.9) 0%,
rgba(10, 10, 10, 0.7) 70%,
transparent 100%);
backdrop-filter: blur(4px);
border-bottom: 1px solid var(--grid-border);
padding: var(--space-lg) var(--space-md);
background: #2d1b69; /* Deep purple solid background */
border-radius: var(--home-radius);
border: 1px solid var(--mkdocs-purple);
box-shadow: 0 0 20px rgba(111, 66, 193, 0.3);
position: relative;
z-index: 10; /* Ensure it stays above other content */
overflow: hidden; /* Prevent any content bleeding */
}
.section-header h2 {
font-size: 1.8rem;
font-weight: 700;
margin: 0 0 var(--space-xs) 0;
color: var(--home-dark-text);
color: var(--trans-white);
position: relative;
display: inline-block;
}
@ -332,12 +334,12 @@ body[data-md-template="home"] .md-main__inner {
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, var(--trans-blue), transparent);
background: linear-gradient(90deg, transparent, var(--trans-pink), transparent);
}
.section-header p {
font-size: 0.9rem;
color: var(--home-dark-text-muted);
color: var(--trans-white-dim);
margin: 0;
}
@ -345,11 +347,23 @@ body[data-md-template="home"] .md-main__inner {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: var(--space-sm);
padding-top: var(--space-md); /* Add padding to accommodate service badges too */
}
.service-card {
text-decoration: none;
color: inherit;
text-align: center;
transition: all 0.3s ease;
position: relative;
cursor: pointer;
min-height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: var(--space-md); /* Reset to normal padding */
margin-top: 0; /* Remove margin, use grid padding instead */
}
.service-card:hover .service-icon {
@ -402,6 +416,204 @@ body[data-md-template="home"] .md-main__inner {
display: inline-block;
}
/* =================================
PROOFS SECTION - NEW
================================= */
.proofs-grid {
padding: var(--space-lg) 0;
border-top: 1px solid var(--grid-border);
}
/* Example Sites */
.proof-sites {
margin-bottom: var(--space-xl);
}
.proof-sites h3 {
font-size: 1.2rem;
margin: 0 0 var(--space-lg) 0;
color: var(--trans-blue);
text-align: center;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.sites-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--space-sm);
margin-bottom: var(--space-xl);
max-width: 900px;
margin-left: auto;
margin-right: auto;
padding-top: var(--space-md); /* Add padding to accommodate badges */
}
.site-card {
text-decoration: none;
color: inherit;
text-align: center;
transition: all 0.3s ease;
position: relative;
cursor: pointer;
min-height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: var(--space-md);
margin-top: 0; /* Remove margin, use grid padding instead */
}
.site-card:hover {
transform: translateY(-3px) scale(1.02);
box-shadow: 0 0 20px rgba(91, 206, 250, 0.4);
}
.site-card.featured {
border-color: var(--trans-blue);
box-shadow: 0 0 15px rgba(91, 206, 250, 0.3);
}
.site-badge {
position: absolute;
top: -4px; /* Bring badge even closer to card */
left: 50%;
transform: translateX(-50%);
background: var(--trans-blue);
color: #000;
padding: 0.1rem 0.6rem;
border-radius: 10px;
font-size: 0.65rem;
font-weight: 700;
z-index: 5;
white-space: nowrap; /* Prevent text wrapping */
}
.site-icon {
font-size: 2.5rem;
margin-bottom: var(--space-sm);
animation: site-float 3s ease-in-out infinite;
}
@keyframes site-float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
}
.site-name {
font-size: 1rem;
font-weight: 600;
margin-bottom: var(--space-xs);
color: var(--home-dark-text);
}
.site-desc {
font-size: 0.8rem;
color: var(--home-dark-text-muted);
}
/* Live Stats */
.proof-stats h3 {
font-size: 1.2rem;
margin: 0 0 var(--space-lg) 0;
color: var(--trans-pink);
text-align: center;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-sm);
max-width: 1000px;
margin: 0 auto;
}
.stat-card {
text-align: center;
position: relative;
overflow: hidden;
min-height: 160px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: var(--space-md);
}
.stat-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg,
var(--trans-blue),
var(--trans-pink),
var(--trans-blue));
animation: stat-glow 2s ease-in-out infinite;
}
@keyframes stat-glow {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
.stat-icon {
font-size: 2rem;
margin-bottom: var(--space-xs);
animation: stat-pulse 2s ease-in-out infinite;
}
@keyframes stat-pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.stat-counter {
font-size: 1.5rem;
font-weight: 700;
color: var(--trans-pink); /* Changed to pink to match section header */
margin-bottom: var(--space-xs);
/* Removed text-shadow and animation for better readability */
}
.stat-label {
font-size: 0.9rem;
font-weight: 600;
color: var(--home-dark-text);
margin-bottom: var(--space-xs);
}
.stat-detail {
font-size: 0.7rem;
color: var(--home-dark-text-muted);
}
/* Animated counter effect */
.stat-counter.counting {
animation: counter-count 1.2s ease-out;
}
@keyframes counter-count {
0% {
transform: scale(0.5) rotateY(-90deg);
opacity: 0;
}
50% {
transform: scale(1.2) rotateY(0deg);
opacity: 0.8;
}
100% {
transform: scale(1) rotateY(0deg);
opacity: 1;
}
}
/* =================================
COMPARISON TABLE - GRID STYLE
================================= */
@ -474,11 +686,14 @@ body[data-md-template="home"] .md-main__inner {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-sm);
margin-bottom: var(--space-lg);
padding-top: var(--space-md); /* Add padding to accommodate badges */
}
.option-card {
text-align: center;
position: relative;
padding-top: var(--space-md); /* Reduced padding since grid now has padding */
margin-top: 0; /* Remove margin, use grid padding instead */
}
.option-card.featured {
@ -499,7 +714,7 @@ body[data-md-template="home"] .md-main__inner {
.option-badge {
position: absolute;
top: -8px;
top: -4px; /* Bring badge even closer to card */
left: 50%;
transform: translateX(-50%);
background: var(--trans-blue);
@ -508,6 +723,8 @@ body[data-md-template="home"] .md-main__inner {
border-radius: 10px;
font-size: 0.65rem;
font-weight: 700;
z-index: 5;
white-space: nowrap; /* Prevent text wrapping */
}
.option-icon {
@ -582,7 +799,7 @@ body[data-md-template="home"] .md-main__inner {
min-width: 100px;
position: relative;
overflow: hidden;
color: var(--mkdocs-purple-dark);
color: var(--trans-white) !important; /* Force white text with higher specificity */
}
.btn::before {
@ -605,29 +822,52 @@ body[data-md-template="home"] .md-main__inner {
.btn-primary {
background: var(--mkdocs-purple);
color: var(--mkdocs-purple-dark);
color: var(--trans-white) !important; /* Force white text */
border-color: var(--mkdocs-purple);
}
.btn-primary:hover {
background: var(--mkdocs-purple-dark);
color: #000;
color: var(--trans-white) !important; /* Force white text on hover */
box-shadow: 0 0 15px var(--mkdocs-purple);
transform: translateY(-1px);
}
.btn-secondary {
background: transparent;
color: var(--mkdocs-purple);
color: var(--trans-white) !important; /* Force white text */
border-color: var(--mkdocs-purple);
}
.btn-secondary:hover {
background: var(--mkdocs-purple-dark);
color: #000;
color: var(--trans-white) !important; /* Force white text on hover */
box-shadow: 0 0 15px var(--mkdocs-purple);
}
/* Ensure all button variations have white text */
a.btn,
a.btn:visited,
a.btn:link,
a.btn:active {
color: var(--trans-white) !important;
text-decoration: none !important;
}
a.btn-primary,
a.btn-primary:visited,
a.btn-primary:link,
a.btn-primary:active {
color: var(--trans-white) !important;
}
a.btn-secondary,
a.btn-secondary:visited,
a.btn-secondary:link,
a.btn-secondary:active {
color: var(--trans-white) !important;
}
/* =================================
RESPONSIVE - ULTRA TIGHT
================================= */
@ -651,6 +891,16 @@ body[data-md-template="home"] .md-main__inner {
grid-template-columns: 1fr;
}
.sites-grid {
grid-template-columns: repeat(2, 1fr);
max-width: 500px;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
max-width: 500px;
}
.comparison-header,
.comparison-row {
font-size: 0.7rem;
@ -679,6 +929,16 @@ body[data-md-template="home"] .md-main__inner {
grid-template-columns: 1fr;
}
.sites-grid {
grid-template-columns: 1fr;
max-width: 350px;
}
.stats-grid {
grid-template-columns: 1fr;
max-width: 350px;
}
.service-card {
padding: var(--space-sm);
}
@ -686,6 +946,14 @@ body[data-md-template="home"] .md-main__inner {
.hero-main h1 {
font-size: 1.3rem;
}
.stat-counter {
font-size: 1.2rem;
}
.site-icon {
font-size: 2rem;
}
}
/* Row cards at bottom: two cards in a row on desktop, stack on mobile */
@ -734,4 +1002,72 @@ body[data-md-template="home"] .md-main__inner {
letter-spacing: 0.03em;
vertical-align: middle;
box-shadow: 0 0 6px var(--mkdocs-purple-dark);
}
/* Ensure all cards have consistent slate background */
.grid-card,
.site-card,
.stat-card,
.service-card,
.option-card,
.final-cta,
.subscribe-card {
background: var(--home-dark-card) !important;
color: var(--home-dark-text) !important;
}
/* Fix form elements in subscribe card */
.subscribe-card input[type="email"],
.subscribe-card input[type="text"] {
background: var(--home-dark-surface);
color: var(--home-dark-text);
border: 1px solid var(--home-dark-border);
border-radius: 4px;
padding: 0.5rem;
width: 100%;
box-sizing: border-box;
}
.subscribe-card input[type="email"]:focus,
.subscribe-card input[type="text"]:focus {
outline: none;
border-color: var(--trans-blue);
box-shadow: 0 0 0 2px rgba(91, 206, 250, 0.2);
}
.subscribe-card label {
color: var(--home-dark-text-muted);
font-size: 0.9rem;
}
.subscribe-card .action-btn {
background: var(--mkdocs-purple);
color: #000;
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.subscribe-card .action-btn:hover {
background: var(--mkdocs-purple-dark);
transform: translateY(-1px);
box-shadow: 0 0 10px rgba(111, 66, 193, 0.4);
}
/* Ensure all section content respects the header layering */
.solution-grid,
.proofs-grid,
.comparison-grid,
.get-started-grid {
position: relative;
z-index: 1; /* Lower than section headers */
}
/* Make sure grid cards don't interfere with section headers */
.grid-card {
position: relative;
z-index: 2; /* Higher than section content but lower than headers */
}