Compare commits
59 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1261e55c4a | ||
|
|
8cf676f049 | ||
|
|
e0415e0f66 | ||
|
|
09ba589a00 | ||
|
|
1de4aa798c | ||
|
|
51b4c7ca97 | ||
|
|
de2d06d3a1 | ||
|
|
6bd35e5160 | ||
|
|
458dc41147 | ||
|
|
e8a54bd396 | ||
|
|
b9975435c2 | ||
|
|
9f179b1ead | ||
|
|
7db03ad35e | ||
|
|
11921aa07a | ||
|
|
ec88d58e05 | ||
|
|
9fa33e81c2 | ||
|
|
1b1e4dc154 | ||
|
|
4421378529 | ||
|
|
c7a3fe9412 | ||
|
|
5e0f482db1 | ||
|
|
fbc488cc95 | ||
|
|
69f69be5e4 | ||
|
|
4b4425a2d9 | ||
|
|
f7abb6bf42 | ||
|
|
6e1cdf4018 | ||
|
|
a3ec22a70a | ||
|
|
3aade4630b | ||
|
|
06f0c739df | ||
|
|
c4d21b72ea | ||
|
|
aac22735e4 | ||
|
|
a1db08f32e | ||
|
|
fa0b34c3c2 | ||
|
|
2b2edc7505 | ||
|
|
5b0ff60ac8 | ||
|
|
69119f347d | ||
|
|
d1f405bde1 | ||
|
|
0871b22709 | ||
|
|
a31d6ac095 | ||
|
|
f6f7bd7115 | ||
|
|
95d04f7a0e | ||
|
|
7d58c330a6 | ||
|
|
2537e4d5af | ||
|
|
0fbe169815 | ||
|
|
dd37f2ea40 | ||
|
|
7c1143befc | ||
|
|
cff4e8c8ee | ||
|
|
9bc2a55251 | ||
|
|
b1e129ed6e | ||
|
|
bc94fb954c | ||
|
|
8491b0f751 | ||
|
|
2eb1170992 | ||
|
|
b042f43cdd | ||
|
|
1ca6266464 | ||
|
|
6fea770e71 | ||
|
|
d399f510b7 | ||
|
|
54e74a0f04 | ||
|
|
4e9e16b735 | ||
|
|
12494bf0f0 | ||
|
|
8b0a086d37 |
58
.forgejo/workflows/docs.yml
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
name: Deploy Docs
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
run: |
|
||||||
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- name: Install Python 3.12 via uv
|
||||||
|
run: |
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
uv python install 3.12
|
||||||
|
|
||||||
|
- name: Build site
|
||||||
|
run: |
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
uv venv --python 3.12 /tmp/venv
|
||||||
|
. /tmp/venv/bin/activate
|
||||||
|
python --version
|
||||||
|
uv pip install zensical
|
||||||
|
uv pip install -e .
|
||||||
|
python3 main.py
|
||||||
|
zensical build --clean
|
||||||
|
|
||||||
|
- name: Deploy to pages branch
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
git config user.name "forgejo-actions"
|
||||||
|
git config user.email "forgejo-actions@noreply.local"
|
||||||
|
|
||||||
|
git fetch origin pages
|
||||||
|
git worktree add /tmp/pages-deploy origin/pages
|
||||||
|
cd /tmp/pages-deploy
|
||||||
|
|
||||||
|
git rm -rf --ignore-unmatch .
|
||||||
|
cp -r "$GITHUB_WORKSPACE"/site/* .
|
||||||
|
cp "$GITHUB_WORKSPACE"/site/.[!.]* . 2>/dev/null || true
|
||||||
|
|
||||||
|
git add .
|
||||||
|
if ! git diff --staged --quiet; then
|
||||||
|
git commit -m "deploy: zensical build from ${GITHUB_SHA::7}"
|
||||||
|
git push origin HEAD:pages
|
||||||
|
else
|
||||||
|
echo "No changes to deploy"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
GITHUB_WORKSPACE: ${{ github.workspace }}
|
||||||
|
GITHUB_SHA: ${{ github.sha }}
|
||||||
10
.gitignore
vendored
|
|
@ -162,3 +162,13 @@ cython_debug/
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
PASSWORD.txt
|
PASSWORD.txt
|
||||||
|
.hermes
|
||||||
|
codedb.snapshot
|
||||||
|
|
||||||
|
# Old build artifacts (now in site/)
|
||||||
|
/404.html
|
||||||
|
/index.html
|
||||||
|
/search.json
|
||||||
|
/sitemap.xml
|
||||||
|
/objects.inv
|
||||||
|
TODO.md
|
||||||
|
|
|
||||||
367
404.html
|
|
@ -1,367 +0,0 @@
|
||||||
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en" class="no-js">
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
||||||
|
|
||||||
<meta name="description" content="Tools for a more conscious and free humanity">
|
|
||||||
|
|
||||||
|
|
||||||
<meta name="author" content="aja">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<link rel="icon" href="/assets/images/favicon.png">
|
|
||||||
<meta name="generator" content="zensical-0.0.43">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<title>up</title>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/assets/stylesheets/modern/main.fba56155.min.css">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/assets/stylesheets/modern/palette.dfe2e883.min.css">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
|
|
||||||
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script>__md_scope=new URL("/",location),__md_scope.pathname.endsWith("/")||(__md_scope=new URL(__md_scope.pathname+"/",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+"."+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+"."+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute("data-platform",navigator.platform)</script>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
|
|
||||||
|
|
||||||
|
|
||||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
|
||||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
|
||||||
<label class="md-overlay" for="__drawer" aria-label="Navigation"></label>
|
|
||||||
<div data-md-component="skip">
|
|
||||||
|
|
||||||
<a href="#__skip" class="md-skip">
|
|
||||||
Skip to content
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div data-md-component="announce">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header class="md-header md-header--shadow" data-md-component="header">
|
|
||||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
|
||||||
<a href="/" title="up" class="md-header__button md-logo" aria-label="up" data-md-component="logo">
|
|
||||||
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-book-open" viewBox="0 0 24 24"><path d="M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
<label class="md-header__button md-icon" for="__drawer" aria-label="Navigation">
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-menu" viewBox="0 0 24 24"><path d="M4 5h16M4 12h16M4 19h16"/></svg>
|
|
||||||
</label>
|
|
||||||
<div class="md-header__title" data-md-component="header-title">
|
|
||||||
<div class="md-header__ellipsis">
|
|
||||||
<div class="md-header__topic">
|
|
||||||
<span class="md-ellipsis">
|
|
||||||
up
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="md-header__topic" data-md-component="header-topic">
|
|
||||||
<span class="md-ellipsis">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<form class="md-header__option" data-md-component="palette">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<input class="md-option" data-md-color-media="none" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
|
|
||||||
|
|
||||||
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<input class="md-option" data-md-color-media="none" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
|
|
||||||
|
|
||||||
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-moon" viewBox="0 0 24 24"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/></svg>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<label class="md-header__button md-icon" for="__search" aria-label="Search">
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-search" viewBox="0 0 24 24"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg>
|
|
||||||
</label>
|
|
||||||
<div class="md-search" data-md-component="search" role="dialog" aria-label="Search">
|
|
||||||
<button type="button" class="md-search__button">
|
|
||||||
Search
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="md-header__source">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="md-container" data-md-component="container">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<main class="md-main" data-md-component="main">
|
|
||||||
<div class="md-main__inner md-grid">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
|
||||||
<div class="md-sidebar__scrollwrap">
|
|
||||||
<div class="md-sidebar__inner">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
|
||||||
<label class="md-nav__title" for="__drawer">
|
|
||||||
<a href="/" title="up" class="md-nav__button md-logo" aria-label="up" data-md-component="logo">
|
|
||||||
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-book-open" viewBox="0 0 24 24"><path d="M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
up
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<ul class="md-nav__list" data-md-scrollfix>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="md-nav__item">
|
|
||||||
<a href="/" class="md-nav__link">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-rocket" viewBox="0 0 24 24"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"/><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"/></svg>
|
|
||||||
|
|
||||||
<span class="md-ellipsis">
|
|
||||||
|
|
||||||
|
|
||||||
Welcome!
|
|
||||||
|
|
||||||
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="md-nav__item">
|
|
||||||
<a href="/markdown/" class="md-nav__link">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M22.27 19.385H1.73A1.73 1.73 0 0 1 0 17.655V6.345a1.73 1.73 0 0 1 1.73-1.73h20.54A1.73 1.73 0 0 1 24 6.345v11.308a1.73 1.73 0 0 1-1.73 1.731zM5.769 15.923v-4.5l2.308 2.885 2.307-2.885v4.5h2.308V8.078h-2.308l-2.307 2.885-2.308-2.885H3.46v7.847zM21.232 12h-2.309V8.077h-2.307V12h-2.308l3.461 4.039z"/></svg>
|
|
||||||
|
|
||||||
<span class="md-ellipsis">
|
|
||||||
|
|
||||||
|
|
||||||
Markdown in 5min
|
|
||||||
|
|
||||||
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
|
||||||
<div class="md-sidebar__scrollwrap">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="md-sidebar__inner">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav class="md-nav md-nav--secondary" aria-label="On this page">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="md-content" data-md-component="content">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<article class="md-content__inner md-typeset">
|
|
||||||
|
|
||||||
<h1>404 - Not found</h1>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
|
|
||||||
|
|
||||||
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-circle-arrow-up" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m16 12-4-4-4 4M12 16V8"/></svg>
|
|
||||||
Back to top
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="md-footer">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="md-footer-meta md-typeset">
|
|
||||||
<div class="md-footer-meta__inner md-grid">
|
|
||||||
<div class="md-copyright">
|
|
||||||
|
|
||||||
<div class="md-copyright__highlight">
|
|
||||||
Copyright © 2026 The authors
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
Made with
|
|
||||||
<a href="https://zensical.org/" target="_blank" rel="noopener">
|
|
||||||
Zensical
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="md-dialog" data-md-component="dialog">
|
|
||||||
<div class="md-dialog__inner md-typeset"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script id="__config" type="application/json">{"annotate":null,"base":"/","features":["announce.dismiss","content.code.annotate","content.code.copy","content.code.select","content.footnote.tooltips","content.tabs.link","content.tooltips","navigation.footer","navigation.indexes","navigation.instant","navigation.instant.prefetch","navigation.path","navigation.sections","navigation.top","navigation.tracking","search.highlight"],"search":"/assets/javascripts/workers/search.e2d2d235.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>
|
|
||||||
|
|
||||||
|
|
||||||
<script src="/assets/javascripts/bundle.6e5f0216.min.js"></script>
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
194
_extensions/wikilinks.py
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
"""
|
||||||
|
Python-Markdown extension: converts [[Wikilinks]] to standard Markdown links.
|
||||||
|
|
||||||
|
Mirrors the behavior of mkdocs-ezlinks-plugin's WikiLinkScanner, but as a
|
||||||
|
pure Markdown preprocessor (no MkDocs plugin API needed). Zensical handles
|
||||||
|
the resulting links natively.
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
[[Page Name]] → [Page Name](/page-name/)
|
||||||
|
[[Page Name|Display Text]] → [Display Text](/page-name/)
|
||||||
|
[[Page Name#anchor]] → [Page Name](/page-name/#anchor)
|
||||||
|
[[Page Name#anchor|Text]] → [Text](/page-name/#anchor)
|
||||||
|
![[image.png]] → 
|
||||||
|
|
||||||
|
Tolaria-compatible: when the vault root is the project root, links like
|
||||||
|
``[[docs/contributing/index]]`` are stripped of the ``docs/`` prefix and
|
||||||
|
converted to root-relative URLs (e.g. ``/contributing/``) that work from
|
||||||
|
any page regardless of depth.
|
||||||
|
|
||||||
|
Code blocks (fenced and inline) are skipped — wiki links inside them pass
|
||||||
|
through unchanged.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
from markdown.preprocessors import Preprocessor
|
||||||
|
from markdown.extensions import Extension
|
||||||
|
|
||||||
|
|
||||||
|
# Regex for a wiki link. Borrowed from mkdocs-ezlinks-plugin's
|
||||||
|
# WikiLinkScanner with minor adjustments.
|
||||||
|
_WIKILINK_RE = re.compile(
|
||||||
|
r"""
|
||||||
|
(?P<image>\!?) # optional ! for image embeds
|
||||||
|
\[\[ # opening [[
|
||||||
|
(?P<link>[^#\|\]]*?) # target (everything before #, |, or ]])
|
||||||
|
(?:\#(?P<anchor>[^\|\]]+)?)? # optional #anchor
|
||||||
|
(?:\|(?P<text>[^\]]+)?)? # optional |display text
|
||||||
|
\]\] # closing ]]
|
||||||
|
""",
|
||||||
|
re.VERBOSE,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Match fenced code blocks or inline code spans (single capture group).
|
||||||
|
_CODE_RE = re.compile(
|
||||||
|
r"(```.*?```|`[^`\n]+`)",
|
||||||
|
re.DOTALL,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Prefix to strip from Tolaria-generated links when the vault root is
|
||||||
|
# the project root (so links look like [[docs/foo/bar]]).
|
||||||
|
_DOCS_PREFIX = "docs/"
|
||||||
|
|
||||||
|
|
||||||
|
def _slugify(text: str) -> str:
|
||||||
|
"""Convert a human page name into a filename slug.
|
||||||
|
|
||||||
|
Mirrors ezlinks: lowercase, spaces → hyphens, strip unsupported chars.
|
||||||
|
Keeps forward slashes for subdirectory paths, dots for extensions, and CJK.
|
||||||
|
"""
|
||||||
|
slug = text.strip().lower()
|
||||||
|
slug = re.sub(r"\s+", "-", slug)
|
||||||
|
# Keep: word chars, hyphens, dots, forward slashes, CJK
|
||||||
|
slug = re.sub(r"[^\w./\u4e00-\u9fff\-]", "", slug)
|
||||||
|
return slug
|
||||||
|
|
||||||
|
|
||||||
|
def _url_from_link(link: str) -> str:
|
||||||
|
"""Convert a wiki link target to a root-relative URL.
|
||||||
|
|
||||||
|
Handles Tolaria-style full paths: strips ``docs/`` prefix,
|
||||||
|
removes ``.md`` extension, collapses ``/index`` suffixes,
|
||||||
|
slugifies each component, and prepends ``/``.
|
||||||
|
"""
|
||||||
|
raw = link.strip()
|
||||||
|
|
||||||
|
# Strip .md extension
|
||||||
|
raw = re.sub(r"\.md$", "", raw, flags=re.IGNORECASE)
|
||||||
|
|
||||||
|
# Strip docs/ prefix (Tolaria vault root = project root)
|
||||||
|
if raw.lower().startswith(_DOCS_PREFIX):
|
||||||
|
raw = raw[len(_DOCS_PREFIX) :]
|
||||||
|
|
||||||
|
# Collapse trailing /index — section index pages resolve to the dir
|
||||||
|
raw = re.sub(r"/index$", "", raw)
|
||||||
|
|
||||||
|
if not raw:
|
||||||
|
return "/"
|
||||||
|
|
||||||
|
# Slugify each path component
|
||||||
|
parts = [_slugify(p) for p in raw.split("/") if p]
|
||||||
|
return "/" + "/".join(parts) + "/"
|
||||||
|
|
||||||
|
|
||||||
|
def _display_name(link: str) -> str:
|
||||||
|
"""Derive a human-readable title from a wiki link path.
|
||||||
|
|
||||||
|
``[[docs/contributing/index]]`` → ``Contributing``
|
||||||
|
``[[docs/strategies/collective-awakening]]`` → ``Collective Awakening``
|
||||||
|
``[[Contributing]]`` → ``Contributing``
|
||||||
|
"""
|
||||||
|
raw = link.strip()
|
||||||
|
|
||||||
|
# Strip .md extension
|
||||||
|
raw = re.sub(r"\.md$", "", raw, flags=re.IGNORECASE)
|
||||||
|
|
||||||
|
# Strip docs/ prefix
|
||||||
|
if raw.lower().startswith(_DOCS_PREFIX):
|
||||||
|
raw = raw[len(_DOCS_PREFIX) :]
|
||||||
|
|
||||||
|
parts = [p for p in raw.split("/") if p]
|
||||||
|
if not parts:
|
||||||
|
return link
|
||||||
|
|
||||||
|
# If the last component is "index", use the parent directory name
|
||||||
|
if parts[-1].lower() == "index":
|
||||||
|
name = parts[-2] if len(parts) >= 2 else parts[-1]
|
||||||
|
else:
|
||||||
|
name = parts[-1]
|
||||||
|
|
||||||
|
# Replace hyphens/underscores with spaces, title-case
|
||||||
|
name = name.replace("-", " ").replace("_", " ")
|
||||||
|
return name.title()
|
||||||
|
|
||||||
|
|
||||||
|
class WikilinksPreprocessor(Preprocessor):
|
||||||
|
"""Preprocessor that converts [[wikilinks]] to root-relative [text](/url/)."""
|
||||||
|
|
||||||
|
def run(self, lines: list[str]) -> list[str]:
|
||||||
|
text = "\n".join(lines)
|
||||||
|
|
||||||
|
# Walk through the text, skipping code spans. Use finditer to
|
||||||
|
# extract code regions, then transform wiki links in the gaps.
|
||||||
|
result: list[str] = []
|
||||||
|
cursor = 0
|
||||||
|
for m in _CODE_RE.finditer(text):
|
||||||
|
before = text[cursor : m.start()]
|
||||||
|
if before:
|
||||||
|
result.append(_WIKILINK_RE.sub(self._replace, before))
|
||||||
|
result.append(m.group(0))
|
||||||
|
cursor = m.end()
|
||||||
|
|
||||||
|
tail = text[cursor:]
|
||||||
|
if tail:
|
||||||
|
result.append(_WIKILINK_RE.sub(self._replace, tail))
|
||||||
|
|
||||||
|
return "\n".join(result).split("\n")
|
||||||
|
|
||||||
|
def _replace(self, match: re.Match) -> str:
|
||||||
|
groups = match.groupdict()
|
||||||
|
is_image = groups.get("image") or ""
|
||||||
|
link = groups.get("link") or ""
|
||||||
|
anchor = groups.get("anchor") or ""
|
||||||
|
text = groups.get("text") or (link if is_image else _display_name(link)) or anchor
|
||||||
|
|
||||||
|
if not (link or text or anchor):
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
# Build the href: root-relative URL for pages; relative for images
|
||||||
|
if is_image:
|
||||||
|
# Images: keep filename, strip docs/ prefix, make root-relative
|
||||||
|
raw = link.strip()
|
||||||
|
if raw.lower().startswith(_DOCS_PREFIX):
|
||||||
|
raw = raw[len(_DOCS_PREFIX) :]
|
||||||
|
# Non-image assets might have extensions; keep them
|
||||||
|
href = raw if "." in raw else _slugify(raw)
|
||||||
|
if not href.startswith("/"):
|
||||||
|
href = "/" + href
|
||||||
|
else:
|
||||||
|
href = _url_from_link(link)
|
||||||
|
|
||||||
|
# Append anchor if present
|
||||||
|
if anchor:
|
||||||
|
anchor_slug = _slugify(anchor)
|
||||||
|
if anchor_slug:
|
||||||
|
href = href.rstrip("/") + "#" + anchor_slug
|
||||||
|
|
||||||
|
if is_image:
|
||||||
|
return f""
|
||||||
|
else:
|
||||||
|
return f"[{text}]({href})"
|
||||||
|
|
||||||
|
|
||||||
|
class WikilinksExtension(Extension):
|
||||||
|
"""Register the WikilinksPreprocessor."""
|
||||||
|
|
||||||
|
def extendMarkdown(self, md):
|
||||||
|
# Priority 35: after normalize_whitespace (30), before html_block (20)
|
||||||
|
md.preprocessors.register(WikilinksPreprocessor(md), "wikilinks", 35)
|
||||||
|
|
||||||
|
|
||||||
|
def makeExtension(**kwargs):
|
||||||
|
return WikilinksExtension(**kwargs)
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
# About this space
|
|
||||||
|
|
||||||
_This is a living archive for reigniting the spark within._
|
|
||||||
|
|
||||||
Multiple voices are welcome here. Not a performance of awareness, but a practice of it.
|
|
||||||
|
|
||||||
- Share what calls to you
|
|
||||||
- Add notes, reflections, or small practices
|
|
||||||
- Let contributions grow the whole garden gently
|
|
||||||
BIN
codedb.snapshot
BIN
docs/assets/images/cards/practices-digital.jpg
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
docs/assets/images/cards/practices-grounding.jpg
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
docs/assets/images/cards/practices-hygiene.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
docs/assets/images/cards/practices-nourishing.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
docs/assets/images/cards/practices-sadhana.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
docs/assets/images/cards/strategies-awakening.jpg
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
docs/assets/images/cards/strategies-community-sov.jpg
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
docs/assets/images/cards/strategies-digital-sov.jpg
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
docs/assets/images/cards/strategies-purpose.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
docs/assets/images/collective-awakening.jpg
Normal file
|
After Width: | Height: | Size: 3.1 MiB |
BIN
docs/assets/images/community-sovereignty.jpg
Normal file
|
After Width: | Height: | Size: 2.9 MiB |
BIN
docs/assets/images/daily-sadhana.jpg
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
docs/assets/images/digital-wellness.jpg
Normal file
|
After Width: | Height: | Size: 6.7 MiB |
BIN
docs/assets/images/nature_bathing.jpg
Normal file
|
After Width: | Height: | Size: 291 KiB |
|
|
@ -1,12 +1,13 @@
|
||||||
---
|
---
|
||||||
title: Contributing
|
title: Contributing
|
||||||
|
icon: lucide/heart-handshake
|
||||||
---
|
---
|
||||||
|
|
||||||
# Contributing to Tree of Ascension Docs
|
# Contributing to Tree of Ascension Docs
|
||||||
|
|
||||||
Welcome! This guide will get you from zero to making your first edit — even if you've never used git before.
|
Welcome! This guide will get you from zero to making your first edit or new post contribution to Tree of Ascension Docs.
|
||||||
|
|
||||||
> **🔒 Registration is currently closed.** New contributor accounts are not available at this moment. If you'd like to get involved, solve the puzzle below to reveal the contact email and request access.
|
> **🔒 Registration is currently closed.** Self-registration of new contributor accounts are not available at this moment. If you'd like to get involved, solve the puzzle below to reveal the contact email and request access.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -63,6 +64,10 @@ Welcome! This guide will get you from zero to making your first edit — even if
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
!!! info "Single article"
|
||||||
|
|
||||||
|
If you just want to contriubute a simple edit or a single article you can send it to the above address and we'll handle adding it to the site for you.
|
||||||
|
|
||||||
Once you have access, read on below.
|
Once you have access, read on below.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -70,15 +75,15 @@ Once you have access, read on below.
|
||||||
## 🛠 How it works
|
## 🛠 How it works
|
||||||
|
|
||||||
| What | Details |
|
| What | Details |
|
||||||
|------|---------|
|
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **Site host** | [Forgejo](https://forgejo.org) — a friendly, self-hosted git platform |
|
| **Code and file hosting** | [Forgejo](https://forgejo.org) — a friendly, self-hosted git (version control) platform that manages changes and files between many users. Git is a distributed open source tool that lets you work on a folder of files and handles the cases where two users have edited the same file (called merge conflicts). |
|
||||||
| **Repo** | [bali.krystl.org/aja/up](https://bali.krystl.org/aja/up) |
|
| **Repo** | [bali.krystl.org/aja/up](https://bali.krystl.org/aja/up) |
|
||||||
| **Built with** | [Zensical](https://zensical.org) — turns Markdown files into a beautiful docs site |
|
| **Built with** | [Zensical](https://zensical.org) — turns Markdown files into a beautiful docs site |
|
||||||
| **Local editor** | [Tolaria](https://tolaria.dev) — a simple desktop app for editing Markdown with git built in |
|
| **Local editor** | [Tolaria](https://tolaria.dev) — a simple desktop app for editing Markdown with git built in |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✏️ Making your first edit
|
## ✏️ Making your first edit directly on Forgejo (easiest as no local setup required)
|
||||||
|
|
||||||
Follow these steps. If you get stuck, the answer is usually just a few clicks away.
|
Follow these steps. If you get stuck, the answer is usually just a few clicks away.
|
||||||
|
|
||||||
|
|
@ -88,7 +93,7 @@ Go to **[bali.krystl.org/aja/up](https://bali.krystl.org/aja/up)** and sign in w
|
||||||
|
|
||||||
### Step 2 — Create your branch
|
### Step 2 — Create your branch
|
||||||
|
|
||||||
Every edit lives on its own branch. This keeps the main site safe while you work.
|
Every edit lives on its own branch. A branch is a copy of the code that can be kept independent and later merged. This keeps the main site safe while you work and allows us to review and approve or comment on changes.
|
||||||
|
|
||||||
- Click the **branch dropdown** (near the top of the page, it probably says `main` or `master`)
|
- Click the **branch dropdown** (near the top of the page, it probably says `main` or `master`)
|
||||||
- Type a short name for your branch — like `add-meditation-guide` or `fix-typo-daily-sadhana`
|
- Type a short name for your branch — like `add-meditation-guide` or `fix-typo-daily-sadhana`
|
||||||
|
|
@ -100,7 +105,7 @@ You're now on your own copy of the site. Any changes you make stay on this branc
|
||||||
|
|
||||||
- Browse to the file you want to edit (all content lives in the `docs/` folder)
|
- Browse to the file you want to edit (all content lives in the `docs/` folder)
|
||||||
- Click the **pencil icon** (✏️) in the toolbar above the file
|
- Click the **pencil icon** (✏️) in the toolbar above the file
|
||||||
- Make your changes using Markdown (see our [Markdown quick reference](markdown.md))
|
- Make your changes using [Markdown](https://zensical.org/docs/authoring/markdown/)
|
||||||
- Scroll down and write a short commit message — something like `Add breathing exercise section`
|
- Scroll down and write a short commit message — something like `Add breathing exercise section`
|
||||||
- Click **"Commit changes"**
|
- Click **"Commit changes"**
|
||||||
|
|
||||||
|
|
@ -109,7 +114,7 @@ You're now on your own copy of the site. Any changes you make stay on this branc
|
||||||
When your changes are ready:
|
When your changes are ready:
|
||||||
|
|
||||||
- Go back to the repo homepage
|
- Go back to the repo homepage
|
||||||
- You'll see a banner: *"You pushed to your branch — want to open a pull request?"*
|
- You'll see a banner: _"You pushed to your branch — want to open a pull request?"_
|
||||||
- Click **"Compare & pull request"**
|
- Click **"Compare & pull request"**
|
||||||
- Add a title and a short description of what you changed
|
- Add a title and a short description of what you changed
|
||||||
- Click **"Create pull request"**
|
- Click **"Create pull request"**
|
||||||
|
|
@ -124,12 +129,13 @@ If you prefer to work on your own computer:
|
||||||
|
|
||||||
### You'll need
|
### You'll need
|
||||||
|
|
||||||
- **[git](https://git-scm.com/downloads)** — the version control tool
|
|
||||||
- **[Tolaria](https://tolaria.dev)** — a friendly Markdown editor with git support
|
- **[Tolaria](https://tolaria.dev)** — a friendly Markdown editor with git support
|
||||||
|
- You can also use any text editor together with **[git](https://git-scm.com/downloads)** — the version control tool
|
||||||
|
|
||||||
### Steps
|
### Steps
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
# 1. Clone the repo
|
# 1. Clone the repo
|
||||||
git clone https://bali.krystl.org/aja/up.git
|
git clone https://bali.krystl.org/aja/up.git
|
||||||
cd up
|
cd up
|
||||||
|
|
@ -143,6 +149,9 @@ git checkout -b my-edit
|
||||||
git add .
|
git add .
|
||||||
git commit -m "Describe your changes"
|
git commit -m "Describe your changes"
|
||||||
git push -u origin my-edit
|
git push -u origin my-edit
|
||||||
|
|
||||||
|
# At this point you'll be asked for your username and password.
|
||||||
|
# You can also set up an SSH key which will mean you don't need to type these every time (you will need to email us your public key)
|
||||||
```
|
```
|
||||||
|
|
||||||
Then follow Step 4 above ("Open a Pull Request") to open your pull request on Forgejo.
|
Then follow Step 4 above ("Open a Pull Request") to open your pull request on Forgejo.
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,13 @@ icon: simple/markdown
|
||||||
|
|
||||||
# Markdown in 5min
|
# Markdown in 5min
|
||||||
|
|
||||||
|
## Introduction to Markdown Language
|
||||||
|
|
||||||
|
Markdown is a simple language to build web pages. It is easier to read and write than HTML (the language web browsers read) and so we use it to write articles and have a system called Zensical that will compile your Markdown into HTML. You can use this reference to help you write posts and pages directly in our repository where the source documents for this wiki are held. See [[docs/contributing/index]] for more and check the Zensical docs on authoring for a more complete set of markdown notations you can use with Tree.
|
||||||
|
|
||||||
## Headers
|
## Headers
|
||||||
|
|
||||||
```
|
```text
|
||||||
# H1 Header
|
# H1 Header
|
||||||
## H2 Header
|
## H2 Header
|
||||||
### H3 Header
|
### H3 Header
|
||||||
|
|
@ -17,7 +21,7 @@ icon: simple/markdown
|
||||||
|
|
||||||
## Text formatting
|
## Text formatting
|
||||||
|
|
||||||
```
|
```text
|
||||||
**bold text**
|
**bold text**
|
||||||
*italic text*
|
*italic text*
|
||||||
***bold and italic***
|
***bold and italic***
|
||||||
|
|
@ -27,16 +31,16 @@ icon: simple/markdown
|
||||||
|
|
||||||
## Links and images
|
## Links and images
|
||||||
|
|
||||||
```
|
```text
|
||||||
[Link text](https://example.com)
|
[Link text](https://example.com)
|
||||||
[Link with title](https://example.com "Hover title")
|
[Link with title](https://example.com "Hover title")
|
||||||

|

|
||||||

|

|
||||||
```
|
```
|
||||||
|
|
||||||
## Lists
|
## Lists
|
||||||
|
|
||||||
```
|
```yaml
|
||||||
Unordered:
|
Unordered:
|
||||||
|
|
||||||
- Item 1
|
- Item 1
|
||||||
|
|
@ -52,7 +56,7 @@ Ordered:
|
||||||
|
|
||||||
## Blockquotes
|
## Blockquotes
|
||||||
|
|
||||||
```
|
```text
|
||||||
> This is a blockquote
|
> This is a blockquote
|
||||||
> Multiple lines
|
> Multiple lines
|
||||||
>> Nested quote
|
>> Nested quote
|
||||||
|
|
@ -60,17 +64,17 @@ Ordered:
|
||||||
|
|
||||||
## Code blocks
|
## Code blocks
|
||||||
|
|
||||||
````
|
````javascript
|
||||||
```javascript
|
```javascript
|
||||||
function hello() {
|
function hello() {
|
||||||
console.log("Hello, world!");
|
console.log("Hello, world!");
|
||||||
}
|
}
|
||||||
```
|
```;
|
||||||
````
|
````
|
||||||
|
|
||||||
## Tables
|
## Tables
|
||||||
|
|
||||||
```
|
```text
|
||||||
| Header 1 | Header 2 | Header 3 |
|
| Header 1 | Header 2 | Header 3 |
|
||||||
|----------|----------|----------|
|
|----------|----------|----------|
|
||||||
| Row 1 | Data | Data |
|
| Row 1 | Data | Data |
|
||||||
|
|
@ -79,7 +83,7 @@ function hello() {
|
||||||
|
|
||||||
## Horizontal rule
|
## Horizontal rule
|
||||||
|
|
||||||
```
|
```text
|
||||||
---
|
---
|
||||||
or
|
or
|
||||||
***
|
***
|
||||||
|
|
@ -89,7 +93,7 @@ ___
|
||||||
|
|
||||||
## Task lists
|
## Task lists
|
||||||
|
|
||||||
```
|
```text
|
||||||
- [x] Completed task
|
- [x] Completed task
|
||||||
- [ ] Incomplete task
|
- [ ] Incomplete task
|
||||||
- [ ] Another task
|
- [ ] Another task
|
||||||
|
|
@ -97,13 +101,13 @@ ___
|
||||||
|
|
||||||
## Escaping characters
|
## Escaping characters
|
||||||
|
|
||||||
```
|
```text
|
||||||
Use backslash to escape: \* \_ \# \`
|
Use backslash to escape: \* \_ \# \`
|
||||||
```
|
```
|
||||||
|
|
||||||
## Line breaks
|
## Line breaks
|
||||||
|
|
||||||
```
|
```text
|
||||||
End a line with two spaces
|
End a line with two spaces
|
||||||
to create a line break.
|
to create a line break.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,52 @@
|
||||||
---
|
---
|
||||||
icon: lucide/leaf
|
icon: lucide/leaf
|
||||||
|
comments: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Tree of Ascension Docs
|
# Tree of Ascension Docs
|
||||||
|
|
||||||
<figure class="godspark-hero" markdown="1">
|
## Why Tree of Ascension
|
||||||
<img src="assets/images/hero.jpg" alt="Tree of Ascension" />
|
|
||||||
<figcaption>Every branch reaches toward the light.</figcaption>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<p class="intro-lead gp-reveal">
|
The world can seem so chaotic that we feel we have no way to make an impact. But if we start with ourselves using time honoured [[docs/practices/index]] in our daily life and adopt [[docs/strategies/index]] to work together with other like hearted beings (physical or otherwise), we can certainly bring about peace and a lighter timeline, one day at a time.
|
||||||
A living guide for those climbing upward — practices for the body, teachings for the mind, and community for the soul. Not a destination, but a tree growing one branch at a time.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<hr class="wp-divider" />
|
### Action steps
|
||||||
|
|
||||||
<section class="wp-section gp-reveal">
|
Many sprouts in this tree have action points hidden inside that you can adopt into your life if you feel resonant. Checking these items will help you feel the satisfaction of making progress. Here's a first one for free! Try checking the box below:
|
||||||
## How to contribute
|
|
||||||
|
|
||||||
- **Add a reflection** — short notes, practices, or questions
|
- [ ] Read the introduction
|
||||||
- **Plant an idea** — link into new themed pages
|
|
||||||
- **Tend the tone** — kind, grounded edits keep the garden coherent
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<p class="wp-spacer"></p>
|
## How this site came about
|
||||||
|
|
||||||
|
A small group of us kept having the same kind of conversation. Late nights, voice notes, walls of text — sharing things that had actually moved the needle in our own lives. Practices that stuck. Realizations that rearranged something. Books and teachers and mistakes and breakthroughs.
|
||||||
|
|
||||||
|
At some point we thought: why keep this scattered across chat logs? Let's put it somewhere. Not as experts. Not as a finished thing. Just as what it is — notes from people climbing, passing the lantern back down the trail.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What we mean by ascension
|
||||||
|
|
||||||
|
Not floating off into the clouds. Not bypassing the hard stuff. Ascension, the way we talk about it, is waking up _here_. In your actual body, in your actual life, with your actual pain and joy and confusion.
|
||||||
|
|
||||||
|
It's learning to hold more light without burning out. It's noticing when you're running a program that isn't yours — from culture, from family, from fear — and gently putting it down. It goes in layers. You think you've arrived and then the next onion skin peels back and you realize you were just getting started. That's the game. That's the fun of it.
|
||||||
|
|
||||||
|
Some people call it awakening. Some call it remembering. The name doesn't matter much. What matters is that it's possible, it's happening to ordinary people everywhere, and nobody needs permission to begin.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Consciousness isn't abstract
|
||||||
|
|
||||||
|
You can feel it. When your mind goes quiet and there's still someone there — aware, alive, unimpressed by the chatter. That's consciousness. Not a concept. It is you, yourself, the light of awareness reading these words.
|
||||||
|
|
||||||
|
Practices — meditation, grounding, fasting, silence, community, sound, service — are just ways of clearing the static so you can hear what was already there. The tree doesn't need to _become_ something. It just needs enough light and water to grow into what it already is.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to use this site
|
||||||
|
|
||||||
|
The [[Practices]] section is where to start. Pick one thing and try it. Not all of them. One. Give it a week.
|
||||||
|
|
||||||
|
The Strategies section is for when a practice opens a door and you want to understand the room you just walked into. Frameworks, context, the bigger picture.
|
||||||
|
|
||||||
|
Everything here is a draft. We update it when we learn something new or when someone points out we got something wrong. If something lands for you — or if it doesn't — we'd love to hear about it.
|
||||||
|
|
||||||
|
- [ ] Mark this sprout complete
|
||||||
|
|
|
||||||
12
docs/javascripts/toa-totals.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"/": 2,
|
||||||
|
"/practices/daily-sadhana/": 15,
|
||||||
|
"/practices/digital-wellness/": 4,
|
||||||
|
"/practices/grounding-in-nature/": 2,
|
||||||
|
"/practices/nourishing-the-body/": 4,
|
||||||
|
"/practices/spiritual-hygiene/": 5,
|
||||||
|
"/strategies/collective-awakening/": 4,
|
||||||
|
"/strategies/community-sovereignty/": 8,
|
||||||
|
"/strategies/digital-sovereignty/": 8,
|
||||||
|
"/strategies/finding-purpose/": 4
|
||||||
|
}
|
||||||
|
|
@ -1,46 +1,77 @@
|
||||||
---
|
---
|
||||||
icon: material/meditation
|
icon: material/meditation
|
||||||
---
|
---
|
||||||
|
|
||||||
# Daily Sadhana
|
# Daily Sadhana
|
||||||
|
|
||||||
*Sadhana* means daily spiritual practice — not something you do when you have time, but the foundation you build everything else upon. It doesn't require a temple or a teacher. It requires showing up.
|
*Sadhana* means daily spiritual practice — not something you do when you have time, but the foundation upon which you build everything else. The best time to practice is first thing in the morning, ideally waking an hour before sunrise. At this hour the energy is quiet, as the world is still asleep. Settling into meditation during the 48 minutes surrounding sunrise lets you ride a moment when the energy is in transition — and your practice can have a far greater impact.
|
||||||
|
|
||||||
---
|
***
|
||||||
|
|
||||||
|
## Morning routine
|
||||||
|
|
||||||
|
Drinking water on waking helps re-hydrate, as the body hasn't drunk anything for several hours. Warm water, or at least room temperature (not cold) is best.
|
||||||
|
|
||||||
|
Juice of one lemon or lime, 2 or 3 fingers of water, half spoon of bicarbonate of soda/baking soda (food grade, aluminium free) mixed in a tall glass, first thing in the morning helps regulate any excess acidity and re-hydrate.
|
||||||
|
|
||||||
## Meditation
|
## Meditation
|
||||||
|
|
||||||
Sit. Breathe. That's the whole instruction.
|
- [ ] Sit quietly for 5 minutes — your bed, a chair, a floor, anywhere
|
||||||
|
- [ ] Notice when the mind wanders and gently return to breath
|
||||||
|
- [ ] Do this every morning for one week
|
||||||
|
|
||||||
Start with five minutes. The mind will wander — that's what minds do. The practice is not emptying the mind but noticing when it has wandered and gently returning. Every return is a rep. Like any muscle, attention strengthens with use.
|
Start with five minutes. The mind will wander — that's what minds do. The practice is not emptying the mind but noticing when it has drifted and gently returning to the breath. Every return is a rep, and like any muscle, attention strengthens with use.
|
||||||
|
|
||||||
No app needed. No special cushion. A chair, a floor, a patch of grass — anywhere you can be still.
|
You can use meditate on your bed, in the car, on a chair or the floor, a patch of grass — anywhere you can be still.
|
||||||
|
|
||||||
---
|
### Zen
|
||||||
|
|
||||||
|
The word *zen* traces back through the Chinese *chan* to the Sanskrit *dhyāna*, meaning meditation or deep absorption. The ancient sages studied this state with extraordinary care, and the depth of their insight is something our modern mind can only begin to appreciate. See Patanjali's *Yoga Sutras* if you'd like to go deeper.
|
||||||
|
|
||||||
|
#### Focus
|
||||||
|
|
||||||
|
The mind can rest on many different objects in meditation. We suggest starting with the breath, since it is a simple and direct link to your soul and to the universe — every breath is an exchange between your being and the greater oneness that holds it.
|
||||||
|
|
||||||
|
You can also choose another single point of focus to help the mind settle — a sound (mantra) or a form (yantra). In all, there are 112 techniques for focusing the mind, explored in the ancient text *Vijñāna Bhairava Tantra*.[1](#user-content-fn-1)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## Gratitude journal
|
## Gratitude journal
|
||||||
|
|
||||||
Before bed or first thing in the morning, write down three things you are genuinely grateful for. Not generic blessings — specific moments. The warmth of sunlight through a window. A conversation that landed. The taste of a ripe fruit.
|
- [ ] Before bed or first thing, write down 3 specific things you're grateful for
|
||||||
|
- [ ] Do this every day for one week and notice the shift
|
||||||
|
|
||||||
Gratitude is not toxic positivity. It is the deliberate practice of noticing what is already good, which rewires the brain away from its negativity bias over time.
|
Not generic blessings — specific moments. The warmth of sunlight through a window. A conversation that landed. The taste of a ripe fruit.
|
||||||
|
|
||||||
---
|
Gratitude is the deliberate practice of noticing what is already good, which rewires the brain away from its negativity bias over time.
|
||||||
|
|
||||||
## Personality defect removal
|
## Merit journal
|
||||||
|
|
||||||
This is the inner work few want to do: asking honestly where you are still reactive.
|
The merit journal is a practice for reinforcing the virtues in our personality. It can be as simple as noting a smile you offered a stranger on the street or the time you spent truly listening to a friend's concern. By writing down the good you've done, you create a record to reflect upon — especially valuable in the moments before leaving the body at the end of life. Our character is the one thing we carry with us when we depart, so it is well worth the effort to reflect upon and cultivate it.
|
||||||
|
|
||||||
- Where am I still carrying anger?
|
- [ ] Write an entry in your merit journal
|
||||||
- What am I afraid of?
|
|
||||||
- How can I be more patient today?
|
|
||||||
- Where could I replace judgment with kindness?
|
|
||||||
|
|
||||||
Don't fix it all at once. Pick one thread and follow it. The goal is not to become perfect — it is to become less defended, more available, more unconditionally loving. Not toward everyone else first — toward yourself.
|
***
|
||||||
|
|
||||||
|
## Improvements journal
|
||||||
|
|
||||||
|
This is the inner work few want to do: asking honestly where you are still reactive, and where your character could grow more harmonious and balanced.
|
||||||
|
|
||||||
|
Almost every emotion has its time and place. Sometimes it is good to rest or to feel impatient, and anger can be necessary to provoke action. In general, though, we can soften the distorted forms of these emotions (emotion is energy in motion) and cultivate their positive counterparts instead. Balance is the aim.
|
||||||
|
|
||||||
|
- [ ] Ask yourself: Where am I still carrying anger?
|
||||||
|
- [ ] Ask yourself: What am I afraid of?
|
||||||
|
- [ ] Ask yourself: How can I be more patient today?
|
||||||
|
- [ ] Replace one judgment with kindness today
|
||||||
|
|
||||||
|
To start, pick the one with the most impact, often anger. The goal is not to become perfect — it is to become less impulsive, more available, more unconditionally loving. Starting with yourself is key. Notice your thought patterns and how you speak to yourself. Do you scold yourself over a trivial mistake? How might you extend and deepen your patience toward yourself?
|
||||||
|
|
||||||
??? question "A simple evening practice"
|
??? question "A simple evening practice"
|
||||||
Sit quietly and replay the day. Notice any moment where you contracted — irritation, defensiveness, avoidance. Don't judge the reaction. Just see it. Tomorrow, you'll have another chance.
|
|
||||||
|
|
||||||
---
|
Sit quietly and replay the day. Notice any moment where you contracted — irritation, defensiveness, avoidance. Don't judge the reaction. Just see it. Tomorrow, you'll have another chance. If you like you can journal your reflections and over time you may see just by noticing them things have started to resolve.
|
||||||
|
|
||||||
|
After reviewing the key area you'd like to work on you can use auto-suggestion to improve it.
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## Movement: energy and strength
|
## Movement: energy and strength
|
||||||
|
|
||||||
|
|
@ -48,20 +79,30 @@ The body needs two kinds of movement every day:
|
||||||
|
|
||||||
**Energy practice** — yoga, tai chi, qigong, or simple stretching with breath awareness. This moves *prana* (life force) through the channels of the body. Even ten minutes shifts the nervous system from fight-or-flight to rest-and-digest.
|
**Energy practice** — yoga, tai chi, qigong, or simple stretching with breath awareness. This moves *prana* (life force) through the channels of the body. Even ten minutes shifts the nervous system from fight-or-flight to rest-and-digest.
|
||||||
|
|
||||||
**Cardio and strength** — walking briskly, running, bodyweight exercises, lifting. The body evolved to move against resistance. Without it, the mind stagnates too.
|
- [ ] Do 10 minutes of energy practice this morning (yoga, stretching, tai chi)
|
||||||
|
- [ ] Do 20 minutes of cardio or strength work today
|
||||||
|
|
||||||
|
**Cardio and strength** — walking briskly, running, bodyweight exercises, lifting. The body evolved to move against resistance. Without it, the mind stagnates too. Cardio comes in two intensities, and both are necessary: low intensity (such as energy practice or gardening) and high intensity (such as running, cycling, swimming, or tennis). High intensity is anything that raises your heart rate and makes you sweat.
|
||||||
|
|
||||||
Pair them. Energy practice in the morning to open; strength in the afternoon to ground.
|
Pair them. Energy practice in the morning to open; strength in the afternoon to ground.
|
||||||
|
|
||||||
---
|
***
|
||||||
|
|
||||||
## Visualization: morning and night
|
## Visualization: morning and night
|
||||||
|
|
||||||
Every morning and every night before sleep, spend two minutes visualizing the future you want — for yourself, your family, your community, your 'tribe.' See it as if it is real *now*. Feel the gratitude as if it has already arrived.
|
- [ ] Spend 2 minutes each morning visualizing the future you want — see it as real *now*
|
||||||
|
- [ ] Spend 2 minutes before sleep visualizing the same — feel the gratitude as if it arrived
|
||||||
|
|
||||||
This is not magical thinking. It is the practice of orienting the subconscious toward what you are building, so that during the day, you recognize the doors when they appear.
|
This is the practice of orienting the subconscious toward what you are building, so that during the day, you recognize the doors when they appear.
|
||||||
|
|
||||||
---
|
***
|
||||||
|
|
||||||
**Related:** [Finding Your Purpose](../../teachings/finding-purpose.md) — when sadhana meets direction.
|
**Related:** [Finding Your Purpose](../../strategies/finding-purpose.md) — when sadhana meets direction.
|
||||||
|
|
||||||
*What practice will you show up for tomorrow?*
|
*What practice will you show up for tomorrow?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
||||||
|
## Footnotes
|
||||||
|
|
||||||
|
1. The *Vijñāna Bhairava Tantra*, a 7th–8th century Kashmir Shaivism text, presents 112 dhāraṇās (meditation techniques) as a dialogue between Bhairava and the goddess Bhairavi, who together personify the interplay between consciousness and energy. [Wikipedia](https://en.wikipedia.org/wiki/Vij%C3%B1%C4%81na_Bhairava_Tantra) [↩](#user-content-fnref-1)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,11 @@ icon: material/phone-check
|
||||||
|
|
||||||
# Digital Wellness
|
# Digital Wellness
|
||||||
|
|
||||||
|
<figure class="page-hero">
|
||||||
|
<img src="../assets/images/digital-wellness.jpg" alt="A peaceful nature scene — digital detox in the forest" loading="lazy">
|
||||||
|
<figcaption>Photo by <a href="https://unsplash.com/@lianhao">Lianhao Qu</a> on Unsplash</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
Your attention is the most valuable resource you own. Every notification, every algorithmic feed, every autoplay is designed to extract it. Taking it back is not a luxury — it is a prerequisite for any kind of awakening.
|
Your attention is the most valuable resource you own. Every notification, every algorithmic feed, every autoplay is designed to extract it. Taking it back is not a luxury — it is a prerequisite for any kind of awakening.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -12,6 +17,8 @@ Your attention is the most valuable resource you own. Every notification, every
|
||||||
|
|
||||||
Try this: no news for one week. No headlines, no push alerts, no doom-scrolling. The world will continue. The things you actually need to know will reach you through people, not algorithms.
|
Try this: no news for one week. No headlines, no push alerts, no doom-scrolling. The world will continue. The things you actually need to know will reach you through people, not algorithms.
|
||||||
|
|
||||||
|
- [ ] Try a one-week news fast — no headlines, no push alerts, no doom-scrolling
|
||||||
|
|
||||||
After a week, notice: is your anxiety lower? Is your attention span longer? Are you more present with the people in front of you?
|
After a week, notice: is your anxiety lower? Is your attention span longer? Are you more present with the people in front of you?
|
||||||
|
|
||||||
!!! note "The 0% horror rule"
|
!!! note "The 0% horror rule"
|
||||||
|
|
@ -35,9 +42,10 @@ Set boundaries you can actually keep:
|
||||||
- [ScreenZen](https://screenzen.co/) — makes you pause before opening apps, breaking the reflex loop.
|
- [ScreenZen](https://screenzen.co/) — makes you pause before opening apps, breaking the reflex loop.
|
||||||
- [Kids360](https://kids360.app/) — for children's devices, with transparent limits rather than secret surveillance.
|
- [Kids360](https://kids360.app/) — for children's devices, with transparent limits rather than secret surveillance.
|
||||||
- No screens in the bedroom. Charge devices in another room.
|
- No screens in the bedroom. Charge devices in another room.
|
||||||
- Read a physical book or have a real conversation instead of reaching for a screen in idle moments.
|
- [ ] Remove or mute one app that drains your attention
|
||||||
|
- [ ] Replace one hour of screen time this week with an outdoor activity
|
||||||
|
|
||||||
The goal is not abstinence. It's agency.
|
The point is to cultivate your agency and command over your tech, you should be the one in control.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -55,6 +63,8 @@ The internet is a tool. When it becomes the environment, you've lost the plot.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Related:** [Digital Sovereignty](../../teachings/digital-sovereignty.md) — when wellness meets infrastructure.
|
**Related:** [Digital Sovereignty](../../strategies/digital-sovereignty.md) — when wellness meets infrastructure.
|
||||||
|
|
||||||
*What's the first app you'll set a limit on today?*
|
*What's the first app you'll set a limit on today?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,42 @@ icon: material/nature-people
|
||||||
|
|
||||||
# Grounding in Nature
|
# Grounding in Nature
|
||||||
|
|
||||||
The earth beneath your feet has been waiting for you. Not metaphorically — literally. Every moment spent with bare skin on soil, grass, or sand is a reconnection to the electromagnetic field that humans evolved within for hundreds of thousands of years.
|
<figure class="page-hero">
|
||||||
|
<img src="../assets/images/nature_bathing.jpg" alt="Forest bathing — a person immersed in dappled woodland light" loading="lazy">
|
||||||
|
<figcaption>Photo by Adamu</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
Every moment spent with bare skin on soil, grass, or sand is a reconnection to the electromagnetic field that humans evolved within for hundreds of thousands of years.
|
||||||
|
|
||||||
|
The Earth (whose other names include mother Gaia, Aurora, Aurelia, Tara), is a living being, and we are a small part of her.
|
||||||
|
|
||||||
|
But connecting to the ground, whether that's by contact with our bare feet, using grounding blanket or pad, or even lying down and rolling (one of the best ways to rebalance energy when it gets too high!) we are chemically interacting with our physical Source via ionic exchange.
|
||||||
|
|
||||||
|
Even if we can't physically touch the earth we can use awareness, visualisation and intention to guide our energy body down and root it into the crystalline core of mother Gaia. This crystalline core differs from the iron core of earth and is in a higher dimension.
|
||||||
|
|
||||||
|
!!! info inline end "Coming soon"
|
||||||
|
|
||||||
|
Guided meditation for grounding to mother earth
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Why ground?
|
## Why ground?
|
||||||
|
|
||||||
Modern life separates us from the earth: rubber-soled shoes, elevated buildings, concrete pavements. The simple act of barefoot contact — called *earthing* or *grounding* — allows the body to absorb free electrons from the earth's surface. Research suggests this can reduce inflammation, improve sleep, and calm the nervous system.
|
Modern life separates us from the earth: rubber-soled shoes, elevated buildings, concrete pavements. The simple act of barefoot contact — called _earthing_ or _grounding_ — allows the body to absorb free electrons from the earth's surface. Research has documented reductions in inflammation, improved sleep, and measurable shifts in nervous system function from regular grounding practice.[^1]
|
||||||
|
|
||||||
!!! note "Start small"
|
!!! note "Start small"
|
||||||
|
|
||||||
Five minutes of bare feet on grass in the morning is enough to begin. You don't need a forest retreat — a patch of lawn, a beach, or even damp soil in a garden works.
|
Five minutes of bare feet on grass in the morning is enough to begin. You don't need a forest retreat — a patch of lawn, a beach, or even damp soil in a garden works.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Sun gazing: reconnecting with light
|
## Sun gazing: reconnecting with light
|
||||||
|
|
||||||
Sun gazing is an ancient practice of looking at the sun during the first or last hour of daylight, when UV levels are safe. Start with 10 seconds and never push beyond comfort. The practice is less about the eyes and more about allowing the body's circadian rhythm to realign with natural light cycles.
|
Sun gazing is an ancient practice of looking at the sun during the first or last hour of daylight, when UV levels are lower. Start with 10 seconds and never push beyond comfort. The practice is less about the eyes and more about allowing the body's circadian rhythm to realign with natural light cycles.
|
||||||
|
|
||||||
|
!!! warning "Eye safety"
|
||||||
|
|
||||||
|
Tilt you head down and look 2 inches above the Sun, not directly at it. Stop if you feel discomfort and only gradually build up the duration, starting with 10 seconds and working up to 15 minutes over 6 months is a realistic goal. Some yogis look directly at the sun during midday but this is achieved over many years of practice.
|
||||||
|
|
||||||
Sit. Breathe. Let the light wash over you. No agenda.
|
Sit. Breathe. Let the light wash over you. No agenda.
|
||||||
|
|
||||||
|
|
@ -27,22 +47,30 @@ Sit. Breathe. Let the light wash over you. No agenda.
|
||||||
|
|
||||||
## Sitting practice: temples, forests, waterfalls
|
## Sitting practice: temples, forests, waterfalls
|
||||||
|
|
||||||
Find a place where nature is doing its thing without human orchestration — a forest floor, a temple courtyard, beside a waterfall. Then do the hardest thing: nothing.
|
Find a place where nature is doing its thing without human orchestration — a forest floor, a temple courtyard, beside a waterfall. Looking at the fractal form of nature found in trees, leaves, and the entire environment is highly nourishing for the nervous system. More significantly the energy flow in nature is more balanced and harmonious, whereas buildings and rooms composed of steel, aluminium and electrosmog are dissonant and disturb this flow.
|
||||||
|
|
||||||
Don't meditate. Don't journal. Don't photograph.
|
??? info "Discover more"
|
||||||
|
|
||||||
Just sit and watch. Notice how the mind, given no task, eventually settles. This is *melukat* in the Balinese tradition — water purification not just of the body, but of the energetic residue we carry. Even sitting beside moving water, without entering it, can shift something.
|
- [ ] See Dan Winter's talks on fractal geometry on YouTube
|
||||||
|
|
||||||
|
Just sit and watch. Notice how the mind, given no task, eventually settles. This is _melukat_ in the Balinese tradition — water purification not just of the body, but of the energetic residue we carry.[^2] Even sitting beside moving water, without entering it, can shift something.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Integrating nature time
|
## Integrating nature time
|
||||||
|
|
||||||
The guideline is simple: for every hour spent on a device, spend an equal hour in direct contact with the natural world. This isn't a punishment — it's a restoration.
|
The guideline is simple: for every hour on a device, spend an equal hour in direct contact with the natural world. Think of it as restoration and a reward.
|
||||||
|
|
||||||
Start tracking it loosely. You may find, as many do, that the nature hours become the ones you crave.
|
Start tracking it loosely. You may find, as many do, that the nature hours become the ones you crave.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Related:** [Nourishing the Body](../practices/nourishing-the-body.md) — bringing nature inside through food and materials.
|
**Related:** [Nourishing the Body](nourishing-the-body.md) — bringing nature inside through food and materials.
|
||||||
|
|
||||||
*What patch of earth will you stand on tomorrow morning?*
|
_What patch of earth will you stand on tomorrow morning?_
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
||||||
|
[^1]: Oschman JL, Chevalier G, Brown R. "The effects of grounding (earthing) on inflammation, the immune response, wound healing, and prevention and treatment of chronic inflammatory and autoimmune diseases." *Journal of Inflammation Research*, 2015. [PMC4378297](https://pmc.ncbi.nlm.nih.gov/articles/PMC4378297/)
|
||||||
|
|
||||||
|
[^2]: Melukat is a Balinese Hindu water purification ritual performed at holy springs (*tirta*) to cleanse the body and spirit. [merusaka.com](https://merusaka.com/bali-cultural-experience/bali-sacred-water-melukat-purification-ritual/)
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,15 @@ icon: material/run
|
||||||
|
|
||||||
# Practices
|
# Practices
|
||||||
|
|
||||||
Small, doable actions. Each practice here is something you can try today — no preparation, no expertise, just willingness.
|
Small, doable actions. Each one is something you can try today — no preparation, no expertise, just willingness.
|
||||||
|
|
||||||
<div class="grid cards" markdown>
|
<div class="grid cards gp-cards-practices" markdown>
|
||||||
|
|
||||||
- [:material-nature-people: **Grounding in Nature**](grounding-in-nature.md) — Barefoot contact, sun gazing, sitting practice, melukat
|
- [:material-nature-people: **Grounding in Nature**](grounding-in-nature.md) Barefoot contact, sun gazing, sitting practice, melukat
|
||||||
- [:material-food-apple: **Nourishing the Body**](nourishing-the-body.md) — Real food, herbal teas, fasting, natural materials, self-massage
|
- [:material-food-apple: **Nourishing the Body**](nourishing-the-body.md) Real food, herbal teas, fasting, natural materials, self-massage
|
||||||
- [:material-meditation: **Daily Sadhana**](daily-sadhana.md) — Meditation, gratitude, shadow work, movement, visualization
|
- [:material-meditation: **Daily Sadhana**](daily-sadhana.md) Meditation, gratitude, shadow work, movement, visualization
|
||||||
- [:material-phone-check: **Digital Wellness**](digital-wellness.md) — News fast, screen limits, curating what enters your mind
|
- [:material-phone-check: **Digital Wellness**](digital-wellness.md) News fast, screen limits, curating what enters your mind
|
||||||
|
- [:material-spa: **Spiritual Hygiene**](spiritual-hygiene.md) Cleanse your space, set intention, sound as medicine
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,40 @@
|
||||||
---
|
---
|
||||||
icon: material/food-apple
|
icon: material/food-apple
|
||||||
---
|
---
|
||||||
|
|
||||||
# Nourishing the Body
|
# Nourishing the Body
|
||||||
|
|
||||||
The body is not a machine to be fueled — it is a living garden that responds to everything you place in it, on it, and around it. Nourishment goes far beyond calories.
|
The body is a highly sophisticated ecosystem that responds to everything you place in it, on it, and around it.
|
||||||
|
|
||||||
---
|
Our focus has been guided towards numbers like calories, steps, BMI (weight and height). These quantitative perspectives can be practical, but they often overlook the more subtle qualitative dimensions of health that can be observed and felt more easily through focused awareness than with measures and scales or lab equipment.
|
||||||
|
|
||||||
## Food from people, not corporations
|
??? info "Dive deeper"
|
||||||
|
|
||||||
|
```text
|
||||||
|
The body is comprised of a fine balance of elements in different frequencies and states. These are a reflection of the state of the underlying aether at phases and degrees of motion. For instance solid materials are heavy, dense and even though it appears inert, their molecules are actually moving, albeit very slowly. Whereas when these molecules are heated, they undergo a dissolution of the bonds (which are really not a solid thing either, more an electrostatic coupling), and they 'melt' and move from solid to liquid and eventually to a gas and residue (solid aggregate byproduct). If we take more descriptive names to the states we could say the solid "earth" moves through liquid "water" by a process called "fire" and transforms into a gas called "air". Really all these states are part of one all encompassing consciousness and energy, the essence of which is plasma or "aether" as named in Ancient Greek. Modern science disregards this final point, owing to an experiment in 1887 called the Michelson Morley experiment, however this does not actually disprove the existence aether. You can read more about this at Aether Force Blog
|
||||||
|
```
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## Food from farmers, gardens and your plant pots, not corporations
|
||||||
|
|
||||||
Most of what fills supermarket shelves is the product of monopolized supply chains — processed, preserved, and profited from at every step. The alternative is older and simpler: know who grows your food.
|
Most of what fills supermarket shelves is the product of monopolized supply chains — processed, preserved, and profited from at every step. The alternative is older and simpler: know who grows your food.
|
||||||
|
|
||||||
Work with local farmers. Join a CSA (community-supported agriculture). Buy from a neighbor who keeps hens. Trade skills for produce. When you eat food grown by someone you've spoken to, something shifts — you're no longer a consumer but a participant in a living exchange.
|
Work with local farmers. Join a CSA (community-supported agriculture). Buy from a neighbor who keeps hens. Trade skills for produce. When you eat food grown by yourself or someone you've spoken to, something shifts — you feel the livingness of the food and the vitality it brings you.
|
||||||
|
|
||||||
!!! warning "The supermarket trap"
|
!!! warning "The supermarket trap"
|
||||||
Nearly every aisle in a conventional supermarket funnels money into a handful of conglomerates. The [documentary on monopoly food systems](https://www.youtube.com/watch?v=nLZV5EesNNI) is worth watching. Start by removing one aisle at a time from your routine.
|
|
||||||
|
|
||||||
---
|
```text
|
||||||
|
Nearly every aisle in a conventional supermarket funnels money into a handful of conglomerates. The [documentary on monopolies](https://www.youtube.com/watch?v=nLZV5EesNNI) covers how all the big brand food items are owned by a handful of conglomerates and VC firms and is worth watching to see how it is possible that near everything in your Walgreens or 7 eleven has been engineered for profit and without your best interest or health at heart. You could also see Pam Peeke's fantastic lecture on the Hacked and Hijacked brain on how fast food acts like cocaine on the dopamine centres of the brain, and how to reset via meditation. Start by removing one aisle at a time from your routine and soon you'll feel your taste buds catching up to your desire for healthy organic and fresh natural food and drinks.
|
||||||
|
```
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## Herbal teas as daily medicine
|
## Herbal teas as daily medicine
|
||||||
|
|
||||||
Herbal teas are one of the gentlest ways to rebalance the body throughout the day:
|
Herbal teas are one of the gentlest ways to rebalance the body throughout the day:
|
||||||
|
|
||||||
| Time | Tea | Purpose |
|
| Time | Tea | Purpose |
|
||||||
|------|-----|---------|
|
| --------------- | ------------------------------------------------ | ------------------------- |
|
||||||
| Morning | Flower teas (chamomile, jasmine, rose) | Light, opening, uplifting |
|
| Morning | Flower teas (chamomile, jasmine, rose) | Light, opening, uplifting |
|
||||||
| After meals | Ginger tea | Digestive fire, warmth |
|
| After meals | Ginger tea | Digestive fire, warmth |
|
||||||
| When agitated | Vata-pacifying (licorice, cinnamon, ashwagandha) | Grounding, calming |
|
| When agitated | Vata-pacifying (licorice, cinnamon, ashwagandha) | Grounding, calming |
|
||||||
|
|
@ -32,15 +42,19 @@ Herbal teas are one of the gentlest ways to rebalance the body throughout the da
|
||||||
|
|
||||||
Learn your own patterns. The tea that works for someone else may not be yours — experiment gently.
|
Learn your own patterns. The tea that works for someone else may not be yours — experiment gently.
|
||||||
|
|
||||||
---
|
- [ ] Try a new herbal tea
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## Fasting as reset
|
## Fasting as reset
|
||||||
|
|
||||||
Fasting doesn't need to be extreme to be effective. Start with one day a week of liquids only — fresh juices, soups, herbal teas. From there, try a 24-hour water fast. With guidance, you can work toward a 3-day water fast, which triggers deeper cellular repair processes (autophagy).
|
Fasting doesn't need to be extreme to be effective. Start with one day a week of liquids only — fresh juices, soups, herbal teas. From there, try a 24-hour water fast. With guidance, you can work toward a 3-day water fast, which triggers deeper cellular repair processes (autophagy).[1](#user-content-fn-1)
|
||||||
|
|
||||||
The goal is not deprivation. It's giving the digestive system the rest it rarely receives in a culture of constant consumption.
|
It's about giving the digestive system the rest it rarely receives in a culture of constant consumption.
|
||||||
|
|
||||||
---
|
- [ ] Try eating or drinking only fruits (smoothies allowed with coconut water) for 24 hours
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## What touches your skin
|
## What touches your skin
|
||||||
|
|
||||||
|
|
@ -48,7 +62,13 @@ Gradually replace clothing and bed linen with natural, non-toxic materials: orga
|
||||||
|
|
||||||
The same applies to what you put *on* your body. A self oil massage (*abhyanga*) with a simple, chemical-free oil suited to your constitution — or just pure coconut oil — is a daily practice that nourishes skin, calms the nervous system, and reconnects you to your own body with care rather than criticism.
|
The same applies to what you put *on* your body. A self oil massage (*abhyanga*) with a simple, chemical-free oil suited to your constitution — or just pure coconut oil — is a daily practice that nourishes skin, calms the nervous system, and reconnects you to your own body with care rather than criticism.
|
||||||
|
|
||||||
---
|
- [ ] Replace one item of synthetic clothing with a fully natural alternative
|
||||||
|
|
||||||
|
??? info "Hint"
|
||||||
|
|
||||||
|
Start with underwear. A 1993 study found that polyester underwear caused significant (mostly reversible) damage to sperm production in dogs, while cotton had no effect — the cause was electrostatic charge or some other effect from wearing synthetic fabrics.[2](#user-content-fn-2)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## Small detox steps
|
## Small detox steps
|
||||||
|
|
||||||
|
|
@ -58,8 +78,15 @@ The same applies to what you put *on* your body. A self oil massage (*abhyanga*)
|
||||||
|
|
||||||
None of this needs to happen overnight. One change, held consistently, reshapes a life.
|
None of this needs to happen overnight. One change, held consistently, reshapes a life.
|
||||||
|
|
||||||
---
|
***
|
||||||
|
|
||||||
**Related:** [Grounding in Nature](../practices/grounding-in-nature.md) — where nourishment meets the earth.
|
**Related:** [Grounding in Nature](grounding-in-nature.md) — where nourishment meets the earth.
|
||||||
|
|
||||||
*What's one thing your body has been quietly asking you to change?*
|
*What's one thing your body has been quietly asking you to change?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
||||||
|
## Footnotes
|
||||||
|
|
||||||
|
1. Autophagy — the body's cellular cleanup and recycling process — was the subject of Yoshinori Ohsumi's 2016 Nobel Prize in Physiology or Medicine. Fasting is one of the most reliable ways to trigger it. [nobelprize.org](https://www.nobelprize.org/prizes/medicine/2016/ohsumi/facts/) [↩](#user-content-fnref-1)
|
||||||
|
2. Shafik A. "Effect of different types of textile fabric on spermatogenesis: an experimental study." *Urological Research*, 1993. [PMID: 8279095](https://pubmed.ncbi.nlm.nih.gov/8279095/) — Note: this was an animal study (dogs). [↩](#user-content-fnref-2)
|
||||||
|
|
|
||||||
99
docs/practices/spiritual-hygiene.md
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
---
|
||||||
|
icon: material/spa
|
||||||
|
---
|
||||||
|
# Spiritual Hygiene
|
||||||
|
|
||||||
|
Just as you wash your body, your space and energy field benefit from regular tending too. Environments hold residue, and your intention shapes what you encounter.
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## Cleansing your space
|
||||||
|
|
||||||
|
- See the [[docs/practices/daily-sadhana]] action items that will also affect your space. The humans in a space have the greatest impact upon its vibration.
|
||||||
|
- Chanting is a very powerful way to raise vibration in a space. You can use any sound you enjoy that connects you to yourself. Chanting in the mind is more powerful than out loud.
|
||||||
|
- [ ] Clear and declutter one space in your home right now
|
||||||
|
- Clean and declutter: every object carries a subtle energetic weight, see [Marie Kondo](https://www.youtube.com/@MarieKondoTV) and [A monk's guide to a clean house and mind](https://www.thezengateway.com/culture/an-interview-with-shoukei-matsumoto-author-of-a-monk-s-guide-to-a-clean-house-and-mind)
|
||||||
|
- Cleaning is extremely important, as any dirt and detritus will repel higher consciousness beings and attract those from the lower realms, just like how if you leave a mess insects will be drawn to it, the same applies to non physical beings. A clean home and a clean heart are pre-requisites to connecting to angelic and divine beings.
|
||||||
|
- Open windows daily and allow light and fresh air to circulate through your space
|
||||||
|
- Remove electronics from the room, or at minimum cover screens
|
||||||
|
- [ ] Try a sound cleansing — ring a brass bell, play a singing bowl, or put on Solfeggio tones for 10 minutes
|
||||||
|
- Use pure frequency: a brass bell with bright tones, a tibetan or crystal singing bowl, download and play a Tarpan music, or Solfeggio tone music in the background on your phone.
|
||||||
|
- Burn natural incense or diffuse pure essential oils (frankincense, sage, palo santo)
|
||||||
|
|
||||||
|
!!! info "Discover more"
|
||||||
|
|
||||||
|
- Healing with Form, Energy and Light by Tenzin Wangyal Rinpoche
|
||||||
|
- Pranic Healing by Master Choa Kok Sui
|
||||||
|
|
||||||
|
??? question "How often should I cleanse?"
|
||||||
|
|
||||||
|
A light daily clearing (open window, intention setting) and a deeper weekly reset (sound, smoke, decluttering) is a sustainable rhythm. After arguments, illness, or visits from heavy energy, cleanse immediately and go outside for a walk.
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## Clearing Sleep Space
|
||||||
|
|
||||||
|
Your bedroom is the most important room to tend. You spend a third of your life there, in a more unconscious and receptive state. Make your bed as soon as you wake up, crumpled sheets create surprisingly discordant energy. It also helps you feel you've achieved something and sets the precedent to take care of yourself and your life.
|
||||||
|
|
||||||
|
Before sleeping you can light a ghee or sattvic oil lamp, being careful it will not be disturbed or near any flammable items. You could keep a shrine or altar with items that make you happy and feel love, that could be family or those who have inspired you who have good character.
|
||||||
|
|
||||||
|
### Intention
|
||||||
|
|
||||||
|
Before sleep, state clearly — aloud or internally:
|
||||||
|
|
||||||
|
> *I invite only energies of the highest light to interact with me. My space is sovereign. My field is clear.*
|
||||||
|
|
||||||
|
- [ ] Set this intention aloud before sleep tonight
|
||||||
|
|
||||||
|
You don't need to believe in guides for this to work. The practice is about setting a boundary and orienting your awareness toward what is loving, clear, and true. Whatever your framework — ancestors, angels, higher self, or simply the clearest version of your own consciousness — the act of calling it in is what matters.
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## Sound as medicine
|
||||||
|
|
||||||
|
The frequencies you surround yourself with shape your nervous system. Consider:
|
||||||
|
|
||||||
|
- Solfeggio tones — a set of frequencies used in alternative healing traditions:[^1]
|
||||||
|
- **432 Hz** — often described as calming and naturally resonant
|
||||||
|
- **528 Hz** — sometimes called the "love frequency" and associated with transformation in alternative medicine circles
|
||||||
|
- **Natural classical** — Debussy, Ravi Shankar — music that creates space rather than filling it
|
||||||
|
- **Kirtan and mantra** — collective chanting that synchronizes heart rates and entrains the group field
|
||||||
|
|
||||||
|
The rule is simple: if a song has a single negative word or message, skip it. The subconscious absorbs everything. Curate your sound environment as carefully as your food.
|
||||||
|
|
||||||
|
- [ ] Try a week of only positive, uplifting music — no negative lyrics
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## Group singing, toning, and joy
|
||||||
|
|
||||||
|
Human voices together are one of the most powerful frequency generators available. Group singing — kirtan, toning, community choirs, or just friends around a fire — synchronizes nervous systems, releases oxytocin, and creates a field of shared vibration that lingers long after the sound stops.
|
||||||
|
|
||||||
|
Pair this with:
|
||||||
|
|
||||||
|
- **Uplifting art** — surround yourself with images that open the heart
|
||||||
|
- **Light-hearted comedy** — laughter is a genuine cleansing practice
|
||||||
|
- **Positive energy events** — gatherings where the purpose is simply to feel good together
|
||||||
|
- **Joy maxxing** is relentlessly choosing what your heart calls you to do, even if you would have been shy or too scared to pursue it normally. It could be wearing that silly hat, or singing and dancing in the rain. Take at least one day a week or one hour a day to really follow your heart!
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## Mass meditations and peace visualization
|
||||||
|
|
||||||
|
When large numbers of people hold the same intention simultaneously, something measurable shifts. A 2017 study of large Transcendental Meditation groups found a 28.4% reduction in murder rates across 206 US urban areas during periods when the practicing group exceeded a critical threshold.[^2] Similar studies have reported reductions in violent crime, traffic fatalities, and drug-related deaths during the same periods.
|
||||||
|
|
||||||
|
Join global mass meditations when they are called. Or gather a small group — even three people — and sit together with the intention of peace and the most positive timeline for humanity.
|
||||||
|
|
||||||
|
Create something tangible to crystallize the intention: a doodle, a piece of art, a short written statement of what that positive timeline looks like *for you*. Make it specific. Make it beautiful. Keep it visible.
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
**Related:** [Daily Sadhana](daily-sadhana.md) — spiritual hygiene as daily practice.
|
||||||
|
|
||||||
|
*What's the first thing you'll clear from your bedroom tonight?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
||||||
|
[^1]: Solfeggio frequencies originate from a medieval hymn to St. John the Baptist and were reinterpreted in the 1970s by Dr. Joseph Puleo as healing tones. While many people find them subjectively calming, there is no rigorous scientific evidence that specific frequencies repair DNA or produce specific physiological effects. A 2019 review noted that most published studies on 432 Hz music are small and preliminary. [scienceinsights.org](https://scienceinsights.org/what-is-528-hz-the-love-frequency-explained/)
|
||||||
|
|
||||||
|
[^2]: Cavanaugh KL, Dillbeck MC. "Field-effects of consciousness: A follow-up study on the reduction of murder rates in large US urban areas." *Journal of Health and Environmental Research*, 2017. The study was conducted by researchers at Maharishi University of Management, the institution founded by the founder of Transcendental Meditation. Results are debated in the wider scientific community. [EurekAlert summary](https://www.eurekalert.org/news-releases/511271)
|
||||||
|
|
@ -4,18 +4,23 @@ icon: material/hand-heart
|
||||||
|
|
||||||
# Collective Awakening
|
# Collective Awakening
|
||||||
|
|
||||||
|
<figure class="page-hero">
|
||||||
|
<img src="../assets/images/collective-awakening.jpg" alt="Group of people meditating together in nature at golden hour" loading="lazy">
|
||||||
|
<figcaption>Photo by <a href="https://unsplash.com/@rishikesh_yogpeeth">Rishikesh Yogpeeth</a> on Unsplash</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
Awakening is often described as an individual journey, but it has never been a solo project. Consciousness shifts ripple through groups, communities, and fields — and when enough people hold the same frequency simultaneously, something in the collective field changes.
|
Awakening is often described as an individual journey, but it has never been a solo project. Consciousness shifts ripple through groups, communities, and fields — and when enough people hold the same frequency simultaneously, something in the collective field changes.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## The power of mass intention
|
## The power of mass intention
|
||||||
|
|
||||||
Decades of research on group meditation — particularly large Transcendental Meditation assemblies — has documented statistically significant reductions in crime, violence, hospital admissions, and traffic fatalities when a critical mass (roughly the square root of 1% of a population) meditates together.
|
Decades of research on group meditation — particularly large Transcendental Meditation assemblies — has documented correlations between group practice and reductions in crime, violence, and other social stress indicators when a critical mass (roughly the square root of 1% of a population) meditates together.[^1]
|
||||||
|
|
||||||
The mechanism is debated. The data is not.
|
|
||||||
|
|
||||||
When you join a mass meditation — whether online or in person — you are not just calming your own nervous system. You are contributing to a field. The intention you hold for peace, for the most positive timeline, is not private. It radiates.
|
When you join a mass meditation — whether online or in person — you are not just calming your own nervous system. You are contributing to a field. The intention you hold for peace, for the most positive timeline, is not private. It radiates.
|
||||||
|
|
||||||
|
- [ ] Join a mass meditation this month — search online for upcoming global events
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Creating your own circle
|
## Creating your own circle
|
||||||
|
|
@ -35,11 +40,12 @@ Do it weekly. The consistency matters more than the size.
|
||||||
|
|
||||||
Between gatherings, make something tangible:
|
Between gatherings, make something tangible:
|
||||||
|
|
||||||
|
- [ ] Create a vision artifact — a doodle, statement, or drawing of the world you want to see
|
||||||
- **Doodles or drawings** — what does the peaceful world look like through your eyes?
|
- **Doodles or drawings** — what does the peaceful world look like through your eyes?
|
||||||
- **Written statements of intent** — short, present-tense declarations: *"Clean water flows freely. Children laugh without fear. Elders are honored. The land is tended."*
|
- **Written statements of intent** — short, present-tense declarations: *"Clean water flows freely. Children laugh without fear. Elders are honored. The land is tended."*
|
||||||
- **A shared board or album** — where each person contributes their vision of the positive timeline
|
- **A shared board or album** — where each person contributes their vision of the positive timeline
|
||||||
|
|
||||||
These artifacts are not wishful thinking. They are anchors. When the external world looks chaotic, the images and words you've created together remind you what you are building toward — and that you are building it together.
|
These artifacts serve as anchors. When the external world looks chaotic, the images and words you've created together remind you what you are building toward — and that you are building it together.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -59,7 +65,7 @@ Do this offline where possible. Face-to-face relationships with decision makers
|
||||||
|
|
||||||
Through all of this, hold a simple compass:
|
Through all of this, hold a simple compass:
|
||||||
|
|
||||||
- Is this action arising from love or from fear?
|
- [ ] Before the next emotional action, ask: Is this arising from love or from fear?
|
||||||
- Is it connecting people or dividing them?
|
- Is it connecting people or dividing them?
|
||||||
- Is it building something or only tearing something down?
|
- Is it building something or only tearing something down?
|
||||||
|
|
||||||
|
|
@ -67,6 +73,10 @@ Fear-based activism burns out. Love-based activism regenerates. The most radical
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Related:** [Spiritual Hygiene](./spiritual-hygiene.md) — keeping your own field clear so you can contribute cleanly to the collective.
|
**Related:** [Spiritual Hygiene](../practices/spiritual-hygiene.md) — keeping your own field clear so you can contribute cleanly to the collective.
|
||||||
|
|
||||||
*What does the most positive timeline look like to you — in one sentence?*
|
*What does the most positive timeline look like to you — in one sentence?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
||||||
|
[^1]: Cavanaugh KL, Dillbeck MC. "Field-effects of consciousness: A follow-up study on the reduction of murder rates in large US urban areas." *Journal of Health and Environmental Research*, 2017. A series of studies from Maharishi University researchers has found correlations between large TM-Sidhi groups and reductions in social stress indicators; the interpretation of these findings is not universally accepted. [EurekAlert summary](https://www.eurekalert.org/news-releases/511271)
|
||||||
|
|
@ -4,7 +4,12 @@ icon: material/crowd
|
||||||
|
|
||||||
# Community Sovereignty
|
# Community Sovereignty
|
||||||
|
|
||||||
Sovereignty is not something you achieve alone. It is built in relationship — with the land, with the people who grow food, with neighbors who share skills, and with networks that operate outside the extractive economy.
|
<figure class="page-hero">
|
||||||
|
<img src="../assets/images/community-sovereignty.jpg" alt="People shopping at a farmers market with fresh produce" loading="lazy">
|
||||||
|
<figcaption>Photo by <a href="https://unsplash.com/@theguccer2100">Spencer Plouzek</a> on Unsplash</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
Sovereignty grows in relationship — with the land, with the people who grow food, with neighbors who share skills, and with networks that operate outside the extractive economy.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -13,9 +18,9 @@ Sovereignty is not something you achieve alone. It is built in relationship —
|
||||||
Every dollar spent at a supermarket feeds a system designed to concentrate wealth and power. The alternative is older than capitalism: direct relationships with the people who produce what you consume.
|
Every dollar spent at a supermarket feeds a system designed to concentrate wealth and power. The alternative is older than capitalism: direct relationships with the people who produce what you consume.
|
||||||
|
|
||||||
- Join a local CSA (community-supported agriculture)
|
- Join a local CSA (community-supported agriculture)
|
||||||
- Buy from farmers' markets — talk to the people behind the stall
|
- [ ] Buy from farmers' markets — talk to the people behind the stall
|
||||||
- Trade skills: help with a harvest, offer web design, teach a class
|
- [ ] Trade skills: help with a harvest, offer web design, teach a class
|
||||||
- Grow something yourself, even if it's just herbs on a windowsill
|
- [ ] Grow something yourself, even if it's just herbs on a windowsill
|
||||||
|
|
||||||
When your food comes from someone you know, the transaction becomes a relationship. That relationship is the foundation of a parallel economy.
|
When your food comes from someone you know, the transaction becomes a relationship. That relationship is the foundation of a parallel economy.
|
||||||
|
|
||||||
|
|
@ -45,10 +50,10 @@ Research what's possible in your jurisdiction. Find lawyers and politicians with
|
||||||
|
|
||||||
Start small:
|
Start small:
|
||||||
|
|
||||||
- Cook a meal for someone who is struggling
|
- [ ] Cook a meal for someone who is struggling
|
||||||
- Sit and listen to someone who is lonely — just listen, no advice
|
- [ ] Sit and listen to someone who is lonely — just listen, no advice
|
||||||
- Clean a section of your local park or river
|
- [ ] Clean a section of your local park or river
|
||||||
- Offer your skills (legal, technical, therapeutic) to those who cannot pay
|
- [ ] Offer your skills (legal, technical, therapeutic) to those who cannot pay
|
||||||
|
|
||||||
Do three kind things every week that you tell no one about. The anonymity is part of the practice — it purifies the motivation.
|
Do three kind things every week that you tell no one about. The anonymity is part of the practice — it purifies the motivation.
|
||||||
|
|
||||||
|
|
@ -86,3 +91,5 @@ Consult aligned professionals. The goal is to keep resources circulating within
|
||||||
**Related:** [Digital Sovereignty](./digital-sovereignty.md) — because freedom networks need free infrastructure.
|
**Related:** [Digital Sovereignty](./digital-sovereignty.md) — because freedom networks need free infrastructure.
|
||||||
|
|
||||||
*Who in your community could you reach out to this week?*
|
*Who in your community could you reach out to this week?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
@ -10,7 +10,7 @@ Digital sovereignty means owning your own digital life — the hardware, the sof
|
||||||
|
|
||||||
## The hardware you already own
|
## The hardware you already own
|
||||||
|
|
||||||
You don't need a new device. An old laptop — the one gathering dust — can run Linux perfectly. Modern distributions like Linux Mint, Ubuntu, or Fedora breathe new life into aging hardware and free you from operating systems designed to extract data.
|
An old laptop — the one gathering dust — can run Linux perfectly. Modern distributions like MX Linux or Linux Mint breathe new life into aging hardware and free you from operating systems designed to extract data.
|
||||||
|
|
||||||
For phones, the path is similar:
|
For phones, the path is similar:
|
||||||
|
|
||||||
|
|
@ -27,11 +27,12 @@ For phones, the path is similar:
|
||||||
|
|
||||||
## Network sovereignty
|
## Network sovereignty
|
||||||
|
|
||||||
**Switch from WiFi to Ethernet** for your main computer. It's faster, more stable, and eliminates constant radio-frequency exposure at close range.
|
- [ ] Switch your main computer from WiFi to Ethernet
|
||||||
|
- [ ] On your phone: switch 5G to 4G, use airplane mode when not needed
|
||||||
|
- [ ] Install and use a trusted VPN with a clear no-logging policy
|
||||||
|
- [ ] Keep your phone away from your body — not in a pocket, not against your head
|
||||||
|
|
||||||
**On your phone**: switch 5G to 4G (lower frequency = less power = less exposure). Keep your phone on airplane mode when not actively needed. Keep it away from your body — not in a pocket, not against your head. Zero wearables (no smartwatch, no fitness tracker, no bluetooth earbuds).
|
**VPN**: A simple, trusted VPN prevents your internet provider from building a profile of every site you visit. Choose one with a clear no-logging policy and preferably based outside surveillance alliances. Mullvad, Nyx are good. If you want extra privacy pay via Monero.
|
||||||
|
|
||||||
**VPN**: A simple, trusted VPN prevents your internet provider from building a profile of every site you visit. Choose one with a clear no-logging policy and preferably based outside surveillance alliances.
|
|
||||||
|
|
||||||
**Meshtastic**: When the grid is not your friend, build your own. [Meshtastic](https://meshtastic.org/) lets you create off-grid, encrypted text networks using inexpensive LoRa radios. It's community infrastructure — no cell towers, no subscriptions, no central authority.
|
**Meshtastic**: When the grid is not your friend, build your own. [Meshtastic](https://meshtastic.org/) lets you create off-grid, encrypted text networks using inexpensive LoRa radios. It's community infrastructure — no cell towers, no subscriptions, no central authority.
|
||||||
|
|
||||||
|
|
@ -45,8 +46,8 @@ Move away from Google piece by piece:
|
||||||
|-----------|-----|
|
|-----------|-----|
|
||||||
| Gmail | [Proton Mail](https://proton.me/mail), self-hosted mail |
|
| Gmail | [Proton Mail](https://proton.me/mail), self-hosted mail |
|
||||||
| Google Drive | [Syncthing](https://syncthing.net/), [Nextcloud](https://nextcloud.com/) |
|
| Google Drive | [Syncthing](https://syncthing.net/), [Nextcloud](https://nextcloud.com/) |
|
||||||
| Google Photos | [Immich](https://immich.app/), local storage |
|
| Google Photos | [Ente](https://ente.com/), local storage shared by Syncthing |
|
||||||
| Google Docs | [CryptPad](https://cryptpad.fr/), local office suite |
|
| Google Docs | [CryptPad](https://cryptpad.fr/), Libre Office suite |
|
||||||
|
|
||||||
The principle is simple: **self-hosted first, local-first, privacy-first**. If your data lives on someone else's computer, it is not your data.
|
The principle is simple: **self-hosted first, local-first, privacy-first**. If your data lives on someone else's computer, it is not your data.
|
||||||
|
|
||||||
|
|
@ -54,20 +55,17 @@ The principle is simple: **self-hosted first, local-first, privacy-first**. If y
|
||||||
|
|
||||||
## Passwords and keys
|
## Passwords and keys
|
||||||
|
|
||||||
Use [KeePassXC](https://keepassxc.org/) — a local, offline, open-source password manager. Unlike browser-based password managers or online services, your password database lives on your device. You control the file. Nobody can leak what they don't have.
|
- [ ] Install KeePassXC and create your first password database
|
||||||
|
- [ ] Generate unique passwords for every important service
|
||||||
|
- [ ] Get a hardware security key (like a YubiKey) where possible
|
||||||
|
|
||||||
Generate unique passwords for every service. Use a hardware security key (like a YubiKey) where possible. Treat your digital keys as carefully as the keys to your home.
|
Treat your digital keys as carefully as the keys to your home.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The bigger picture
|
|
||||||
|
|
||||||
This isn't about becoming a hermit with a tin-foil hat. It's about intentionality. Every service you leave is a vote. Every open-source tool you adopt strengthens an alternative ecosystem. Every friend you help migrate multiplies the effect.
|
|
||||||
|
|
||||||
Digital sovereignty is not isolation — it's the foundation for authentic connection.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Related:** [Digital Wellness](../../practices/digital-wellness.md) — sovereignty begins with what you consume.
|
**Related:** [Digital Wellness](../../practices/digital-wellness.md) — sovereignty begins with what you consume.
|
||||||
|
|
||||||
*What's one service you could migrate away from this month?*
|
*What's one service you could migrate away from this month?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
|
|
@ -10,14 +10,14 @@ Beyond making a living lies the question that has quietly followed you for years
|
||||||
|
|
||||||
## The passion that was always there
|
## The passion that was always there
|
||||||
|
|
||||||
For many, purpose is not something you find — it's something you remember. It was there when you were a child, before the world told you to be practical. It was in the activities that made you lose track of time.
|
Your purpose is innate and can be seen in your passions, what you naturally feel drawn to. In childhood these may have been more evident by how you spent your free time. Your soul was born with a particular intention to experience and contribute something to this reality, this can be seen in your natural tendencies and skills or gifts. Meditation or Spiritual Hypnotherapy can be powerful way to discover life's purpose more clearly.
|
||||||
|
|
||||||
Ask yourself:
|
Ask yourself:
|
||||||
|
|
||||||
- What would I do if money were not a concern?
|
- [ ] Write down your answer: What would I do if money were not a concern?
|
||||||
|
- [ ] Write down your answer: What challenge have I lived through that I could help others navigate?
|
||||||
- What topic could I talk about for hours without tiring?
|
- What topic could I talk about for hours without tiring?
|
||||||
- What makes me feel most alive — and who benefits when I am in that state?
|
- What makes me feel most alive — and who benefits when I am in that state?
|
||||||
- What challenge have I lived through that I could help others navigate?
|
|
||||||
|
|
||||||
That last question is often the most direct path. The wound becomes the gift.
|
That last question is often the most direct path. The wound becomes the gift.
|
||||||
|
|
||||||
|
|
@ -58,15 +58,18 @@ Spend more time with people who are on a positive frequency — those who energi
|
||||||
|
|
||||||
You don't need to quit your job tomorrow. Start with:
|
You don't need to quit your job tomorrow. Start with:
|
||||||
|
|
||||||
|
- [ ] Do one unannounced act of kindness each day this week
|
||||||
- One hour a week on the thing that lights you up
|
- One hour a week on the thing that lights you up
|
||||||
- One conversation with someone doing what you feel called to do
|
- One conversation with someone doing what you feel called to do
|
||||||
- One small act of service, unannounced
|
- One small act of service, unannounced
|
||||||
- One visualization, morning and night, of the future you are building
|
- One visualization, morning and night, of the future you are building
|
||||||
|
|
||||||
Purpose is not a destination. It is a direction you calibrate toward, daily, with each small choice.
|
Purpose is a direction you calibrate toward, daily, with each small choice. Which of your daily actions feel aligned with your purpose, and which ones could use a nudge in the right direction?
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Related:** [Community Sovereignty](./community-sovereignty.md) — purpose expressed through collective action.
|
**Related:** [Community Sovereignty](./community-sovereignty.md) — purpose expressed through collective action.
|
||||||
|
|
||||||
*What challenge have you lived through that someone else needs help with right now?*
|
*What challenge have you lived through that someone else needs help with right now?*
|
||||||
|
|
||||||
|
- [ ] Mark this sprout read
|
||||||
18
docs/strategies/index.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
icon: material/chess-knight
|
||||||
|
---
|
||||||
|
|
||||||
|
# Strategies
|
||||||
|
|
||||||
|
Big-picture frameworks for when a practice opens a door and you're ready to walk through. These are the patterns, mindsets, and structural shifts — the strategy beneath the tactics.
|
||||||
|
|
||||||
|
<div class="grid cards gp-cards-strategies" markdown>
|
||||||
|
|
||||||
|
- [:material-shield-lock: **Digital Sovereignty**](digital-sovereignty.md) Own your hardware, software, data, and networks
|
||||||
|
- [:material-crowd: **Community Sovereignty**](community-sovereignty.md) Parallel economies, PMAs, seva, freedom networks
|
||||||
|
- [:material-compass: **Finding Your Purpose**](finding-purpose.md) Passion, suffering into service, building your tribe
|
||||||
|
- [:material-hand-heart: **Collective Awakening**](collective-awakening.md) Mass intention, circles, crystallizing the vision
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Come back to these. They'll mean something different each time.
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
---
|
|
||||||
icon: material/book-open-variant
|
|
||||||
---
|
|
||||||
|
|
||||||
# Teachings
|
|
||||||
|
|
||||||
Deeper explorations for when a practice opens a door and you want to walk through it. Frameworks, context, and the why beneath the how.
|
|
||||||
|
|
||||||
<div class="grid cards" markdown>
|
|
||||||
|
|
||||||
- [:material-shield-lock: **Digital Sovereignty**](digital-sovereignty.md) — Own your hardware, software, data, and networks
|
|
||||||
- [:material-crowd: **Community Sovereignty**](community-sovereignty.md) — Parallel economies, PMAs, seva, freedom networks
|
|
||||||
- [:material-spa: **Spiritual Hygiene**](spiritual-hygiene.md) — Cleanse your space, set intention, sound as medicine
|
|
||||||
- [:material-compass: **Finding Your Purpose**](finding-purpose.md) — Passion, suffering into service, building your tribe
|
|
||||||
- [:material-hand-heart: **Collective Awakening**](collective-awakening.md) — Mass intention, circles, crystallizing the vision
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
These are living documents. Return to them. They'll mean something different each time.
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
---
|
|
||||||
icon: material/spa
|
|
||||||
---
|
|
||||||
|
|
||||||
# Spiritual Hygiene
|
|
||||||
|
|
||||||
Just as you wash your body, your space and energy field require regular cleansing. This is not superstition — it is the recognition that environments hold residue, and that your intention shapes what you encounter.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Cleansing your space
|
|
||||||
|
|
||||||
Your bedroom is the most important room to tend. You spend a third of your life there, unconscious and receptive.
|
|
||||||
|
|
||||||
- Open windows daily — stagnant air holds stagnant energy
|
|
||||||
- Remove electronics from the room, or at minimum cover screens
|
|
||||||
- Declutter: every object carries a subtle energetic weight
|
|
||||||
- Use sound: a bell, singing bowl, or simple clapping in corners breaks up density
|
|
||||||
- Burn natural incense or diffuse pure essential oils (frankincense, sage, palo santo)
|
|
||||||
|
|
||||||
??? question "How often should I cleanse?"
|
|
||||||
A light daily clearing (open window, intention setting) and a deeper weekly reset (sound, smoke, decluttering) is a sustainable rhythm. After arguments, illness, or visits from heavy energy, cleanse immediately.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Setting intention and calling guides
|
|
||||||
|
|
||||||
Before sleep, state clearly — aloud or internally:
|
|
||||||
|
|
||||||
> *I invite only energies of the highest light to interact with me. My space is sovereign. My field is clear.*
|
|
||||||
|
|
||||||
You don't need to believe in guides for this to work. The practice is about setting a boundary and orienting your awareness toward what is loving, clear, and true. Whatever your framework — ancestors, angels, higher self, or simply the clearest version of your own consciousness — the act of calling it in is what matters.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sound as medicine
|
|
||||||
|
|
||||||
The frequencies you surround yourself with shape your nervous system. Consider:
|
|
||||||
|
|
||||||
- **432 Hz** — associated with heart coherence and natural resonance
|
|
||||||
- **528 Hz** — often called the "love frequency," used in DNA repair research
|
|
||||||
- **Natural classical** — Bach, Debussy, Ravi Shankar — music that creates space rather than filling it
|
|
||||||
- **Kirtan and mantra** — collective chanting that synchronizes heart rates and entrains the group field
|
|
||||||
|
|
||||||
The rule is simple: if a song has a single negative word or message, skip it. The subconscious absorbs everything. Curate your sound environment as carefully as your food.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Group singing, toning, and joy
|
|
||||||
|
|
||||||
Human voices together are one of the most powerful frequency generators available. Group singing — kirtan, toning, community choirs, or just friends around a fire — synchronizes nervous systems, releases oxytocin, and creates a field of shared vibration that lingers long after the sound stops.
|
|
||||||
|
|
||||||
Pair this with:
|
|
||||||
|
|
||||||
- **Uplifting art** — surround yourself with images that open the heart
|
|
||||||
- **Light-hearted comedy** — laughter is a genuine cleansing practice
|
|
||||||
- **Positive energy events** — gatherings where the purpose is simply to feel good together
|
|
||||||
|
|
||||||
"Joy maxxing" is not avoidance. It is deliberate nervous system nourishment.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Mass meditations and peace visualization
|
|
||||||
|
|
||||||
When large numbers of people hold the same intention simultaneously, something measurable shifts. Research on transcendental meditation groups has shown reductions in crime rates, hospital admissions, and conflict when a critical mass is reached.
|
|
||||||
|
|
||||||
Join global mass meditations when they are called. Or gather a small group — even three people — and sit together with the intention of peace and the most positive timeline for humanity.
|
|
||||||
|
|
||||||
Create something tangible to crystallize the intention: a doodle, a piece of art, a short written statement of what that positive timeline looks like *for you*. Make it specific. Make it beautiful. Keep it visible.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Related:** [Daily Sadhana](../../practices/daily-sadhana.md) — spiritual hygiene as daily practice.
|
|
||||||
|
|
||||||
*What's the first thing you'll clear from your bedroom tonight?*
|
|
||||||
1265
index.html
73
main.py
|
|
@ -1,5 +1,74 @@
|
||||||
def main():
|
#!/usr/bin/env python3
|
||||||
print("Hello from up!")
|
"""Generate the Tree of Ascension action-points totals manifest.
|
||||||
|
|
||||||
|
Scans docs/**/*.md for Markdown tasklist items (`- [ ]` / `- [x]`), counts
|
||||||
|
them per page, and writes docs/javascripts/toa-totals.json mapping each
|
||||||
|
page's site URL -> total task count.
|
||||||
|
|
||||||
|
The action-points JS (docs/javascripts/extra.js) fetches this manifest once
|
||||||
|
on first load so nav badges show correct totals BEFORE a user has visited
|
||||||
|
every page. Counts are fully static (known from the Markdown), so this has
|
||||||
|
zero runtime cost — it's a build-time artifact.
|
||||||
|
|
||||||
|
Run before `zensical build`:
|
||||||
|
python3 main.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parent
|
||||||
|
DOCS = ROOT / "docs"
|
||||||
|
OUT = DOCS / "javascripts" / "toa-totals.json"
|
||||||
|
|
||||||
|
# Matches a Markdown tasklist item: optional indent, list marker, [ ] or [x].
|
||||||
|
TASK_RE = re.compile(r"^\s*[-*+]\s+\[[ xX]\]\s+", re.MULTILINE)
|
||||||
|
|
||||||
|
# Matches fenced code blocks (``` or ~~~), incl. language hint, non-greedy.
|
||||||
|
# These contain tasklist *examples* (e.g. the Markdown reference doc) that render
|
||||||
|
# as plain text, NOT interactive checkboxes — so we strip them before counting.
|
||||||
|
FENCE_RE = re.compile(r"^([ \t]*)(`{3,}|~{3,}).*?\n.*?^\1\2[ \t]*$", re.MULTILINE | re.DOTALL)
|
||||||
|
|
||||||
|
|
||||||
|
def count_tasks(text: str) -> int:
|
||||||
|
"""Count real (interactive) tasklist items, excluding fenced code examples."""
|
||||||
|
stripped = FENCE_RE.sub("", text)
|
||||||
|
return len(TASK_RE.findall(stripped))
|
||||||
|
|
||||||
|
|
||||||
|
def url_for(md_path: Path) -> str:
|
||||||
|
"""Map a docs/*.md path to its built site URL (directory-style URLs).
|
||||||
|
|
||||||
|
docs/index.md -> /
|
||||||
|
docs/practices/index.md -> /practices/
|
||||||
|
docs/practices/daily-sadhana.md-> /practices/daily-sadhana/
|
||||||
|
"""
|
||||||
|
rel = md_path.relative_to(DOCS).with_suffix("")
|
||||||
|
parts = list(rel.parts)
|
||||||
|
if parts and parts[-1] == "index":
|
||||||
|
parts = parts[:-1]
|
||||||
|
path = "/" + "/".join(parts)
|
||||||
|
if not path.endswith("/"):
|
||||||
|
path += "/"
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
totals: dict[str, int] = {}
|
||||||
|
for md in sorted(DOCS.rglob("*.md")):
|
||||||
|
text = md.read_text(encoding="utf-8")
|
||||||
|
count = count_tasks(text)
|
||||||
|
if count:
|
||||||
|
totals[url_for(md)] = count
|
||||||
|
|
||||||
|
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
OUT.write_text(json.dumps(totals, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||||
|
print(f"toa-totals: wrote {len(totals)} page(s) -> {OUT.relative_to(ROOT)}")
|
||||||
|
for url, n in sorted(totals.items()):
|
||||||
|
print(f" {url} {n}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
25
overrides/main.html
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{#
|
||||||
|
Action Points feature flag.
|
||||||
|
|
||||||
|
Exposes the zensical.toml setting `[project.extra.action_points] enabled`
|
||||||
|
to client-side JS as `window.TOA_ACTION_POINTS_ENABLED`. This block renders
|
||||||
|
in <head>, before extra_javascript loads in {% block scripts %}, so the
|
||||||
|
action-points engine in docs/javascripts/extra.js can bail out immediately
|
||||||
|
when the feature is disabled.
|
||||||
|
|
||||||
|
Set `enabled = false` in zensical.toml to turn the ENTIRE interactive
|
||||||
|
checklist feature off — no localStorage, no nav badges, no confetti, no
|
||||||
|
per-click work. Checkboxes then fall back to Material's default read-only
|
||||||
|
rendering. Defaults to ON when the key is absent.
|
||||||
|
#}
|
||||||
|
{% block extrahead %}
|
||||||
|
{{ super() }}
|
||||||
|
<script>
|
||||||
|
window.TOA_ACTION_POINTS_ENABLED =
|
||||||
|
{{ "false" if config.extra.action_points and config.extra.action_points.enabled == false else "true" }};
|
||||||
|
window.TOA_KEEP_IN_TOUCH_ENDPOINT =
|
||||||
|
{{ ('"' + config.extra.keep_in_touch.endpoint + '"') if config.extra.keep_in_touch and config.extra.keep_in_touch.endpoint else '""' }};
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
13
overrides/partials/comments.html
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{% include "partials/keep-in-touch.html" %}
|
||||||
|
|
||||||
|
<h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
|
||||||
|
<div id="cusdis_thread"
|
||||||
|
data-host="{{ config.extra.cusdis.host }}"
|
||||||
|
data-app-id="{{ config.extra.cusdis.app_id }}"
|
||||||
|
data-page-id="{{ page.canonical_url }}"
|
||||||
|
data-page-url="{{ page.canonical_url }}"
|
||||||
|
data-page-title="{{ page.title }}"
|
||||||
|
data-theme="auto">
|
||||||
|
</div>
|
||||||
|
<script async defer src="{{ config.extra.cusdis.host }}/js/cusdis.es.js"></script>
|
||||||
|
<noscript>Please enable JavaScript to view the comments.</noscript>
|
||||||
20
overrides/partials/copyright.html
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<div class="md-copyright">
|
||||||
|
{% if config.copyright %}
|
||||||
|
<div class="md-copyright__highlight">
|
||||||
|
{{ config.copyright }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if not config.extra.generator == false %}
|
||||||
|
<div class="md-copyright__badges">
|
||||||
|
<span class="md-copyright__zensical">
|
||||||
|
Built with
|
||||||
|
<a href="https://zensical.org/" target="_blank" rel="noopener">
|
||||||
|
Zensical
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
<a href="https://grebedoc.dev" class="md-copyright__grebedoc" title="served by Grebedoc">
|
||||||
|
<img src="https://grebedoc.dev/88x31.gif" alt="served by Grebedoc" style="image-rendering: pixelated; height: 31px; width: 88px;">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
92
overrides/partials/keep-in-touch.html
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
{#
|
||||||
|
Keep In Touch — newsletter / contact capture admonition.
|
||||||
|
|
||||||
|
Rendered above the comments section on every page (included from
|
||||||
|
partials/comments.html). Lets a visitor leave a WhatsApp number and/or
|
||||||
|
email to get updates. Each field submits independently; once both are
|
||||||
|
present the widget asks for their name. Submissions POST as JSON to the
|
||||||
|
endpoint configured in zensical.toml under [project.extra.keep_in_touch].
|
||||||
|
|
||||||
|
Config (zensical.toml):
|
||||||
|
[project.extra.keep_in_touch]
|
||||||
|
endpoint = "https://subscribe.krystl.org/api/subscribe"
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
The endpoint is also exposed to JS as window.TOA_KEEP_IN_TOUCH_ENDPOINT
|
||||||
|
via overrides/main.html. Styling lives in docs/stylesheets/extra.css
|
||||||
|
(.toa-kit-*), behaviour in docs/javascripts/extra.js (Keep-In-Touch IIFE).
|
||||||
|
#}
|
||||||
|
{% if config.extra.keep_in_touch and config.extra.keep_in_touch.enabled != false %}
|
||||||
|
<section class="toa-kit gp-reveal"
|
||||||
|
data-endpoint="{{ config.extra.keep_in_touch.endpoint | default('') }}"
|
||||||
|
aria-labelledby="toa-kit-title">
|
||||||
|
<div class="toa-kit__inner">
|
||||||
|
<div class="toa-kit__glow" aria-hidden="true"></div>
|
||||||
|
|
||||||
|
<header class="toa-kit__header">
|
||||||
|
<span class="toa-kit__icon" aria-hidden="true">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
viewBox="0 0 24 24" class="lucide">
|
||||||
|
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
|
||||||
|
<path d="m22 6-10 7L2 6"></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<div class="toa-kit__heading">
|
||||||
|
<h2 id="toa-kit-title" class="toa-kit__titletext">Keep In Touch</h2>
|
||||||
|
<p class="toa-kit__sub">Leave your WhatsApp or email to get updates on the journey.</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<form class="toa-kit__form" novalidate>
|
||||||
|
{# WhatsApp #}
|
||||||
|
<label class="toa-kit__field" data-kind="whatsapp">
|
||||||
|
<span class="toa-kit__fieldicon" aria-hidden="true">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
viewBox="0 0 24 24" class="lucide">
|
||||||
|
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="tel" class="toa-kit__input" name="whatsapp"
|
||||||
|
inputmode="tel" autocomplete="tel"
|
||||||
|
placeholder="WhatsApp number" aria-label="WhatsApp number">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{# Email #}
|
||||||
|
<label class="toa-kit__field" data-kind="email">
|
||||||
|
<span class="toa-kit__fieldicon" aria-hidden="true">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
viewBox="0 0 24 24" class="lucide">
|
||||||
|
<rect width="20" height="16" x="2" y="4" rx="2"></rect>
|
||||||
|
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="email" class="toa-kit__input" name="email"
|
||||||
|
inputmode="email" autocomplete="email"
|
||||||
|
placeholder="Email address" aria-label="Email address">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{# Name — revealed after both whatsapp + email are captured #}
|
||||||
|
<label class="toa-kit__field toa-kit__field--name" data-kind="name" hidden>
|
||||||
|
<span class="toa-kit__fieldicon" aria-hidden="true">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
viewBox="0 0 24 24" class="lucide">
|
||||||
|
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path>
|
||||||
|
<circle cx="12" cy="7" r="4"></circle>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" class="toa-kit__input" name="name"
|
||||||
|
autocomplete="name"
|
||||||
|
placeholder="Your name (optional)" aria-label="Your name">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button type="submit" class="toa-kit__send">Send</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p class="toa-kit__notice" role="status" aria-live="polite" hidden></p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
296
planning/action-points-prd.md
Normal file
|
|
@ -0,0 +1,296 @@
|
||||||
|
# Action Points — Interactive Checklist PRD
|
||||||
|
|
||||||
|
**Status:** Draft
|
||||||
|
**Author:** aja + Hermes
|
||||||
|
**Date:** 2026-06-03
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Problem Statement
|
||||||
|
|
||||||
|
The Tree of Ascension site contains practices and strategies that invite the reader to *do* something — meditate, journal, take a walk barefoot, migrate off a service. Right now those calls to action are flat text. A reader who returns tomorrow has no way to see what they've already tried or what remains.
|
||||||
|
|
||||||
|
We want to make the site *participatory*: let readers check off action items, see their progress, and feel a sense of momentum. Completion should be visible and celebratory — not gamified in a manipulative way, but genuinely satisfying.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Feature Overview
|
||||||
|
|
||||||
|
| # | Feature | Summary |
|
||||||
|
|---|---------|---------|
|
||||||
|
| 1 | **Checkable action points** | Markdown `- [ ]` task lists that are clickable and persist checked state in `localStorage` |
|
||||||
|
| 2 | **Heading counters** | Each heading with action items underneath shows a counter (e.g., `3/5`). When all items are checked, the heading changes color and confetti drops from the top of the page |
|
||||||
|
| 3 | **Navigation badges** | Sidebar navigation items show a checkmark and color change when all action items on that page are checked |
|
||||||
|
| 4 | **Page-level completion** | The top-of-page heading (h1) reflects overall page completion with a counter |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Detailed Specifications
|
||||||
|
|
||||||
|
### 3.1 Checkable Action Points
|
||||||
|
|
||||||
|
**What they are:**
|
||||||
|
Any `- [ ]` Markdown task list item rendered on a page. The site already uses `pymdownx.tasklist` with `custom_checkbox = true`, which renders checkboxes. We layer interactivity + persistence on top.
|
||||||
|
|
||||||
|
**Behavior:**
|
||||||
|
- Clicking a checkbox toggles its state (unchecked ↔ checked)
|
||||||
|
- State is immediately persisted to `localStorage`
|
||||||
|
- On page load (and on instant navigation), previously saved state is restored
|
||||||
|
- If a checkbox's label text no longer matches any saved entry (content was edited), the stale entry is silently ignored
|
||||||
|
|
||||||
|
**Checkbox identification:**
|
||||||
|
Each checkbox is identified by a key derived from:
|
||||||
|
1. The page's canonical URL path (e.g., `/practices/daily-sadhana/`)
|
||||||
|
2. The normalized label text (trimmed, lowercased, collapsed whitespace)
|
||||||
|
|
||||||
|
```
|
||||||
|
Key = URL + "::" + normalized_label
|
||||||
|
```
|
||||||
|
|
||||||
|
This is stable across reloads and survives minor whitespace changes but intentionally breaks on substantial rewrites (which should reset progress anyway).
|
||||||
|
|
||||||
|
**Visual style:**
|
||||||
|
- Unchecked: current Zensical tasklist styling (green-tinted)
|
||||||
|
- Checked: strikethrough + muted color, consistent with existing site palette
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 Heading Counters & Completion Celebration
|
||||||
|
|
||||||
|
**Counter display:**
|
||||||
|
For each heading (h2, h3, h4) that has one or more action items in its scope, a pill badge is floated to the right of the heading:
|
||||||
|
```
|
||||||
|
## Meditation [0/2]
|
||||||
|
```
|
||||||
|
When partially complete:
|
||||||
|
```
|
||||||
|
## Meditation [1/2]
|
||||||
|
```
|
||||||
|
When fully complete — the heading and badge both shift to the site's accent aurora purple (`--gp-accent`).
|
||||||
|
|
||||||
|
**Heading scope:**
|
||||||
|
An action item belongs to the nearest preceding heading at or above its level. Concretely:
|
||||||
|
- Items after an h2 but before the next h2 belong to that h2
|
||||||
|
- Items after an h3 but before the next h2 or h3 belong to that h3
|
||||||
|
|
||||||
|
**Confetti trigger:**
|
||||||
|
When the last unchecked item under a heading is checked (counter goes from `(n-1)/n` to `n/n`):
|
||||||
|
- A confetti burst animates from the top of the viewport
|
||||||
|
- Confetti uses the site's palette (greens, aurora purple, soft gold)
|
||||||
|
- Animation lasts ~3 seconds
|
||||||
|
- Respects `prefers-reduced-motion` (skips entirely)
|
||||||
|
|
||||||
|
**Confetti implementation:** Custom canvas animation (zero dependency).
|
||||||
|
Two tiers:
|
||||||
|
- **Heading completion:** Subtle aurora particle shower — ~2s, calm, particles in site palette. Accompanied by a soft 432 Hz sine chime (Web Audio API, gentle attack/decay envelope).
|
||||||
|
- **Page-level completion:** More energetic burst — ~3s, denser particles. Accompanied by an ascending arpeggio centered on 528 Hz (Web Audio API, sine waves with smooth envelope).
|
||||||
|
|
||||||
|
Both respect `prefers-reduced-motion` (confetti skipped, sounds skipped).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 Navigation Integration
|
||||||
|
|
||||||
|
**Sidebar nav items:**
|
||||||
|
Each link in the left sidebar that points to a page with action items:
|
||||||
|
- Displays a pill badge next to the link text showing the completion count (e.g., `2/5`)
|
||||||
|
- When all items on that page are complete, the badge becomes a ✓ checkmark and the link text shifts to the accent color
|
||||||
|
|
||||||
|
**Index page aggregation:**
|
||||||
|
Section index pages (e.g., `/practices/`) aggregate completion across all their sub-pages. The badge shows the combined total — e.g., `12/28` summing all practice pages. Sub-page grouping is derived from URL structure: `/practices/daily-sadhana/` is a child of `/practices/`.
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
1. After a page renders and checkboxes are initialized, compute `{ checked, total }` for that page
|
||||||
|
2. Store the summary in `localStorage` under the page URL
|
||||||
|
3. Find the corresponding `<a>` element in the sidebar navigation and inject the badge/checkmark
|
||||||
|
4. Re-run on every page navigation (instant or full)
|
||||||
|
|
||||||
|
**Edge cases:**
|
||||||
|
- Pages with no action items: no badge, no color change
|
||||||
|
- Deleted pages: stale localStorage entries don't render (no nav element to match)
|
||||||
|
|
||||||
|
---
|
||||||
|
### 3.4 Page-Level Heading
|
||||||
|
|
||||||
|
The top-of-page `<h1>` gets a pill badge (right-aligned) showing overall page progress:
|
||||||
|
```
|
||||||
|
# Daily Sadhana [4/12]
|
||||||
|
```
|
||||||
|
Same color-change logic as section headings: when complete, the h1 turns accent-colored.
|
||||||
|
|
||||||
|
The h1 counter aggregates *all* action items on the page — it's the sum of all section counts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.5 Progress Export (trivial add-on)
|
||||||
|
|
||||||
|
A small "Download my progress" link in the page footer or near the comments section. Clicking it triggers a browser download of a JSON file containing the full localStorage state. This lets users:
|
||||||
|
- Back up their progress before clearing browser data
|
||||||
|
- Share their completion state (import could come later)
|
||||||
|
|
||||||
|
Implementation is ~10 lines: read `localStorage`, create a `Blob`, trigger download via a temporary `<a>` element.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Technical Design
|
||||||
|
|
||||||
|
### 4.1 localStorage Schema
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"toa-action-points": {
|
||||||
|
"version": 1,
|
||||||
|
"pages": {
|
||||||
|
"/practices/daily-sadhana/": {
|
||||||
|
"lastUpdated": "2026-06-03T12:00:00.000Z",
|
||||||
|
"checked": [
|
||||||
|
"sit. breathe. that's the whole instruction.",
|
||||||
|
"write down three things you are genuinely grateful for"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/strategies/digital-sovereignty/": {
|
||||||
|
"lastUpdated": "2026-06-03T12:30:00.000Z",
|
||||||
|
"checked": [
|
||||||
|
"switch from wifi to ethernet for your main computer"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Keys are the site-relative URL path (without domain; works across environments)
|
||||||
|
- `checked` is an array of normalized label strings
|
||||||
|
- `version` allows future schema migrations
|
||||||
|
- One key per page keeps reads/writes small
|
||||||
|
|
||||||
|
### 4.2 Instant Navigation Compatibility
|
||||||
|
|
||||||
|
The site uses `navigation.instant` (SPA-style page transitions). Zensical/Material for MkDocs exposes `document$` as an observable for navigation events.
|
||||||
|
|
||||||
|
Our JS hooks into:
|
||||||
|
- `DOMContentLoaded` — for initial page load
|
||||||
|
- `document$.subscribe` — for instant navigation transitions
|
||||||
|
|
||||||
|
On each navigation:
|
||||||
|
1. Wait for DOM to settle (the new page content is rendered)
|
||||||
|
2. Scan for tasklist items
|
||||||
|
3. Restore saved state from localStorage
|
||||||
|
4. Inject counters into headings and h1
|
||||||
|
5. Update sidebar nav badges for *all* pages (not just current — because the current page's completion may have changed)
|
||||||
|
|
||||||
|
### 4.3 Storage Limit
|
||||||
|
|
||||||
|
`localStorage` is typically 5–10 MB per origin. Our schema is compact (a few KB even with many pages). No practical risk of hitting the limit.
|
||||||
|
|
||||||
|
### 4.4 Performance
|
||||||
|
|
||||||
|
- DOM scanning on each navigation: O(n) where n = number of tasklist items on a page (typically < 30)
|
||||||
|
- Nav badge updates: O(sidebar links × pages with data), well under 1ms
|
||||||
|
- confetti: canvas-based, runs off main thread via `requestAnimationFrame`
|
||||||
|
|
||||||
|
All work is < 5ms per navigation; no perceptible impact.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Future: Cross-Device Persistence (v2)
|
||||||
|
|
||||||
|
### 5.1 Problem
|
||||||
|
`localStorage` is per-browser, per-device. A reader who checks items on their phone won't see them on their laptop.
|
||||||
|
|
||||||
|
### 5.2 Solution sketch
|
||||||
|
- User optionally enters their email address
|
||||||
|
- We store a mapping: `email → checked_items` on a lightweight server
|
||||||
|
- On page load, if an email is stored in localStorage, fetch state from the server
|
||||||
|
- On checkbox toggle, sync to server (debounced)
|
||||||
|
- No authentication required — email is the identifier (like Cusdis comments)
|
||||||
|
- Server can be a simple SQLite-backed Python/FastAPI service or even a Cloudflare Worker + D1
|
||||||
|
|
||||||
|
### 5.3 Why not now
|
||||||
|
- Requires deploying and maintaining a server
|
||||||
|
- Adds latency and failure modes
|
||||||
|
- `localStorage` solves 80% of the value with 0% of the infrastructure cost
|
||||||
|
- We ship v1, learn from usage, then decide if cross-device is worth it
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Content Authoring Guide
|
||||||
|
|
||||||
|
For content authors, "action points" are simply `- [ ]` Markdown task lists. No special syntax, no frontmatter, no directives.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Meditation
|
||||||
|
|
||||||
|
- [ ] Sit quietly for 5 minutes
|
||||||
|
- [ ] Notice when the mind wanders and return to breath
|
||||||
|
- [ ] Do this every morning for one week
|
||||||
|
```
|
||||||
|
|
||||||
|
The JS layer automatically detects these and adds interactivity. To opt a page *out* of action-point tracking entirely (e.g., index pages with task lists that aren't meant to be checked off), add frontmatter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
action_points: false
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Open Questions
|
||||||
|
|
||||||
|
1. **Confetti style — subtle or playful?**
|
||||||
|
A gentle aurora-colored particle shower that respects the site's calm aesthetic, or a more energetic celebration? The site's ethos ("not gamified in a manipulative way, but genuinely satisfying") points toward subtle — soft particles in the site palette, ~2-second duration, no sound.
|
||||||
|
|
||||||
|
2. **Should index pages (e.g., `/practices/`) track action items?**
|
||||||
|
Index pages use grid cards, not task lists. Likely `action_points: false` by default for any page without `- [ ]` items. But if someone adds checklist items to an index, should they track? Probably yes — detection is automatic unless explicitly opted out.
|
||||||
|
|
||||||
|
3. **Counter placement on headings — inline badge or superscript?**
|
||||||
|
`## Meditation [0/2]` (inline, after heading text) vs `## Meditation` with a small pill badge. Inline is simpler, less DOM manipulation, and works with existing heading anchors. I'd recommend inline.
|
||||||
|
|
||||||
|
4. **Navigation badges — all pages or only pages with action items?**
|
||||||
|
Only pages with at least one action item should get a badge. Empty counters clutter the sidebar. This means we compute on first page visit and store the `total` count — pages with total=0 get no badge.
|
||||||
|
|
||||||
|
5. **When a user edits the Markdown source (adding/removing items), how should we handle stale localStorage entries?**
|
||||||
|
Stale entries (label text no longer matches any rendered checkbox) are silently dropped. New items start unchecked. This is the least-surprising behavior — edits "reset" progress only for changed items, not the whole page.
|
||||||
|
|
||||||
|
6. **Should completion state be exportable/downloadable?**
|
||||||
|
A "download my progress" button would let users save their state as a JSON file before clearing browser data. Nice-to-have for v1.1.
|
||||||
|
|
||||||
|
7. **Confetti: custom canvas or `canvas-confetti` library?**
|
||||||
|
- Custom: ~60 lines of JS, full control over palette and behavior, zero dependency, but more code to maintain
|
||||||
|
- `canvas-confetti`: battle-tested, good defaults, one function call, but adds ~7 KB dependency
|
||||||
|
|
||||||
|
Leaning custom — the palette matching and reduced-motion respect are trivial to implement and the site already values self-contained minimalism.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Implementation Plan (high-level)
|
||||||
|
|
||||||
|
| Phase | What | Files touched |
|
||||||
|
|-------|------|--------------|
|
||||||
|
| 1 | Core checkbox persistence (read/write localStorage) | `docs/javascripts/extra.js` |
|
||||||
|
| 2 | Heading counters + color change | `docs/javascripts/extra.js`, `docs/stylesheets/extra.css` |
|
||||||
|
| 3 | Confetti on completion | `docs/javascripts/extra.js` (custom canvas) |
|
||||||
|
| 4 | Navigation badge injection | `docs/javascripts/extra.js`, `docs/stylesheets/extra.css` |
|
||||||
|
| 5 | Page-level h1 counter | `docs/javascripts/extra.js`, `docs/stylesheets/extra.css` |
|
||||||
|
| 6 | Opt-out frontmatter support | `docs/javascripts/extra.js` |
|
||||||
|
| 7 | Test across all content pages + mobile | manual QA |
|
||||||
|
|
||||||
|
All JS goes in the existing `docs/javascripts/extra.js`. All CSS in `docs/stylesheets/extra.css`. No new files, no new dependencies, no build pipeline changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Success Criteria
|
||||||
|
|
||||||
|
- [ ] Clicking a `- [ ]` checkbox toggles its visual state
|
||||||
|
- [ ] Refreshing the page preserves checked state
|
||||||
|
- [ ] Navigating to another page and back preserves checked state
|
||||||
|
- [ ] Headings show accurate counters (e.g., `2/5`)
|
||||||
|
- [ ] When a heading reaches full completion, it changes to accent color
|
||||||
|
- [ ] Confetti plays when the last item under a heading is checked (and not on reduced-motion)
|
||||||
|
- [ ] Navigation sidebar shows badges for pages with action items
|
||||||
|
- [ ] Fully-completed pages show ✓ checkmark in nav
|
||||||
|
- [ ] Page h1 shows overall completion counter
|
||||||
|
- [ ] Zero console errors on any page
|
||||||
|
- [ ] Works on mobile (touch events fire correctly on checkboxes)
|
||||||
|
- [ ] No visual regression on pages without action items
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "up"
|
name = "up"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -6,7 +10,8 @@ readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = []
|
dependencies = []
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
packages = ["_extensions"]
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = ["zensical>=0.0.43"]
|
||||||
"zensical>=0.0.43",
|
|
||||||
]
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
||||||
</urlset>
|
|
||||||
4
subscribe-service/.dockerignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
node_modules
|
||||||
|
data
|
||||||
|
.git
|
||||||
|
*.md
|
||||||
33
subscribe-service/Dockerfile
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# ── Subscribe Service ────────────────────────────────────────────────────
|
||||||
|
# Keep In Touch — subscribe capture endpoint for Tree of Ascension docs.
|
||||||
|
#
|
||||||
|
# Deploy on Coolify:
|
||||||
|
# 1. Point the service to this repo (or a subfolder if supported)
|
||||||
|
# 2. Set Build Pack: Dockerfile
|
||||||
|
# 3. Add a persistent volume at /app/data
|
||||||
|
# 4. Set env vars (PORT, ALLOW_ORIGIN, ADMIN_TOKEN)
|
||||||
|
# 5. Map your domain (e.g. subscribe.krystl.org)
|
||||||
|
|
||||||
|
FROM node:22-alpine
|
||||||
|
|
||||||
|
# Create unprivileged user
|
||||||
|
RUN addgroup -S app && adduser -S -G app app
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Dependencies first for layer caching
|
||||||
|
COPY package.json ./
|
||||||
|
RUN npm install --omit=dev && npm cache clean --force
|
||||||
|
|
||||||
|
# Application
|
||||||
|
COPY server.js ./
|
||||||
|
|
||||||
|
# Persistent data volume + ownership
|
||||||
|
RUN mkdir -p /app/data && chown -R app:app /app
|
||||||
|
|
||||||
|
USER app
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
ENV PORT=8080
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
16
subscribe-service/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "toa-subscribe-service",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Keep In Touch — subscribe capture endpoint for Tree of Ascension docs. Captures WhatsApp / email / name into SQLite.",
|
||||||
|
"type": "module",
|
||||||
|
"main": "server.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"better-sqlite3": "^11.8.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
248
subscribe-service/server.js
Normal file
|
|
@ -0,0 +1,248 @@
|
||||||
|
/**
|
||||||
|
* Keep In Touch — subscribe capture service.
|
||||||
|
*
|
||||||
|
* A tiny dependency-light HTTP service (Node core http + better-sqlite3) that
|
||||||
|
* receives JSON submissions from the docs site "Keep In Touch" widget and
|
||||||
|
* upserts them into a SQLite database. Designed to run in a single container
|
||||||
|
* on Coolify with a persistent volume, mirroring the Cusdis deployment.
|
||||||
|
*
|
||||||
|
* Endpoints:
|
||||||
|
* POST /api/subscribe capture/upsert a subscriber -> { ok: true }
|
||||||
|
* GET /api/health liveness probe -> { ok: true }
|
||||||
|
* GET /api/subscribers list (requires ADMIN_TOKEN) -> [ ... ]
|
||||||
|
*
|
||||||
|
* A submission is keyed by whatsapp OR email — whichever is present. As the
|
||||||
|
* widget collects more fields across submissions (email after whatsapp, then
|
||||||
|
* name), each POST sends the full known set, and we merge into the existing
|
||||||
|
* row rather than creating duplicates.
|
||||||
|
*
|
||||||
|
* Environment:
|
||||||
|
* PORT listen port (default 8080)
|
||||||
|
* DB_PATH SQLite file path (default ./data/subscribers.db)
|
||||||
|
* ALLOW_ORIGIN CORS allow-origin (default "*"; set to your site origin)
|
||||||
|
* ADMIN_TOKEN if set, required as `Authorization: Bearer <token>` for
|
||||||
|
* GET /api/subscribers
|
||||||
|
*/
|
||||||
|
|
||||||
|
import http from "node:http";
|
||||||
|
import { dirname } from "node:path";
|
||||||
|
import { mkdirSync } from "node:fs";
|
||||||
|
import Database from "better-sqlite3";
|
||||||
|
|
||||||
|
const PORT = parseInt(process.env.PORT || "8080", 10);
|
||||||
|
const DB_PATH = process.env.DB_PATH || "./data/subscribers.db";
|
||||||
|
const ALLOW_ORIGIN = process.env.ALLOW_ORIGIN || "*";
|
||||||
|
const ADMIN_TOKEN = process.env.ADMIN_TOKEN || "";
|
||||||
|
const MAX_BODY = 16 * 1024; // 16 KB cap — these payloads are tiny.
|
||||||
|
|
||||||
|
// ── Database ────────────────────────────────────────────────────────────
|
||||||
|
mkdirSync(dirname(DB_PATH), { recursive: true });
|
||||||
|
const db = new Database(DB_PATH);
|
||||||
|
db.pragma("journal_mode = WAL");
|
||||||
|
db.pragma("busy_timeout = 5000");
|
||||||
|
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS subscribers (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
whatsapp TEXT,
|
||||||
|
email TEXT,
|
||||||
|
name TEXT,
|
||||||
|
first_page TEXT,
|
||||||
|
first_url TEXT,
|
||||||
|
user_agent TEXT,
|
||||||
|
ip TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_subscribers_email
|
||||||
|
ON subscribers(email) WHERE email IS NOT NULL AND email <> '';
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_subscribers_whatsapp
|
||||||
|
ON subscribers(whatsapp) WHERE whatsapp IS NOT NULL AND whatsapp <> '';
|
||||||
|
`);
|
||||||
|
|
||||||
|
const findByEmail = db.prepare(
|
||||||
|
"SELECT * FROM subscribers WHERE email = ? LIMIT 1"
|
||||||
|
);
|
||||||
|
const findByWhatsApp = db.prepare(
|
||||||
|
"SELECT * FROM subscribers WHERE whatsapp = ? LIMIT 1"
|
||||||
|
);
|
||||||
|
const insertRow = db.prepare(`
|
||||||
|
INSERT INTO subscribers (whatsapp, email, name, first_page, first_url, user_agent, ip)
|
||||||
|
VALUES (@whatsapp, @email, @name, @first_page, @first_url, @user_agent, @ip)
|
||||||
|
`);
|
||||||
|
const updateRow = db.prepare(`
|
||||||
|
UPDATE subscribers
|
||||||
|
SET whatsapp = COALESCE(NULLIF(@whatsapp, ''), whatsapp),
|
||||||
|
email = COALESCE(NULLIF(@email, ''), email),
|
||||||
|
name = COALESCE(NULLIF(@name, ''), name),
|
||||||
|
updated_at = datetime('now')
|
||||||
|
WHERE id = @id
|
||||||
|
`);
|
||||||
|
const listRows = db.prepare(
|
||||||
|
"SELECT * FROM subscribers ORDER BY updated_at DESC LIMIT 1000"
|
||||||
|
);
|
||||||
|
|
||||||
|
// ── Validation / normalization ──────────────────────────────────────────
|
||||||
|
function normEmail(v) {
|
||||||
|
return typeof v === "string" ? v.trim().toLowerCase() : "";
|
||||||
|
}
|
||||||
|
function normWhatsApp(v) {
|
||||||
|
if (typeof v !== "string") return "";
|
||||||
|
const cleaned = v.trim().replace(/[^\d+]/g, "");
|
||||||
|
const digits = cleaned.replace(/[^\d]/g, "");
|
||||||
|
if (digits.length < 7 || digits.length > 15) return "";
|
||||||
|
return cleaned;
|
||||||
|
}
|
||||||
|
function isValidEmail(v) {
|
||||||
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
|
||||||
|
}
|
||||||
|
function clean(v, max = 200) {
|
||||||
|
return typeof v === "string" ? v.trim().slice(0, max) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upsert: find an existing row by email or whatsapp, merge; else insert.
|
||||||
|
const upsert = db.transaction((rec) => {
|
||||||
|
let existing = null;
|
||||||
|
if (rec.email) existing = findByEmail.get(rec.email);
|
||||||
|
if (!existing && rec.whatsapp) existing = findByWhatsApp.get(rec.whatsapp);
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
updateRow.run({
|
||||||
|
id: existing.id,
|
||||||
|
whatsapp: rec.whatsapp,
|
||||||
|
email: rec.email,
|
||||||
|
name: rec.name,
|
||||||
|
});
|
||||||
|
return { id: existing.id, created: false };
|
||||||
|
}
|
||||||
|
const info = insertRow.run(rec);
|
||||||
|
return { id: info.lastInsertRowid, created: true };
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── HTTP helpers ──────────────────────────────────────────────────────────
|
||||||
|
function cors(res) {
|
||||||
|
res.setHeader("Access-Control-Allow-Origin", ALLOW_ORIGIN);
|
||||||
|
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
|
||||||
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||||
|
res.setHeader("Vary", "Origin");
|
||||||
|
}
|
||||||
|
function json(res, status, obj) {
|
||||||
|
cors(res);
|
||||||
|
res.writeHead(status, { "Content-Type": "application/json" });
|
||||||
|
res.end(JSON.stringify(obj));
|
||||||
|
}
|
||||||
|
function clientIp(req) {
|
||||||
|
const xff = req.headers["x-forwarded-for"];
|
||||||
|
if (typeof xff === "string" && xff.length) return xff.split(",")[0].trim();
|
||||||
|
return req.socket.remoteAddress || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBody(req) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let size = 0;
|
||||||
|
const chunks = [];
|
||||||
|
req.on("data", (c) => {
|
||||||
|
size += c.length;
|
||||||
|
if (size > MAX_BODY) {
|
||||||
|
reject(new Error("payload too large"));
|
||||||
|
req.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chunks.push(c);
|
||||||
|
});
|
||||||
|
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
||||||
|
req.on("error", reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Server ─────────────────────────────────────────────────────────────
|
||||||
|
const server = http.createServer(async (req, res) => {
|
||||||
|
const url = new URL(req.url, `http://${req.headers.host}`);
|
||||||
|
|
||||||
|
if (req.method === "OPTIONS") {
|
||||||
|
cors(res);
|
||||||
|
res.writeHead(204);
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.method === "GET" && url.pathname === "/api/health") {
|
||||||
|
return json(res, 200, { ok: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.method === "GET" && url.pathname === "/api/subscribers") {
|
||||||
|
if (ADMIN_TOKEN) {
|
||||||
|
const auth = req.headers["authorization"] || "";
|
||||||
|
if (auth !== `Bearer ${ADMIN_TOKEN}`) {
|
||||||
|
return json(res, 401, { ok: false, error: "unauthorized" });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No admin token configured — refuse rather than leak data.
|
||||||
|
return json(res, 403, { ok: false, error: "admin token not configured" });
|
||||||
|
}
|
||||||
|
return json(res, 200, { ok: true, subscribers: listRows.all() });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.method === "POST" && url.pathname === "/api/subscribe") {
|
||||||
|
let raw;
|
||||||
|
try {
|
||||||
|
raw = await readBody(req);
|
||||||
|
} catch (e) {
|
||||||
|
return json(res, 413, { ok: false, error: "payload too large" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(raw || "{}");
|
||||||
|
} catch (e) {
|
||||||
|
return json(res, 400, { ok: false, error: "invalid JSON" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const email = normEmail(data.email);
|
||||||
|
const whatsapp = normWhatsApp(data.whatsapp);
|
||||||
|
|
||||||
|
if (email && !isValidEmail(email)) {
|
||||||
|
return json(res, 422, { ok: false, error: "invalid email" });
|
||||||
|
}
|
||||||
|
if (!email && !whatsapp) {
|
||||||
|
return json(res, 422, {
|
||||||
|
ok: false,
|
||||||
|
error: "provide a valid email or whatsapp number",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const rec = {
|
||||||
|
whatsapp,
|
||||||
|
email,
|
||||||
|
name: clean(data.name, 120),
|
||||||
|
first_page: clean(data.page, 300),
|
||||||
|
first_url: clean(data.url, 500),
|
||||||
|
user_agent: clean(req.headers["user-agent"], 400),
|
||||||
|
ip: clientIp(req),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = upsert(rec);
|
||||||
|
return json(res, 200, { ok: true, id: result.id, created: result.created });
|
||||||
|
} catch (e) {
|
||||||
|
console.error("upsert failed:", e);
|
||||||
|
return json(res, 500, { ok: false, error: "server error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json(res, 404, { ok: false, error: "not found" });
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(PORT, () => {
|
||||||
|
console.log(`[subscribe] listening on :${PORT} (db: ${DB_PATH})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Graceful shutdown so SQLite WAL checkpoints cleanly.
|
||||||
|
function shutdown() {
|
||||||
|
server.close(() => {
|
||||||
|
try { db.close(); } catch {}
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
process.on("SIGTERM", shutdown);
|
||||||
|
process.on("SIGINT", shutdown);
|
||||||
86
theming.md
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
---
|
||||||
|
title: Theming
|
||||||
|
---
|
||||||
|
|
||||||
|
# Zensical Consciousness Theme — Plan & Prompt Document
|
||||||
|
|
||||||
|
## 1. Goal
|
||||||
|
|
||||||
|
Build a nature/consciousness-themed, beautiful, pastel/iridescent, performance-safe theme
|
||||||
|
for a multi-contributor Zensical awareness site about reigniting the God Spark within.
|
||||||
|
|
||||||
|
## 2. What we learned from Zensical customization
|
||||||
|
|
||||||
|
- Theme extension is mostly additive:
|
||||||
|
- `zensical.toml` → `extra_css` for extra stylesheets.
|
||||||
|
- Page templates can be overridden by placing matching files under `overrides/`.
|
||||||
|
- Site theming is largely controlled by palette/color attributes:
|
||||||
|
- `data-md-color-scheme`
|
||||||
|
- `data-md-color-primary`
|
||||||
|
- `data-md-color-accent`
|
||||||
|
- `extra.css` is the safest layer; it shouldn’t break Zensical if it only adds selectors
|
||||||
|
and doesn’t overwrite core layout-critical rules blindly.
|
||||||
|
- We should keep JS minimal, lazy-friendly, and nonblocking for contributors.
|
||||||
|
|
||||||
|
## 3. Non-goals / constraints
|
||||||
|
|
||||||
|
- No TypeScript/React build pipeline rerouting.
|
||||||
|
- No breaking built-in Zensical navigation/search/skip behavior.
|
||||||
|
- No space/technology motif — instead: botanical/organic/aurora/nature.
|
||||||
|
- Animations must respect load speed and reduced-motion.
|
||||||
|
- Theme should still be readable as Markdown documentation after styling.
|
||||||
|
|
||||||
|
## 4. Adapting MotionSites-style prompts for Kimi
|
||||||
|
|
||||||
|
From the example landing-page prompts:
|
||||||
|
|
||||||
|
- Use: typography system, motion patterns, component thinking, copy composition.
|
||||||
|
- Remove: React/TS/Vite/Framer Motion specifics.
|
||||||
|
- Replace with: plain HTML/CSS + minimal vanilla JS utilities that Zensical can load.
|
||||||
|
|
||||||
|
## 5. Ready-to-run Kimi prompt (refined)
|
||||||
|
|
||||||
|
You are a web designer specializing in calm, premium editorial interfaces.
|
||||||
|
Create a Zensical theme add-on for a consciousness/awakening awareness site.
|
||||||
|
Theme name placeholder: "God Spark". Site title is temporary and may change later.
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
|
||||||
|
- Output must be plain HTML/CSS/JS only.
|
||||||
|
- Must work as a Zensical `extra.css` drop-in plus optional `overrides/` partials.
|
||||||
|
- Do NOT use React, TypeScript, Tailwind build, Framer Motion, or shadcn/ui.
|
||||||
|
- Do NOT break Zensical core behavior.
|
||||||
|
- Performance-first: no heavy dependencies; any JS should be small and optional.
|
||||||
|
- Accessibility-first: readable contrast, reduced-motion safe, semantic markup.
|
||||||
|
|
||||||
|
Design brief:
|
||||||
|
|
||||||
|
- Aesthetic: futuristic pastel + iridescent, but inspired by nature rather than space/tech.
|
||||||
|
Soft aurora-like gradients, botanical motifs, dappled-light effects, gentle watercolor-like transitions.
|
||||||
|
- Color palette references: soft lavender, mist, pearl, sage, blush, iris, morning frost.
|
||||||
|
- Typography: elegant serif headings, clean sans-serif body. Use standard system fonts or
|
||||||
|
Google Fonts loaded with `preconnect` if needed.
|
||||||
|
- Contributions UI must remain friendly for many contributors: simple class names, clear areas
|
||||||
|
to edit content blocks, great default headings, friendly call-to-action language.
|
||||||
|
|
||||||
|
Functional requirements:
|
||||||
|
|
||||||
|
1. Provide one CSS file intended as Zensical's `extra.css` entry.
|
||||||
|
2. Provide optional HTML/JS micro-animations:
|
||||||
|
- fade-up reveal on scroll via IntersectionObserver
|
||||||
|
- soft parallax cursor glow (optional, turned off by default)
|
||||||
|
3. Provide at least 2 override template examples for `overrides/` (e.g., `main.html`, `footer.html`)
|
||||||
|
that layer glass surfaces and brand text without removing existing placeholders.
|
||||||
|
4. Include README with install steps, customization guidance, and contributor notes.
|
||||||
|
|
||||||
|
## 6. Execution plan
|
||||||
|
|
||||||
|
1. Create an isolated sandbox outside the project.
|
||||||
|
2. Generate theme kit using the prompt above with Kimi.
|
||||||
|
3. Review generated files for Zensical safety before pulling into the project.
|
||||||
|
4. Keep the prompt in `docs/zensical-theme-plan.md` for refinement.
|
||||||
|
|
||||||
|
## 7. Where this is saved
|
||||||
|
|
||||||
|
- Path: `/home/a/w/up/docs/zensical-theme-plan.md`
|
||||||
|
- Reuse by updating this file and rerunning Kimi from the same sandboxed branch/tree.
|
||||||
2
uv.lock
|
|
@ -232,7 +232,7 @@ wheels = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "up"
|
name = "up"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = { virtual = "." }
|
source = { editable = "." }
|
||||||
|
|
||||||
[package.dev-dependencies]
|
[package.dev-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
[project]
|
[project]
|
||||||
|
|
||||||
|
|
||||||
repo_url = "https://bali.krystl.org/aja/up"
|
# repo_url = "https://bali.krystl.org/aja/up"
|
||||||
repo_name = "Contribute"
|
# repo_name = "Contribute"
|
||||||
# The site_name is shown in the page header and the browser window title
|
# The site_name is shown in the page header and the browser window title
|
||||||
#
|
#
|
||||||
# Read more: https://zensical.org/docs/setup/basics/#site_name
|
# Read more: https://zensical.org/docs/setup/basics/#site_name
|
||||||
|
|
@ -47,10 +47,25 @@ Copyright © 2026 The authors
|
||||||
# can be defined using TOML syntax.
|
# can be defined using TOML syntax.
|
||||||
#
|
#
|
||||||
# Read more: https://zensical.org/docs/setup/navigation/
|
# Read more: https://zensical.org/docs/setup/navigation/
|
||||||
# nav = [
|
nav = [
|
||||||
# { "Get started" = "index.md" },
|
{ "Home" = "index.md" },
|
||||||
# { "Markdown in 5min" = "markdown.md" },
|
{ "Practices" = [
|
||||||
# ]
|
"practices/index.md",
|
||||||
|
"practices/daily-sadhana.md",
|
||||||
|
"practices/digital-wellness.md",
|
||||||
|
"practices/grounding-in-nature.md",
|
||||||
|
"practices/nourishing-the-body.md",
|
||||||
|
"practices/spiritual-hygiene.md",
|
||||||
|
] },
|
||||||
|
{ "Strategies" = [
|
||||||
|
"strategies/index.md",
|
||||||
|
"strategies/collective-awakening.md",
|
||||||
|
"strategies/community-sovereignty.md",
|
||||||
|
"strategies/digital-sovereignty.md",
|
||||||
|
"strategies/finding-purpose.md",
|
||||||
|
] },
|
||||||
|
{ "Contributing" = "contributing/index.md" },
|
||||||
|
]
|
||||||
|
|
||||||
# With the "extra_css" option you can add your own CSS styling to customize
|
# With the "extra_css" option you can add your own CSS styling to customize
|
||||||
# your Zensical project according to your needs. You can add any number of
|
# your Zensical project according to your needs. You can add any number of
|
||||||
|
|
@ -307,6 +322,34 @@ toggle.name = "Switch to light mode"
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# The "extra" section contains miscellaneous settings.
|
# The "extra" section contains miscellaneous settings.
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
[project.extra.cusdis]
|
||||||
|
host = "https://cusdis.krystl.org"
|
||||||
|
app_id = "d9ab4b66-d5f1-4514-a475-1a824f69530f"
|
||||||
|
lang = "en"
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Action Points — interactive checklist feature flag.
|
||||||
|
# Set enabled = false to disable the ENTIRE feature (localStorage progress,
|
||||||
|
# nav badges, heading pills, confetti, and all per-click JS). Checkboxes then
|
||||||
|
# render as Material's default read-only tasklist. The flag is exposed to the
|
||||||
|
# client via overrides/main.html as window.TOA_ACTION_POINTS_ENABLED.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
[project.extra.action_points]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Keep In Touch — subscribe widget (rendered above comments on every page).
|
||||||
|
# Captures a visitor's WhatsApp number and/or email (and later their name)
|
||||||
|
# and POSTs them as JSON to `endpoint`. Set enabled = false to hide the
|
||||||
|
# widget entirely. The endpoint is exposed to client JS as
|
||||||
|
# window.TOA_KEEP_IN_TOUCH_ENDPOINT via overrides/main.html and as the
|
||||||
|
# data-endpoint attribute on the widget (overrides/partials/keep-in-touch.html).
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
[project.extra.keep_in_touch]
|
||||||
|
enabled = true
|
||||||
|
endpoint = "https://subscribe.krystl.org/api/subscribe"
|
||||||
|
|
||||||
|
|
||||||
#[[project.extra.social]]
|
#[[project.extra.social]]
|
||||||
#icon = "fontawesome/brands/github"
|
#icon = "fontawesome/brands/github"
|
||||||
#link = "https://github.com/user/repo"
|
#link = "https://github.com/user/repo"
|
||||||
|
|
@ -327,6 +370,7 @@ toggle.name = "Switch to light mode"
|
||||||
[project.markdown_extensions.md_in_html]
|
[project.markdown_extensions.md_in_html]
|
||||||
[project.markdown_extensions.toc]
|
[project.markdown_extensions.toc]
|
||||||
permalink = true
|
permalink = true
|
||||||
|
[project.markdown_extensions."_extensions.wikilinks:WikilinksExtension"]
|
||||||
[project.markdown_extensions.pymdownx.arithmatex]
|
[project.markdown_extensions.pymdownx.arithmatex]
|
||||||
generic = true
|
generic = true
|
||||||
[project.markdown_extensions.pymdownx.betterem]
|
[project.markdown_extensions.pymdownx.betterem]
|
||||||
|
|
|
||||||