diff --git a/docs/overrides/main.html b/docs/overrides/main.html
index 0c36899..bf2f092 100644
--- a/docs/overrides/main.html
+++ b/docs/overrides/main.html
@@ -41,15 +41,15 @@
}
});
-
+zensic
diff --git a/docs/resume/mambu-cli.md b/docs/resume/mambu-cli.md
index 85d8a8b..60c4927 100644
--- a/docs/resume/mambu-cli.md
+++ b/docs/resume/mambu-cli.md
@@ -30,7 +30,7 @@ div.tooling p {
:material-language-typescript: TypeScript ⋅ :material-nodejs: NodeJS
-{ height=300px }
+{ height=300px }
## Challenge
@@ -54,4 +54,4 @@ Embedded documentation with the engineering team, where I was part of the race t
gugulet.hu/dev
-
\ No newline at end of file
+
diff --git a/hook.sh b/hook.sh
new file mode 100644
index 0000000..aa54992
--- /dev/null
+++ b/hook.sh
@@ -0,0 +1,184 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Colors
+RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
+
+echo -e "${GREEN}Running pre-push checks...${NC}"
+
+# Paths
+REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
+CONTENT_DIR="$REPO_ROOT/core/content"
+MKDOCS_CFG_PATH="$CONTENT_DIR/mkdocs.yml"
+SITE_DIR="$REPO_ROOT/site"
+LOG_DIR="$REPO_ROOT/test/log"
+
+# Clean logs
+rm -rf "$LOG_DIR"; mkdir -p "$LOG_DIR"
+
+SERVER_PID=""
+cleanup() {
+ if [[ -n "${SERVER_PID:-}" ]] && ps -p "$SERVER_PID" >/dev/null 2>&1; then
+ kill "$SERVER_PID" >/dev/null 2>&1 || true
+ for _ in {1..30}; do ps -p "$SERVER_PID" >/dev/null 2>&1 || break; sleep 0.1; done
+ fi
+}
+trap cleanup EXIT INT TERM
+
+# --- Optional lightweight checks (keep or remove) ---
+if command -v trivy &>/dev/null; then
+ echo -e "${GREEN}Running Trivy scan...${NC}"
+ trivy fs . --exit-code 1 --severity CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN --no-progress \
+ >"$LOG_DIR/trivy.log" 2>&1 || { echo -e "${RED}Trivy failed. See $LOG_DIR/trivy.log${NC}"; exit 1; }
+else
+ echo -e "${YELLOW}Trivy not installed. Skipping vulnerability scan.${NC}"
+fi
+
+if command -v trufflehog &>/dev/null && command -v jq &>/dev/null; then
+ echo -e "${GREEN}Running TruffleHog (verified only)...${NC}"
+ TMPF="$(mktemp)"
+ trufflehog filesystem . --json >"$TMPF" 2>"$LOG_DIR/trufflehog.log" || true
+ VERIFIED="$(jq 'select(.verified==true)' "$TMPF" | wc -l | tr -d ' ')"
+ if [[ "$VERIFIED" -gt 0 ]]; then
+ cp "$TMPF" "$LOG_DIR/trufflehog-findings.json"
+ echo -e "${RED}Verified secrets found. See $LOG_DIR/trufflehog-findings.json${NC}"
+ rm -f "$TMPF"; exit 1
+ fi
+ rm -f "$TMPF"
+else
+ echo -e "${YELLOW}TruffleHog or jq not installed. Skipping secrets scan.${NC}"
+fi
+
+if command -v markdownlint &>/dev/null; then
+ echo -e "${GREEN}Running markdownlint...${NC}"
+ MD_FILES="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$' || true)"
+ if [[ -n "$MD_FILES" ]]; then
+ # shellcheck disable=SC2086
+ echo $MD_FILES | xargs markdownlint >"$LOG_DIR/markdownlint.log" 2>&1 || {
+ echo -e "${RED}markdownlint failed. See $LOG_DIR/markdownlint.log${NC}"; exit 1; }
+ fi
+else
+ echo -e "${YELLOW}markdownlint not installed. Skipping markdown check.${NC}"
+fi
+
+if command -v vale &>/dev/null && [[ -f "$REPO_ROOT/.vale.ini" ]]; then
+ echo -e "${GREEN}Running Vale...${NC}"
+ VALE_FILES="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$' || true)"
+ if [[ -n "$VALE_FILES" ]]; then
+ # shellcheck disable=SC2086
+ echo $VALE_FILES | xargs vale >"$LOG_DIR/vale.log" 2>&1 || {
+ echo -e "${RED}Vale issues. See $LOG_DIR/vale.log${NC}"; exit 1; }
+ fi
+else
+ echo -e "${YELLOW}Vale not installed or .vale.ini missing. Skipping Vale.${NC}"
+fi
+
+# --- MkDocs build (strict) ---
+if ! command -v mkdocs >/dev/null 2>&1; then
+ echo -e "${RED}MkDocs not installed; cannot build docs.${NC}"; exit 1
+fi
+echo -e "${GREEN}Building documentation (strict)…${NC}"
+mkdocs build -f "$MKDOCS_CFG_PATH" -d "$SITE_DIR" --strict >"$LOG_DIR/mkdocs-build.log" 2>&1 || {
+ echo -e "${RED}MkDocs build failed. See $LOG_DIR/mkdocs-build.log${NC}"; exit 1; }
+
+# --- Serve built site ---
+# if ! command -v python3 >/dev/null 2>&1; then
+# echo -e "${RED}python3 not found; cannot serve static site.${NC}"; exit 1
+# fi
+
+# PORT="$(python3 - <<'PY'
+# import socket
+# s=socket.socket(); s.bind(('127.0.0.1',0))
+# print(s.getsockname()[1]); s.close()
+# PY
+# )"
+
+# STATIC_LOG="$LOG_DIR/static-serve.log"
+# echo -e "${GREEN}Serving built site at http://127.0.0.1:$PORT …${NC}"
+# python3 -m http.server "$PORT" --bind 127.0.0.1 --directory "$SITE_DIR" >"$STATIC_LOG" 2>&1 &
+# SERVER_PID="$!"
+
+# Wait for server
+# echo -e "${GREEN}Waiting for local server to be reachable…${NC}"
+# START_TIME="$(date +%s)"; TIMEOUT=60
+# while : ; do
+# if ! ps -p "$SERVER_PID" >/dev/null 2>&1; then
+# echo -e "${RED}Static server died during startup. See $STATIC_LOG${NC}"; exit 1
+# fi
+# if curl --fail --silent -I "http://127.0.0.1:$PORT/" >/dev/null 2>>"$STATIC_LOG"; then break; fi
+# if (( $(date +%s) - START_TIME >= TIMEOUT )); then
+# echo -e "${RED}Static server did not come up in ${TIMEOUT}s.${NC}"
+# tail -n 50 "$STATIC_LOG" || true; exit 1
+# fi
+# sleep 0.5
+# done
+
+# --- Build URL list (all *.html pages) ---
+# URLS_FILE="$LOG_DIR/urls.txt"
+# BASE_URL="http://127.0.0.1:$PORT/"
+
+# export SITE_DIR BASE_URL
+# python3 - <<'PY' > "$URLS_FILE"
+# import os
+# site = os.environ['SITE_DIR']; base = os.environ['BASE_URL']
+# urls = []
+# for root, _, files in os.walk(site):
+# for name in files:
+# if name.endswith('.html'):
+# rel = os.path.relpath(os.path.join(root, name), site).replace(os.sep, '/')
+# urls.append(base + rel)
+# for u in sorted(urls): print(u)
+# PY
+
+# TOTAL="$(wc -l < "$URLS_FILE" | tr -d ' ')"
+# echo -e "${GREEN}Lychee will scan ${TOTAL} pages…${NC}"
+
+# # --- Lychee (single run, unbuffered, higher FD limit) ---
+# if ! command -v lychee >/dev/null 2>&1; then
+# echo -e "${YELLOW}Lychee not installed. Skipping link check.${NC}"
+# cleanup; exit 0
+# fi
+
+# # Raise macOS open-file limit (best-effort) to avoid mid-run aborts
+# ulimit -n 4096 || true
+
+# CSV_OUT="$LOG_DIR/lychee.csv"
+# RUN_LOG="$LOG_DIR/lychee-run.log"
+
+# echo -e "${GREEN}Starting Lychee…${NC}"
+# set +e
+# # Use script(1) to allocate a PTY so output is line-buffered; tee to file.
+# # Capture Lychee's real exit code via PIPESTATUS.
+# script -q /dev/null lychee \
+# --base-url "http://127.0.0.1:$PORT/" \
+# --format detailed \
+# --output "$CSV_OUT" \
+# --verbose \
+# --no-progress \
+# --max-concurrency 16 \
+# --timeout 30 \
+# --max-retries 2 \
+# --retry-wait-time 2 \
+# --accept '100..=103,200..=399' \
+# --exclude 'https?://(www\.)?github\.com/spread-ai' \
+# --exclude 'https?://[^/]*app\.spread\.ai' \
+# --exclude 'https?://[^/]*stage\.spread\.ai' \
+# --exclude '\?q=' \
+# --exclude '#__.*_annotation_.*' \
+# - < "$URLS_FILE" 2>&1 | tee "$RUN_LOG"
+# LYCHEE_RC=${PIPESTATUS[1]}
+# set -e
+
+# Stop server
+# cleanup
+
+# # Summarize and exit appropriately
+# if [[ "$LYCHEE_RC" -ne 0 ]]; then
+# echo -e "${RED}Lychee reported problems (exit $LYCHEE_RC). See:${NC}"
+# echo " - $RUN_LOG"
+# echo " - $CSV_OUT"
+# echo " - $STATIC_LOG"
+# exit 1
+# else
+# echo -e "${GREEN}Lychee completed successfully. See $CSV_OUT${NC}"
+# fi
diff --git a/main.py b/main.py
deleted file mode 100644
index 11b2230..0000000
--- a/main.py
+++ /dev/null
@@ -1,6 +0,0 @@
-def main():
- print("Hello from gugulet-hu!")
-
-
-if __name__ == "__main__":
- main()
diff --git a/mkdocs.yml b/mkdocs.yml
index e105628..1877430 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -81,7 +81,7 @@ nav:
# - Transactions: qself/transactions.md
# - Reference: qself/reference/index.md
# - Devices: qself/devices.md
- - Resumé:
+ - Resumé:
- resume.md
- PcVue assessment: resume/pcvue.md
- Mambu CLI: resume/mambu-cli.md
diff --git a/name: lint.yaml b/name: lint.yaml
new file mode 100644
index 0000000..ce54366
--- /dev/null
+++ b/name: lint.yaml
@@ -0,0 +1,16 @@
+name: lint
+on: push
+
+jobs:
+ vale:
+ name: runner / vale
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: errata-ai/vale-action@reviewdog
+ with:
+ version: 3.7.1
+ level: "error"
+ vale_flags: "--config=core/content/vale/.vale.ini --no-global --output=line --glob=*.md"
+ fail_on_error: false
+ files: "core/content/docs"
diff --git a/pyproject.toml b/pyproject.toml
index 203aa13..c1230f8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,7 @@
[project]
name = "gugulet-hu"
-version = "0.1.0"
-description = "Add your description here"
+version = "2.0.0"
+description = "The perosnal website of gugulet.hu"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
@@ -52,5 +52,6 @@ dependencies = [
"typing-extensions==4.15.0",
"urllib3==2.5.0",
"watchdog==6.0.0",
+ "zensical>=0.0.5",
"zipp==3.23.0",
]
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 8c5be24..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-babel==2.17.0
-backrefs==5.9
-beautifulsoup4==4.14.2
-certifi==2025.10.5
-charset-normalizer==3.4.4
-click==8.1.8
-colorama==0.4.6
-csscompressor==0.9.5
-EditorConfig==0.17.1
-ghp-import==2.1.0
-hjson==3.1.0
-htmlmin2==0.1.13
-idna==3.11
-importlib_metadata==8.7.0
-Jinja2==3.1.6
-jsbeautifier==1.15.4
-jsmin==3.0.1
-Markdown==3.9
-MarkupSafe==3.0.3
-mergedeep==1.3.4
-mkdocs==1.6.1
-mkdocs-get-deps==0.2.0
-mkdocs-glightbox==0.5.1
-mkdocs-macros-plugin==1.4.0
-mkdocs-material==9.6.22
-mkdocs-material-extensions==1.3.1
-mkdocs-mermaid2-plugin==1.2.3
-mkdocs-minify-plugin==0.8.0
-mkdocs-section-index==0.3.10
-packaging==25.0
-paginate==0.5.7
-pathspec==0.12.1
-platformdirs==4.4.0
-Pygments==2.19.2
-pymdown-extensions==10.16.1
-python-dateutil==2.9.0.post0
-PyYAML==6.0.3
-pyyaml_env_tag==1.1
-requests==2.32.5
-selectolax==0.3.29
-six==1.17.0
-soupsieve==2.8
-super_collections==0.6.2
-termcolor==3.1.0
-typing_extensions==4.15.0
-urllib3==2.5.0
-watchdog==6.0.0
-zipp==3.23.0
diff --git a/site/404.html b/site/404.html
index 3e2caad..340b7df 100644
--- a/site/404.html
+++ b/site/404.html
@@ -1,36 +1,351 @@
- Gugulethu Hlekwayo
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 404 - Not found
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+