Tonnes of updates to the site documentation and general processes

This commit is contained in:
admin 2025-06-30 15:49:39 -06:00
parent 438e9678d1
commit b5cabd7a72
94 changed files with 14823 additions and 6347 deletions

View File

@ -2,6 +2,13 @@ FROM codercom/code-server:latest
USER root
# Install Node.js 18+ and npm
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y nodejs
# Install Claude Code globally as root
RUN npm install -g @anthropic-ai/claude-code
# Install Python and dependencies
RUN apt-get update && apt-get install -y \
python3 \
@ -81,4 +88,4 @@ RUN mkdir -p /home/coder/.local/bin \
&& echo '#!/bin/bash\ncd /home/coder/mkdocs\nmkdocs "$@"' > /home/coder/.local/bin/run-mkdocs \
&& chmod +x /home/coder/.local/bin/run-mkdocs
WORKDIR /home/coder
WORKDIR /home/coder

View File

@ -1,300 +0,0 @@
# Changemaker Lite Landing Page Development Plan
*UPDATED: Grid-Optimized Media Integration Strategy*
## Executive Summary
We've revolutionized the Changemaker Lite landing page with an Alibaba-style grid system that maximizes screen real estate while aggressively promoting our self-hosting message: **"This Site Runs On Changemaker Lite."** The page is now a living proof-of-concept that converts visitors through demonstration, not just explanation.
## 🚀 SELF-HOSTING HYPE STRATEGY
**Core Message:** "The Infrastructure That Runs Itself"
### Primary Positioning:
- **"🤯 This Site Runs On Changemaker Lite"** - Meta-badge visible throughout
- **Live Proof Points** - Show actual BNKops infrastructure running on the same hardware
- **Real Savings Data** - Our actual $13,800/year savings vs corporate SaaS
- **Zero Corporate Dependencies** - Emphasize complete digital liberation
### Proof-of-Concept Integration:
1. **Meta-Validation** - Every page element proves the platform works
2. **Behind-the-Scenes Access** - Video demos of actual running services
3. **Real Stats Display** - Live subscriber counts, uptime metrics, cost savings
4. **Transparent Operations** - Show the actual $200 hardware running everything
## 🎯 GRID SYSTEM ARCHITECTURE
**Maximum Screen Real Estate - Alibaba Style**
### Grid Layout Principles:
- **Tight Spacing** - 0.5rem base gaps for content density
- **Modular Cards** - Every element in contained, hover-interactive cards
- **Responsive Scaling** - 4-column desktop → 2-column tablet → 1-column mobile
- **Information Hierarchy** - Color-coded importance levels
### Section Structure:
1. **Hero Grid** - 2x2 layout: Main message + Video + Stats + Trust indicators
2. **Proof Grid** - 4-card layout showing live infrastructure
3. **Hardware Grid** - 3-option purchase matrix
4. **Services Grid** - Tight showcase of all 11 included services
## 📹 MEDIA INTEGRATION STRATEGY
### Video Content Requirements:
#### 1. HERO VIDEO: "See Changemaker Lite In Action" (3:00)
**Script Outline:**
```
[0:00-0:15] HOOK: "What you're looking at right now is running on $200 hardware"
[0:15-0:45] TERMINAL DEMO: docker compose ps, service URLs, real data
[0:45-1:30] DASHBOARD TOUR: Homepage overview, all 11 services working
[1:30-2:15] BACKEND ACCESS: NocoDB, Listmonk, email campaigns
[2:15-2:45] COST COMPARISON: Corporate bills vs our $50/month
[2:45-3:00] CTA: "Get the same setup for $200"
```
#### 2. BACKEND DEMO: "Homepage Dashboard Tour" (1:30)
**Script Outline:**
```
[0:00-0:20] Homepage overview - all services green status
[0:20-0:50] Click through key services (NocoDB, Listmonk, Gitea)
[0:50-1:10] Show actual data - newsletters, databases, code repos
[1:10-1:30] "This is what you get out of the box"
```
#### 3. SETUP DEMO: "30-Minute Time-lapse" (5:23)
**Script Outline:**
```
[0:00-0:30] Unboxing hardware, connection setup
[0:30-2:00] Initial boot, docker compose deployment
[2:00-3:30] Service configuration, domain setup
[3:30-4:30] Testing all services, sending first email
[4:30-5:23] Final dashboard tour, "You're live!"
```
#### 4. COST BREAKDOWN: "Corporate vs Changemaker" (2:00)
**Script Outline:**
```
[0:00-0:30] Show typical SaaS stack bills ($1,200/mo)
[0:30-1:00] Break down each service cost vs Changemaker equivalent
[1:00-1:30] Annual savings calculation ($13,800)
[1:30-2:00] "Money for organizing, not shareholders"
```
### Video Production Specs:
- **Resolution:** 1920x1080 minimum, 4K preferred for hero video
- **Format:** MP4 with H.264 encoding
- **Length:** Keep under 3 minutes for engagement
- **Captions:** Required for accessibility
- **Hosting:** Self-hosted on Changemaker Lite (of course!)
## 🎨 VISUAL DESIGN UPDATES
### Grid-Optimized Elements:
- **Micro-interactions** - Card hovers, button states, loading animations
- **Progressive Enhancement** - Mobile-first, desktop-enhanced
- **Performance Focus** - Lazy loading, optimized assets, minimal JS
- **Brand Consistency** - Trans flag colors throughout
### Component Library:
1. **Grid Cards** - Standardized containers with consistent padding
2. **Video Placeholders** - Interactive preview states with play buttons
3. **Stat Displays** - Animated counters with real data integration
4. **CTA Buttons** - Primary/secondary hierarchy with hover effects
## 💰 CONVERSION OPTIMIZATION
### Three-Path Strategy:
1. **Plug & Play ($200)** - Recommended, ships in 5 days
2. **DIY Install (Free)** - Technical users, community support
3. **Managed Hosting ($150/mo)** - Hands-off but still your infrastructure
### Conversion Elements:
- **Social Proof** - "Powers BNKops.com" trust indicators
- **Urgency** - "Ships in 5 days" immediacy
- **Risk Reduction** - "30-minute setup" simplicity promise
- **Value Demonstration** - Live cost savings calculator
## 🎭 CONTENT PERSONALITY
### Voice & Tone:
- **Confident Revolutionary** - "We're not just selling it - we're living it"
- **Technical Transparency** - Show the actual infrastructure
- **Community-Focused** - "Trans liberation tech"
- **Anti-Corporate** - "Zero surveillance" messaging
### Key Phrases:
- "The Infrastructure That Runs Itself"
- "What You're Looking At Right Now"
- "Money for organizing, not shareholders"
- "Your data, your power, your movement"
- "Digital liberation movement"
## 📊 SUCCESS METRICS
### Primary KPIs:
1. **Hardware Orders** - Track $200 package conversions
2. **Installation Attempts** - DIY guide engagement
3. **Video Completion Rates** - Media effectiveness
4. **Time on Page** - Grid layout engagement
### Secondary Metrics:
1. **Self-hosting Message Retention** - Post-visit surveys
2. **Social Shares** - Viral potential tracking
3. **Return Visits** - Community building indicator
4. **Email Signups** - Newsletter conversion funnel
## 🚧 TECHNICAL IMPLEMENTATION
### Completed Updates:
1. ✅ **Grid-optimized CSS** - Alibaba-style layout system
2. ✅ **Self-hosting badges** - Meta-validation throughout
3. ✅ **Grid HTML structure** - Maximum screen real estate utilization
4. ✅ **Video placeholder integration** - Ready for content production
### Next Phase:
1. 📹 **Video Production** - Execute scripted content strategy
2. 📊 **Analytics Setup** - Privacy-respecting conversion tracking
3. 🧪 **A/B Testing Framework** - Message optimization capability
4. 🚀 **Performance Optimization** - Mobile loading improvements
### Performance Targets:
- **Load Time:** <2 seconds on 3G
- **Mobile Score:** >90 Lighthouse
- **Accessibility:** AA WCAG compliance
- **SEO:** Structured data, meta optimization
## 🎬 VIDEO PRODUCTION ROADMAP
### Phase 1: Hero Content (Priority 1)
1. **"See Changemaker Lite In Action" (3:00)** - Main conversion driver
2. **"30-Minute Setup Time-lapse" (5:23)** - Risk reduction
### Phase 2: Proof Content (Priority 2)
3. **"Homepage Dashboard Tour" (1:30)** - Technical demonstration
4. **"Corporate vs Changemaker Costs" (2:00)** - Value proposition
### Phase 3: Advanced Content (Priority 3)
5. **"Behind the Scenes: How BNKops Runs" (4:00)** - Advanced proof
6. **"Community Testimonials" (2:30)** - Social proof compilation
### Production Requirements:
- **Screen Recording:** OBS Studio with 1080p60 capture
- **Hardware Demo:** Good lighting, stable camera setup
- **Audio:** Clear narration, background music optional
- **Editing:** Simple cuts, captions, brand consistency
- **Hosting:** Self-hosted on Changemaker Lite infrastructure
## 📈 CONVERSION FUNNEL OPTIMIZATION
### Landing Paths:
1. **Curious Visitor** → Video Demo → Understanding → Newsletter Signup
2. **Ready Buyer** → "Order Hardware" → Immediate conversion
3. **DIY Techie** → Installation Guide → Community Engagement
4. **Managed Solution** → Hosting Inquiry → Sales Process
### Optimization Priorities:
1. **Video Completion Rates** - Shorter, punchier content
2. **Hardware Order Flow** - Streamlined purchase process
3. **Newsletter Value** - Immediate PDF guides/resources
4. **Mobile Experience** - Touch-optimized interactions
## 🎯 IMMEDIATE ACTION ITEMS
### This Week:
1. **Video Script Finalization** - Get all 4 core scripts approved
2. **Screen Recording Setup** - Prepare clean demo environment
3. **Analytics Integration** - Privacy-respecting tracking setup
4. **Mobile Testing** - Cross-device grid layout verification
### Next Week:
1. **Hero Video Production** - Priority 1 content creation
2. **Setup Demo Recording** - Time-lapse capture
3. **Performance Audit** - Loading speed optimization
4. **A/B Testing Framework** - Message variation testing
### Month 1:
1. **Full Video Suite** - All 6 videos produced and integrated
2. **Conversion Optimization** - Data-driven improvements
3. **Community Feedback** - User testing and iteration
4. **SEO Enhancement** - Search visibility improvements
## 🏆 SUCCESS DEFINITION
### Quantitative Goals:
- **50% video completion rate** for hero video
- **15% conversion rate** from visitor to newsletter signup
- **10% hardware order rate** from engaged visitors
- **<2 second load time** on mobile devices
### Qualitative Goals:
- **"I get it now"** - Clear self-hosting value proposition
- **"This looks professional"** - Trust and credibility establishment
- **"I want this"** - Emotional connection to digital sovereignty
- **"It's actually simple"** - Technical barrier reduction
---
**THE LANDING PAGE IS NOW A LIVING PROOF THAT CHANGEMAKER LITE WORKS. EVERY VISITOR SEES EXACTLY WHAT THEY'LL GET - BECAUSE THEY'RE LOOKING AT IT.**
## 📹 FUTURE MEDIA INTEGRATION
### Video Content to Add Later:
#### 1. HERO VIDEO: "The FOSS Campaign Revolution" (2:30)
**Location:** Hero grid section
**Script Outline:**
```
[0:00-0:15] HOOK: "Stop paying $1,200/month for campaign tech"
[0:15-0:45] PROBLEM: Show corporate SaaS bills, vendor lock-in
[0:45-1:30] SOLUTION: Changemaker Lite demo - all services running
[1:30-2:00] PROOF: Real campaigns using it, cost savings
[2:00-2:30] CTA: "Join the digital liberation movement"
```
#### 2. SERVICE DEMOS: Individual Tool Showcases (0:30 each)
**Location:** Service cards in solution grid
- **Listmonk Demo:** Email campaign creation
- **NocoDB Demo:** Voter database management
- **Chatwoot Demo:** Text banking in action
- **n8n Demo:** Automation workflows
#### 3. COMPARISON VIDEO: "Corporate vs FOSS" (1:30)
**Location:** Comparison grid section
**Content:** Side-by-side comparison of costs, features, data ownership
#### 4. SETUP WALKTHROUGH: "From Box to Campaign" (5:00)
**Location:** Get started section
**Content:** Complete setup process time-lapse
### Screenshot Requirements:
- Dashboard overview showing all services
- Individual service interfaces
- Cost comparison charts
- Hardware photos (unboxing, setup)
- Real campaign examples (anonymized)
### Animation Enhancements:
- Service icon animations (already implemented)
- Interactive comparison table
- Live visitor counter
- Real-time savings calculator
## 🎯 COMPLETED UPDATES
### Page Focus:
✅ **Repositioned as FOSS political campaign solution**
✅ **Removed video placeholders for cleaner grid**
✅ **Added comparison with corporate alternatives**
✅ **Emphasized cost savings and data ownership**
### Design Implementation:
✅ **Ultra-tight grid system (Alibaba-style)**
✅ **Neon animations with trans flag colors**
✅ **Smooth scroll and parallax effects**
✅ **Responsive grid that reflows perfectly**
✅ **Stagger animations on scroll**
✅ **Interactive hover states**
### Content Strategy:
✅ **Clear problem/solution messaging**
✅ **Service-by-service breakdown**
✅ **Direct corporate alternative comparisons**
✅ **Three-tier pricing strategy**
✅ **Trust indicators and social proof**

View File

@ -1,40 +0,0 @@
# Cloudflare Configuration Guide for Changemaker.lite
This guide will help you properly configure Cloudflare credentials for use with Changemaker.lite's production deployment.
## Finding Your Zone ID
The Zone ID is a unique identifier for your domain in Cloudflare.
1. Log in to the [Cloudflare Dashboard](https://dash.cloudflare.com)
2. Select your domain (e.g., cmlite.org)
3. On the right sidebar under "API", you'll see "Zone ID"
4. Copy this value - it should look something like: `1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p`
## Creating an API Token
You need an API token with proper permissions to manage DNS records and access policies.
1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) > Profile (top right) > API Tokens
2. Click "Create Token"
3. Use the "Edit zone DNS" template (or create a custom token)
4. For a custom token, ensure it has the following permissions:
- Zone - DNS - Edit
- Zone - Settings - Read
- Account - Cloudflare Tunnel - Read
5. Under "Zone Resources", select "Include - Specific zone" and choose your domain
6. Create the token and copy its value
## Finding Your Account ID
The Account ID is needed for some Cloudflare Tunnel operations.
1. Go to the [Cloudflare Dashboard](https://dash.cloudflare.com)
2. Look at the URL when logged in - it will contain your account ID:
`https://dash.cloudflare.com/1a2b3c4d5e6f7g8h9i0j/your-domain.com`
3. The string after `/dash.cloudflare.com/` is your Account ID (e.g., `1a2b3c4d5e6f7g8h9i0j`)
## Updating Your .env File
Update your `.env` file with these values:

View File

@ -79,6 +79,11 @@
<label for="edit-location-email">Email</label>
<input type="email" id="edit-location-email" name="Email">
</div>
<div class="form-group">
<label for="edit-location-phone">Phone Number</label>
<input type="tel" id="edit-location-phone" name="Phone">
</div>
<div class="form-row">
<div class="form-group">
@ -124,6 +129,11 @@
</select>
</div>
</div>
<div class="form-group">
<label for="edit-location-notes">Notes</label>
<textarea id="edit-location-notes" name="Notes" rows="4"></textarea>
</div>
<div class="form-row">
<div class="form-group">
@ -177,6 +187,12 @@
<input type="email" id="location-email" name="Email"
placeholder="Enter email address">
</div>
<div class="form-group">
<label for="location-phone">Phone Number</label>
<input type="tel" id="location-phone" name="Phone"
placeholder="Enter phone number">
</div>
<div class="form-row">
<div class="form-group">
@ -224,6 +240,12 @@
</select>
</div>
</div>
<div class="form-group">
<label for="location-notes">Notes</label>
<textarea id="location-notes" name="Notes" rows="4"
placeholder="Enter additional details"></textarea>
</div>
<div class="form-row">
<div class="form-group">

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
mkdocs/core Normal file

Binary file not shown.

View File

@ -0,0 +1,16 @@
{
"full_name": "admin/changemaker.lite",
"name": "changemaker.lite",
"description": "Changemaker-lite is the current active development branch of Changemaker, focused on streamlining core services. These improvements will be merged into the master branch once ready.",
"html_url": "https://gitea.bnkops.com/admin/changemaker.lite",
"language": "HTML",
"stars_count": 0,
"forks_count": 0,
"open_issues_count": 0,
"updated_at": "2025-06-30T10:01:47-06:00",
"created_at": "2025-05-28T14:54:59-06:00",
"clone_url": "https://gitea.bnkops.com/admin/changemaker.lite.git",
"ssh_url": "git@gitea.bnkops.com:admin/changemaker.lite.git",
"default_branch": "main",
"last_build_update": "2025-06-30T10:01:47-06:00"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "coder/code-server",
"name": "code-server",
"description": "VS Code in the browser",
"html_url": "https://github.com/coder/code-server",
"language": "TypeScript",
"stars_count": 72491,
"forks_count": 6060,
"open_issues_count": 132,
"updated_at": "2025-06-30T21:31:29Z",
"created_at": "2019-02-27T16:50:41Z",
"clone_url": "https://github.com/coder/code-server.git",
"ssh_url": "git@github.com:coder/code-server.git",
"default_branch": "main",
"last_build_update": "2025-06-25T21:18:52Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "gethomepage/homepage",
"name": "homepage",
"description": "A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.",
"html_url": "https://github.com/gethomepage/homepage",
"language": "JavaScript",
"stars_count": 24565,
"forks_count": 1519,
"open_issues_count": 1,
"updated_at": "2025-06-30T20:44:09Z",
"created_at": "2022-08-24T07:29:42Z",
"clone_url": "https://github.com/gethomepage/homepage.git",
"ssh_url": "git@github.com:gethomepage/homepage.git",
"default_branch": "dev",
"last_build_update": "2025-06-30T12:13:58Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "knadh/listmonk",
"name": "listmonk",
"description": "High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.",
"html_url": "https://github.com/knadh/listmonk",
"language": "Go",
"stars_count": 17238,
"forks_count": 1656,
"open_issues_count": 103,
"updated_at": "2025-06-30T20:57:12Z",
"created_at": "2019-06-26T05:08:39Z",
"clone_url": "https://github.com/knadh/listmonk.git",
"ssh_url": "git@github.com:knadh/listmonk.git",
"default_branch": "master",
"last_build_update": "2025-06-30T10:45:51Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "n8n-io/n8n",
"name": "n8n",
"description": "Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.",
"html_url": "https://github.com/n8n-io/n8n",
"language": "TypeScript",
"stars_count": 113623,
"forks_count": 33244,
"open_issues_count": 1061,
"updated_at": "2025-06-30T21:38:07Z",
"created_at": "2019-06-22T09:24:21Z",
"clone_url": "https://github.com/n8n-io/n8n.git",
"ssh_url": "git@github.com:n8n-io/n8n.git",
"default_branch": "master",
"last_build_update": "2025-06-30T20:59:49Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "nocodb/nocodb",
"name": "nocodb",
"description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 Open Source Airtable Alternative",
"html_url": "https://github.com/nocodb/nocodb",
"language": "TypeScript",
"stars_count": 55465,
"forks_count": 3980,
"open_issues_count": 714,
"updated_at": "2025-06-30T21:39:01Z",
"created_at": "2017-10-29T18:51:48Z",
"clone_url": "https://github.com/nocodb/nocodb.git",
"ssh_url": "git@github.com:nocodb/nocodb.git",
"default_branch": "develop",
"last_build_update": "2025-06-30T20:21:14Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "squidfunk/mkdocs-material",
"name": "mkdocs-material",
"description": "Documentation that simply works",
"html_url": "https://github.com/squidfunk/mkdocs-material",
"language": "Python",
"stars_count": 23757,
"forks_count": 3783,
"open_issues_count": 4,
"updated_at": "2025-06-30T21:37:52Z",
"created_at": "2016-01-28T22:09:23Z",
"clone_url": "https://github.com/squidfunk/mkdocs-material.git",
"ssh_url": "git@github.com:squidfunk/mkdocs-material.git",
"default_branch": "master",
"last_build_update": "2025-06-29T16:43:26Z"
}

147
mkdocs/docs/build/build-server.md vendored Normal file
View File

@ -0,0 +1,147 @@
# BNKops Server Build
Purpose: a Ubuntu server build-out for general application
---
This documentation is a overview of the full build out for a server OS and baseline for running Changemaker-lite. It is a manual to re-install this server on any machine.
All of the following systems are free and the majority are open source.
## [Ubuntu](https://ubuntu.com/) OS
_Ubuntu_ is a Linux distribution derived from Debian and composed mostly of free and open-source software.
### [Install Ubuntu](https://ubuntu.com/tutorials/install-ubuntu-desktop#1-overview)
### Post Install
Post installation, run update:
```
sudo apt update
```
```
sudo apt upgrade
```
### Configuration
Further configurations:
- User profile was updated to Automatically Login
- Remote Desktop, Sharing, and Login have all been enabled.
- Default system settings have been set to dark mode.
## [VSCode Insiders](https://code.visualstudio.com/insiders/)
Visual Studio Code is a new choice of tool that combines the simplicity of a code editor with what developers need for the core edit-build-debug cycle.
### Install Using App Centre
## [Obsidian](https://obsidian.md/)
The free and flexible app for your private thoughts.
### Install Using App Center
## [Curl](https://curl.se/)
command line tool and library for transferring data with URLs (since 1998)
### Install
```
sudo apt install curl
```
## [Glances](https://github.com/nicolargo/glances)
Glances an Eye on your system. A top/htop alternative for GNU/Linux, BSD, Mac OS and Windows operating systems.
### Install
```
sudo snap install glances
```
## [Syncthing](https://syncthing.net/)
Syncthing is a continuous file synchronization program. It synchronizes files between two or more computers in real time, safely protected from prying eyes. Your data is your data alone and you deserve to choose where it is stored, whether it is shared with some third party, and how its transmitted over the internet.
### Install
```
# Add the release PGP keys:
sudo mkdir -p /etc/apt/keyrings
sudo curl -L -o /etc/apt/keyrings/syncthing-archive-keyring.gpg https://syncthing.net/release-key.gpg
```
```
# Add the "stable" channel to your APT sources:
echo "deb [signed-by=/etc/apt/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable" | sudo tee /etc/apt/sources.list.d/syncthing.list
```
```
# Update and install syncthing:
sudo apt-get update
sudo apt-get install syncthing
```
### Post Install
Run syncthing as a system service.
```
sudo systemctl start syncthing@yourusername
```
```
sudo systemctl enable syncthing@yourusername
```
## [Docker](https://www.docker.com/)
Docker helps developers build, share, run, and verify applications anywhere — without tedious environment configuration or management.
```
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
```
```
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
### Update Users
```
sudo groupadd docker
```
```
sudo usermod -aG docker $USER
```
```
newgrp docker
```
### Enable on Boot
```
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
```
## [Cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)
Connect, protect, and build everywhere. We make websites, apps, and networks faster and more secure. Our developer platform is the best place to build modern apps and deliver AI initiatives.
```
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
```
```
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
```
```
sudo apt-get update && sudo apt-get install cloudflared
```
### Post Install
Login to Cloudflare
```
cloudflared login
```
### Configuration
- Setting up the [[service.cloudflared]] enables your cloudflared tunnel to automatically run on reboot
## [Pandoc](https://pandoc.org/)
If you need to convert files from one markup format into another, pandoc is your swiss-army knife.
```
sudo apt install pandoc
```
## [Changemaker (V3.9.9.1)](https://changemaker.bnkops.com)

View File

@ -1,6 +1,42 @@
# Getting Started with Digital Liberation 🏳️‍⚧️
# Getting Started with Digital Liberation
Welcome to Changemaker-Lite! You're about to reclaim your digital sovereignty and stop feeding your secrets to corporations. This guide will help you set up your own political infrastructure that you actually own and control.
## Quick Start
### Build Changemkaer-Lite
```bash
# Clone the repository
git clone https://gitea.bnkops.com/admin/changemaker.lite
cd changemaker.lite
```
!!! warning "Cloudflare Credentials"
The config.sh script will ask you for your Cloudflare credentials to get started. You can find more information on how to find this in the [Cloudlflare Configuration](./config/cloudflare-config.md)
```
# Configure environment (creates .env file)
./config.sh
```
```
# Start all services
docker compose up -d
```
### Deploy
!!! note "Cloudflare"
Right now, we suggest deploying using Cloudflare for simplicity and protections against 99% of surface level attacks to digital infrastructure. If you want to avoid using this service, we recommend checking out [Pagolin](https://github.com/fosrl/pangolin) as a drop in replacement.
For secure public access, use the production deployment script:
```bash
./start-production.sh
```
Welcome to Changemaker Lite! You're about to reclaim your digital sovereignty and stop feeding your secrets to corporations. This guide will help you set up your own political infrastructure that you actually own and control.
## Why Changemaker Lite?
@ -30,8 +66,13 @@ Before we dive into the technical setup, let's be clear about what you're doing
### Operating System
- **Ubuntu 24.04 LTS (Noble Numbat)** - Recommended and tested
!!! note "Getting Started on Ubunut"
Want some help getting started with a baseline buildout for a Ubunut server? You can use our [BNKops Server Build Script](./build-server.md)
- Other Linux distributions with systemd support
- WSL2 on Windows (limited functionality)
- Mac OS
!!! tip "New to Linux?"
Consider [Linux Mint](https://www.linuxmint.com/) - it looks like Windows but opens the door to true digital freedom.
@ -44,10 +85,13 @@ Before we dive into the technical setup, let's be clear about what you're doing
- **Network**: Stable internet connection
!!! info "Cloud Hosting"
You can run this on a VPS from providers like Hetzner, DigitalOcean, or Linode for $20-50/month.
You can run this on a VPS from providers like Hetzner, DigitalOcean, or Linode for ~$20/month.
### Software Prerequisites
!!! tip "Getting Started on Docker"
Want some help getting started with a baseline buildout for a Ubunutu server? You can use our [BNKops Server Build Script](./build-server.md) to roll out a configured server in about 20 mins!
1. **Docker Engine** (24.0+)
```bash
@ -159,34 +203,29 @@ Expected output should show all services as "Up":
Once services are running, access them locally:
### 🏠 Homepage Dashboard
- **URL**: http://localhost:3010
- **Purpose**: Central hub for all services
### 🏠 Homepage Dashboard
- **URL**: [http://localhost:3010](http://localhost:3010)
- **Purpose**: Central hub for all services
- **Features**: Service status, quick links, monitoring
### 💻 Development Tools
### 💻 Development Tools
- **Code Server**: [http://localhost:8888](http://localhost:8888) — VS Code in browser
- **Gitea**: [http://localhost:3030](http://localhost:3030) — Git repository management
- **MkDocs Dev**: [http://localhost:4000](http://localhost:4000) — Live documentation preview
- **MkDocs Prod**: [http://localhost:4001](http://localhost:4001) — Built documentation
- **Code Server**: http://localhost:8888 - VS Code in browser
- **Gitea**: http://localhost:3030 - Git repository management
- **MkDocs Dev**: http://localhost:4000 - Live documentation preview
- **MkDocs Prod**: http://localhost:4001 - Built documentation
### 📧 Communication
- **Listmonk**: [http://localhost:9000](http://localhost:9000) — Email campaigns
_Login with credentials set during configuration_
### 📧 Communication
### 🔄 Automation & Data
- **n8n**: [http://localhost:5678](http://localhost:5678) — Workflow automation
_Login with credentials set during configuration_
- **NocoDB**: [http://localhost:8090](http://localhost:8090) — No-code database
- **Listmonk**: http://localhost:9000 - Email campaigns
- Login with credentials set during configuration
### 🔄 Automation & Data
- **n8n**: http://localhost:5678 - Workflow automation
- Login with credentials set during configuration
- **NocoDB**: http://localhost:8090 - No-code database
### 🛠️ Interactive Tools
- **Map Viewer**: http://localhost:3000 - Geographic data visualization
- **Mini QR**: http://localhost:8089 - QR code generator
### 🛠️ Interactive Tools
- **Map Viewer**: [http://localhost:3000](http://localhost:3000) — Geographic data visualization
- **Mini QR**: [http://localhost:8089](http://localhost:8089) — QR code generator
## Production Deployment

View File

@ -1,7 +0,0 @@
# Cloudflare
In this section, you will find instructions on how to properly set up Cloudflare for managing a Changemaker-lite.
## Config
When you first run the `./config.sh` it will prompt you for the a api token, zone id, and a tunnel id. A

View File

@ -0,0 +1,57 @@
# Configure Cloudflare
Cloudflare is the largest DNS routing service on the planet. We use their free service tier to provide Changemaker users with a fast, secure, and reliable way to get online that blocks 99% of surface level attacks and has built in user authenticaion (if you so choose to use it)
## Credentials
The `config.sh` and `start-production.sh` scripts require the following Cloudflare credentials to function properly:
### 1. **Cloudflare API Token**
- **Purpose**: Used to authenticate API requests to Cloudflare for managing DNS records, tunnels, and access policies.
- **Required Permissions**:
- `Zone.DNS` (Read/Write)
- `Account.Cloudflare Tunnel` (Read/Write)
- **How to Obtain**:
- Log in to your Cloudflare account.
- Go to **My Profile** > **API Tokens** > **Create Token**.
- Use the **Edit zone DNS** template and add **Cloudflare Tunnel** permissions.
### 2. **Cloudflare Zone ID**
- **Purpose**: Identifies the specific DNS zone (domain) in Cloudflare where DNS records will be created.
- **How to Obtain**:
- Log in to your Cloudflare account.
- Select the domain you want to use.
- The Zone ID is displayed in the **Overview** section under **API**.
### 3. **Cloudflare Account ID**
- **Purpose**: Identifies your Cloudflare account for tunnel creation and management.
- **How to Obtain**:
- Log in to your Cloudflare account.
- Go to **My Profile** > **API Tokens**.
- The Account ID is displayed at the top of the page.
### 4. **Cloudflare Tunnel ID** (Optional in config.sh, Required in start-production.sh)
- **Purpose**: Identifies the specific Cloudflare Tunnel that will be used to route traffic to your services.
- **How to Obtain**:
- This is automatically generated when you create a tunnel using `cloudflared tunnel create` or via the Cloudflare dashboard.
- The start-production.sh script will create this for you if it doesn't exist.
### Summary of Required Credentials:
```bash
# In .env file
CF_API_TOKEN=your_cloudflare_api_token
CF_ZONE_ID=your_cloudflare_zone_id
CF_ACCOUNT_ID=your_cloudflare_account_id
CF_TUNNEL_ID=will_be_set_by_start_production # This will be set by start-production.sh
```
### Notes:
- The config.sh script will prompt you for these credentials during setup.
- The start-production.sh script will verify these credentials and use them to configure DNS records, create tunnels, and set up access policies.
- Ensure that the API token has the correct permissions, or the scripts will fail to configure Cloudflare services.

View File

@ -0,0 +1,6 @@
# Configuration
There are several configuration steps to building a production ready Changemaker-Lite.
In the order we suggest doing them:

View File

@ -0,0 +1,132 @@
"""
MkDocs Hook for Repository Widget Data Generation
Fetches repository data and generates JSON files during build
"""
import json
import os
import requests
from pathlib import Path
from typing import Dict, Any
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def on_pre_build(config: Dict[str, Any]) -> None:
"""
Hook that runs before MkDocs builds the site
Generates repository JSON data files
"""
logger.info("Generating repository widget data...")
# Define repositories to fetch - all repos from services.md
repositories = [
# Gitea repositories
{
"repo": "admin/changemaker.lite",
"gitea_url": "https://gitea.bnkops.com",
"token": os.getenv("GITEA_TOKEN")
},
# GitHub repositories
{
"repo": "coder/code-server",
"github": True
},
{
"repo": "n8n-io/n8n",
"github": True
},
{
"repo": "knadh/listmonk",
"github": True
},
{
"repo": "nocodb/nocodb",
"github": True
},
{ "repo": "squidfunk/mkdocs-material",
"github": True
},
{
"repo": "gethomepage/homepage",
"github": True
}
]
# Create output directory
docs_dir = config.get('docs_dir', 'docs')
output_dir = Path(docs_dir) / 'assets' / 'repo-data'
output_dir.mkdir(parents=True, exist_ok=True)
# Generate data for each repository
for repo_config in repositories:
try:
generate_repo_data(repo_config, output_dir)
except Exception as e:
logger.error(f"Failed to generate data for {repo_config['repo']}: {e}")
def generate_repo_data(repo_config: Dict[str, Any], output_dir: Path) -> None:
"""Generate JSON data file for a single repository"""
repo = repo_config['repo']
logger.info(f"Fetching data for {repo}")
# Determine API URL and headers
if repo_config.get('github'):
api_url = f"https://api.github.com/repos/{repo}"
headers = {'Accept': 'application/vnd.github.v3+json'}
github_token = os.getenv('GITHUB_TOKEN')
if github_token:
headers['Authorization'] = f'token {github_token}'
else:
gitea_url = repo_config.get('gitea_url', 'https://gitea.bnkops.com')
api_url = f"{gitea_url}/api/v1/repos/{repo}"
headers = {'Accept': 'application/json'}
token = repo_config.get('token') or os.getenv('GITEA_TOKEN')
if token:
headers['Authorization'] = f'token {token}'
# Fetch repository data
try:
response = requests.get(api_url, headers=headers, timeout=10)
response.raise_for_status()
data = response.json()
except requests.RequestException as e:
logger.error(f"Failed to fetch {repo}: {e}")
return
# Extract widget data
widget_data = {
'full_name': data.get('full_name'),
'name': data.get('name'),
'description': data.get('description'),
'html_url': data.get('html_url'),
'language': data.get('language'),
'stars_count': data.get('stargazers_count') or data.get('stars_count', 0),
'forks_count': data.get('forks_count', 0),
'open_issues_count': data.get('open_issues_count', 0),
'updated_at': data.get('updated_at'),
'created_at': data.get('created_at'),
'clone_url': data.get('clone_url'),
'ssh_url': data.get('ssh_url'),
'default_branch': data.get('default_branch', 'main'),
'last_build_update': data.get('pushed_at') or data.get('updated_at')
}
# Generate filename
filename = f"{repo.replace('/', '-')}.json"
file_path = output_dir / filename
# Write JSON file
try:
with open(file_path, 'w') as f:
json.dump(widget_data, f, indent=2)
logger.info(f"Generated: {filename}")
except Exception as e:
logger.error(f"Failed to write {filename}: {e}")
def on_post_build(config: Dict[str, Any]) -> None:
"""Hook that runs after MkDocs builds the site"""
logger.info("Repository widget data generation complete")

View File

@ -0,0 +1,132 @@
document.addEventListener('DOMContentLoaded', function() {
const widgets = document.querySelectorAll('.gitea-widget');
widgets.forEach(widget => {
const repo = widget.dataset.repo;
// Auto-generate data file path from repo name
const dataFile = `/assets/repo-data/${repo.replace('/', '-')}.json`;
const showDescription = widget.dataset.showDescription !== 'false';
const showLanguage = widget.dataset.showLanguage !== 'false';
const showLastUpdate = widget.dataset.showLastUpdate !== 'false';
// Show loading state
widget.innerHTML = `
<div class="gitea-widget-loading">
<div class="loading-spinner"></div>
<span>Loading ${repo}...</span>
</div>
`;
// Fetch repository data
fetch(dataFile)
.then(response => {
if (!response.ok) {
throw new Error(`Could not load data for ${repo}`);
}
return response.json();
})
.then(data => {
renderWidget(widget, data, { showDescription, showLanguage, showLastUpdate });
})
.catch(error => {
renderError(widget, repo, error.message);
});
});
});
function renderWidget(widget, data, options) {
const lastUpdate = new Date(data.updated_at).toLocaleDateString();
const language = data.language || 'Not specified';
widget.innerHTML = `
<div class="gitea-widget-container">
<div class="gitea-widget-header">
<div class="gitea-widget-title">
<svg class="gitea-icon" viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M2 2.5A2.5 2.5 0 014.5 0h8.75a.75.75 0 01.75.75v12.5a.75.75 0 01-.75.75h-2.5a.75.75 0 110-1.5h1.75v-2h-8a1 1 0 00-.714 1.7.75.75 0 01-1.072 1.05A2.495 2.495 0 012 11.5v-9zm10.5-1V9h-8c-.356 0-.694.074-1 .208V2.5a1 1 0 011-1h8zM5 12.25v3.25a.25.25 0 00.4.2l1.45-1.087a.25.25 0 01.3 0L8.6 15.7a.25.25 0 00.4-.2v-3.25a.25.25 0 00-.25-.25h-3.5a.25.25 0 00-.25.25z"/>
</svg>
<a href="${data.html_url}" target="_blank" rel="noopener noreferrer" class="repo-link">
${data.full_name}
</a>
</div>
<div class="gitea-widget-stats">
<span class="stat-item" title="Stars">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z"/>
</svg>
${data.stars_count.toLocaleString()}
</span>
<span class="stat-item" title="Forks">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25V5.372a2.25 2.25 0 10-1.5 0v.878A.75.75 0 0110.25 7H5.75A.75.75 0 015 6.25v-.878zm3.75 7.378a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm3-8.75a.75.75 0 100-1.5.75.75 0 000 1.5z"/>
</svg>
${data.forks_count.toLocaleString()}
</span>
<span class="stat-item" title="Open Issues">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"/>
<path fill="currentColor" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"/>
</svg>
${data.open_issues_count.toLocaleString()}
</span>
</div>
</div>
${options.showDescription && data.description ? `
<div class="gitea-widget-description">
${data.description}
</div>
` : ''}
<div class="gitea-widget-footer">
${options.showLanguage ? `
<span class="language-info">
<span class="language-dot" style="background-color: ${getLanguageColor(language)}"></span>
${language}
</span>
` : ''}
${options.showLastUpdate ? `
<span class="last-update">Updated ${lastUpdate}</span>
` : ''}
</div>
</div>
`;
}
function renderError(widget, repo, error) {
widget.innerHTML = `
<div class="gitea-widget-error">
<svg viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"/>
</svg>
<span>Failed to load ${repo}</span>
<small>${error}</small>
</div>
`;
}
function getLanguageColor(language) {
const colors = {
'JavaScript': '#f1e05a',
'TypeScript': '#2b7489',
'Python': '#3572A5',
'Java': '#b07219',
'C++': '#f34b7d',
'C': '#555555',
'C#': '#239120',
'PHP': '#4F5D95',
'Ruby': '#701516',
'Go': '#00ADD8',
'Rust': '#dea584',
'Swift': '#ffac45',
'Kotlin': '#F18E33',
'Scala': '#c22d40',
'Shell': '#89e051',
'HTML': '#e34c26',
'CSS': '#563d7c',
'Vue': '#2c3e50',
'React': '#61dafb',
'Dockerfile': '#384d54',
'Markdown': '#083fa1'
};
return colors[language] || '#586069';
}

View File

@ -0,0 +1,167 @@
let widgetsInitialized = new Set();
function initializeGitHubWidgets() {
const widgets = document.querySelectorAll('.github-widget');
widgets.forEach(widget => {
// Skip if already initialized
const widgetId = widget.dataset.repo + '-' + Math.random().toString(36).substr(2, 9);
if (widget.dataset.initialized) return;
widget.dataset.initialized = 'true';
const repo = widget.dataset.repo;
// Auto-generate data file path from repo name
const dataFile = `/assets/repo-data/${repo.replace('/', '-')}.json`;
const showDescription = widget.dataset.showDescription !== 'false';
const showLanguage = widget.dataset.showLanguage !== 'false';
const showLastUpdate = widget.dataset.showLastUpdate !== 'false';
// Show loading state
widget.innerHTML = `
<div class="github-widget-loading">
<div class="loading-spinner"></div>
<span>Loading ${repo}...</span>
</div>
`;
// Fetch repository data from pre-generated JSON file
fetch(dataFile)
.then(response => {
if (!response.ok) {
throw new Error(`Could not load data for ${repo}`);
}
return response.json();
})
.then(data => {
const lastUpdate = new Date(data.updated_at).toLocaleDateString();
const language = data.language || 'Not specified';
widget.innerHTML = `
<div class="github-widget-container">
<div class="github-widget-header">
<div class="github-widget-title">
<svg class="github-icon" viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
</svg>
<a href="${data.html_url}" target="_blank" rel="noopener noreferrer" class="repo-link">
${data.full_name}
</a>
</div>
<div class="github-widget-stats">
<span class="stat-item" title="Stars">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z"/>
</svg>
${data.stars_count.toLocaleString()}
</span>
<span class="stat-item" title="Forks">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25V5.372a2.25 2.25 0 10-1.5 0v.878A.75.75 0 0110.25 7H5.75A.75.75 0 015 6.25v-.878zm3.75 7.378a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm3-8.75a.75.75 0 100-1.5.75.75 0 000 1.5z"/>
</svg>
${data.forks_count.toLocaleString()}
</span>
<span class="stat-item" title="Open Issues">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"/>
<path fill="currentColor" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"/>
</svg>
${data.open_issues_count.toLocaleString()}
</span>
</div>
</div>
${showDescription && data.description ? `
<div class="github-widget-description">
${data.description}
</div>
` : ''}
<div class="github-widget-footer">
${showLanguage ? `
<span class="language-info">
<span class="language-dot" style="background-color: ${getLanguageColor(language)}"></span>
${language}
</span>
` : ''}
${showLastUpdate ? `
<span class="last-update">Updated ${lastUpdate}</span>
` : ''}
${data.license ? `
<span class="license-info">${data.license.spdx_id || data.license.name}</span>
` : ''}
</div>
</div>
`;
})
.catch(error => {
console.error('Error loading repository data:', error);
widget.innerHTML = `
<div class="github-widget-error">
<svg viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"/>
</svg>
<span>Failed to load ${repo}</span>
<small>${error.message}</small>
</div>
`;
});
});
}
// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', initializeGitHubWidgets);
// Watch for DOM changes (MkDocs Material dynamic content)
const observer = new MutationObserver((mutations) => {
let shouldReinitialize = false;
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
// Check if any github-widget elements were added
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1 && // Element node
(node.classList?.contains('github-widget') ||
node.querySelector?.('.github-widget'))) {
shouldReinitialize = true;
}
});
}
});
if (shouldReinitialize) {
// Small delay to ensure DOM is stable
setTimeout(initializeGitHubWidgets, 100);
}
});
// Start observing
observer.observe(document.body, {
childList: true,
subtree: true
});
// Language color mapping (simplified version)
function getLanguageColor(language) {
const colors = {
'JavaScript': '#f1e05a',
'TypeScript': '#2b7489',
'Python': '#3572A5',
'Java': '#b07219',
'C++': '#f34b7d',
'C': '#555555',
'C#': '#239120',
'PHP': '#4F5D95',
'Ruby': '#701516',
'Go': '#00ADD8',
'Rust': '#dea584',
'Swift': '#ffac45',
'Kotlin': '#F18E33',
'Scala': '#c22d40',
'Shell': '#89e051',
'HTML': '#e34c26',
'CSS': '#563d7c',
'Vue': '#2c3e50',
'React': '#61dafb',
'Dockerfile': '#384d54'
};
return colors[language] || '#586069';
}

View File

@ -1,339 +1,369 @@
{% extends "main.html" %}
{% block extrahead %}
{{ super() }}
<script>
{{ super() }}
<script>
// Add data attribute for CSS targeting
document.body.setAttribute('data-md-template', 'home');
</script>
</script>
{% endblock %}
{% block content %}
<div class="md-content--home">
<!-- Hero Grid Section -->
<section class="hero-grid">
<div class="grid-container">
<!-- Main Hero Block -->
<div class="hero-main grid-card">
<div class="meta-badge">🤯 This Site Runs On Changemaker Lite</div>
<h1>The Only FOSS Political Campaign Stack</h1>
<p>Stop paying $1,200/month to corporate platforms. Run your entire political campaign on $200 hardware with fewer corporate dependencies every day.</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 $200</a>
</div>
</div>
<!-- Problem Statement Block -->
<div class="hero-problem grid-card">
<h3>The Problem</h3>
<div class="problem-list">
<div class="problem-item">💸 NGP VAN: $1,000+/mo</div>
<div class="problem-item">📧 Mailchimp: $200+/mo</div>
<div class="problem-item">🔒 Your data: Their servers</div>
<div class="problem-item">👁️ Surveillance: Always on</div>
</div>
</div>
<!-- Solution Stats Block -->
<div class="hero-stats grid-card">
<h3>The Solution</h3>
<div class="stat-grid">
<div class="stat-item">
<div class="stat-number">$200</div>
<div class="stat-label">One-time cost</div>
</div>
<div class="stat-item">
<div class="stat-number">11</div>
<div class="stat-label">Campaign tools</div>
</div>
<div class="stat-item">
<div class="stat-number">100%</div>
<div class="stat-label">Your data</div>
</div>
<div class="stat-item">
<div class="stat-number"></div>
<div class="stat-label">Fewer corporate deps every day</div>
</div>
</div>
</div>
<!-- Trust Indicators -->
<div class="hero-trust grid-card">
<h3>Proven By</h3>
<div class="trust-items">
<div class="trust-item">
<span class="trust-icon"></span>
<span class="trust-text">Powers BNKops.com</span>
</div>
<div class="trust-item">
<span class="trust-icon">🏳️‍⚧️</span>
<span class="trust-text">Trans liberation tech</span>
</div>
<div class="trust-item">
<span class="trust-icon">🛡️</span>
<span class="trust-text">Zero surveillance</span>
</div>
<div class="trust-item">
<span class="trust-icon">🚀</span>
<span class="trust-text">30-min setup</span>
</div>
</div>
</div>
</div>
</section>
<!-- Hero Grid Section -->
<section class="hero-grid">
<div class="grid-container">
<!-- Main Hero Block -->
<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 Stack</h1>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled and your supports data sold to the highest bidder. Run your entire political campaign on ~$200 hardware and
with fewer corporate dependencies every day.</p>
<!-- Solution Grid -->
<section class="solution-grid" id="solution">
<div class="grid-container">
<div class="section-header">
<h2>Everything Your Campaign Needs</h2>
<p>Replace your entire SaaS stack with open source alternatives. <b>First free and open source canvassing solution included.</b></p>
</div>
<div class="services-grid">
<!-- Code Server -->
<div class="service-card grid-card">
<div class="service-icon">💻</div>
<h3>Code Server</h3>
<div class="service-replaces">Replaces: VS Code</div>
<ul class="service-features">
<li>Browser-based IDE</li>
<li>Customizable workspace</li>
<li>Live collaboration</li>
</ul>
<div class="service-tool">Code Server</div>
<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>
</div>
</div>
<!-- MkDocs -->
<div class="service-card grid-card">
<div class="service-icon">📖</div>
<h3>Documentation</h3>
<div class="service-replaces">Replaces: Confluence</div>
<ul class="service-features">
<li>Markdown-based</li>
<li>Live preview</li>
<li>Static site generation</li>
</ul>
<div class="service-tool">MkDocs</div>
</div>
<!-- Listmonk -->
<div class="service-card grid-card">
<div class="service-icon">📧</div>
<h3>Email Campaigns</h3>
<div class="service-replaces">Replaces: Mailchimp</div>
<ul class="service-features">
<li>Unlimited subscribers</li>
<li>A/B testing</li>
<li>Analytics</li>
</ul>
<div class="service-tool">Listmonk</div>
</div>
<!-- NocoDB -->
<div class="service-card grid-card">
<div class="service-icon">📊</div>
<h3>Database & Canvassing</h3>
<div class="service-replaces">Replaces: Airtable</div>
<ul class="service-features">
<li>Contact management</li>
<li>Custom fields</li>
<li>Canvassing support</li>
</ul>
<div class="service-tool">NocoDB</div>
</div>
<!-- Map Viewer -->
<div class="service-card grid-card">
<div class="service-icon">🗺️</div>
<h3>Interactive Maps</h3>
<div class="service-replaces">Replaces: Google Maps</div>
<ul class="service-features">
<li>Real-time geolocation</li>
<li>Custom map layers</li>
<li>Location management</li>
</ul>
<div class="service-tool">Map Viewer</div>
</div>
<!-- Automation -->
<div class="service-card grid-card">
<div class="service-icon">🔄</div>
<h3>Workflow Automation</h3>
<div class="service-replaces">Replaces: Zapier</div>
<ul class="service-features">
<li>Workflow builder</li>
<li>API connections</li>
<li>Event triggers</li>
</ul>
<div class="service-tool">n8n</div>
</div>
<!-- QR Code Generator -->
<div class="service-card grid-card">
<div class="service-icon">📱</div>
<h3>QR Code Generator</h3>
<div class="service-replaces">Replaces: QR Code SaaS</div>
<ul class="service-features">
<li>Customizable codes</li>
<li>Batch generation</li>
<li>Static and dynamic codes</li>
</ul>
<div class="service-tool">Mini QR</div>
</div>
<!-- Gitea -->
<div class="service-card grid-card">
<div class="service-icon">🔧</div>
<h3>Version Control</h3>
<div class="service-replaces">Replaces: GitHub</div>
<ul class="service-features">
<li>Self-hosted Git</li>
<li>Collaborative development</li>
<li>Issue tracking</li>
</ul>
<div class="service-tool">Gitea</div>
</div>
</div>
</div>
</section>
<!-- Comparison Grid -->
<section class="comparison-grid">
<div class="grid-container">
<div class="section-header">
<h2>Corporate SaaS vs Changemaker Lite</h2>
<p>Why campaigns are switching to self-hosted FOSS</p>
</div>
<div class="comparison-table">
<div class="comparison-header grid-card">
<div></div>
<div class="compare-col">Corporate SaaS</div>
<div class="compare-col highlight">Changemaker Lite</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Monthly Cost</div>
<div class="compare-value bad">$1,200+</div>
<div class="compare-value good">$50 hosting</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Data Ownership</div>
<div class="compare-value bad">Their servers</div>
<div class="compare-value good">100% yours</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Surveillance</div>
<div class="compare-value bad">Always tracked</div>
<div class="compare-value good">Zero tracking</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Vendor Lock-in</div>
<div class="compare-value bad">Trapped forever</div>
<div class="compare-value good">Export anytime</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Customization</div>
<div class="compare-value bad">Limited options</div>
<div class="compare-value good">Full control</div>
</div>
</div>
</div>
</section>
<!-- Get Started Grid -->
<section class="get-started-grid" id="get-started">
<div class="grid-container">
<div class="section-header">
<h2>Start Your Digital Liberation</h2>
<p>Three ways to break free from corporate campaign tech</p>
</div>
<div class="options-grid">
<!-- Plug & Play -->
<div class="option-card grid-card featured">
<div class="option-badge">Most Popular</div>
<div class="option-icon">🚀</div>
<h3>Plug & Play</h3>
<div class="option-price">$200</div>
<div class="option-features">
<div class="feature">✓ Pre-configured hardware</div>
<div class="feature">✓ 30-minute setup</div>
<div class="feature">✓ All 11 services ready</div>
<div class="feature">✓ Priority support</div>
<div class="feature">✓ Ships on request</div>
<!-- Problem Statement Block -->
<div class="hero-problem grid-card">
<h3>The Problem</h3>
<div class="problem-list">
<div class="problem-item">💸 Canvassing: $100+/mo</div>
<div class="problem-item">📊 Nationbuilder: $500+/mo</div>
<div class="problem-item">📧 Mailchimp: $200+/mo</div>
<div class="problem-item">👁️ Surveillance: Always on</div>
<div class="problem-item">🔒 Vendor lock-in: Trapped forever</div>
<div class="problem-item">📉 Data ownership: Not yours</div>
<div class="promlem-itme">😠 Implicitly Supporting Evil Corporations</div>
</div>
<a href="https://bnkops.com/hardware" class="btn btn-primary">Order Hardware</a>
</div>
<!-- DIY -->
<div class="option-card grid-card">
<div class="option-icon">🛠️</div>
<h3>DIY Install</h3>
<div class="option-price">Free</div>
<div class="option-features">
<div class="feature">✓ Use your hardware</div>
<div class="feature">✓ Docker compose</div>
<div class="feature">✓ Full documentation</div>
<div class="feature">✓ Community support</div>
<div class="feature">✓ Learn the system</div>
<!-- Solution Stats Block -->
<div class="hero-stats grid-card">
<h3>The Solution</h3>
<div class="stat-grid">
<div class="stat-item">
<div class="stat-number">Runs on ~$200 Hardware</div>
<div class="stat-label">One-time cost</div>
</div>
<div class="stat-item">
<div class="stat-number">11</div>
<div class="stat-label">Campaign tools</div>
</div>
<div class="stat-item">
<div class="stat-number">Your Data</div>
<div class="stat-label">Localized & Secure</div>
</div>
<div class="stat-item">
<div class="stat-number"></div>
<div class="stat-label">Fewer corporate deps every day</div>
</div>
</div>
<a href="/getting-started/" class="btn btn-secondary">Install Guide</a>
</div>
<!-- Managed -->
<div class="option-card grid-card">
<div class="option-icon">☁️</div>
<h3>Managed Hosting</h3>
<div class="option-price">$???/mo</div>
<div class="option-features">
<div class="feature">✓ We manage everything</div>
<div class="feature">✓ Your domain</div>
<div class="feature">✓ Daily backups</div>
<div class="feature">✓ 24/7 monitoring</div>
<div class="feature">✓ Still your data</div>
<!-- Trust Indicators -->
<div class="hero-trust grid-card">
<h3>Proven By</h3>
<div class="trust-items">
<div class="trust-item">
<span class="trust-icon"></span>
<span class="trust-text">Powers BNKops.com</span>
</div>
<div class="trust-item">
<span class="trust-icon"> 🌈 </span>
<span class="trust-text">Liberation tech</span>
</div>
<div class="trust-item">
<span class="trust-icon">🛡️</span>
<span class="trust-text">Zero surveillance</span>
</div>
<div class="trust-item">
<span class="trust-icon">🚀</span>
<span class="trust-text">30-min setup</span>
</div>
</div>
<a href="https://bnkops.com/hosting" class="btn btn-secondary">Learn More</a>
</div>
</div>
<!-- Final CTA -->
<div class="final-cta grid-card">
<h3>Join the Movement</h3>
<p>Some of the biggest players in local politics are already using it; maybe give it a try?</p>
<div class="cta-buttons">
<a href="https://bnkops.com/newsletter" class="btn btn-primary">Get Campaign Tips</a>
<a href="https://docs.bnkops.com" class="btn btn-secondary">Read Documentation</a>
</section>
<!-- Solution Grid -->
<section class="solution-grid" id="solution">
<div class="grid-container">
<div class="section-header">
<h2>Your Complete Campaign Toolkit</h2>
<p>Simple, powerful tools designed for campaign staff - no technical skills needed</p>
</div>
<div class="services-grid">
<!-- Documentation Editor -->
<div class="service-card grid-card">
<div class="service-icon">✍️</div>
<h3>Campaign Content Editor</h3>
<div class="service-replaces">Replaces: Google Docs + WordPress (~$50/month)</div>
<ul class="service-features">
<li>Edit docs & blog posts</li>
<li>Live preview as you type</li>
<li>Simple formatting tools</li>
<li>Works in any browser</li>
</ul>
<div class="service-tool">Code Server</div>
</div>
<!-- Canvassing System -->
<div class="service-card grid-card featured">
<div class="service-badge">Field Team Essential</div>
<div class="service-icon">🚪</div>
<h3>Smart Canvassing</h3>
<div class="service-replaces">Replaces: Qumon (~$100+/mo)</div>
<ul class="service-features">
<li>Interactive voter maps</li>
<li>Track door knocks</li>
<li>Mobile-friendly</li>
<li>Works offline</li>
</ul>
<div class="service-tool">NocoDB + Map Viewer</div>
</div>
<!-- Email System -->
<div class="service-card grid-card">
<div class="service-icon">📩</div>
<h3>Email Blasts</h3>
<div class="service-replaces">Replaces: Mailchimp (~$200+/mo)</div>
<ul class="service-features">
<li>Simple email creator</li>
<li>Track opens/clicks</li>
<li>Unlimited subscribers</li>
<li>Pre-made templates</li>
</ul>
<div class="service-tool">Listmonk</div>
</div>
<!-- Voter Database -->
<div class="service-card grid-card">
<div class="service-icon">🗃️</div>
<h3>Voter Database</h3>
<div class="service-replaces">Replaces: NationBuilder (~$500+/mo)</div>
<ul class="service-features">
<li>Spreadsheet interface</li>
<li>Easy voter searches</li>
<li>Custom survey forms</li>
<li>Export walk lists</li>
</ul>
<div class="service-tool">NocoDB</div>
</div>
<!-- Automation -->
<div class="service-card grid-card">
<div class="service-icon">🤖</div>
<h3>Smart Automation</h3>
<div class="service-replaces">Replaces: Zapier (~$300/month)</div>
<ul class="service-features">
<li>Auto follow-up emails</li>
<li>Volunteer reminders</li>
<li>Donation thank yous</li>
<li>Pre-built workflows</li>
</ul>
<div class="service-tool">n8n</div>
</div>
<!-- Website -->
<div class="service-card grid-card">
<div class="service-icon">🌐</div>
<h3>Campaign Website</h3>
<div class="service-replaces">Replaces: Squarespace (~$100/month)</div>
<ul class="service-features">
<li>Pre-designed templates</li>
<li>Easy content updates</li>
<li>Built-in blog</li>
<li>Fast loading</li>
</ul>
<div class="service-tool">MkDocs</div>
</div>
<!-- Volunteer Management -->
<div class="service-card grid-card">
<div class="service-icon">👥</div>
<h3>Volunteer HQ</h3>
<div class="service-replaces">Replaces: Mobilize (~$200/month)</div>
<ul class="service-features">
<li>Shift scheduling</li>
<li>Automated reminders</li>
<li>Skills matching</li>
<li>Progress tracking</li>
</ul>
<div class="service-tool">NocoDB + n8n</div>
</div>
<!-- Linking Features -->
<div class="service-card grid-card">
<div class="service-icon">👀</div>
<h3> Mobile, Social, & Hot Link Friendly</h3>
<div class="service-replaces">Replaces: Linktree (~$20/month)</div>
<ul class="service-features">
<li>Automatic Social Cards</li>
<li>Hot Linking to All Assets & Headers</li>
<li>Documentation Indexing & Search</li>
<li>Progress tracking</li>
</ul>
<div class="service-tool">NocoDB + n8n</div>
</div>
<!-- Rapid Response -->
<div class="service-card grid-card">
<div class="service-icon"></div>
<h3>Rapid Response</h3>
<div class="service-replaces">Replaces: Slack + Google Docs (~$50/month)</div>
<ul class="service-features">
<li>Real-time collaboration</li>
<li>Community Editing</li>
<li>Open source documentation</li>
<li>Version control</li>
</ul>
<div class="service-tool">Code Server + Gitea</div>
</div>
</div>
</div>
<!-- Subscribe Card -->
<div class="subscribe-card grid-card">
<h3>Subscribe</h3>
<form action="https://newsletter.bnkops.com/subscription/form" method="POST" target="_blank" autocomplete="off">
<input type="hidden" name="nonce">
<p>
<input type="email" name="email" required placeholder="E-mail">
</p>
<p>
<input type="text" name="name" placeholder="Name (optional)">
</p>
<p>
<input id="48b84" type="checkbox" name="l" checked value="48b841e7-841b-458b-95f8-63903a1c0912">
<label for="48b84">~ Weekly Updates</label>
</p>
<input type="submit" value="Subscribe" class="action-btn primary">
</form>
</section>
<!-- Comparison Grid -->
<section class="comparison-grid">
<div class="grid-container">
<div class="section-header">
<h2>Corporate SaaS vs Changemaker Lite</h2>
<p>Why campaigns are switching to self-hosted FOSS</p>
</div>
<div class="comparison-table">
<div class="comparison-header grid-card">
<div></div>
<div class="compare-col">Corporate SaaS</div>
<div class="compare-col highlight">Changemaker Lite</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Monthly Cost</div>
<div class="compare-value bad">$1,200+</div>
<div class="compare-value good">$0 Self-Hosted</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Data Ownership</div>
<div class="compare-value bad">Their servers</div>
<div class="compare-value good">100% yours</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Surveillance</div>
<div class="compare-value bad">Always tracked</div>
<div class="compare-value good">Zero tracking</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Vendor Lock-in</div>
<div class="compare-value bad">Trapped forever</div>
<div class="compare-value good">Export anytime</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Customization</div>
<div class="compare-value bad">Limited options</div>
<div class="compare-value good">Full control</div>
</div>
</div>
</div>
</div>
</section>
</section>
<!-- Get Started Grid -->
<section class="get-started-grid" id="get-started">
<div class="grid-container">
<div class="section-header">
<h2>Start Your Digital Liberation</h2>
<p>Three ways to break free from corporate campaign tech</p>
</div>
<div class="options-grid">
<!-- Plug & Play -->
<div class="option-card grid-card featured">
<div class="option-badge">Most Popular</div>
<div class="option-icon">🚀</div>
<h3>Plug & Play</h3>
<div class="option-price">~$400 (Built to Suit)</div>
<div class="option-features">
<div class="feature">✓ Pre-configured hardware</div>
<div class="feature">✓ 30-minute setup</div>
<div class="feature">✓ All 11 services ready</div>
<div class="feature">✓ Priority support</div>
<div class="feature">✓ Ships on request</div>
</div>
<a href="https://bnkops.com/hardware" class="btn btn-primary">Order Hardware</a>
</div>
<!-- DIY -->
<div class="option-card grid-card">
<div class="option-icon">🛠️</div>
<h3>DIY Install</h3>
<div class="option-price">Free</div>
<div class="option-features">
<div class="feature">✓ Use your hardware</div>
<div class="feature">✓ Docker compose</div>
<div class="feature">✓ Full documentation</div>
<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>
</div>
<!-- Managed -->
<div class="option-card grid-card">
<div class="option-icon">☁️</div>
<h3>Managed Hosting</h3>
<div class="option-price">$???/mo</div>
<div class="option-features">
<div class="feature">✓ We manage everything</div>
<div class="feature">✓ Your domain</div>
<div class="feature">✓ Daily backups</div>
<div class="feature">✓ 24/7 monitoring</div>
<div class="feature">✓ Still your data</div>
</div>
<a href="https://bnkops.com" class="btn btn-secondary">Learn More</a>
</div>
</div>
<!-- Cards in a row -->
<div class="row-cards">
<div class="final-cta grid-card">
<h3>Join the Movement</h3>
<p>Some of the biggest players in local politics are already using it; maybe give it a try?</p>
<div class="cta-buttons">
<a href="https://bnkops.com/newsletter" class="btn btn-primary">Get Campaign Tips</a>
<a href="https://docs.bnkops.com" class="btn btn-secondary">Read Documentation</a>
</div>
</div>
<div class="subscribe-card grid-card">
<h3>Subscribe</h3>
<form action="https://newsletter.bnkops.com/subscription/form" method="POST" target="_blank"
autocomplete="off">
<input type="hidden" name="nonce">
<p>
<input type="email" name="email" required placeholder="E-mail">
</p>
<p>
<input type="text" name="name" placeholder="Name (optional)">
</p>
<p>
<input id="48b84" type="checkbox" name="l" checked
value="48b841e7-841b-458b-95f8-63903a1c0912">
<label for="48b84">~ Weekly Updates</label>
</p>
<input type="submit" value="Subscribe" class="action-btn primary">
</form>
</div>
</div>
</div>
</section>
</div>
{% endblock %}
{% endblock %}

View File

@ -104,6 +104,8 @@ The tools we use shape the movements we build. Corporate tools create corporate
**No.** We specifically designed Changemaker Lite for organizers, activists, and movement builders who may not have technical backgrounds. Our philosophy is that everyone deserves digital sovereignty, not just people with computer science degrees.
This is not to say that you won't need to learn! These tools are just that; tools. They have no fancy or white-labeled marketing and are technical in nature. You will need to learn to use them, just as any worker needs to learn the power tools they use on the job.
### "What about convenience?"
Corporate platforms are convenient because they've extracted billions of dollars from users to fund that convenience. When you own your tools, there's a learning curve—but it's the same learning curve as learning to organize, learning to build power, learning to create change.

View File

@ -1,6 +1,6 @@
# Code Server
Visual Studio Code in your browser for remote development.
<div class="github-widget" data-repo="coder/code-server"></div>
## Overview

View File

@ -6,6 +6,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [Code Server](code-server.md)
**Port: 8888** | Visual Studio Code in your browser for remote development
<div class="github-widget" data-repo="coder/code-server"></div>
- Full IDE experience
- Extensions support
- Git integration
@ -13,6 +14,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [Listmonk](listmonk.md)
**Port: 9000** | Self-hosted newsletter and mailing list manager
<div class="github-widget" data-repo="knadh/listmonk"></div>
- Email campaigns
- Subscriber management
- Analytics
@ -27,6 +29,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [MkDocs Material](mkdocs.md)
**Port: 4000** | Documentation site generator with live preview
<div class="github-widget" data-repo="squidfunk/mkdocs-material"></div>
- Material Design theme
- Live reload
- Search functionality
@ -41,6 +44,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [n8n](n8n.md)
**Port: 5678** | Workflow automation tool
<div class="github-widget" data-repo="n8n-io/n8n"></div>
- Visual workflow editor
- 400+ integrations
- Custom code execution
@ -48,6 +52,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [NocoDB](nocodb.md)
**Port: 8090** | No-code database platform
<div class="github-widget" data-repo="nocodb/nocodb"></div>
- Smart spreadsheet interface
- Form builder and API generation
- Real-time collaboration
@ -55,6 +60,7 @@ Changemaker Lite includes several powerful services that work together to provid
### [Homepage](homepage.md)
**Port: 3010** | Modern dashboard for all services
<div class="github-widget" data-repo="gethomepage/homepage"></div>
- Service dashboard and monitoring
- Docker integration
- Customizable layout

View File

@ -1,5 +1,7 @@
# n8n
<div class="github-widget" data-repo="n8n-io/n8n"></div>
Workflow automation tool for connecting services and automating tasks.
## Overview

View File

@ -0,0 +1,554 @@
.login-button {
display: inline-block;
padding: 2px 10px;
margin-left: auto; /* Push the button to the right */
margin-right: 10px;
background-color: hsl(315, 80%, 42%); /* Use a solid, high-contrast color */
color: #fff; /* Ensure text is white */
text-decoration: none;
border-radius: 4px;
font-weight: bold;
transition: background-color 0.2s ease;
font-size: 0.9em;
vertical-align: middle;
}
.login-button:hover {
background-color: #003c8f; /* Darker shade for hover */
text-decoration: none;
}
.git-code-button {
display: inline-block;
background: #30363d;
color: white !important;
padding: 0.6rem 1.2rem;
border-radius: 20px;
text-decoration: none;
font-size: 0.95rem;
font-weight: bold;
margin-left: 1rem;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
.git-code-button:hover {
background: #444d56;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
text-decoration: none;
}
.git-code-button .material-icons {
font-size: 1rem;
vertical-align: middle;
margin-right: 4px;
}
/* GitHub Widget Styles */
.github-widget {
margin: 1.5rem 0;
display: block;
}
.github-widget-container {
border: 1px solid rgba(var(--md-primary-fg-color--rgb), 0.15);
border-radius: 12px;
padding: 20px;
background: linear-gradient(135deg, var(--md-code-bg-color) 0%, rgba(var(--md-primary-fg-color--rgb), 0.03) 100%);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.github-widget-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, var(--md-primary-fg-color), var(--md-accent-fg-color));
border-radius: 12px 12px 0 0;
}
.github-widget-container:hover {
border-color: var(--md-accent-fg-color);
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.github-widget-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
flex-wrap: wrap;
gap: 12px;
}
.github-widget-title {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
min-width: 0;
}
.github-icon {
color: var(--md-default-fg-color--light);
flex-shrink: 0;
width: 20px;
height: 20px;
}
.github-widget .repo-link {
color: var(--md-accent-fg-color);
text-decoration: none;
font-weight: 600;
font-size: 16px;
transition: color 0.2s ease;
word-break: break-word;
}
.github-widget .repo-link:hover {
color: var(--md-primary-fg-color);
text-decoration: none;
}
.github-widget-stats {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
}
.stat-item {
display: flex;
align-items: center;
gap: 6px;
color: var(--md-default-fg-color);
font-size: 13px;
font-weight: 600;
background: rgba(var(--md-primary-fg-color--rgb), 0.08);
padding: 4px 8px;
border-radius: 16px;
transition: all 0.2s ease;
}
.stat-item:hover {
background: rgba(var(--md-accent-fg-color--rgb), 0.15);
transform: scale(1.05);
}
.stat-item svg {
color: var(--md-accent-fg-color);
width: 14px;
height: 14px;
}
.github-widget-description {
color: var(--md-default-fg-color--light);
margin-bottom: 16px;
line-height: 1.5;
font-size: 14px;
font-style: italic;
padding: 12px;
background: rgba(var(--md-default-fg-color--rgb), 0.03);
border-radius: 8px;
border-left: 3px solid var(--md-accent-fg-color);
}
.github-widget-footer {
display: flex;
gap: 20px;
align-items: center;
font-size: 12px;
color: var(--md-default-fg-color--lighter);
border-top: 1px solid rgba(var(--md-default-fg-color--rgb), 0.1);
padding-top: 16px;
margin-top: 16px;
flex-wrap: wrap;
}
.language-info {
display: flex;
align-items: center;
gap: 6px;
}
.language-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
}
.last-update,
.license-info {
color: var(--md-default-fg-color--lighter);
}
/* Loading State */
.github-widget-loading {
display: flex;
align-items: center;
gap: 12px;
padding: 20px;
color: var(--md-default-fg-color--light);
justify-content: center;
}
.loading-spinner {
width: 20px;
height: 20px;
border: 2px solid var(--md-default-fg-color--lightest);
border-top: 2px solid var(--md-accent-fg-color);
border-radius: 50%;
animation: github-widget-spin 1s linear infinite;
}
@keyframes github-widget-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Error State */
.github-widget-error {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 20px;
color: var(--md-typeset-color);
text-align: center;
background: var(--md-code-bg-color);
border: 1px solid #f85149;
border-radius: 6px;
}
.github-widget-error svg {
color: #f85149;
}
.github-widget-error small {
color: var(--md-default-fg-color--lighter);
font-size: 11px;
}
/* Dark mode specific adjustments */
[data-md-color-scheme="slate"] .github-widget-container {
background: var(--md-code-bg-color);
border-color: #30363d;
}
[data-md-color-scheme="slate"] .github-widget-container:hover {
border-color: var(--md-accent-fg-color);
}
/* Multiple widgets in a row */
.github-widgets-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.github-widgets-row .github-widget {
margin: 0;
}
/* Compact widget variant */
.github-widget.compact .github-widget-container {
padding: 12px;
}
.github-widget.compact .github-widget-header {
margin-bottom: 8px;
}
.github-widget.compact .github-widget-description {
display: none;
}
.github-widget.compact .github-widget-footer {
margin-top: 8px;
padding-top: 8px;
}
/* GitHub Widget Responsive - placed after existing mobile styles */
@media (max-width: 768px) {
.github-widget-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.github-widget-stats {
gap: 12px;
}
.github-widget-footer {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}
/* Gitea Widget Styles */
.gitea-widget {
margin: 1.5rem 0;
display: block;
}
.gitea-widget-container {
border: 1px solid rgba(var(--md-primary-fg-color--rgb), 0.15);
border-radius: 12px;
padding: 20px;
background: linear-gradient(135deg, var(--md-code-bg-color) 0%, rgba(var(--md-primary-fg-color--rgb), 0.03) 100%);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.gitea-widget-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, #609926, #89c442);
border-radius: 12px 12px 0 0;
}
.gitea-widget-container:hover {
border-color: #89c442;
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.gitea-widget-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
flex-wrap: wrap;
gap: 12px;
}
.gitea-widget-title {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
min-width: 0;
}
.gitea-icon {
color: #89c442;
flex-shrink: 0;
width: 20px;
height: 20px;
}
.gitea-widget .repo-link {
color: #89c442;
text-decoration: none;
font-weight: 600;
font-size: 16px;
transition: color 0.2s ease;
word-break: break-word;
}
.gitea-widget .repo-link:hover {
color: #609926;
text-decoration: none;
}
.gitea-widget-stats {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
}
.gitea-widget .stat-item {
display: flex;
align-items: center;
gap: 6px;
color: var(--md-default-fg-color);
font-size: 13px;
font-weight: 600;
background: rgba(137, 196, 66, 0.1);
padding: 4px 8px;
border-radius: 16px;
transition: all 0.2s ease;
}
.gitea-widget .stat-item:hover {
background: rgba(137, 196, 66, 0.2);
transform: scale(1.05);
}
.gitea-widget .stat-item svg {
color: #89c442;
width: 14px;
height: 14px;
}
.gitea-widget-description {
color: var(--md-default-fg-color--light);
margin-bottom: 16px;
line-height: 1.5;
font-size: 14px;
font-style: italic;
padding: 12px;
background: rgba(var(--md-default-fg-color--rgb), 0.03);
border-radius: 8px;
border-left: 3px solid #89c442;
}
.gitea-widget-footer {
display: flex;
gap: 20px;
align-items: center;
font-size: 12px;
color: var(--md-default-fg-color--lighter);
border-top: 1px solid rgba(var(--md-default-fg-color--rgb), 0.1);
padding-top: 16px;
margin-top: 16px;
flex-wrap: wrap;
}
.gitea-widget .language-info {
display: flex;
align-items: center;
gap: 6px;
}
.gitea-widget .language-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
}
.gitea-widget .last-update,
.gitea-widget .license-info {
color: var(--md-default-fg-color--lighter);
}
/* Gitea Loading State */
.gitea-widget-loading {
display: flex;
align-items: center;
gap: 12px;
padding: 20px;
color: var(--md-default-fg-color--light);
justify-content: center;
}
.gitea-widget-loading .loading-spinner {
width: 20px;
height: 20px;
border: 2px solid var(--md-default-fg-color--lightest);
border-top: 2px solid #89c442;
border-radius: 50%;
animation: gitea-widget-spin 1s linear infinite;
}
@keyframes gitea-widget-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Gitea Error State */
.gitea-widget-error {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 20px;
color: var(--md-typeset-color);
text-align: center;
background: var(--md-code-bg-color);
border: 1px solid #f85149;
border-radius: 6px;
}
.gitea-widget-error svg {
color: #f85149;
}
.gitea-widget-error small {
color: var(--md-default-fg-color--lighter);
font-size: 11px;
}
/* Dark mode specific adjustments for Gitea */
[data-md-color-scheme="slate"] .gitea-widget-container {
background: var(--md-code-bg-color);
border-color: #30363d;
}
[data-md-color-scheme="slate"] .gitea-widget-container:hover {
border-color: #89c442;
}
/* Multiple Gitea widgets in a row */
.gitea-widgets-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.gitea-widgets-row .gitea-widget {
margin: 0;
}
/* Compact Gitea widget variant */
.gitea-widget.compact .gitea-widget-container {
padding: 12px;
}
.gitea-widget.compact .gitea-widget-header {
margin-bottom: 8px;
}
.gitea-widget.compact .gitea-widget-description {
display: none;
}
.gitea-widget.compact .gitea-widget-footer {
margin-top: 8px;
padding-top: 8px;
}
/* Gitea Widget Responsive */
@media (max-width: 768px) {
.gitea-widget-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.gitea-widget-stats {
gap: 12px;
}
.gitea-widget-footer {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}

View File

@ -265,7 +265,7 @@ body[data-md-template="home"] .md-main__inner {
.stat-number {
font-size: 1.2rem;
font-weight: 700;
color: var(--trans-blue);
color: var(--trans-pink);
margin: 0;
animation: number-glow 4s ease-in-out infinite;
}
@ -309,6 +309,8 @@ body[data-md-template="home"] .md-main__inner {
.section-header {
text-align: center;
margin-bottom: var(--space-lg);
position: relative;
z-index: 10;
}
.section-header h2 {
@ -672,6 +674,21 @@ body[data-md-template="home"] .md-main__inner {
}
}
/* Row cards at bottom: two cards in a row on desktop, stack on mobile */
.row-cards {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-sm);
margin-top: var(--space-lg);
}
@media (max-width: 768px) {
.row-cards {
grid-template-columns: 1fr;
gap: var(--space-xs);
}
}
/* =================================
PERFORMANCE
================================= */

View File

@ -79,6 +79,11 @@ extra_css:
extra_javascript:
- javascripts/home.js
- javascripts/github-widget.js
- javascripts/gitea-widget.js
hooks:
- docs/hooks/repo_widget_hook.py
# Markdown Extensions
markdown_extensions:
@ -131,14 +136,6 @@ extra:
- icon: fontawesome/solid/paper-plane
link: https://listmonk.bnkops.com/subscription/form
name: Newsletter
# Removed analytics as plausible is not built-in
consent:
title: Cookie consent
description: >-
We use cookies to recognize your repeated visits and preferences, as well
as to measure the effectiveness of our documentation and whether users
find what they're searching for. With your consent, you're helping us to
make our documentation better.
# Copyright
copyright: >
@ -148,22 +145,31 @@ copyright: >
# Navigation - Updated to match existing files
nav:
- Home: index.md
- Getting Started: getting-started.md
- Philosophy: philosophy.md
- Philosophy:
- phil/index.md
- Who Reads Your Secrets: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/If%20you%20do%20politics%20who%20is%20reading%20your%20secrets%20-%20why%20you%20should%20de-corp%20your%20software%20stack/
- How To Not Get Got Making Content: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/How%20not%20to%20get%20got%20making%20content%20v2/
- Digital Organizing: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/Distributed%20Digital%20Organizing%20is%20The%20Way%20Out/#why-not-give-it-a-shot
- What is Security Culture: https://docs.bnkops.com/archive/repo.archive/Zines%20We%20Like%20%F0%9F%98%8E/What%20Is%20Security%20Culture%20%E2%98%A0/#what-is-security-culture
- Getting Started:
- build/index.md
- Build Server: build/build-server.md
- Services:
- services/index.md
- Homepage: services/homepage.md
- Code Server: services/code-server.md
- MkDocs: services/mkdocs.md
- Static Server: services/static-server.md
- Listmonk: services/listmonk.md
- PostgreSQL: services/postgresql.md
- n8n: services/n8n.md
- NocoDB: services/nocodb.md
- Gitea: services/gitea.md
- Map Viewer: services/map.md
- Mini QR: services/mini-qr.md
- Configuration:
- config/index.md
- Cloudflare: config/cloudflare-config.md
- Cost Comparison: cost-comparison.md
- Services:
- services/index.md
- Homepage: services/homepage.md
- Code Server: services/code-server.md
- MkDocs: services/mkdocs.md
- Static Server: services/static-server.md
- Listmonk: services/listmonk.md
- PostgreSQL: services/postgresql.md
- n8n: services/n8n.md
- NocoDB: services/nocodb.md
- Gitea: services/gitea.md
- Map Viewer: services/map.md
- Mini QR: services/mini-qr.md
- Cloudflare Tunnels: cloudflare/index.md
- Blog:
- blog/index.md
- blog/index.md

View File

@ -258,17 +258,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="/getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="/phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -277,17 +280,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="/philosophy/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="/build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -317,47 +323,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="/services/" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="/cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
<li class="md-tabs__item">
<a href="/blog/" class="md-tabs__link">
@ -452,72 +417,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="/getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="/philosophy/" class="md-nav__link">
<span class="md-ellipsis">
Philosophy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="/cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -526,20 +425,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -567,12 +452,72 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="/services/" class="md-nav__link">
<a href="/phil/" class="md-nav__link">
<span class="md-ellipsis">
Services
Philosophy
</span>
<span class="md-nav__icon md-icon"></span>
</a>
</li>
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="/build/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
@ -595,12 +540,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="/cloudflare/" class="md-nav__link">
<a href="/cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -761,51 +706,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "/", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "/assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -815,6 +715,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="/javascripts/home.js"></script>
<script src="/javascripts/github-widget.js"></script>
<script src="/javascripts/gitea-widget.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,16 @@
{
"full_name": "admin/changemaker.lite",
"name": "changemaker.lite",
"description": "Changemaker-lite is the current active development branch of Changemaker, focused on streamlining core services. These improvements will be merged into the master branch once ready.",
"html_url": "https://gitea.bnkops.com/admin/changemaker.lite",
"language": "HTML",
"stars_count": 0,
"forks_count": 0,
"open_issues_count": 0,
"updated_at": "2025-06-30T10:01:47-06:00",
"created_at": "2025-05-28T14:54:59-06:00",
"clone_url": "https://gitea.bnkops.com/admin/changemaker.lite.git",
"ssh_url": "git@gitea.bnkops.com:admin/changemaker.lite.git",
"default_branch": "main",
"last_build_update": "2025-06-30T10:01:47-06:00"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "coder/code-server",
"name": "code-server",
"description": "VS Code in the browser",
"html_url": "https://github.com/coder/code-server",
"language": "TypeScript",
"stars_count": 72491,
"forks_count": 6060,
"open_issues_count": 132,
"updated_at": "2025-06-30T21:31:29Z",
"created_at": "2019-02-27T16:50:41Z",
"clone_url": "https://github.com/coder/code-server.git",
"ssh_url": "git@github.com:coder/code-server.git",
"default_branch": "main",
"last_build_update": "2025-06-25T21:18:52Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "gethomepage/homepage",
"name": "homepage",
"description": "A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.",
"html_url": "https://github.com/gethomepage/homepage",
"language": "JavaScript",
"stars_count": 24565,
"forks_count": 1519,
"open_issues_count": 1,
"updated_at": "2025-06-30T20:44:09Z",
"created_at": "2022-08-24T07:29:42Z",
"clone_url": "https://github.com/gethomepage/homepage.git",
"ssh_url": "git@github.com:gethomepage/homepage.git",
"default_branch": "dev",
"last_build_update": "2025-06-30T12:13:58Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "knadh/listmonk",
"name": "listmonk",
"description": "High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.",
"html_url": "https://github.com/knadh/listmonk",
"language": "Go",
"stars_count": 17238,
"forks_count": 1656,
"open_issues_count": 103,
"updated_at": "2025-06-30T20:57:12Z",
"created_at": "2019-06-26T05:08:39Z",
"clone_url": "https://github.com/knadh/listmonk.git",
"ssh_url": "git@github.com:knadh/listmonk.git",
"default_branch": "master",
"last_build_update": "2025-06-30T10:45:51Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "n8n-io/n8n",
"name": "n8n",
"description": "Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.",
"html_url": "https://github.com/n8n-io/n8n",
"language": "TypeScript",
"stars_count": 113623,
"forks_count": 33244,
"open_issues_count": 1061,
"updated_at": "2025-06-30T21:38:07Z",
"created_at": "2019-06-22T09:24:21Z",
"clone_url": "https://github.com/n8n-io/n8n.git",
"ssh_url": "git@github.com:n8n-io/n8n.git",
"default_branch": "master",
"last_build_update": "2025-06-30T20:59:49Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "nocodb/nocodb",
"name": "nocodb",
"description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 Open Source Airtable Alternative",
"html_url": "https://github.com/nocodb/nocodb",
"language": "TypeScript",
"stars_count": 55465,
"forks_count": 3980,
"open_issues_count": 714,
"updated_at": "2025-06-30T21:39:01Z",
"created_at": "2017-10-29T18:51:48Z",
"clone_url": "https://github.com/nocodb/nocodb.git",
"ssh_url": "git@github.com:nocodb/nocodb.git",
"default_branch": "develop",
"last_build_update": "2025-06-30T20:21:14Z"
}

View File

@ -0,0 +1,16 @@
{
"full_name": "squidfunk/mkdocs-material",
"name": "mkdocs-material",
"description": "Documentation that simply works",
"html_url": "https://github.com/squidfunk/mkdocs-material",
"language": "Python",
"stars_count": 23757,
"forks_count": 3783,
"open_issues_count": 4,
"updated_at": "2025-06-30T21:37:52Z",
"created_at": "2016-01-28T22:09:23Z",
"clone_url": "https://github.com/squidfunk/mkdocs-material.git",
"ssh_url": "git@github.com:squidfunk/mkdocs-material.git",
"default_branch": "master",
"last_build_update": "2025-06-29T16:43:26Z"
}

View File

@ -15,7 +15,7 @@
<link rel="canonical" href="https://cmlite.org/blog/">
<link rel="prev" href="../cloudflare/">
<link rel="prev" href="../cost-comparison/">
@ -288,17 +288,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -307,17 +310,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../philosophy/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -344,47 +350,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../services/" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -484,72 +449,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../philosophy/" class="md-nav__link">
<span class="md-ellipsis">
Philosophy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -558,20 +457,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -599,12 +484,72 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="../services/" class="md-nav__link">
<a href="../phil/" class="md-nav__link">
<span class="md-ellipsis">
Services
Philosophy
</span>
<span class="md-nav__icon md-icon"></span>
</a>
</li>
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../build/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
@ -627,12 +572,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../cloudflare/" class="md-nav__link">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -677,7 +622,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<div class="md-nav__link md-nav__container">
@ -694,14 +639,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link md-nav__link--active" for="__nav_7" id="__nav_7_label" tabindex="">
<label class="md-nav__link md-nav__link--active" for="__nav_5" id="__nav_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_7">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Blog
</label>
@ -795,7 +740,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../cloudflare/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Cloudflare Tunnels">
<a href="../cost-comparison/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Cost Comparison">
<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>
@ -805,7 +750,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
Previous
</span>
<div class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</div>
</div>
</a>
@ -858,51 +803,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -912,6 +812,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../javascripts/home.js"></script>
<script src="../javascripts/github-widget.js"></script>
<script src="../javascripts/gitea-widget.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -12,13 +12,13 @@
<meta name="author" content="Bunker Operations">
<link rel="canonical" href="https://cmlite.org/cloudflare/">
<link rel="canonical" href="https://cmlite.org/config/">
<link rel="prev" href="../services/mini-qr/">
<link rel="next" href="../blog/">
<link rel="next" href="cloudflare-config/">
<link rel="icon" href="../assets/images/favicon.png">
@ -26,7 +26,7 @@
<title>Cloudflare Tunnels - Changemaker Lite</title>
<title>Configuration - Changemaker Lite</title>
@ -65,11 +65,11 @@
<meta property="og:type" content="website" >
<meta property="og:title" content="Cloudflare Tunnels - Changemaker Lite" >
<meta property="og:title" content="Configuration - Changemaker Lite" >
<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/cloudflare/index.png" >
<meta property="og:image" content="https://cmlite.org/assets/images/social/config/index.png" >
<meta property="og:image:type" content="image/png" >
@ -77,15 +77,15 @@
<meta property="og:image:height" content="630" >
<meta property="og:url" content="https://cmlite.org/cloudflare/" >
<meta property="og:url" content="https://cmlite.org/config/" >
<meta name="twitter:card" content="summary_large_image" >
<meta name="twitter:title" content="Cloudflare Tunnels - Changemaker Lite" >
<meta name="twitter:title" content="Configuration - Changemaker Lite" >
<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/cloudflare/index.png" >
<meta name="twitter:image" content="https://cmlite.org/assets/images/social/config/index.png" >
@ -111,7 +111,7 @@
<div data-md-component="skip">
<a href="#cloudflare" class="md-skip">
<a href="#configuration" class="md-skip">
Skip to content
</a>
@ -165,7 +165,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Cloudflare Tunnels
Configuration
</span>
</div>
@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -354,49 +362,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../services/" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
<li class="md-tabs__item">
<a href="../blog/" class="md-tabs__link">
@ -491,72 +456,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../philosophy/" class="md-nav__link">
<span class="md-ellipsis">
Philosophy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,20 +464,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,12 +491,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="../services/" class="md-nav__link">
<a href="../phil/" class="md-nav__link">
<span class="md-ellipsis">
Services
Philosophy
</span>
@ -635,72 +520,566 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../build/" class="md-nav__link ">
<span class="md-ellipsis">
Cloudflare Tunnels
Getting Started
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Build Server
</span>
</a>
</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_3" >
<div class="md-nav__link md-nav__container">
<a href="../services/" class="md-nav__link ">
<span class="md-ellipsis">
Services
</span>
<nav class="md-nav md-nav--secondary" aria-label="On this page">
</a>
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../services/homepage/" class="md-nav__link">
<span class="md-ellipsis">
Homepage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/code-server/" class="md-nav__link">
<span class="md-ellipsis">
Code Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/mkdocs/" class="md-nav__link">
<span class="md-ellipsis">
MkDocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/static-server/" class="md-nav__link">
<span class="md-ellipsis">
Static Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/listmonk/" class="md-nav__link">
<span class="md-ellipsis">
Listmonk
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/postgresql/" class="md-nav__link">
<span class="md-ellipsis">
PostgreSQL
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/n8n/" class="md-nav__link">
<span class="md-ellipsis">
n8n
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/nocodb/" class="md-nav__link">
<span class="md-ellipsis">
NocoDB
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/gitea/" class="md-nav__link">
<span class="md-ellipsis">
Gitea
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/map/" class="md-nav__link">
<span class="md-ellipsis">
Map Viewer
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../services/mini-qr/" class="md-nav__link">
<span class="md-ellipsis">
Mini QR
</span>
</a>
</li>
</ul>
</nav>
</li>
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
On this page
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#config" class="md-nav__link">
<span class="md-ellipsis">
Config
</span>
</a>
</li>
</ul>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4" checked>
<div class="md-nav__link md-nav__container">
<a href="./" class="md-nav__link md-nav__link--active">
</nav>
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link md-nav__link--active" for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -780,23 +1159,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
On this page
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#config" class="md-nav__link">
<span class="md-ellipsis">
Config
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
@ -811,10 +1173,9 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<h1 id="cloudflare">Cloudflare<a class="headerlink" href="#cloudflare" title="Permanent link">&para;</a></h1>
<p>In this section, you will find instructions on how to properly set up Cloudflare for managing a Changemaker-lite. </p>
<h2 id="config">Config<a class="headerlink" href="#config" title="Permanent link">&para;</a></h2>
<p>When you first run the <code>./config.sh</code> it will prompt you for the a api token, zone id, and a tunnel id. A</p>
<h1 id="configuration">Configuration<a class="headerlink" href="#configuration" title="Permanent link">&para;</a></h1>
<p>There are several configuration steps to building a production ready Changemaker-Lite. </p>
<p>In the order we suggest doing them: </p>
@ -870,13 +1231,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="cloudflare-config/" class="md-footer__link md-footer__link--next" aria-label="Next: Cloudflare">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Index
Cloudflare
</div>
</div>
<div class="md-footer__button md-icon">
@ -932,51 +1293,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -986,6 +1302,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../javascripts/home.js"></script>
<script src="../javascripts/github-widget.js"></script>
<script src="../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -15,10 +15,10 @@
<link rel="canonical" href="https://cmlite.org/cost-comparison/">
<link rel="prev" href="../philosophy/">
<link rel="prev" href="../config/cloudflare-config/">
<link rel="next" href="../services/">
<link rel="next" href="../blog/">
<link rel="icon" href="../assets/images/favicon.png">
@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -314,17 +317,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../philosophy/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -356,47 +362,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../services/" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
<li class="md-tabs__item">
<a href="../blog/" class="md-tabs__link">
@ -491,18 +456,58 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../getting-started/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../phil/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
Philosophy
</span>
</a>
<span class="md-nav__icon md-icon"></span>
</a>
</li>
@ -513,18 +518,56 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../build/" class="md-nav__link">
<span class="md-ellipsis">
Philosophy
Getting Started
</span>
</a>
<span class="md-nav__icon md-icon"></span>
</a>
</li>
@ -922,104 +965,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../services/" class="md-nav__link">
<span class="md-ellipsis">
Services
</span>
<span class="md-nav__icon md-icon"></span>
</a>
</li>
<li class="md-nav__item">
<a href="../cloudflare/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
</span>
</a>
</li>
@ -1911,7 +1856,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../philosophy/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Philosophy">
<a href="../config/cloudflare-config/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Cloudflare">
<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>
@ -1921,20 +1866,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
Previous
</span>
<div class="md-ellipsis">
Philosophy
Cloudflare
</div>
</div>
</a>
<a href="../services/" class="md-footer__link md-footer__link--next" aria-label="Next: Services">
<a href="../blog/" class="md-footer__link md-footer__link--next" aria-label="Next: Index">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Services
Index
</div>
</div>
<div class="md-footer__button md-icon">
@ -1990,51 +1935,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -2044,6 +1944,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../javascripts/home.js"></script>
<script src="../javascripts/github-widget.js"></script>
<script src="../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -0,0 +1,132 @@
"""
MkDocs Hook for Repository Widget Data Generation
Fetches repository data and generates JSON files during build
"""
import json
import os
import requests
from pathlib import Path
from typing import Dict, Any
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def on_pre_build(config: Dict[str, Any]) -> None:
"""
Hook that runs before MkDocs builds the site
Generates repository JSON data files
"""
logger.info("Generating repository widget data...")
# Define repositories to fetch - all repos from services.md
repositories = [
# Gitea repositories
{
"repo": "admin/changemaker.lite",
"gitea_url": "https://gitea.bnkops.com",
"token": os.getenv("GITEA_TOKEN")
},
# GitHub repositories
{
"repo": "coder/code-server",
"github": True
},
{
"repo": "n8n-io/n8n",
"github": True
},
{
"repo": "knadh/listmonk",
"github": True
},
{
"repo": "nocodb/nocodb",
"github": True
},
{ "repo": "squidfunk/mkdocs-material",
"github": True
},
{
"repo": "gethomepage/homepage",
"github": True
}
]
# Create output directory
docs_dir = config.get('docs_dir', 'docs')
output_dir = Path(docs_dir) / 'assets' / 'repo-data'
output_dir.mkdir(parents=True, exist_ok=True)
# Generate data for each repository
for repo_config in repositories:
try:
generate_repo_data(repo_config, output_dir)
except Exception as e:
logger.error(f"Failed to generate data for {repo_config['repo']}: {e}")
def generate_repo_data(repo_config: Dict[str, Any], output_dir: Path) -> None:
"""Generate JSON data file for a single repository"""
repo = repo_config['repo']
logger.info(f"Fetching data for {repo}")
# Determine API URL and headers
if repo_config.get('github'):
api_url = f"https://api.github.com/repos/{repo}"
headers = {'Accept': 'application/vnd.github.v3+json'}
github_token = os.getenv('GITHUB_TOKEN')
if github_token:
headers['Authorization'] = f'token {github_token}'
else:
gitea_url = repo_config.get('gitea_url', 'https://gitea.bnkops.com')
api_url = f"{gitea_url}/api/v1/repos/{repo}"
headers = {'Accept': 'application/json'}
token = repo_config.get('token') or os.getenv('GITEA_TOKEN')
if token:
headers['Authorization'] = f'token {token}'
# Fetch repository data
try:
response = requests.get(api_url, headers=headers, timeout=10)
response.raise_for_status()
data = response.json()
except requests.RequestException as e:
logger.error(f"Failed to fetch {repo}: {e}")
return
# Extract widget data
widget_data = {
'full_name': data.get('full_name'),
'name': data.get('name'),
'description': data.get('description'),
'html_url': data.get('html_url'),
'language': data.get('language'),
'stars_count': data.get('stargazers_count') or data.get('stars_count', 0),
'forks_count': data.get('forks_count', 0),
'open_issues_count': data.get('open_issues_count', 0),
'updated_at': data.get('updated_at'),
'created_at': data.get('created_at'),
'clone_url': data.get('clone_url'),
'ssh_url': data.get('ssh_url'),
'default_branch': data.get('default_branch', 'main'),
'last_build_update': data.get('pushed_at') or data.get('updated_at')
}
# Generate filename
filename = f"{repo.replace('/', '-')}.json"
file_path = output_dir / filename
# Write JSON file
try:
with open(file_path, 'w') as f:
json.dump(widget_data, f, indent=2)
logger.info(f"Generated: {filename}")
except Exception as e:
logger.error(f"Failed to write {filename}: {e}")
def on_post_build(config: Dict[str, Any]) -> None:
"""Hook that runs after MkDocs builds the site"""
logger.info("Repository widget data generation complete")

View File

@ -16,7 +16,7 @@
<link rel="next" href="getting-started/">
<link rel="next" href="phil/">
<link rel="icon" href="assets/images/favicon.png">
@ -87,14 +87,14 @@
<!-- Custom meta tags or head content can go here -->
<script>
<script>
// Add data attribute for CSS targeting
document.body.setAttribute('data-md-template', 'home');
</script>
</script>
</head>
@ -301,17 +301,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -320,17 +323,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="philosophy/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -360,47 +366,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="services/" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
<li class="md-tabs__item">
<a href="blog/" class="md-tabs__link">
@ -646,72 +611,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="philosophy/" class="md-nav__link">
<span class="md-ellipsis">
Philosophy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -720,20 +619,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -761,12 +646,72 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="services/" class="md-nav__link">
<a href="phil/" class="md-nav__link">
<span class="md-ellipsis">
Services
Philosophy
</span>
<span class="md-nav__icon md-icon"></span>
</a>
</li>
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="build/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
@ -789,12 +734,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="cloudflare/" class="md-nav__link">
<a href="cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1009,223 +954,359 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-content--home">
<!-- Hero Grid Section -->
<section class="hero-grid">
<div class="grid-container">
<!-- Main Hero Block -->
<div class="hero-main">
<div class="meta-badge">🤯 This Site Runs On Changemaker Lite</div>
<h1>The Infrastructure That Runs Itself</h1>
<p>You're looking at Changemaker Lite right now. This entire documentation platform, our email campaigns, databases, and automation all run on the same $200 hardware we're selling you.</p>
<div class="self-hosting-proof">
<div class="proof-item">
<span class="proof-icon">🏠</span>
<span class="proof-text">This website</span>
</div>
<div class="proof-item">
<span class="proof-icon">📧</span>
<span class="proof-text">BNKops newsletters</span>
</div>
<div class="proof-item">
<span class="proof-icon">💾</span>
<span class="proof-text">Community database</span>
</div>
<div class="proof-item">
<span class="proof-icon">🔄</span>
<span class="proof-text">Automated workflows</span>
</div>
</div>
<div class="hero-ctas">
<a href="#video-demo" class="btn btn-primary">Watch It Work ▶️</a>
<a href="#get-started" class="btn btn-secondary">Get Started $200</a>
</div>
</div>
<!-- Video Demo Block -->
<div class="hero-video" id="video-demo">
<div class="video-placeholder">
<div class="video-icon">▶️</div>
<h3>See Changemaker Lite In Action</h3>
<p>3-minute demo of everything running on one box</p>
<!-- VIDEO PLACEHOLDER: Terminal demo showing docker compose ps, accessing services -->
</div>
</div>
<!-- Stats Block -->
<div class="hero-stats">
<div class="stat-item">
<div class="stat-number">$200</div>
<div class="stat-label">Total hardware cost</div>
</div>
<div class="stat-item">
<div class="stat-number">11</div>
<div class="stat-label">Services included</div>
</div>
<div class="stat-item">
<div class="stat-number">100%</div>
<div class="stat-label">Data ownership</div>
</div>
</div>
<!-- Trust Indicators -->
<div class="hero-trust">
<div class="trust-item">
<span class="trust-icon"></span>
<span class="trust-text">Powers BNKops.com</span>
</div>
<div class="trust-item">
<span class="trust-icon">🏳️‍⚧️</span>
<span class="trust-text">Trans liberation tech</span>
</div>
<div class="trust-item">
<span class="trust-icon">🛡️</span>
<span class="trust-text">Zero surveillance</span>
</div>
</div>
</div>
</section>
<!-- Hero Grid Section -->
<section class="hero-grid">
<div class="grid-container">
<!-- Main Hero Block -->
<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 Stack</h1>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled and your supports data sold to the highest bidder. Run your entire political campaign on ~$200 hardware and
with fewer corporate dependencies every day.</p>
<!-- Self-Hosting Proof Grid -->
<section class="proof-grid-section">
<div class="grid-container">
<div class="section-header">
<h2>What You're Looking At Right Now</h2>
<p>This entire platform runs on Changemaker Lite. We're not just selling it - we're living it.</p>
</div>
<div class="proof-grid-layout">
<!-- Backend Demo -->
<div class="proof-card">
<div class="proof-header">
<span class="proof-icon">🖥️</span>
<h3>Backend Demo</h3>
<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>
</div>
<div class="video-placeholder small">
<!-- VIDEO: Screen recording of homepage dashboard -->
<div class="video-icon">▶️</div>
<p>Homepage dashboard tour</p>
</div>
<p>Live view of all 11 services running on one box</p>
</div>
<!-- Email System -->
<div class="proof-card">
<div class="proof-header">
<span class="proof-icon">📧</span>
<h3>Email System</h3>
<!-- Problem Statement Block -->
<div class="hero-problem grid-card">
<h3>The Problem</h3>
<div class="problem-list">
<div class="problem-item">💸 Canvassing: $100+/mo</div>
<div class="problem-item">📊 Nationbuilder: $500+/mo</div>
<div class="problem-item">📧 Mailchimp: $200+/mo</div>
<div class="problem-item">👁️ Surveillance: Always on</div>
<div class="problem-item">🔒 Vendor lock-in: Trapped forever</div>
<div class="problem-item">📉 Data ownership: Not yours</div>
<div class="promlem-itme">😠 Implicitly Supporting Evil Corporations</div>
</div>
<div class="live-stats">
<div class="stat">2.3K subscribers</div>
<div class="stat">98% delivery rate</div>
</div>
<p>Listmonk powers all BNKops newsletters</p>
</div>
<!-- Database -->
<div class="proof-card">
<div class="proof-header">
<span class="proof-icon">💾</span>
<h3>Database</h3>
</div>
<div class="video-placeholder small">
<!-- VIDEO: Quick NocoDB demo -->
<div class="video-icon">▶️</div>
<p>NocoDB interface</p>
</div>
<p>Managing inquiries, contacts, projects</p>
</div>
<!-- Cost Savings -->
<div class="proof-card highlighted">
<div class="proof-header">
<span class="proof-icon">💰</span>
<h3>Our Savings</h3>
</div>
<div class="savings-breakdown">
<div class="savings-item">
<span class="corporate">Corporate SaaS: $1,200/mo</span>
<span class="ours">Changemaker: $50/mo</span>
<!-- Solution Stats Block -->
<div class="hero-stats grid-card">
<h3>The Solution</h3>
<div class="stat-grid">
<div class="stat-item">
<div class="stat-number">Runs on ~$200 Hardware</div>
<div class="stat-label">One-time cost</div>
</div>
<div class="stat-item">
<div class="stat-number">11</div>
<div class="stat-label">Campaign tools</div>
</div>
<div class="stat-item">
<div class="stat-number">Your Data</div>
<div class="stat-label">Localized & Secure</div>
</div>
<div class="stat-item">
<div class="stat-number"></div>
<div class="stat-label">Fewer corporate deps every day</div>
</div>
<div class="savings-total">Saving $13,800/year</div>
</div>
<p>Money that goes to organizing, not shareholders</p>
</div>
</div>
</div>
</section>
<!-- Hardware Options Grid -->
<section class="hardware-grid-section" id="get-started">
<div class="grid-container">
<div class="section-header">
<h2>Get The Same Setup</h2>
<p>Three ways to join the digital liberation movement</p>
</div>
<div class="hardware-options-grid">
<!-- Plug & Play -->
<div class="option-card featured">
<div class="option-badge">Recommended</div>
<div class="option-icon">🚀</div>
<h3>Plug & Play</h3>
<div class="option-price">$200</div>
<div class="option-features">
<div class="feature">✓ Pre-configured hardware</div>
<div class="feature">✓ 30-minute setup</div>
<div class="feature">✓ Everything included</div>
<div class="feature">✓ Priority support</div>
</div>
<a href="https://bnkops.com/hardware" class="btn btn-primary">Order Hardware</a>
<div class="option-note">Ships in 5 days</div>
</div>
<!-- DIY -->
<div class="option-card">
<div class="option-icon">🛠️</div>
<h3>DIY Install</h3>
<div class="option-price">Free</div>
<div class="option-features">
<div class="feature">✓ Use your hardware</div>
<div class="feature">✓ Learn the system</div>
<div class="feature">✓ Full control</div>
<div class="feature">✓ Community support</div>
</div>
<a href="/getting-started/" class="btn btn-secondary">Install Guide</a>
<div class="option-note">+$50/mo hosting</div>
</div>
<!-- Managed -->
<div class="option-card">
<div class="option-icon">☁️</div>
<h3>Managed Hosting</h3>
<div class="option-price">$150/mo</div>
<div class="option-features">
<div class="feature">✓ We handle everything</div>
<div class="feature">✓ Your domain</div>
<div class="feature">✓ Your data</div>
<div class="feature">✓ 24/7 monitoring</div>
</div>
<a href="https://bnkops.com/hosting" class="btn btn-secondary">Learn More</a>
<div class="option-note">Still your infrastructure</div>
</div>
</div>
<!-- Quick Setup Demo -->
<div class="setup-demo">
<h3>See The 30-Minute Setup</h3>
<div class="video-placeholder">
<!-- VIDEO: Time-lapse of complete setup process -->
<div class="video-icon">▶️</div>
<div class="video-meta">
<span>5:23</span>
<span>Time-lapse setup</span>
<!-- Trust Indicators -->
<div class="hero-trust grid-card">
<h3>Proven By</h3>
<div class="trust-items">
<div class="trust-item">
<span class="trust-icon"></span>
<span class="trust-text">Powers BNKops.com</span>
</div>
<div class="trust-item">
<span class="trust-icon"> 🌈 </span>
<span class="trust-text">Liberation tech</span>
</div>
<div class="trust-item">
<span class="trust-icon">🛡️</span>
<span class="trust-text">Zero surveillance</span>
</div>
<div class="trust-item">
<span class="trust-icon">🚀</span>
<span class="trust-text">30-min setup</span>
</div>
</div>
</div>
</div>
</div>
</section>
</section>
<!-- Solution Grid -->
<section class="solution-grid" id="solution">
<div class="grid-container">
<div class="section-header">
<h2>Your Complete Campaign Toolkit</h2>
<p>Simple, powerful tools designed for campaign staff - no technical skills needed</p>
</div>
<div class="services-grid">
<!-- Documentation Editor -->
<div class="service-card grid-card">
<div class="service-icon">✍️</div>
<h3>Campaign Content Editor</h3>
<div class="service-replaces">Replaces: Google Docs + WordPress (~$50/month)</div>
<ul class="service-features">
<li>Edit docs & blog posts</li>
<li>Live preview as you type</li>
<li>Simple formatting tools</li>
<li>Works in any browser</li>
</ul>
<div class="service-tool">Code Server</div>
</div>
<!-- Canvassing System -->
<div class="service-card grid-card featured">
<div class="service-badge">Field Team Essential</div>
<div class="service-icon">🚪</div>
<h3>Smart Canvassing</h3>
<div class="service-replaces">Replaces: Qumon (~$100+/mo)</div>
<ul class="service-features">
<li>Interactive voter maps</li>
<li>Track door knocks</li>
<li>Mobile-friendly</li>
<li>Works offline</li>
</ul>
<div class="service-tool">NocoDB + Map Viewer</div>
</div>
<!-- Email System -->
<div class="service-card grid-card">
<div class="service-icon">📩</div>
<h3>Email Blasts</h3>
<div class="service-replaces">Replaces: Mailchimp (~$200+/mo)</div>
<ul class="service-features">
<li>Simple email creator</li>
<li>Track opens/clicks</li>
<li>Unlimited subscribers</li>
<li>Pre-made templates</li>
</ul>
<div class="service-tool">Listmonk</div>
</div>
<!-- Voter Database -->
<div class="service-card grid-card">
<div class="service-icon">🗃️</div>
<h3>Voter Database</h3>
<div class="service-replaces">Replaces: NationBuilder (~$500+/mo)</div>
<ul class="service-features">
<li>Spreadsheet interface</li>
<li>Easy voter searches</li>
<li>Custom survey forms</li>
<li>Export walk lists</li>
</ul>
<div class="service-tool">NocoDB</div>
</div>
<!-- Automation -->
<div class="service-card grid-card">
<div class="service-icon">🤖</div>
<h3>Smart Automation</h3>
<div class="service-replaces">Replaces: Zapier (~$300/month)</div>
<ul class="service-features">
<li>Auto follow-up emails</li>
<li>Volunteer reminders</li>
<li>Donation thank yous</li>
<li>Pre-built workflows</li>
</ul>
<div class="service-tool">n8n</div>
</div>
<!-- Website -->
<div class="service-card grid-card">
<div class="service-icon">🌐</div>
<h3>Campaign Website</h3>
<div class="service-replaces">Replaces: Squarespace (~$100/month)</div>
<ul class="service-features">
<li>Pre-designed templates</li>
<li>Easy content updates</li>
<li>Built-in blog</li>
<li>Fast loading</li>
</ul>
<div class="service-tool">MkDocs</div>
</div>
<!-- Volunteer Management -->
<div class="service-card grid-card">
<div class="service-icon">👥</div>
<h3>Volunteer HQ</h3>
<div class="service-replaces">Replaces: Mobilize (~$200/month)</div>
<ul class="service-features">
<li>Shift scheduling</li>
<li>Automated reminders</li>
<li>Skills matching</li>
<li>Progress tracking</li>
</ul>
<div class="service-tool">NocoDB + n8n</div>
</div>
<!-- Linking Features -->
<div class="service-card grid-card">
<div class="service-icon">👀</div>
<h3> Mobile, Social, & Hot Link Friendly</h3>
<div class="service-replaces">Replaces: Linktree (~$20/month)</div>
<ul class="service-features">
<li>Automatic Social Cards</li>
<li>Hot Linking to All Assets & Headers</li>
<li>Documentation Indexing & Search</li>
<li>Progress tracking</li>
</ul>
<div class="service-tool">NocoDB + n8n</div>
</div>
<!-- Rapid Response -->
<div class="service-card grid-card">
<div class="service-icon"></div>
<h3>Rapid Response</h3>
<div class="service-replaces">Replaces: Slack + Google Docs (~$50/month)</div>
<ul class="service-features">
<li>Real-time collaboration</li>
<li>Community Editing</li>
<li>Open source documentation</li>
<li>Version control</li>
</ul>
<div class="service-tool">Code Server + Gitea</div>
</div>
</div>
</div>
</section>
<!-- Comparison Grid -->
<section class="comparison-grid">
<div class="grid-container">
<div class="section-header">
<h2>Corporate SaaS vs Changemaker Lite</h2>
<p>Why campaigns are switching to self-hosted FOSS</p>
</div>
<div class="comparison-table">
<div class="comparison-header grid-card">
<div></div>
<div class="compare-col">Corporate SaaS</div>
<div class="compare-col highlight">Changemaker Lite</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Monthly Cost</div>
<div class="compare-value bad">$1,200+</div>
<div class="compare-value good">$0 Self-Hosted</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Data Ownership</div>
<div class="compare-value bad">Their servers</div>
<div class="compare-value good">100% yours</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Surveillance</div>
<div class="compare-value bad">Always tracked</div>
<div class="compare-value good">Zero tracking</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Vendor Lock-in</div>
<div class="compare-value bad">Trapped forever</div>
<div class="compare-value good">Export anytime</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Customization</div>
<div class="compare-value bad">Limited options</div>
<div class="compare-value good">Full control</div>
</div>
</div>
</div>
</section>
<!-- Get Started Grid -->
<section class="get-started-grid" id="get-started">
<div class="grid-container">
<div class="section-header">
<h2>Start Your Digital Liberation</h2>
<p>Three ways to break free from corporate campaign tech</p>
</div>
<div class="options-grid">
<!-- Plug & Play -->
<div class="option-card grid-card featured">
<div class="option-badge">Most Popular</div>
<div class="option-icon">🚀</div>
<h3>Plug & Play</h3>
<div class="option-price">~$400 (Built to Suit)</div>
<div class="option-features">
<div class="feature">✓ Pre-configured hardware</div>
<div class="feature">✓ 30-minute setup</div>
<div class="feature">✓ All 11 services ready</div>
<div class="feature">✓ Priority support</div>
<div class="feature">✓ Ships on request</div>
</div>
<a href="https://bnkops.com/hardware" class="btn btn-primary">Order Hardware</a>
</div>
<!-- DIY -->
<div class="option-card grid-card">
<div class="option-icon">🛠️</div>
<h3>DIY Install</h3>
<div class="option-price">Free</div>
<div class="option-features">
<div class="feature">✓ Use your hardware</div>
<div class="feature">✓ Docker compose</div>
<div class="feature">✓ Full documentation</div>
<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>
</div>
<!-- Managed -->
<div class="option-card grid-card">
<div class="option-icon">☁️</div>
<h3>Managed Hosting</h3>
<div class="option-price">$???/mo</div>
<div class="option-features">
<div class="feature">✓ We manage everything</div>
<div class="feature">✓ Your domain</div>
<div class="feature">✓ Daily backups</div>
<div class="feature">✓ 24/7 monitoring</div>
<div class="feature">✓ Still your data</div>
</div>
<a href="https://bnkops.com" class="btn btn-secondary">Learn More</a>
</div>
</div>
<!-- Cards in a row -->
<div class="row-cards">
<div class="final-cta grid-card">
<h3>Join the Movement</h3>
<p>Some of the biggest players in local politics are already using it; maybe give it a try?</p>
<div class="cta-buttons">
<a href="https://bnkops.com/newsletter" class="btn btn-primary">Get Campaign Tips</a>
<a href="https://docs.bnkops.com" class="btn btn-secondary">Read Documentation</a>
</div>
</div>
<div class="subscribe-card grid-card">
<h3>Subscribe</h3>
<form action="https://newsletter.bnkops.com/subscription/form" method="POST" target="_blank"
autocomplete="off">
<input type="hidden" name="nonce">
<p>
<input type="email" name="email" required placeholder="E-mail">
</p>
<p>
<input type="text" name="name" placeholder="Name (optional)">
</p>
<p>
<input id="48b84" type="checkbox" name="l" checked
value="48b841e7-841b-458b-95f8-63903a1c0912">
<label for="48b84">~ Weekly Updates</label>
</p>
<input type="submit" value="Subscribe" class="action-btn primary">
</form>
</div>
</div>
</div>
</section>
</div>
@ -1254,13 +1335,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="getting-started/" class="md-footer__link md-footer__link--next" aria-label="Next: Getting Started">
<a href="phil/" class="md-footer__link md-footer__link--next" aria-label="Next: Philosophy: Your Secrets, Your Power, Your Movement">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Getting Started
Philosophy: Your Secrets, Your Power, Your Movement
</div>
</div>
<div class="md-footer__button md-icon">
@ -1316,51 +1397,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": ".", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1370,6 +1406,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="javascripts/home.js"></script>
<script src="javascripts/github-widget.js"></script>
<script src="javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -0,0 +1,132 @@
document.addEventListener('DOMContentLoaded', function() {
const widgets = document.querySelectorAll('.gitea-widget');
widgets.forEach(widget => {
const repo = widget.dataset.repo;
// Auto-generate data file path from repo name
const dataFile = `/assets/repo-data/${repo.replace('/', '-')}.json`;
const showDescription = widget.dataset.showDescription !== 'false';
const showLanguage = widget.dataset.showLanguage !== 'false';
const showLastUpdate = widget.dataset.showLastUpdate !== 'false';
// Show loading state
widget.innerHTML = `
<div class="gitea-widget-loading">
<div class="loading-spinner"></div>
<span>Loading ${repo}...</span>
</div>
`;
// Fetch repository data
fetch(dataFile)
.then(response => {
if (!response.ok) {
throw new Error(`Could not load data for ${repo}`);
}
return response.json();
})
.then(data => {
renderWidget(widget, data, { showDescription, showLanguage, showLastUpdate });
})
.catch(error => {
renderError(widget, repo, error.message);
});
});
});
function renderWidget(widget, data, options) {
const lastUpdate = new Date(data.updated_at).toLocaleDateString();
const language = data.language || 'Not specified';
widget.innerHTML = `
<div class="gitea-widget-container">
<div class="gitea-widget-header">
<div class="gitea-widget-title">
<svg class="gitea-icon" viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M2 2.5A2.5 2.5 0 014.5 0h8.75a.75.75 0 01.75.75v12.5a.75.75 0 01-.75.75h-2.5a.75.75 0 110-1.5h1.75v-2h-8a1 1 0 00-.714 1.7.75.75 0 01-1.072 1.05A2.495 2.495 0 012 11.5v-9zm10.5-1V9h-8c-.356 0-.694.074-1 .208V2.5a1 1 0 011-1h8zM5 12.25v3.25a.25.25 0 00.4.2l1.45-1.087a.25.25 0 01.3 0L8.6 15.7a.25.25 0 00.4-.2v-3.25a.25.25 0 00-.25-.25h-3.5a.25.25 0 00-.25.25z"/>
</svg>
<a href="${data.html_url}" target="_blank" rel="noopener noreferrer" class="repo-link">
${data.full_name}
</a>
</div>
<div class="gitea-widget-stats">
<span class="stat-item" title="Stars">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z"/>
</svg>
${data.stars_count.toLocaleString()}
</span>
<span class="stat-item" title="Forks">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25V5.372a2.25 2.25 0 10-1.5 0v.878A.75.75 0 0110.25 7H5.75A.75.75 0 015 6.25v-.878zm3.75 7.378a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm3-8.75a.75.75 0 100-1.5.75.75 0 000 1.5z"/>
</svg>
${data.forks_count.toLocaleString()}
</span>
<span class="stat-item" title="Open Issues">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"/>
<path fill="currentColor" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"/>
</svg>
${data.open_issues_count.toLocaleString()}
</span>
</div>
</div>
${options.showDescription && data.description ? `
<div class="gitea-widget-description">
${data.description}
</div>
` : ''}
<div class="gitea-widget-footer">
${options.showLanguage ? `
<span class="language-info">
<span class="language-dot" style="background-color: ${getLanguageColor(language)}"></span>
${language}
</span>
` : ''}
${options.showLastUpdate ? `
<span class="last-update">Updated ${lastUpdate}</span>
` : ''}
</div>
</div>
`;
}
function renderError(widget, repo, error) {
widget.innerHTML = `
<div class="gitea-widget-error">
<svg viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"/>
</svg>
<span>Failed to load ${repo}</span>
<small>${error}</small>
</div>
`;
}
function getLanguageColor(language) {
const colors = {
'JavaScript': '#f1e05a',
'TypeScript': '#2b7489',
'Python': '#3572A5',
'Java': '#b07219',
'C++': '#f34b7d',
'C': '#555555',
'C#': '#239120',
'PHP': '#4F5D95',
'Ruby': '#701516',
'Go': '#00ADD8',
'Rust': '#dea584',
'Swift': '#ffac45',
'Kotlin': '#F18E33',
'Scala': '#c22d40',
'Shell': '#89e051',
'HTML': '#e34c26',
'CSS': '#563d7c',
'Vue': '#2c3e50',
'React': '#61dafb',
'Dockerfile': '#384d54',
'Markdown': '#083fa1'
};
return colors[language] || '#586069';
}

View File

@ -0,0 +1,167 @@
let widgetsInitialized = new Set();
function initializeGitHubWidgets() {
const widgets = document.querySelectorAll('.github-widget');
widgets.forEach(widget => {
// Skip if already initialized
const widgetId = widget.dataset.repo + '-' + Math.random().toString(36).substr(2, 9);
if (widget.dataset.initialized) return;
widget.dataset.initialized = 'true';
const repo = widget.dataset.repo;
// Auto-generate data file path from repo name
const dataFile = `/assets/repo-data/${repo.replace('/', '-')}.json`;
const showDescription = widget.dataset.showDescription !== 'false';
const showLanguage = widget.dataset.showLanguage !== 'false';
const showLastUpdate = widget.dataset.showLastUpdate !== 'false';
// Show loading state
widget.innerHTML = `
<div class="github-widget-loading">
<div class="loading-spinner"></div>
<span>Loading ${repo}...</span>
</div>
`;
// Fetch repository data from pre-generated JSON file
fetch(dataFile)
.then(response => {
if (!response.ok) {
throw new Error(`Could not load data for ${repo}`);
}
return response.json();
})
.then(data => {
const lastUpdate = new Date(data.updated_at).toLocaleDateString();
const language = data.language || 'Not specified';
widget.innerHTML = `
<div class="github-widget-container">
<div class="github-widget-header">
<div class="github-widget-title">
<svg class="github-icon" viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
</svg>
<a href="${data.html_url}" target="_blank" rel="noopener noreferrer" class="repo-link">
${data.full_name}
</a>
</div>
<div class="github-widget-stats">
<span class="stat-item" title="Stars">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z"/>
</svg>
${data.stars_count.toLocaleString()}
</span>
<span class="stat-item" title="Forks">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25V5.372a2.25 2.25 0 10-1.5 0v.878A.75.75 0 0110.25 7H5.75A.75.75 0 015 6.25v-.878zm3.75 7.378a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm3-8.75a.75.75 0 100-1.5.75.75 0 000 1.5z"/>
</svg>
${data.forks_count.toLocaleString()}
</span>
<span class="stat-item" title="Open Issues">
<svg viewBox="0 0 16 16" width="14" height="14">
<path fill="currentColor" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"/>
<path fill="currentColor" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"/>
</svg>
${data.open_issues_count.toLocaleString()}
</span>
</div>
</div>
${showDescription && data.description ? `
<div class="github-widget-description">
${data.description}
</div>
` : ''}
<div class="github-widget-footer">
${showLanguage ? `
<span class="language-info">
<span class="language-dot" style="background-color: ${getLanguageColor(language)}"></span>
${language}
</span>
` : ''}
${showLastUpdate ? `
<span class="last-update">Updated ${lastUpdate}</span>
` : ''}
${data.license ? `
<span class="license-info">${data.license.spdx_id || data.license.name}</span>
` : ''}
</div>
</div>
`;
})
.catch(error => {
console.error('Error loading repository data:', error);
widget.innerHTML = `
<div class="github-widget-error">
<svg viewBox="0 0 16 16" width="16" height="16">
<path fill="currentColor" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"/>
</svg>
<span>Failed to load ${repo}</span>
<small>${error.message}</small>
</div>
`;
});
});
}
// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', initializeGitHubWidgets);
// Watch for DOM changes (MkDocs Material dynamic content)
const observer = new MutationObserver((mutations) => {
let shouldReinitialize = false;
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
// Check if any github-widget elements were added
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1 && // Element node
(node.classList?.contains('github-widget') ||
node.querySelector?.('.github-widget'))) {
shouldReinitialize = true;
}
});
}
});
if (shouldReinitialize) {
// Small delay to ensure DOM is stable
setTimeout(initializeGitHubWidgets, 100);
}
});
// Start observing
observer.observe(document.body, {
childList: true,
subtree: true
});
// Language color mapping (simplified version)
function getLanguageColor(language) {
const colors = {
'JavaScript': '#f1e05a',
'TypeScript': '#2b7489',
'Python': '#3572A5',
'Java': '#b07219',
'C++': '#f34b7d',
'C': '#555555',
'C#': '#239120',
'PHP': '#4F5D95',
'Ruby': '#701516',
'Go': '#00ADD8',
'Rust': '#dea584',
'Swift': '#ffac45',
'Kotlin': '#F18E33',
'Scala': '#c22d40',
'Shell': '#89e051',
'HTML': '#e34c26',
'CSS': '#563d7c',
'Vue': '#2c3e50',
'React': '#61dafb',
'Dockerfile': '#384d54'
};
return colors[language] || '#586069';
}

View File

@ -34,4 +34,189 @@ document.addEventListener('DOMContentLoaded', function() {
style.textContent = '*, *::before, *::after { animation: none !important; transition: none !important; }';
document.head.appendChild(style);
}
});
});
// Changemaker Lite - Smooth Grid Interactions
document.addEventListener('DOMContentLoaded', function() {
// Smooth scroll for anchors
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
// Add stagger animation to grid cards on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}, index * 50);
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe all grid cards
document.querySelectorAll('.grid-card').forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
observer.observe(card);
});
// Neon hover effect for service cards
document.querySelectorAll('.service-card').forEach(card => {
card.addEventListener('mouseenter', function(e) {
const rect = this.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ripple = document.createElement('div');
ripple.style.position = 'absolute';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
ripple.style.width = '0';
ripple.style.height = '0';
ripple.style.borderRadius = '50%';
ripple.style.background = 'rgba(91, 206, 250, 0.3)';
ripple.style.transform = 'translate(-50%, -50%)';
ripple.style.pointerEvents = 'none';
ripple.style.transition = 'width 0.6s, height 0.6s, opacity 0.6s';
this.appendChild(ripple);
setTimeout(() => {
ripple.style.width = '200px';
ripple.style.height = '200px';
ripple.style.opacity = '0';
}, 10);
setTimeout(() => {
ripple.remove();
}, 600);
});
});
// Animated counter for stats
const animateValue = (element, start, end, duration) => {
const range = end - start;
const increment = range / (duration / 16);
let current = start;
const timer = setInterval(() => {
current += increment;
if (current >= end) {
current = end;
clearInterval(timer);
}
element.textContent = Math.round(current);
}, 16);
};
// Animate stat numbers on scroll
const statObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const statNumber = entry.target.querySelector('.stat-number');
if (statNumber && !statNumber.animated) {
statNumber.animated = true;
const value = parseInt(statNumber.textContent);
if (!isNaN(value)) {
statNumber.textContent = '0';
animateValue(statNumber, 0, value, 1000);
}
}
statObserver.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll('.stat-item').forEach(stat => {
statObserver.observe(stat);
});
// Add parallax effect to hero section
let ticking = false;
function updateParallax() {
const scrolled = window.pageYOffset;
const hero = document.querySelector('.hero-grid');
if (hero) {
hero.style.transform = `translateY(${scrolled * 0.3}px)`;
}
ticking = false;
}
function requestTick() {
if (!ticking) {
window.requestAnimationFrame(updateParallax);
ticking = true;
}
}
// Only add parallax on desktop
if (window.innerWidth > 768) {
window.addEventListener('scroll', requestTick);
}
// Button ripple effect
document.querySelectorAll('.btn').forEach(button => {
button.addEventListener('click', function(e) {
const rect = this.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ripple = document.createElement('span');
ripple.style.position = 'absolute';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
ripple.className = 'btn-ripple';
this.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
});
});
// Reduced motion support
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.documentElement.style.scrollBehavior = 'auto';
window.removeEventListener('scroll', requestTick);
}
});
// Add CSS for button ripple
const style = document.createElement('style');
style.textContent = `
.btn-ripple {
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
background: rgba(111, 66, 193, 0.5); /* mkdocs purple */
transform: translate(-50%, -50%) scale(0);
animation: ripple-animation 0.6s ease-out;
pointer-events: none;
}
@keyframes ripple-animation {
to {
transform: translate(-50%, -50%) scale(10);
opacity: 0;
}
}
`;
document.head.appendChild(style);

View File

@ -1,233 +1,369 @@
{% extends "main.html" %}
{% block extrahead %}
{{ super() }}
<script>
{{ super() }}
<script>
// Add data attribute for CSS targeting
document.body.setAttribute('data-md-template', 'home');
</script>
</script>
{% endblock %}
{% block content %}
<div class="md-content--home">
<!-- Hero Grid Section -->
<section class="hero-grid">
<div class="grid-container">
<!-- Main Hero Block -->
<div class="hero-main">
<div class="meta-badge">🤯 This Site Runs On Changemaker Lite</div>
<h1>The Infrastructure That Runs Itself</h1>
<p>You're looking at Changemaker Lite right now. This entire documentation platform, our email campaigns, databases, and automation all run on the same $200 hardware we're selling you.</p>
<div class="self-hosting-proof">
<div class="proof-item">
<span class="proof-icon">🏠</span>
<span class="proof-text">This website</span>
</div>
<div class="proof-item">
<span class="proof-icon">📧</span>
<span class="proof-text">BNKops newsletters</span>
</div>
<div class="proof-item">
<span class="proof-icon">💾</span>
<span class="proof-text">Community database</span>
</div>
<div class="proof-item">
<span class="proof-icon">🔄</span>
<span class="proof-text">Automated workflows</span>
</div>
</div>
<div class="hero-ctas">
<a href="#video-demo" class="btn btn-primary">Watch It Work ▶️</a>
<a href="#get-started" class="btn btn-secondary">Get Started $200</a>
</div>
</div>
<!-- Video Demo Block -->
<div class="hero-video" id="video-demo">
<div class="video-placeholder">
<div class="video-icon">▶️</div>
<h3>See Changemaker Lite In Action</h3>
<p>3-minute demo of everything running on one box</p>
<!-- VIDEO PLACEHOLDER: Terminal demo showing docker compose ps, accessing services -->
</div>
</div>
<!-- Stats Block -->
<div class="hero-stats">
<div class="stat-item">
<div class="stat-number">$200</div>
<div class="stat-label">Total hardware cost</div>
</div>
<div class="stat-item">
<div class="stat-number">11</div>
<div class="stat-label">Services included</div>
</div>
<div class="stat-item">
<div class="stat-number">100%</div>
<div class="stat-label">Data ownership</div>
</div>
</div>
<!-- Trust Indicators -->
<div class="hero-trust">
<div class="trust-item">
<span class="trust-icon"></span>
<span class="trust-text">Powers BNKops.com</span>
</div>
<div class="trust-item">
<span class="trust-icon">🏳️‍⚧️</span>
<span class="trust-text">Trans liberation tech</span>
</div>
<div class="trust-item">
<span class="trust-icon">🛡️</span>
<span class="trust-text">Zero surveillance</span>
</div>
</div>
</div>
</section>
<!-- Hero Grid Section -->
<section class="hero-grid">
<div class="grid-container">
<!-- Main Hero Block -->
<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 Stack</h1>
<p>Stop paying thousands of dollars a month to corporate platforms just to be surveilled and your supports data sold to the highest bidder. Run your entire political campaign on ~$200 hardware and
with fewer corporate dependencies every day.</p>
<!-- Self-Hosting Proof Grid -->
<section class="proof-grid-section">
<div class="grid-container">
<div class="section-header">
<h2>What You're Looking At Right Now</h2>
<p>This entire platform runs on Changemaker Lite. We're not just selling it - we're living it.</p>
</div>
<div class="proof-grid-layout">
<!-- Backend Demo -->
<div class="proof-card">
<div class="proof-header">
<span class="proof-icon">🖥️</span>
<h3>Backend Demo</h3>
<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>
</div>
<div class="video-placeholder small">
<!-- VIDEO: Screen recording of homepage dashboard -->
<div class="video-icon">▶️</div>
<p>Homepage dashboard tour</p>
</div>
<p>Live view of all 11 services running on one box</p>
</div>
<!-- Email System -->
<div class="proof-card">
<div class="proof-header">
<span class="proof-icon">📧</span>
<h3>Email System</h3>
<!-- Problem Statement Block -->
<div class="hero-problem grid-card">
<h3>The Problem</h3>
<div class="problem-list">
<div class="problem-item">💸 Canvassing: $100+/mo</div>
<div class="problem-item">📊 Nationbuilder: $500+/mo</div>
<div class="problem-item">📧 Mailchimp: $200+/mo</div>
<div class="problem-item">👁️ Surveillance: Always on</div>
<div class="problem-item">🔒 Vendor lock-in: Trapped forever</div>
<div class="problem-item">📉 Data ownership: Not yours</div>
<div class="promlem-itme">😠 Implicitly Supporting Evil Corporations</div>
</div>
<div class="live-stats">
<div class="stat">2.3K subscribers</div>
<div class="stat">98% delivery rate</div>
</div>
<p>Listmonk powers all BNKops newsletters</p>
</div>
<!-- Database -->
<div class="proof-card">
<div class="proof-header">
<span class="proof-icon">💾</span>
<h3>Database</h3>
</div>
<div class="video-placeholder small">
<!-- VIDEO: Quick NocoDB demo -->
<div class="video-icon">▶️</div>
<p>NocoDB interface</p>
</div>
<p>Managing inquiries, contacts, projects</p>
</div>
<!-- Cost Savings -->
<div class="proof-card highlighted">
<div class="proof-header">
<span class="proof-icon">💰</span>
<h3>Our Savings</h3>
</div>
<div class="savings-breakdown">
<div class="savings-item">
<span class="corporate">Corporate SaaS: $1,200/mo</span>
<span class="ours">Changemaker: $50/mo</span>
<!-- Solution Stats Block -->
<div class="hero-stats grid-card">
<h3>The Solution</h3>
<div class="stat-grid">
<div class="stat-item">
<div class="stat-number">Runs on ~$200 Hardware</div>
<div class="stat-label">One-time cost</div>
</div>
<div class="stat-item">
<div class="stat-number">11</div>
<div class="stat-label">Campaign tools</div>
</div>
<div class="stat-item">
<div class="stat-number">Your Data</div>
<div class="stat-label">Localized & Secure</div>
</div>
<div class="stat-item">
<div class="stat-number"></div>
<div class="stat-label">Fewer corporate deps every day</div>
</div>
<div class="savings-total">Saving $13,800/year</div>
</div>
<p>Money that goes to organizing, not shareholders</p>
</div>
</div>
</div>
</section>
<!-- Hardware Options Grid -->
<section class="hardware-grid-section" id="get-started">
<div class="grid-container">
<div class="section-header">
<h2>Get The Same Setup</h2>
<p>Three ways to join the digital liberation movement</p>
</div>
<div class="hardware-options-grid">
<!-- Plug & Play -->
<div class="option-card featured">
<div class="option-badge">Recommended</div>
<div class="option-icon">🚀</div>
<h3>Plug & Play</h3>
<div class="option-price">$200</div>
<div class="option-features">
<div class="feature">✓ Pre-configured hardware</div>
<div class="feature">✓ 30-minute setup</div>
<div class="feature">✓ Everything included</div>
<div class="feature">✓ Priority support</div>
</div>
<a href="https://bnkops.com/hardware" class="btn btn-primary">Order Hardware</a>
<div class="option-note">Ships in 5 days</div>
</div>
<!-- DIY -->
<div class="option-card">
<div class="option-icon">🛠️</div>
<h3>DIY Install</h3>
<div class="option-price">Free</div>
<div class="option-features">
<div class="feature">✓ Use your hardware</div>
<div class="feature">✓ Learn the system</div>
<div class="feature">✓ Full control</div>
<div class="feature">✓ Community support</div>
</div>
<a href="/getting-started/" class="btn btn-secondary">Install Guide</a>
<div class="option-note">+$50/mo hosting</div>
</div>
<!-- Managed -->
<div class="option-card">
<div class="option-icon">☁️</div>
<h3>Managed Hosting</h3>
<div class="option-price">$150/mo</div>
<div class="option-features">
<div class="feature">✓ We handle everything</div>
<div class="feature">✓ Your domain</div>
<div class="feature">✓ Your data</div>
<div class="feature">✓ 24/7 monitoring</div>
</div>
<a href="https://bnkops.com/hosting" class="btn btn-secondary">Learn More</a>
<div class="option-note">Still your infrastructure</div>
</div>
</div>
<!-- Quick Setup Demo -->
<div class="setup-demo">
<h3>See The 30-Minute Setup</h3>
<div class="video-placeholder">
<!-- VIDEO: Time-lapse of complete setup process -->
<div class="video-icon">▶️</div>
<div class="video-meta">
<span>5:23</span>
<span>Time-lapse setup</span>
<!-- Trust Indicators -->
<div class="hero-trust grid-card">
<h3>Proven By</h3>
<div class="trust-items">
<div class="trust-item">
<span class="trust-icon"></span>
<span class="trust-text">Powers BNKops.com</span>
</div>
<div class="trust-item">
<span class="trust-icon"> 🌈 </span>
<span class="trust-text">Liberation tech</span>
</div>
<div class="trust-item">
<span class="trust-icon">🛡️</span>
<span class="trust-text">Zero surveillance</span>
</div>
<div class="trust-item">
<span class="trust-icon">🚀</span>
<span class="trust-text">30-min setup</span>
</div>
</div>
</div>
</div>
</div>
</section>
</section>
<!-- Solution Grid -->
<section class="solution-grid" id="solution">
<div class="grid-container">
<div class="section-header">
<h2>Your Complete Campaign Toolkit</h2>
<p>Simple, powerful tools designed for campaign staff - no technical skills needed</p>
</div>
<div class="services-grid">
<!-- Documentation Editor -->
<div class="service-card grid-card">
<div class="service-icon">✍️</div>
<h3>Campaign Content Editor</h3>
<div class="service-replaces">Replaces: Google Docs + WordPress (~$50/month)</div>
<ul class="service-features">
<li>Edit docs & blog posts</li>
<li>Live preview as you type</li>
<li>Simple formatting tools</li>
<li>Works in any browser</li>
</ul>
<div class="service-tool">Code Server</div>
</div>
<!-- Canvassing System -->
<div class="service-card grid-card featured">
<div class="service-badge">Field Team Essential</div>
<div class="service-icon">🚪</div>
<h3>Smart Canvassing</h3>
<div class="service-replaces">Replaces: Qumon (~$100+/mo)</div>
<ul class="service-features">
<li>Interactive voter maps</li>
<li>Track door knocks</li>
<li>Mobile-friendly</li>
<li>Works offline</li>
</ul>
<div class="service-tool">NocoDB + Map Viewer</div>
</div>
<!-- Email System -->
<div class="service-card grid-card">
<div class="service-icon">📩</div>
<h3>Email Blasts</h3>
<div class="service-replaces">Replaces: Mailchimp (~$200+/mo)</div>
<ul class="service-features">
<li>Simple email creator</li>
<li>Track opens/clicks</li>
<li>Unlimited subscribers</li>
<li>Pre-made templates</li>
</ul>
<div class="service-tool">Listmonk</div>
</div>
<!-- Voter Database -->
<div class="service-card grid-card">
<div class="service-icon">🗃️</div>
<h3>Voter Database</h3>
<div class="service-replaces">Replaces: NationBuilder (~$500+/mo)</div>
<ul class="service-features">
<li>Spreadsheet interface</li>
<li>Easy voter searches</li>
<li>Custom survey forms</li>
<li>Export walk lists</li>
</ul>
<div class="service-tool">NocoDB</div>
</div>
<!-- Automation -->
<div class="service-card grid-card">
<div class="service-icon">🤖</div>
<h3>Smart Automation</h3>
<div class="service-replaces">Replaces: Zapier (~$300/month)</div>
<ul class="service-features">
<li>Auto follow-up emails</li>
<li>Volunteer reminders</li>
<li>Donation thank yous</li>
<li>Pre-built workflows</li>
</ul>
<div class="service-tool">n8n</div>
</div>
<!-- Website -->
<div class="service-card grid-card">
<div class="service-icon">🌐</div>
<h3>Campaign Website</h3>
<div class="service-replaces">Replaces: Squarespace (~$100/month)</div>
<ul class="service-features">
<li>Pre-designed templates</li>
<li>Easy content updates</li>
<li>Built-in blog</li>
<li>Fast loading</li>
</ul>
<div class="service-tool">MkDocs</div>
</div>
<!-- Volunteer Management -->
<div class="service-card grid-card">
<div class="service-icon">👥</div>
<h3>Volunteer HQ</h3>
<div class="service-replaces">Replaces: Mobilize (~$200/month)</div>
<ul class="service-features">
<li>Shift scheduling</li>
<li>Automated reminders</li>
<li>Skills matching</li>
<li>Progress tracking</li>
</ul>
<div class="service-tool">NocoDB + n8n</div>
</div>
<!-- Linking Features -->
<div class="service-card grid-card">
<div class="service-icon">👀</div>
<h3> Mobile, Social, & Hot Link Friendly</h3>
<div class="service-replaces">Replaces: Linktree (~$20/month)</div>
<ul class="service-features">
<li>Automatic Social Cards</li>
<li>Hot Linking to All Assets & Headers</li>
<li>Documentation Indexing & Search</li>
<li>Progress tracking</li>
</ul>
<div class="service-tool">NocoDB + n8n</div>
</div>
<!-- Rapid Response -->
<div class="service-card grid-card">
<div class="service-icon"></div>
<h3>Rapid Response</h3>
<div class="service-replaces">Replaces: Slack + Google Docs (~$50/month)</div>
<ul class="service-features">
<li>Real-time collaboration</li>
<li>Community Editing</li>
<li>Open source documentation</li>
<li>Version control</li>
</ul>
<div class="service-tool">Code Server + Gitea</div>
</div>
</div>
</div>
</section>
<!-- Comparison Grid -->
<section class="comparison-grid">
<div class="grid-container">
<div class="section-header">
<h2>Corporate SaaS vs Changemaker Lite</h2>
<p>Why campaigns are switching to self-hosted FOSS</p>
</div>
<div class="comparison-table">
<div class="comparison-header grid-card">
<div></div>
<div class="compare-col">Corporate SaaS</div>
<div class="compare-col highlight">Changemaker Lite</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Monthly Cost</div>
<div class="compare-value bad">$1,200+</div>
<div class="compare-value good">$0 Self-Hosted</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Data Ownership</div>
<div class="compare-value bad">Their servers</div>
<div class="compare-value good">100% yours</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Surveillance</div>
<div class="compare-value bad">Always tracked</div>
<div class="compare-value good">Zero tracking</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Vendor Lock-in</div>
<div class="compare-value bad">Trapped forever</div>
<div class="compare-value good">Export anytime</div>
</div>
<div class="comparison-row grid-card">
<div class="compare-label">Customization</div>
<div class="compare-value bad">Limited options</div>
<div class="compare-value good">Full control</div>
</div>
</div>
</div>
</section>
<!-- Get Started Grid -->
<section class="get-started-grid" id="get-started">
<div class="grid-container">
<div class="section-header">
<h2>Start Your Digital Liberation</h2>
<p>Three ways to break free from corporate campaign tech</p>
</div>
<div class="options-grid">
<!-- Plug & Play -->
<div class="option-card grid-card featured">
<div class="option-badge">Most Popular</div>
<div class="option-icon">🚀</div>
<h3>Plug & Play</h3>
<div class="option-price">~$400 (Built to Suit)</div>
<div class="option-features">
<div class="feature">✓ Pre-configured hardware</div>
<div class="feature">✓ 30-minute setup</div>
<div class="feature">✓ All 11 services ready</div>
<div class="feature">✓ Priority support</div>
<div class="feature">✓ Ships on request</div>
</div>
<a href="https://bnkops.com/hardware" class="btn btn-primary">Order Hardware</a>
</div>
<!-- DIY -->
<div class="option-card grid-card">
<div class="option-icon">🛠️</div>
<h3>DIY Install</h3>
<div class="option-price">Free</div>
<div class="option-features">
<div class="feature">✓ Use your hardware</div>
<div class="feature">✓ Docker compose</div>
<div class="feature">✓ Full documentation</div>
<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>
</div>
<!-- Managed -->
<div class="option-card grid-card">
<div class="option-icon">☁️</div>
<h3>Managed Hosting</h3>
<div class="option-price">$???/mo</div>
<div class="option-features">
<div class="feature">✓ We manage everything</div>
<div class="feature">✓ Your domain</div>
<div class="feature">✓ Daily backups</div>
<div class="feature">✓ 24/7 monitoring</div>
<div class="feature">✓ Still your data</div>
</div>
<a href="https://bnkops.com" class="btn btn-secondary">Learn More</a>
</div>
</div>
<!-- Cards in a row -->
<div class="row-cards">
<div class="final-cta grid-card">
<h3>Join the Movement</h3>
<p>Some of the biggest players in local politics are already using it; maybe give it a try?</p>
<div class="cta-buttons">
<a href="https://bnkops.com/newsletter" class="btn btn-primary">Get Campaign Tips</a>
<a href="https://docs.bnkops.com" class="btn btn-secondary">Read Documentation</a>
</div>
</div>
<div class="subscribe-card grid-card">
<h3>Subscribe</h3>
<form action="https://newsletter.bnkops.com/subscription/form" method="POST" target="_blank"
autocomplete="off">
<input type="hidden" name="nonce">
<p>
<input type="email" name="email" required placeholder="E-mail">
</p>
<p>
<input type="text" name="name" placeholder="Name (optional)">
</p>
<p>
<input id="48b84" type="checkbox" name="l" checked
value="48b841e7-841b-458b-95f8-63903a1c0912">
<label for="48b84">~ Weekly Updates</label>
</p>
<input type="submit" value="Subscribe" class="action-btn primary">
</form>
</div>
</div>
</div>
</section>
</div>
{% endblock %}
{% endblock %}

View File

@ -12,13 +12,13 @@
<meta name="author" content="Bunker Operations">
<link rel="canonical" href="https://cmlite.org/philosophy/">
<link rel="canonical" href="https://cmlite.org/phil/">
<link rel="prev" href="../getting-started/">
<link rel="prev" href="..">
<link rel="next" href="../cost-comparison/">
<link rel="next" href="../build/">
<link rel="icon" href="../assets/images/favicon.png">
@ -26,7 +26,7 @@
<title>Philosophy - Changemaker Lite</title>
<title>Philosophy: Your Secrets, Your Power, Your Movement - Changemaker Lite</title>
@ -65,11 +65,11 @@
<meta property="og:type" content="website" >
<meta property="og:title" content="Philosophy - Changemaker Lite" >
<meta property="og:title" content="Philosophy: Your Secrets, Your Power, Your Movement - Changemaker Lite" >
<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/philosophy.png" >
<meta property="og:image" content="https://cmlite.org/assets/images/social/phil/index.png" >
<meta property="og:image:type" content="image/png" >
@ -77,15 +77,15 @@
<meta property="og:image:height" content="630" >
<meta property="og:url" content="https://cmlite.org/philosophy/" >
<meta property="og:url" content="https://cmlite.org/phil/" >
<meta name="twitter:card" content="summary_large_image" >
<meta name="twitter:title" content="Philosophy - Changemaker Lite" >
<meta name="twitter:title" content="Philosophy: Your Secrets, Your Power, Your Movement - Changemaker Lite" >
<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/philosophy.png" >
<meta name="twitter:image" content="https://cmlite.org/assets/images/social/phil/index.png" >
@ -165,7 +165,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Philosophy
Philosophy: Your Secrets, Your Power, Your Movement
</span>
</div>
@ -294,18 +294,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../getting-started/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,20 +318,21 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -356,47 +362,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../services/" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
<li class="md-tabs__item">
<a href="../blog/" class="md-tabs__link">
@ -489,493 +454,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Philosophy
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Philosophy
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="On this page">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
On this page
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#the-question-that-changes-everything" class="md-nav__link">
<span class="md-ellipsis">
The Question That Changes Everything
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#the-corporate-extraction-machine" class="md-nav__link">
<span class="md-ellipsis">
The Corporate Extraction Machine
</span>
</a>
<nav class="md-nav" aria-label="The Corporate Extraction Machine">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#how-they-hook-you" class="md-nav__link">
<span class="md-ellipsis">
How They Hook You
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#the-real-product" class="md-nav__link">
<span class="md-ellipsis">
The Real Product
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#the-bnkops-alternative" class="md-nav__link">
<span class="md-ellipsis">
The BNKops Alternative
</span>
</a>
<nav class="md-nav" aria-label="The BNKops Alternative">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#who-we-are" class="md-nav__link">
<span class="md-ellipsis">
Who We Are
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#our-principles" class="md-nav__link">
<span class="md-ellipsis">
Our Principles
</span>
</a>
<nav class="md-nav" aria-label="Our Principles">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#trans-liberation-first" class="md-nav__link">
<span class="md-ellipsis">
🏳️‍⚧️ Trans Liberation First
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#community-over-profit" class="md-nav__link">
<span class="md-ellipsis">
🤝 Community Over Profit
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#data-sovereignty" class="md-nav__link">
<span class="md-ellipsis">
⚡ Data Sovereignty
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#security-culture" class="md-nav__link">
<span class="md-ellipsis">
🔒 Security Culture
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#the-changemaker-difference" class="md-nav__link">
<span class="md-ellipsis">
The Changemaker Difference
</span>
</a>
<nav class="md-nav" aria-label="The Changemaker Difference">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#traditional-corporate-flow" class="md-nav__link">
<span class="md-ellipsis">
Traditional Corporate Flow
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#changemaker-flow" class="md-nav__link">
<span class="md-ellipsis">
Changemaker Flow
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#why-this-matters" class="md-nav__link">
<span class="md-ellipsis">
Why This Matters
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#the-philosophy-in-practice" class="md-nav__link">
<span class="md-ellipsis">
The Philosophy in Practice
</span>
</a>
<nav class="md-nav" aria-label="The Philosophy in Practice">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#security-culture-meets-technology" class="md-nav__link">
<span class="md-ellipsis">
Security Culture Meets Technology
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#community-technology" class="md-nav__link">
<span class="md-ellipsis">
Community Technology
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#prefigurative-politics" class="md-nav__link">
<span class="md-ellipsis">
Prefigurative Politics
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#common-questions" class="md-nav__link">
<span class="md-ellipsis">
Common Questions
</span>
</a>
<nav class="md-nav" aria-label="Common Questions">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#isnt-this-just-for-tech-people" class="md-nav__link">
<span class="md-ellipsis">
"Isn't this just for tech people?"
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#what-about-convenience" class="md-nav__link">
<span class="md-ellipsis">
"What about convenience?"
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cant-we-just-use-corporate-tools-carefully" class="md-nav__link">
<span class="md-ellipsis">
"Can't we just use corporate tools carefully?"
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#what-about-security" class="md-nav__link">
<span class="md-ellipsis">
"What about security?"
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#historical-context" class="md-nav__link">
<span class="md-ellipsis">
Historical Context
</span>
</a>
<nav class="md-nav" aria-label="Historical Context">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#learning-from-past-struggles" class="md-nav__link">
<span class="md-ellipsis">
Learning from Past Struggles
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#the-surveillance-capitalism-trap" class="md-nav__link">
<span class="md-ellipsis">
The Surveillance Capitalism Trap
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#taking-action" class="md-nav__link">
<span class="md-ellipsis">
Taking Action
</span>
</a>
<nav class="md-nav" aria-label="Taking Action">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#start-where-you-are" class="md-nav__link">
<span class="md-ellipsis">
Start Where You Are
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#build-community-capacity" class="md-nav__link">
<span class="md-ellipsis">
Build Community Capacity
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#connect-with-others" class="md-nav__link">
<span class="md-ellipsis">
Connect with Others
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#remember-why" class="md-nav__link">
<span class="md-ellipsis">
Remember Why
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#resources-for-deeper-learning" class="md-nav__link">
<span class="md-ellipsis">
Resources for Deeper Learning
</span>
</a>
<nav class="md-nav" aria-label="Resources for Deeper Learning">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#essential-reading" class="md-nav__link">
<span class="md-ellipsis">
Essential Reading
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#community-resources" class="md-nav__link">
<span class="md-ellipsis">
Community Resources
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#technical-learning" class="md-nav__link">
<span class="md-ellipsis">
Technical Learning
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -993,13 +472,167 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" checked>
<div class="md-nav__link md-nav__container">
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Philosophy
</span>
</a>
<label class="md-nav__link md-nav__link--active" for="__nav_2" id="__nav_2_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Philosophy
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="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/" class="md-nav__link">
<span class="md-ellipsis">
Who Reads Your Secrets
</span>
</a>
</li>
<li class="md-nav__item">
<a href="https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/How%20not%20to%20get%20got%20making%20content%20v2/" class="md-nav__link">
<span class="md-ellipsis">
How To Not Get Got Making Content
</span>
</a>
</li>
<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">
<span class="md-ellipsis">
Digital Organizing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="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" class="md-nav__link">
<span class="md-ellipsis">
What is Security Culture
</span>
</a>
</li>
</ul>
</nav>
</li>
@ -1028,12 +661,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="../services/" class="md-nav__link">
<a href="../build/" class="md-nav__link">
<span class="md-ellipsis">
Services
Getting Started
</span>
@ -1056,12 +689,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../cloudflare/" class="md-nav__link">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1227,9 +860,9 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#trans-liberation-first" class="md-nav__link">
<a href="#liberation-first" class="md-nav__link">
<span class="md-ellipsis">
🏳️‍⚧️ Trans Liberation First
🏳️‍⚧️ 🇵🇸 Liberation First
</span>
</a>
@ -1579,7 +1212,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<h3 id="who-we-are">Who We Are<a class="headerlink" href="#who-we-are" title="Permanent link">&para;</a></h3>
<p><strong>BNKops</strong> is a cooperative based in amiskwaciy-wâskahikan (Edmonton, Alberta) on Treaty 6 territory. We're not a corporation—we're a collective of skilled organizers, developers, and community builders who believe technology should serve liberation, not oppression.</p>
<h3 id="our-principles">Our Principles<a class="headerlink" href="#our-principles" title="Permanent link">&para;</a></h3>
<h4 id="trans-liberation-first">🏳️‍⚧️ Trans Liberation First<a class="headerlink" href="#trans-liberation-first" title="Permanent link">&para;</a></h4>
<h4 id="liberation-first">🏳️‍⚧️ 🇵🇸 Liberation First<a class="headerlink" href="#liberation-first" title="Permanent link">&para;</a></h4>
<p>Technology that centers the most marginalized voices and fights for collective liberation. Trans rights are human rights, and our tools reflect this commitment.</p>
<h4 id="community-over-profit">🤝 Community Over Profit<a class="headerlink" href="#community-over-profit" title="Permanent link">&para;</a></h4>
<p>We operate as a cooperative because we believe in shared ownership and democratic decision-making. No venture capitalists, no shareholders, no extraction.</p>
@ -1619,6 +1252,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<h2 id="common-questions">Common Questions<a class="headerlink" href="#common-questions" title="Permanent link">&para;</a></h2>
<h3 id="isnt-this-just-for-tech-people">"Isn't this just for tech people?"<a class="headerlink" href="#isnt-this-just-for-tech-people" title="Permanent link">&para;</a></h3>
<p><strong>No.</strong> We specifically designed Changemaker Lite for organizers, activists, and movement builders who may not have technical backgrounds. Our philosophy is that everyone deserves digital sovereignty, not just people with computer science degrees.</p>
<p>This is not to say that you won't need to learn! These tools are just that; tools. They have no fancy or white-labeled marketing and are technical in nature. You will need to learn to use them, just as any worker needs to learn the power tools they use on the job. </p>
<h3 id="what-about-convenience">"What about convenience?"<a class="headerlink" href="#what-about-convenience" title="Permanent link">&para;</a></h3>
<p>Corporate platforms are convenient because they've extracted billions of dollars from users to fund that convenience. When you own your tools, there's a learning curve—but it's the same learning curve as learning to organize, learning to build power, learning to create change.</p>
<h3 id="cant-we-just-use-corporate-tools-carefully">"Can't we just use corporate tools carefully?"<a class="headerlink" href="#cant-we-just-use-corporate-tools-carefully" title="Permanent link">&para;</a></h3>
@ -1718,7 +1352,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../getting-started/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Getting Started">
<a href=".." class="md-footer__link md-footer__link--prev" aria-label="Previous: Home">
<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>
@ -1728,20 +1362,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
Previous
</span>
<div class="md-ellipsis">
Getting Started
Home
</div>
</div>
</a>
<a href="../cost-comparison/" class="md-footer__link md-footer__link--next" aria-label="Next: Cost Comparison">
<a href="../build/" class="md-footer__link md-footer__link--next" aria-label="Next: Getting Started with Digital Liberation">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Cost Comparison
Getting Started with Digital Liberation
</div>
</div>
<div class="md-footer__button md-icon">
@ -1797,51 +1431,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1851,6 +1440,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../javascripts/home.js"></script>
<script src="../javascripts/github-widget.js"></script>
<script src="../javascripts/gitea-widget.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1028,6 +1083,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1036,12 +1197,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1239,7 +1400,8 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<h1 id="code-server">Code Server<a class="headerlink" href="#code-server" title="Permanent link">&para;</a></h1>
<p>Visual Studio Code in your browser for remote development.</p>
<div class="github-widget" data-repo="coder/code-server"></div>
<h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">&para;</a></h2>
<p>Code Server provides a full Visual Studio Code experience in your web browser, allowing you to develop from any device. It runs on your server and provides access to your development environment through a web interface.</p>
<h2 id="features">Features<a class="headerlink" href="#features" title="Permanent link">&para;</a></h2>
@ -1407,51 +1569,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1461,6 +1578,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1019,6 +1074,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1027,12 +1188,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1384,51 +1545,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1438,6 +1554,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1196,6 +1251,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1204,12 +1365,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1850,51 +2011,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1904,6 +2020,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -15,7 +15,7 @@
<link rel="canonical" href="https://cmlite.org/services/">
<link rel="prev" href="../cost-comparison/">
<link rel="prev" href="../build/build-server/">
<link rel="next" href="homepage/">
@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link md-nav__link--active" for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link md-nav__link--active" for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -897,6 +952,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -905,12 +1066,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../cloudflare/" class="md-nav__link">
<a href="../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1222,17 +1383,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<p>Changemaker Lite includes several powerful services that work together to provide a complete documentation and development platform. Each service is containerized and can be accessed through its dedicated port.</p>
<h2 id="available-services">Available Services<a class="headerlink" href="#available-services" title="Permanent link">&para;</a></h2>
<h3 id="code-server"><a href="code-server/">Code Server</a><a class="headerlink" href="#code-server" title="Permanent link">&para;</a></h3>
<p><strong>Port: 8888</strong> | Visual Studio Code in your browser for remote development
- Full IDE experience
- Extensions support
- Git integration
- Terminal access</p>
<p><strong>Port: 8888</strong> | Visual Studio Code in your browser for remote development</p>
<div class="github-widget" data-repo="coder/code-server"></div>
<ul>
<li>Full IDE experience</li>
<li>Extensions support</li>
<li>Git integration</li>
<li>Terminal access</li>
</ul>
<h3 id="listmonk"><a href="listmonk/">Listmonk</a><a class="headerlink" href="#listmonk" title="Permanent link">&para;</a></h3>
<p><strong>Port: 9000</strong> | Self-hosted newsletter and mailing list manager
- Email campaigns
- Subscriber management
- Analytics
- Template system</p>
<p><strong>Port: 9000</strong> | Self-hosted newsletter and mailing list manager</p>
<div class="github-widget" data-repo="knadh/listmonk"></div>
<ul>
<li>Email campaigns</li>
<li>Subscriber management</li>
<li>Analytics</li>
<li>Template system</li>
</ul>
<h3 id="postgresql"><a href="postgresql/">PostgreSQL</a><a class="headerlink" href="#postgresql" title="Permanent link">&para;</a></h3>
<p><strong>Port: 5432</strong> | Reliable database backend
- Data persistence for Listmonk
@ -1240,11 +1407,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
- High performance
- Backup and restore capabilities</p>
<h3 id="mkdocs-material"><a href="mkdocs/">MkDocs Material</a><a class="headerlink" href="#mkdocs-material" title="Permanent link">&para;</a></h3>
<p><strong>Port: 4000</strong> | Documentation site generator with live preview
- Material Design theme
- Live reload
- Search functionality
- Markdown support</p>
<p><strong>Port: 4000</strong> | Documentation site generator with live preview</p>
<div class="github-widget" data-repo="squidfunk/mkdocs-material"></div>
<ul>
<li>Material Design theme</li>
<li>Live reload</li>
<li>Search functionality</li>
<li>Markdown support</li>
</ul>
<h3 id="static-site-server"><a href="static-server/">Static Site Server</a><a class="headerlink" href="#static-site-server" title="Permanent link">&para;</a></h3>
<p><strong>Port: 4001</strong> | Nginx-powered static site hosting
- High-performance serving
@ -1252,23 +1422,32 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
- Caching and compression
- Security headers</p>
<h3 id="n8n"><a href="n8n/">n8n</a><a class="headerlink" href="#n8n" title="Permanent link">&para;</a></h3>
<p><strong>Port: 5678</strong> | Workflow automation tool
- Visual workflow editor
- 400+ integrations
- Custom code execution
- Webhook support</p>
<p><strong>Port: 5678</strong> | Workflow automation tool</p>
<div class="github-widget" data-repo="n8n-io/n8n"></div>
<ul>
<li>Visual workflow editor</li>
<li>400+ integrations</li>
<li>Custom code execution</li>
<li>Webhook support</li>
</ul>
<h3 id="nocodb"><a href="nocodb/">NocoDB</a><a class="headerlink" href="#nocodb" title="Permanent link">&para;</a></h3>
<p><strong>Port: 8090</strong> | No-code database platform
- Smart spreadsheet interface
- Form builder and API generation
- Real-time collaboration
- Multi-database support</p>
<p><strong>Port: 8090</strong> | No-code database platform</p>
<div class="github-widget" data-repo="nocodb/nocodb"></div>
<ul>
<li>Smart spreadsheet interface</li>
<li>Form builder and API generation</li>
<li>Real-time collaboration</li>
<li>Multi-database support</li>
</ul>
<h3 id="homepage"><a href="homepage/">Homepage</a><a class="headerlink" href="#homepage" title="Permanent link">&para;</a></h3>
<p><strong>Port: 3010</strong> | Modern dashboard for all services
- Service dashboard and monitoring
- Docker integration
- Customizable layout
- Quick search and bookmarks</p>
<p><strong>Port: 3010</strong> | Modern dashboard for all services</p>
<div class="github-widget" data-repo="gethomepage/homepage"></div>
<ul>
<li>Service dashboard and monitoring</li>
<li>Docker integration</li>
<li>Customizable layout</li>
<li>Quick search and bookmarks</li>
</ul>
<h2 id="service-architecture">Service Architecture<a class="headerlink" href="#service-architecture" title="Permanent link">&para;</a></h2>
<div class="language-text highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a>┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>│ Homepage │ │ Code Server │ │ MkDocs │
@ -1402,7 +1581,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../cost-comparison/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Cost Comparison">
<a href="../build/build-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>
@ -1412,7 +1591,7 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
Previous
</span>
<div class="md-ellipsis">
Cost Comparison
Build Server
</div>
</div>
</a>
@ -1481,51 +1660,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1535,6 +1669,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../javascripts/home.js"></script>
<script src="../javascripts/github-widget.js"></script>
<script src="../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1037,6 +1092,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1045,12 +1206,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1431,51 +1592,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1485,6 +1601,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1070,6 +1125,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1078,12 +1239,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1565,51 +1726,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1619,6 +1735,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -18,7 +18,7 @@
<link rel="prev" href="../map/">
<link rel="next" href="../../cloudflare/">
<link rel="next" href="../../config/">
<link rel="icon" href="../../assets/images/favicon.png">
@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1019,6 +1074,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1027,12 +1188,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1309,13 +1470,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<a href="../../cloudflare/" class="md-footer__link md-footer__link--next" aria-label="Next: Cloudflare Tunnels">
<a href="../../config/" class="md-footer__link md-footer__link--next" aria-label="Next: Configuration">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Cloudflare Tunnels
Configuration
</div>
</div>
<div class="md-footer__button md-icon">
@ -1371,51 +1532,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1425,6 +1541,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1094,6 +1149,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1102,12 +1263,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1587,51 +1748,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1641,6 +1757,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1172,6 +1227,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1180,12 +1341,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1527,6 +1688,8 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<h1 id="n8n">n8n<a class="headerlink" href="#n8n" title="Permanent link">&para;</a></h1>
<div class="github-widget" data-repo="n8n-io/n8n"></div>
<p>Workflow automation tool for connecting services and automating tasks.</p>
<h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">&para;</a></h2>
<p>n8n is a powerful workflow automation tool that allows you to connect various apps and services together. It provides a visual interface for creating automated workflows, making it easy to integrate different systems and automate repetitive tasks.</p>
@ -1777,51 +1940,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1831,6 +1949,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1163,6 +1218,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1171,12 +1332,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1756,51 +1917,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1810,6 +1926,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1103,6 +1158,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1111,12 +1272,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1569,51 +1730,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1623,6 +1739,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -295,17 +295,20 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../getting-started/" class="md-tabs__link">
<li class="md-tabs__item">
<a href="../../phil/" class="md-tabs__link">
Getting Started
Philosophy
</a>
</li>
</a>
</li>
@ -313,18 +316,23 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item">
<a href="../../philosophy/" class="md-tabs__link">
<li class="md-tabs__item md-tabs__item--active">
<a href="../../build/" class="md-tabs__link">
Philosophy
Getting Started
</a>
</li>
</a>
</li>
@ -351,49 +359,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-tabs__item md-tabs__item--active">
<a href="../" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../cloudflare/" class="md-tabs__link">
Cloudflare Tunnels
</a>
</li>
@ -491,31 +456,43 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../philosophy/" class="md-nav__link">
<li class="md-nav__item md-nav__item--pruned md-nav__item--nested">
<a href="../../phil/" class="md-nav__link">
<span class="md-ellipsis">
@ -524,29 +501,13 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</span>
</a>
</li>
<span class="md-nav__icon md-icon"></span>
</a>
<li class="md-nav__item">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cost Comparison
</span>
</a>
</li>
@ -565,22 +526,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
@ -606,7 +551,117 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../build/" class="md-nav__link ">
<span class="md-ellipsis">
Getting Started
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../build/build-server/" class="md-nav__link">
<span class="md-ellipsis">
Build Server
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" checked>
<div class="md-nav__link md-nav__container">
@ -623,14 +678,14 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="">
<label class="md-nav__link " for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Services
</label>
@ -1088,6 +1143,112 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
</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_4" >
<div class="md-nav__link md-nav__container">
<a href="../../config/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_3_4" id="__nav_3_4_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">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../config/cloudflare-config/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
@ -1096,12 +1257,12 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<li class="md-nav__item">
<a href="../../cloudflare/" class="md-nav__link">
<a href="../../cost-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Cloudflare Tunnels
Cost Comparison
</span>
@ -1558,51 +1719,6 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
<div class="md-consent__overlay"></div>
<aside class="md-consent__inner">
<form class="md-consent__form md-grid md-typeset" name="consent">
<h4>Cookie consent</h4>
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p>
<input class="md-toggle" type="checkbox" id="__settings" >
<div class="md-consent__settings">
<ul class="task-list">
</ul>
</div>
<div class="md-consent__controls">
<button class="md-button md-button--primary">Accept</button>
<label class="md-button" for="__settings">Manage settings</label>
</div>
</form>
</aside>
</div>
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.expand", "navigation.footer", "navigation.indexes", "navigation.instant", "navigation.instant.prefetch", "navigation.instant.progress", "navigation.path", "navigation.prune", "navigation.sections", "navigation.tabs", "navigation.tabs.sticky", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
@ -1612,6 +1728,10 @@ Changemaker Archive. <a href="https://docs.bnkops.com">Learn more</a>
<script src="../../javascripts/home.js"></script>
<script src="../../javascripts/github-widget.js"></script>
<script src="../../javascripts/gitea-widget.js"></script>
</body>
</html>

View File

@ -8,20 +8,32 @@
<loc>https://cmlite.org/cost-comparison/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/getting-started/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/philosophy/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/blog/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/cloudflare/</loc>
<loc>https://cmlite.org/build/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/build/build-server/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/config/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/config/cloudflare-config/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/phil/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>
<loc>https://cmlite.org/phil/who-reads-your-secrets/</loc>
<lastmod>2025-06-30</lastmod>
</url>
<url>

Binary file not shown.

View File

@ -0,0 +1,554 @@
.login-button {
display: inline-block;
padding: 2px 10px;
margin-left: auto; /* Push the button to the right */
margin-right: 10px;
background-color: hsl(315, 80%, 42%); /* Use a solid, high-contrast color */
color: #fff; /* Ensure text is white */
text-decoration: none;
border-radius: 4px;
font-weight: bold;
transition: background-color 0.2s ease;
font-size: 0.9em;
vertical-align: middle;
}
.login-button:hover {
background-color: #003c8f; /* Darker shade for hover */
text-decoration: none;
}
.git-code-button {
display: inline-block;
background: #30363d;
color: white !important;
padding: 0.6rem 1.2rem;
border-radius: 20px;
text-decoration: none;
font-size: 0.95rem;
font-weight: bold;
margin-left: 1rem;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
.git-code-button:hover {
background: #444d56;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
text-decoration: none;
}
.git-code-button .material-icons {
font-size: 1rem;
vertical-align: middle;
margin-right: 4px;
}
/* GitHub Widget Styles */
.github-widget {
margin: 1.5rem 0;
display: block;
}
.github-widget-container {
border: 1px solid rgba(var(--md-primary-fg-color--rgb), 0.15);
border-radius: 12px;
padding: 20px;
background: linear-gradient(135deg, var(--md-code-bg-color) 0%, rgba(var(--md-primary-fg-color--rgb), 0.03) 100%);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.github-widget-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, var(--md-primary-fg-color), var(--md-accent-fg-color));
border-radius: 12px 12px 0 0;
}
.github-widget-container:hover {
border-color: var(--md-accent-fg-color);
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.github-widget-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
flex-wrap: wrap;
gap: 12px;
}
.github-widget-title {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
min-width: 0;
}
.github-icon {
color: var(--md-default-fg-color--light);
flex-shrink: 0;
width: 20px;
height: 20px;
}
.github-widget .repo-link {
color: var(--md-accent-fg-color);
text-decoration: none;
font-weight: 600;
font-size: 16px;
transition: color 0.2s ease;
word-break: break-word;
}
.github-widget .repo-link:hover {
color: var(--md-primary-fg-color);
text-decoration: none;
}
.github-widget-stats {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
}
.stat-item {
display: flex;
align-items: center;
gap: 6px;
color: var(--md-default-fg-color);
font-size: 13px;
font-weight: 600;
background: rgba(var(--md-primary-fg-color--rgb), 0.08);
padding: 4px 8px;
border-radius: 16px;
transition: all 0.2s ease;
}
.stat-item:hover {
background: rgba(var(--md-accent-fg-color--rgb), 0.15);
transform: scale(1.05);
}
.stat-item svg {
color: var(--md-accent-fg-color);
width: 14px;
height: 14px;
}
.github-widget-description {
color: var(--md-default-fg-color--light);
margin-bottom: 16px;
line-height: 1.5;
font-size: 14px;
font-style: italic;
padding: 12px;
background: rgba(var(--md-default-fg-color--rgb), 0.03);
border-radius: 8px;
border-left: 3px solid var(--md-accent-fg-color);
}
.github-widget-footer {
display: flex;
gap: 20px;
align-items: center;
font-size: 12px;
color: var(--md-default-fg-color--lighter);
border-top: 1px solid rgba(var(--md-default-fg-color--rgb), 0.1);
padding-top: 16px;
margin-top: 16px;
flex-wrap: wrap;
}
.language-info {
display: flex;
align-items: center;
gap: 6px;
}
.language-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
}
.last-update,
.license-info {
color: var(--md-default-fg-color--lighter);
}
/* Loading State */
.github-widget-loading {
display: flex;
align-items: center;
gap: 12px;
padding: 20px;
color: var(--md-default-fg-color--light);
justify-content: center;
}
.loading-spinner {
width: 20px;
height: 20px;
border: 2px solid var(--md-default-fg-color--lightest);
border-top: 2px solid var(--md-accent-fg-color);
border-radius: 50%;
animation: github-widget-spin 1s linear infinite;
}
@keyframes github-widget-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Error State */
.github-widget-error {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 20px;
color: var(--md-typeset-color);
text-align: center;
background: var(--md-code-bg-color);
border: 1px solid #f85149;
border-radius: 6px;
}
.github-widget-error svg {
color: #f85149;
}
.github-widget-error small {
color: var(--md-default-fg-color--lighter);
font-size: 11px;
}
/* Dark mode specific adjustments */
[data-md-color-scheme="slate"] .github-widget-container {
background: var(--md-code-bg-color);
border-color: #30363d;
}
[data-md-color-scheme="slate"] .github-widget-container:hover {
border-color: var(--md-accent-fg-color);
}
/* Multiple widgets in a row */
.github-widgets-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.github-widgets-row .github-widget {
margin: 0;
}
/* Compact widget variant */
.github-widget.compact .github-widget-container {
padding: 12px;
}
.github-widget.compact .github-widget-header {
margin-bottom: 8px;
}
.github-widget.compact .github-widget-description {
display: none;
}
.github-widget.compact .github-widget-footer {
margin-top: 8px;
padding-top: 8px;
}
/* GitHub Widget Responsive - placed after existing mobile styles */
@media (max-width: 768px) {
.github-widget-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.github-widget-stats {
gap: 12px;
}
.github-widget-footer {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}
/* Gitea Widget Styles */
.gitea-widget {
margin: 1.5rem 0;
display: block;
}
.gitea-widget-container {
border: 1px solid rgba(var(--md-primary-fg-color--rgb), 0.15);
border-radius: 12px;
padding: 20px;
background: linear-gradient(135deg, var(--md-code-bg-color) 0%, rgba(var(--md-primary-fg-color--rgb), 0.03) 100%);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.gitea-widget-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, #609926, #89c442);
border-radius: 12px 12px 0 0;
}
.gitea-widget-container:hover {
border-color: #89c442;
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.gitea-widget-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
flex-wrap: wrap;
gap: 12px;
}
.gitea-widget-title {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
min-width: 0;
}
.gitea-icon {
color: #89c442;
flex-shrink: 0;
width: 20px;
height: 20px;
}
.gitea-widget .repo-link {
color: #89c442;
text-decoration: none;
font-weight: 600;
font-size: 16px;
transition: color 0.2s ease;
word-break: break-word;
}
.gitea-widget .repo-link:hover {
color: #609926;
text-decoration: none;
}
.gitea-widget-stats {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
}
.gitea-widget .stat-item {
display: flex;
align-items: center;
gap: 6px;
color: var(--md-default-fg-color);
font-size: 13px;
font-weight: 600;
background: rgba(137, 196, 66, 0.1);
padding: 4px 8px;
border-radius: 16px;
transition: all 0.2s ease;
}
.gitea-widget .stat-item:hover {
background: rgba(137, 196, 66, 0.2);
transform: scale(1.05);
}
.gitea-widget .stat-item svg {
color: #89c442;
width: 14px;
height: 14px;
}
.gitea-widget-description {
color: var(--md-default-fg-color--light);
margin-bottom: 16px;
line-height: 1.5;
font-size: 14px;
font-style: italic;
padding: 12px;
background: rgba(var(--md-default-fg-color--rgb), 0.03);
border-radius: 8px;
border-left: 3px solid #89c442;
}
.gitea-widget-footer {
display: flex;
gap: 20px;
align-items: center;
font-size: 12px;
color: var(--md-default-fg-color--lighter);
border-top: 1px solid rgba(var(--md-default-fg-color--rgb), 0.1);
padding-top: 16px;
margin-top: 16px;
flex-wrap: wrap;
}
.gitea-widget .language-info {
display: flex;
align-items: center;
gap: 6px;
}
.gitea-widget .language-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
}
.gitea-widget .last-update,
.gitea-widget .license-info {
color: var(--md-default-fg-color--lighter);
}
/* Gitea Loading State */
.gitea-widget-loading {
display: flex;
align-items: center;
gap: 12px;
padding: 20px;
color: var(--md-default-fg-color--light);
justify-content: center;
}
.gitea-widget-loading .loading-spinner {
width: 20px;
height: 20px;
border: 2px solid var(--md-default-fg-color--lightest);
border-top: 2px solid #89c442;
border-radius: 50%;
animation: gitea-widget-spin 1s linear infinite;
}
@keyframes gitea-widget-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Gitea Error State */
.gitea-widget-error {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 20px;
color: var(--md-typeset-color);
text-align: center;
background: var(--md-code-bg-color);
border: 1px solid #f85149;
border-radius: 6px;
}
.gitea-widget-error svg {
color: #f85149;
}
.gitea-widget-error small {
color: var(--md-default-fg-color--lighter);
font-size: 11px;
}
/* Dark mode specific adjustments for Gitea */
[data-md-color-scheme="slate"] .gitea-widget-container {
background: var(--md-code-bg-color);
border-color: #30363d;
}
[data-md-color-scheme="slate"] .gitea-widget-container:hover {
border-color: #89c442;
}
/* Multiple Gitea widgets in a row */
.gitea-widgets-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.gitea-widgets-row .gitea-widget {
margin: 0;
}
/* Compact Gitea widget variant */
.gitea-widget.compact .gitea-widget-container {
padding: 12px;
}
.gitea-widget.compact .gitea-widget-header {
margin-bottom: 8px;
}
.gitea-widget.compact .gitea-widget-description {
display: none;
}
.gitea-widget.compact .gitea-widget-footer {
margin-top: 8px;
padding-top: 8px;
}
/* Gitea Widget Responsive */
@media (max-width: 768px) {
.gitea-widget-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.gitea-widget-stats {
gap: 12px;
}
.gitea-widget-footer {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}

View File

@ -0,0 +1,723 @@
/* Changemaker Lite - Ultra-Tight Grid System */
/* Homepage-specific variables */
.md-content--home {
/* Trans flag colors with neon glow variants */
--mkdocs-purple: #6f42c1;
--mkdocs-purple-dark: #3d2064;
--trans-blue: var(--mkdocs-purple); /* override for main accent */
--trans-pink: #F5A9B8;
--trans-white: #FFFFFF;
--trans-white-dim: #E0E0E0;
/* Dark theme colors */
--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;
/* Grid colors */
--grid-primary: var(--trans-blue);
--grid-secondary: var(--trans-pink);
--grid-accent: var(--trans-white);
--grid-border: rgba(91, 206, 250, 0.2);
/* Neon effects - optimized for grid density */
--neon-blue-shadow: 0 0 8px rgba(91, 206, 250, 0.6);
--neon-pink-shadow: 0 0 8px rgba(245, 169, 184, 0.6);
--neon-white-shadow: 0 0 6px rgba(255, 255, 255, 0.4);
/* Tight spacing for maximum content density */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 0.75rem;
--space-lg: 1rem;
--space-xl: 1.5rem;
--space-2xl: 2rem;
/* Compact typography */
--text-xs: 0.7rem;
--text-sm: 0.8rem;
--text-base: 0.9rem;
--text-lg: 1rem;
--text-xl: 1.1rem;
--text-2xl: 1.3rem;
--text-3xl: 1.8rem;
--text-4xl: 2.2rem;
/* Layout */
--home-radius: 8px;
--home-max-width: 1400px;
--grid-gap: var(--space-sm);
--card-padding: var(--space-md);
}
/* Homepage body setup */
body[data-md-template="home"] {
background: var(--home-dark-bg);
margin: 0;
padding: 0;
overflow-x: hidden;
}
/* Hide MkDocs chrome completely */
body[data-md-template="home"] .md-header,
body[data-md-template="home"] .md-tabs,
body[data-md-template="home"] .md-sidebar,
body[data-md-template="home"] .md-footer,
body[data-md-template="home"] .md-footer-meta {
display: none !important;
}
body[data-md-template="home"] .md-content {
padding: 0 !important;
margin: 0 !important;
}
body[data-md-template="home"] .md-main__inner {
margin: 0 !important;
max-width: none !important;
}
/* Homepage content wrapper */
.md-content--home {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: var(--home-dark-text);
background: var(--home-dark-bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
min-height: 100vh;
line-height: 1.4;
}
/* =================================
ULTRA-TIGHT GRID SYSTEM
================================= */
.grid-container {
max-width: 1200px;
margin: 0 auto;
padding: var(--space-sm);
display: grid;
gap: var(--space-xs);
}
.grid-card {
background: var(--home-dark-card);
border: 1px solid var(--grid-border);
border-radius: 4px;
padding: var(--space-md);
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}
.grid-card::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, var(--trans-blue), transparent);
transition: left 0.5s ease;
}
.grid-card:hover::before {
left: 100%;
}
.grid-card:hover {
border-color: var(--trans-blue);
box-shadow: 0 0 15px rgba(91, 206, 250, 0.3);
transform: translateY(-1px);
}
/* =================================
HERO GRID - ULTRA COMPACT
================================= */
.hero-grid {
padding: var(--space-md) 0;
background: linear-gradient(180deg, var(--home-dark-bg) 0%, var(--home-dark-surface) 100%);
}
.hero-grid .grid-container {
grid-template-columns: 2fr 1fr;
grid-template-rows: auto auto;
grid-template-areas:
"hero-main hero-problem"
"hero-stats hero-trust";
gap: var(--space-sm);
}
.hero-main {
grid-area: hero-main;
}
.hero-problem {
grid-area: hero-problem;
}
.hero-stats {
grid-area: hero-stats;
}
.hero-trust {
grid-area: hero-trust;
}
/* Neon badge animation */
.meta-badge {
background: linear-gradient(135deg, var(--trans-blue), var(--trans-pink));
color: #000;
font-size: 0.7rem;
font-weight: 700;
padding: 0.2rem 0.8rem;
border-radius: 20px;
display: inline-block;
margin-bottom: var(--space-sm);
animation: neon-pulse 2s ease-in-out infinite;
}
@keyframes neon-pulse {
0%, 100% {
box-shadow: 0 0 5px rgba(91, 206, 250, 0.8),
0 0 10px rgba(91, 206, 250, 0.6),
0 0 15px rgba(91, 206, 250, 0.4);
}
50% {
box-shadow: 0 0 10px rgba(245, 169, 184, 0.8),
0 0 20px rgba(245, 169, 184, 0.6),
0 0 30px rgba(245, 169, 184, 0.4);
}
}
.hero-main h1 {
font-size: 2rem;
font-weight: 800;
margin: 0 0 var(--space-sm) 0;
line-height: 1.1;
background: linear-gradient(135deg, var(--trans-white), var(--trans-blue));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
animation: text-glow 3s ease-in-out infinite;
}
@keyframes text-glow {
0%, 100% { filter: brightness(1); }
50% { filter: brightness(1.2); }
}
.hero-main p {
font-size: 0.9rem;
color: var(--home-dark-text-muted);
margin: 0 0 var(--space-lg) 0;
line-height: 1.4;
}
.hero-ctas {
display: flex;
gap: var(--space-sm);
}
/* Problem/Solution blocks */
.hero-problem h3,
.hero-stats h3,
.hero-trust h3 {
font-size: 0.9rem;
margin: 0 0 var(--space-sm) 0;
color: var(--trans-blue);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.problem-list {
display: flex;
flex-direction: column;
gap: var(--space-xs);
}
.problem-item {
font-size: 0.8rem;
color: var(--home-dark-text-muted);
padding: var(--space-xs);
background: var(--home-dark-surface);
border-radius: 2px;
}
.stat-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-xs);
}
.stat-item {
text-align: center;
padding: var(--space-xs);
background: var(--home-dark-surface);
border-radius: 2px;
}
.stat-number {
font-size: 1.2rem;
font-weight: 700;
color: var(--trans-pink);
margin: 0;
animation: number-glow 4s ease-in-out infinite;
}
@keyframes number-glow {
0%, 100% { text-shadow: 0 0 5px rgba(91, 206, 250, 0.5); }
50% { text-shadow: 0 0 10px rgba(91, 206, 250, 0.8); }
}
.stat-label {
font-size: 0.65rem;
color: var(--home-dark-text-muted);
margin: 0;
}
.trust-items {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-xs);
}
.trust-item {
display: flex;
align-items: center;
gap: var(--space-xs);
font-size: 0.7rem;
padding: var(--space-xs);
background: var(--home-dark-surface);
border-radius: 2px;
}
/* =================================
SERVICES GRID - ULTRA COMPACT
================================= */
.solution-grid {
padding: var(--space-lg) 0;
border-top: 1px solid var(--grid-border);
}
.section-header {
text-align: center;
margin-bottom: var(--space-lg);
position: relative;
z-index: 10;
}
.section-header h2 {
font-size: 1.8rem;
font-weight: 700;
margin: 0 0 var(--space-xs) 0;
color: var(--home-dark-text);
}
.section-header p {
font-size: 0.9rem;
color: var(--home-dark-text-muted);
margin: 0;
}
.services-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: var(--space-sm);
}
.service-card {
text-align: center;
cursor: pointer;
}
.service-card:hover .service-icon {
animation: icon-bounce 0.5s ease;
}
@keyframes icon-bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.service-icon {
font-size: 2rem;
margin-bottom: var(--space-xs);
}
.service-card h3 {
font-size: 0.9rem;
margin: 0 0 var(--space-xs) 0;
color: var(--home-dark-text);
}
.service-replaces {
font-size: 0.65rem;
color: var(--trans-pink);
margin-bottom: var(--space-sm);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.service-features {
list-style: none;
padding: 0;
margin: 0 0 var(--space-sm) 0;
font-size: 0.7rem;
color: var(--home-dark-text-muted);
}
.service-features li {
padding: 0.1rem 0;
}
.service-tool {
font-size: 0.75rem;
font-weight: 600;
color: var(--trans-blue);
padding: 0.2rem 0.5rem;
background: var(--home-dark-surface);
border-radius: 2px;
display: inline-block;
}
/* =================================
COMPARISON TABLE - GRID STYLE
================================= */
.comparison-grid {
padding: var(--space-lg) 0;
background: var(--home-dark-surface);
}
.comparison-table {
display: grid;
gap: var(--space-xs);
}
.comparison-header,
.comparison-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
align-items: center;
}
.comparison-header {
font-weight: 700;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.compare-col {
text-align: center;
padding: var(--space-sm);
}
.compare-col.highlight {
color: var(--trans-blue);
}
.comparison-row {
font-size: 0.8rem;
}
.compare-label {
padding: var(--space-sm);
font-weight: 600;
}
.compare-value {
text-align: center;
padding: var(--space-sm);
}
.compare-value.bad {
color: #ff6b6b;
}
.compare-value.good {
color: #4ecdc4;
font-weight: 600;
}
/* =================================
OPTIONS GRID - ULTRA COMPACT
================================= */
.get-started-grid {
padding: var(--space-lg) 0;
}
.options-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-sm);
margin-bottom: var(--space-lg);
}
.option-card {
text-align: center;
position: relative;
}
.option-card.featured {
border-color: var(--trans-blue);
animation: featured-glow 3s ease-in-out infinite;
}
@keyframes featured-glow {
0%, 100% {
box-shadow: 0 0 10px rgba(91, 206, 250, 0.4),
0 0 20px rgba(91, 206, 250, 0.2);
}
50% {
box-shadow: 0 0 20px rgba(91, 206, 250, 0.6),
0 0 30px rgba(91, 206, 250, 0.3);
}
}
.option-badge {
position: absolute;
top: -8px;
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;
}
.option-icon {
font-size: 2.5rem;
margin-bottom: var(--space-sm);
}
.option-card h3 {
font-size: 1.2rem;
margin: 0 0 var(--space-xs) 0;
color: var(--home-dark-text);
}
.option-price {
font-size: 2rem;
font-weight: 700;
color: var(--trans-blue);
margin-bottom: var(--space-sm);
}
.option-features {
margin-bottom: var(--space-lg);
text-align: left;
}
.feature {
padding: 0.2rem 0;
color: var(--home-dark-text-muted);
font-size: 0.75rem;
}
/* Final CTA */
.final-cta {
text-align: center;
padding: var(--space-xl);
}
.final-cta h3 {
font-size: 1.5rem;
margin: 0 0 var(--space-sm) 0;
color: var(--home-dark-text);
}
.final-cta p {
font-size: 0.9rem;
color: var(--home-dark-text-muted);
margin: 0 0 var(--space-lg) 0;
}
.cta-buttons {
display: flex;
gap: var(--space-sm);
justify-content: center;
}
/* =================================
BUTTONS - NEON STYLE
================================= */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.4rem 1rem;
font-size: 0.8rem;
font-weight: 600;
text-decoration: none;
border-radius: 4px;
transition: all 0.2s ease;
border: 1px solid transparent;
cursor: pointer;
min-width: 100px;
position: relative;
overflow: hidden;
color: var(--mkdocs-purple-dark);
}
.btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.btn:hover::before {
width: 300px;
height: 300px;
}
.btn-primary {
background: var(--mkdocs-purple);
color: var(--mkdocs-purple-dark);
border-color: var(--mkdocs-purple);
}
.btn-primary:hover {
background: var(--mkdocs-purple-dark);
color: #000;
box-shadow: 0 0 15px var(--mkdocs-purple);
transform: translateY(-1px);
}
.btn-secondary {
background: transparent;
color: var(--mkdocs-purple);
border-color: var(--mkdocs-purple);
}
.btn-secondary:hover {
background: var(--mkdocs-purple-dark);
color: #000;
box-shadow: 0 0 15px var(--mkdocs-purple);
}
/* =================================
RESPONSIVE - ULTRA TIGHT
================================= */
@media (max-width: 768px) {
.grid-container {
gap: var(--space-xs);
padding: var(--space-xs);
}
.hero-grid .grid-container {
grid-template-columns: 1fr;
grid-template-areas:
"hero-main"
"hero-problem"
"hero-stats"
"hero-trust";
}
.services-grid {
grid-template-columns: 1fr;
}
.comparison-header,
.comparison-row {
font-size: 0.7rem;
}
.options-grid {
grid-template-columns: 1fr;
}
.cta-buttons {
flex-direction: column;
}
.hero-main h1 {
font-size: 1.5rem;
}
}
@media (max-width: 480px) {
.grid-card {
padding: var(--space-sm);
}
.trust-items,
.stat-grid {
grid-template-columns: 1fr;
}
.service-card {
padding: var(--space-sm);
}
.hero-main h1 {
font-size: 1.3rem;
}
}
/* Row cards at bottom: two cards in a row on desktop, stack on mobile */
.row-cards {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-sm);
margin-top: var(--space-lg);
}
@media (max-width: 768px) {
.row-cards {
grid-template-columns: 1fr;
gap: var(--space-xs);
}
}
/* =================================
PERFORMANCE
================================= */
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
/* GPU acceleration */
.grid-card,
.btn {
will-change: transform;
backface-visibility: hidden;
}
/* Badge for FOSS First */
.badge-new {
display: inline-block;
background: var(--mkdocs-purple);
color: #fff;
font-size: 0.65em;
font-weight: 700;
border-radius: 8px;
padding: 0.1em 0.5em;
margin-left: 0.3em;
letter-spacing: 0.03em;
vertical-align: middle;
box-shadow: 0 0 6px var(--mkdocs-purple-dark);
}

View File

@ -1,871 +0,0 @@
/* Changemaker Lite - Homepage Specific Styles */
/* Only applies to pages using template: home.html */
/* Homepage-specific variables */
.md-content--home {
/* Trans flag colors with neon glow variants */
--trans-blue: #5BCEFA;
--trans-pink: #F5A9B8;
--trans-white: #FFFFFF;
--trans-white-dim: #E0E0E0;
/* Dark theme colors */
--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;
/* Neon effects - reduced for mobile performance */
--neon-blue-shadow: 0 0 10px rgba(91, 206, 250, 0.8);
--neon-pink-shadow: 0 0 10px rgba(245, 169, 184, 0.8);
--neon-white-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
/* Spacing scale */
--space-xs: 0.5rem;
--space-sm: 0.75rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 3rem;
--space-3xl: 4rem;
/* Typography scale */
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 2rem;
--text-4xl: 2.5rem;
--text-5xl: 3rem;
/* Layout */
--home-radius: 12px;
--home-max-width: 1200px;
}
/* Homepage body styles */
body[data-md-template="home"] {
background: var(--home-dark-bg, #0a0a0a);
}
/* Hide MkDocs chrome only on homepage */
body[data-md-template="home"] .md-header,
body[data-md-template="home"] .md-tabs,
body[data-md-template="home"] .md-sidebar,
body[data-md-template="home"] .md-footer,
body[data-md-template="home"] .md-footer-meta {
display: none !important;
}
body[data-md-template="home"] .md-content {
padding: 0 !important;
}
body[data-md-template="home"] .md-main__inner {
margin: 0 !important;
max-width: none !important;
}
/* Homepage content wrapper */
.md-content--home {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: var(--home-dark-text);
background: var(--home-dark-bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Container */
.md-content--home .container {
width: 100%;
max-width: var(--home-max-width);
margin: 0 auto;
padding: 0 var(--space-md);
}
/* Homepage Buttons */
.md-content--home .btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--space-sm) var(--space-lg);
font-size: var(--text-sm);
font-weight: 600;
text-decoration: none;
border-radius: var(--home-radius);
transition: all 0.2s ease;
border: 2px solid transparent;
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
white-space: nowrap;
}
.md-content--home .btn-large {
padding: var(--space-md) var(--space-xl);
font-size: var(--text-base);
}
.md-content--home .btn-block {
width: 100%;
}
.md-content--home .btn-primary {
background: var(--trans-blue);
color: var(--home-dark-bg);
border-color: var(--trans-blue);
box-shadow: var(--neon-blue-shadow);
}
.md-content--home .btn-primary:hover,
.md-content--home .btn-primary:active {
background: var(--trans-pink);
border-color: var(--trans-pink);
box-shadow: var(--neon-pink-shadow);
transform: translateY(-1px);
}
.md-content--home .btn-secondary {
background: transparent;
color: var(--trans-white);
border-color: var(--trans-white-dim);
}
.md-content--home .btn-secondary:hover,
.md-content--home .btn-secondary:active {
background: rgba(255, 255, 255, 0.1);
border-color: var(--trans-blue);
box-shadow: var(--neon-blue-shadow);
}
.md-content--home .btn-outline {
background: transparent;
color: var(--trans-blue);
border-color: var(--trans-blue);
}
.md-content--home .btn-outline:hover {
background: rgba(91, 206, 250, 0.1);
box-shadow: var(--neon-blue-shadow);
}
/* Hero Section */
.md-content--home .hero-section {
background: linear-gradient(180deg, var(--home-dark-bg) 0%, var(--home-dark-surface) 100%);
padding: var(--space-xl) 0 var(--space-2xl);
text-align: center;
position: relative;
overflow: hidden;
}
.md-content--home .hero-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, var(--trans-blue), var(--trans-pink), transparent);
animation: homepage-scanline 4s linear infinite;
}
@keyframes homepage-scanline {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.md-content--home .hero-badge {
display: inline-flex;
align-items: center;
gap: var(--space-xs);
padding: var(--space-xs) var(--space-md);
background: rgba(91, 206, 250, 0.1);
border: 1px solid var(--trans-blue);
border-radius: 50px;
margin-bottom: var(--space-lg);
font-size: var(--text-xs);
color: var(--trans-blue);
}
.md-content--home .badge-divider {
opacity: 0.5;
}
.md-content--home .hero-title {
font-size: clamp(var(--text-3xl), 8vw, var(--text-5xl));
font-weight: 900;
line-height: 1.1;
margin-bottom: var(--space-md);
background: linear-gradient(90deg, var(--trans-blue), var(--trans-pink), var(--trans-white));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
filter: drop-shadow(0 0 20px rgba(91, 206, 250, 0.5));
}
.md-content--home .hero-subtitle {
font-size: clamp(var(--text-base), 3vw, var(--text-lg));
color: var(--trans-white-dim);
max-width: 600px;
margin: 0 auto var(--space-xl);
padding: 0 var(--space-md);
}
/* Social Proof Grid */
.md-content--home .proof-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-md);
max-width: 400px;
margin: 0 auto var(--space-xl);
}
.md-content--home .proof-item {
text-align: center;
}
.md-content--home .proof-number {
font-size: var(--text-2xl);
font-weight: 700;
color: var(--trans-blue);
text-shadow: var(--neon-blue-shadow);
}
.md-content--home .proof-label {
font-size: var(--text-xs);
color: var(--home-dark-text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.md-content--home .hero-actions {
display: flex;
flex-direction: column;
gap: var(--space-sm);
align-items: center;
padding: 0 var(--space-md);
}
/* Results Bar */
.md-content--home .results-bar {
background: var(--home-dark-surface);
border-top: 1px solid var(--trans-blue);
border-bottom: 1px solid var(--trans-pink);
padding: var(--space-lg) 0;
}
.md-content--home .results-content {
display: flex;
align-items: center;
gap: var(--space-md);
text-align: center;
justify-content: center;
flex-wrap: wrap;
}
.md-content--home .results-icon {
font-size: var(--text-2xl);
filter: drop-shadow(0 0 10px var(--trans-pink));
}
.md-content--home .results-text {
font-size: var(--text-sm);
color: var(--home-dark-text);
margin: 0;
}
.md-content--home .results-link {
color: var(--trans-blue);
text-decoration: none;
border-bottom: 1px solid transparent;
transition: all 0.2s ease;
}
.md-content--home .results-link:hover {
border-bottom-color: var(--trans-blue);
text-shadow: var(--neon-blue-shadow);
}
/* Hardware Section */
.md-content--home .hardware-section {
padding: var(--space-2xl) 0;
background: var(--home-dark-bg);
}
.md-content--home .section-title {
font-size: clamp(var(--text-2xl), 5vw, var(--text-4xl));
font-weight: 700;
text-align: center;
margin-bottom: var(--space-sm);
color: var(--trans-white);
}
.md-content--home .section-subtitle {
font-size: var(--text-base);
text-align: center;
color: var(--home-dark-text-muted);
margin-bottom: var(--space-2xl);
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.md-content--home .hardware-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-lg);
margin-bottom: var(--space-xl);
}
.md-content--home .hardware-card {
background: var(--home-dark-card);
border: 1px solid var(--home-dark-border);
border-radius: var(--home-radius);
padding: var(--space-xl);
text-align: center;
position: relative;
transition: all 0.3s ease;
}
.md-content--home .hardware-featured {
border-color: var(--trans-blue);
box-shadow: 0 0 20px rgba(91, 206, 250, 0.2);
}
.md-content--home .hardware-ribbon {
position: absolute;
top: var(--space-md);
right: var(--space-md);
background: var(--trans-pink);
color: var(--home-dark-bg);
padding: var(--space-xs) var(--space-sm);
border-radius: 20px;
font-size: var(--text-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.md-content--home .hardware-icon {
font-size: var(--text-3xl);
margin-bottom: var(--space-md);
filter: drop-shadow(0 0 10px currentColor);
}
.md-content--home .hardware-card h3 {
font-size: var(--text-xl);
margin-bottom: var(--space-md);
color: var(--trans-white);
}
.md-content--home .hardware-price {
margin-bottom: var(--space-lg);
}
.md-content--home .price-amount {
font-size: var(--text-3xl);
font-weight: 700;
color: var(--trans-blue);
text-shadow: var(--neon-blue-shadow);
}
.md-content--home .price-period {
font-size: var(--text-sm);
color: var(--home-dark-text-muted);
}
.md-content--home .hardware-features {
list-style: none;
text-align: left;
margin-bottom: var(--space-lg);
padding: 0;
}
.md-content--home .hardware-features li {
padding: var(--space-xs) 0;
font-size: var(--text-sm);
color: var(--home-dark-text);
}
.md-content--home .hardware-note {
display: block;
margin-top: var(--space-sm);
font-size: var(--text-xs);
color: var(--home-dark-text-muted);
}
/* FOSS Section */
.md-content--home .foss-section {
background: var(--home-dark-surface);
padding: var(--space-2xl) 0;
text-align: center;
}
.md-content--home .foss-header {
margin-bottom: var(--space-2xl);
}
.md-content--home .foss-header h2 {
font-size: clamp(var(--text-2xl), 5vw, var(--text-3xl));
margin-bottom: var(--space-sm);
color: var(--trans-white);
}
.md-content--home .foss-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-lg);
margin-bottom: var(--space-xl);
}
.md-content--home .foss-card {
padding: var(--space-lg);
}
.md-content--home .foss-icon {
font-size: var(--text-3xl);
margin-bottom: var(--space-sm);
filter: drop-shadow(0 0 10px var(--trans-pink));
}
.md-content--home .foss-card h3 {
font-size: var(--text-lg);
margin-bottom: var(--space-xs);
color: var(--trans-white);
}
.md-content--home .foss-card p {
font-size: var(--text-sm);
color: var(--home-dark-text-muted);
}
/* Features Section */
.md-content--home .features-section {
padding: var(--space-2xl) 0;
background: var(--home-dark-bg);
}
.md-content--home .features-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-md);
margin-bottom: var(--space-2xl);
}
.md-content--home .feature-card {
background: var(--home-dark-card);
border: 1px solid var(--home-dark-border);
border-radius: var(--home-radius);
padding: var(--space-lg);
transition: all 0.3s ease;
}
.md-content--home .feature-card:hover {
border-color: var(--trans-blue);
box-shadow: 0 0 20px rgba(91, 206, 250, 0.2);
transform: translateY(-2px);
}
.md-content--home .feature-icon {
font-size: var(--text-2xl);
margin-bottom: var(--space-sm);
filter: drop-shadow(0 0 5px currentColor);
}
.md-content--home .feature-card h3 {
font-size: var(--text-lg);
margin-bottom: var(--space-xs);
color: var(--trans-white);
}
.md-content--home .feature-card p {
font-size: var(--text-sm);
color: var(--home-dark-text-muted);
margin-bottom: var(--space-md);
}
.md-content--home .feature-compare {
display: flex;
justify-content: space-between;
align-items: center;
font-size: var(--text-xs);
padding-top: var(--space-sm);
border-top: 1px solid var(--home-dark-border);
}
.md-content--home .compare-corp {
color: var(--trans-pink);
text-decoration: line-through;
opacity: 0.8;
}
.md-content--home .compare-us {
color: var(--trans-blue);
font-weight: 600;
text-shadow: var(--neon-blue-shadow);
}
/* Total Savings */
.md-content--home .total-savings {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-md);
padding: var(--space-xl);
background: var(--home-dark-surface);
border-radius: var(--home-radius);
border: 1px solid var(--trans-blue);
}
.md-content--home .savings-box {
text-align: center;
}
.md-content--home .savings-label {
font-size: var(--text-sm);
color: var(--home-dark-text-muted);
margin-bottom: var(--space-xs);
}
.md-content--home .savings-amount {
font-size: var(--text-2xl);
font-weight: 700;
}
.md-content--home .savings-amount.bad {
color: var(--trans-pink);
text-decoration: line-through;
}
.md-content--home .savings-amount.good {
color: var(--trans-blue);
text-shadow: var(--neon-blue-shadow);
}
.md-content--home .savings-arrow {
font-size: var(--text-2xl);
color: var(--trans-white-dim);
}
/* Quickstart Section */
.md-content--home .quickstart-section {
background: var(--home-dark-surface);
padding: var(--space-2xl) 0;
}
.md-content--home .quickstart-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-lg);
margin-bottom: var(--space-2xl);
}
.md-content--home .quickstart-card {
text-align: center;
padding: var(--space-lg);
}
.md-content--home .quickstart-step {
display: inline-flex;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
background: var(--trans-blue);
color: var(--home-dark-bg);
border-radius: 50%;
font-size: var(--text-xl);
font-weight: 700;
margin-bottom: var(--space-md);
box-shadow: var(--neon-blue-shadow);
}
.md-content--home .quickstart-card h3 {
font-size: var(--text-lg);
margin-bottom: var(--space-xs);
color: var(--trans-white);
}
.md-content--home .quickstart-card p {
font-size: var(--text-sm);
color: var(--home-dark-text-muted);
}
/* Terminal Showcase */
.md-content--home .terminal-showcase {
max-width: 600px;
margin: 0 auto;
}
.md-content--home .terminal-header {
background: var(--home-dark-border);
padding: var(--space-sm) var(--space-md);
border-radius: var(--home-radius) var(--home-radius) 0 0;
display: flex;
gap: var(--space-xs);
}
.md-content--home .terminal-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--home-dark-text-muted);
}
.md-content--home .terminal-box {
background: #000;
border: 1px solid var(--trans-blue);
border-top: none;
border-radius: 0 0 var(--home-radius) var(--home-radius);
padding: var(--space-lg);
font-family: 'SF Mono', Monaco, monospace;
font-size: var(--text-sm);
color: var(--trans-blue);
overflow-x: auto;
box-shadow: inset 0 0 20px rgba(91, 206, 250, 0.1);
cursor: pointer;
}
.md-content--home .terminal-box code {
display: block;
white-space: pre;
line-height: 1.6;
}
.md-content--home .terminal-success {
color: var(--trans-pink);
text-shadow: var(--neon-pink-shadow);
}
.md-content--home .terminal-comment {
color: var(--home-dark-text-muted);
font-style: italic;
}
/* Support Section */
.md-content--home .support-section {
padding: var(--space-2xl) 0;
background: var(--home-dark-bg);
}
.md-content--home .support-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-lg);
margin-bottom: var(--space-xl);
}
.md-content--home .support-card {
padding: var(--space-lg);
background: var(--home-dark-card);
border: 1px solid var(--home-dark-border);
border-radius: var(--home-radius);
}
.md-content--home .support-card h3 {
font-size: var(--text-lg);
margin-bottom: var(--space-sm);
color: var(--trans-white);
}
.md-content--home .support-card p {
font-size: var(--text-sm);
color: var(--home-dark-text);
}
.md-content--home .support-card a {
color: var(--trans-blue);
text-decoration: none;
}
.md-content--home .support-card a:hover {
text-shadow: var(--neon-blue-shadow);
}
.md-content--home .support-cta {
text-align: center;
}
/* Final CTA */
.md-content--home .final-cta {
background: linear-gradient(135deg,
rgba(91, 206, 250, 0.2) 0%,
rgba(245, 169, 184, 0.2) 50%,
rgba(255, 255, 255, 0.1) 100%);
padding: var(--space-3xl) 0;
text-align: center;
position: relative;
overflow: hidden;
}
.md-content--home .final-cta::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg,
transparent,
rgba(91, 206, 250, 0.1),
rgba(245, 169, 184, 0.1),
transparent);
animation: homepage-shimmer 3s linear infinite;
}
@keyframes homepage-shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.md-content--home .final-cta h2 {
font-size: clamp(var(--text-xl), 5vw, var(--text-3xl));
margin-bottom: var(--space-sm);
color: var(--trans-white);
text-shadow: var(--neon-white-shadow);
position: relative;
}
.md-content--home .final-cta p {
font-size: var(--text-base);
color: var(--trans-white-dim);
margin-bottom: var(--space-2xl);
position: relative;
}
.md-content--home .cta-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-md);
max-width: 600px;
margin: 0 auto;
position: relative;
}
.md-content--home .cta-box {
display: flex;
align-items: center;
gap: var(--space-md);
padding: var(--space-lg);
background: var(--home-dark-card);
border: 1px solid var(--home-dark-border);
border-radius: var(--home-radius);
text-decoration: none;
transition: all 0.3s ease;
}
.md-content--home .cta-box:hover {
border-color: var(--trans-blue);
box-shadow: var(--neon-blue-shadow);
transform: translateY(-2px);
}
.md-content--home .cta-icon {
font-size: var(--text-2xl);
flex-shrink: 0;
}
.md-content--home .cta-content {
text-align: left;
}
.md-content--home .cta-content h3 {
font-size: var(--text-base);
color: var(--trans-white);
margin-bottom: var(--space-xs);
}
.md-content--home .cta-content p {
font-size: var(--text-sm);
color: var(--home-dark-text-muted);
margin: 0;
}
/* Responsive - Tablet and up */
@media (min-width: 768px) {
.md-content--home {
/* Enhanced shadows for larger screens */
--neon-blue-shadow: 0 0 10px rgba(91, 206, 250, 0.8), 0 0 20px rgba(91, 206, 250, 0.5);
--neon-pink-shadow: 0 0 10px rgba(245, 169, 184, 0.8), 0 0 20px rgba(245, 169, 184, 0.5);
}
.md-content--home .container {
padding: 0 var(--space-xl);
}
.md-content--home .hero-actions {
flex-direction: row;
justify-content: center;
}
.md-content--home .hardware-grid {
grid-template-columns: repeat(3, 1fr);
}
.md-content--home .foss-grid {
grid-template-columns: repeat(3, 1fr);
}
.md-content--home .features-grid {
grid-template-columns: repeat(2, 1fr);
}
.md-content--home .quickstart-grid {
grid-template-columns: repeat(3, 1fr);
}
.md-content--home .support-grid {
grid-template-columns: repeat(3, 1fr);
}
.md-content--home .total-savings {
flex-direction: row;
justify-content: center;
}
.md-content--home .cta-grid {
grid-template-columns: repeat(3, 1fr);
max-width: 900px;
}
}
/* Desktop enhancements */
@media (min-width: 1024px) {
.md-content--home .features-grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.md-content--home *,
.md-content--home *::before,
.md-content--home *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* High contrast mode */
@media (prefers-contrast: high) {
.md-content--home {
--home-dark-bg: #000;
--home-dark-surface: #111;
--home-dark-text: #fff;
}
}
/* Print styles */
@media print {
.md-content--home .hero-actions,
.md-content--home .hardware-section,
.md-content--home .terminal-showcase,
.md-content--home .final-cta {
display: none;
}
}