Commit 11a5ca2792
Verified · cmc
Layout: unified · split
.github/FUNDING.yml added +1
| @@ -0,0 +1 @@ | |||
| 1 | github: [ccleberg] | ||
.github/dependabot.yml added +6
| @@ -0,0 +1,6 @@ | |||
| 1 | version: 2 | ||
| 2 | updates: | ||
| 3 | - package-ecosystem: "uv" | ||
| 4 | directory: "/" | ||
| 5 | schedule: | ||
| 6 | interval: "weekly" | ||
.github/workflows/codeql.yml added +46
| @@ -0,0 +1,46 @@ | |||
| 1 | name: "CodeQL Advanced" | ||
| 2 | |||
| 3 | on: | ||
| 4 | push: | ||
| 5 | branches: [ "main" ] | ||
| 6 | pull_request: | ||
| 7 | branches: [ "main" ] | ||
| 8 | |||
| 9 | jobs: | ||
| 10 | analyze: | ||
| 11 | name: Analyze (${{ matrix.language }}) | ||
| 12 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} | ||
| 13 | permissions: | ||
| 14 | security-events: write | ||
| 15 | packages: read | ||
| 16 | actions: read | ||
| 17 | contents: read | ||
| 18 | |||
| 19 | strategy: | ||
| 20 | fail-fast: false | ||
| 21 | matrix: | ||
| 22 | include: | ||
| 23 | - language: python | ||
| 24 | build-mode: none | ||
| 25 | steps: | ||
| 26 | - name: Checkout repository | ||
| 27 | uses: actions/checkout@v4 | ||
| 28 | - name: Initialize CodeQL | ||
| 29 | uses: github/codeql-action/init@v4 | ||
| 30 | with: | ||
| 31 | languages: ${{ matrix.language }} | ||
| 32 | build-mode: ${{ matrix.build-mode }} | ||
| 33 | - if: matrix.build-mode == 'manual' | ||
| 34 | shell: bash | ||
| 35 | run: | | ||
| 36 | echo 'If you are using a "manual" build mode for one or more of the' \ | ||
| 37 | 'languages you are analyzing, replace this with the commands to build' \ | ||
| 38 | 'your code, for example:' | ||
| 39 | echo ' make bootstrap' | ||
| 40 | echo ' make release' | ||
| 41 | exit 1 | ||
| 42 | |||
| 43 | - name: Perform CodeQL Analysis | ||
| 44 | uses: github/codeql-action/analyze@v4 | ||
| 45 | with: | ||
| 46 | category: "/language:${{matrix.language}}" | ||
.github/workflows/deploy.yml added +68
| @@ -0,0 +1,68 @@ | |||
| 1 | name: Build and Deploy | ||
| 2 | |||
| 3 | on: | ||
| 4 | push: | ||
| 5 | branches: | ||
| 6 | - main | ||
| 7 | paths-ignore: | ||
| 8 | - '.github/**' | ||
| 9 | - 'screenshots/**' | ||
| 10 | - 'utils/**' | ||
| 11 | - 'LICENSE' | ||
| 12 | - 'README.org' | ||
| 13 | |||
| 14 | jobs: | ||
| 15 | build-job: | ||
| 16 | runs-on: ubuntu-latest | ||
| 17 | container: | ||
| 18 | image: ghcr.io/ccleberg/cleberg.net:main | ||
| 19 | |||
| 20 | steps: | ||
| 21 | - name: Checkout code | ||
| 22 | uses: actions/checkout@v4 | ||
| 23 | |||
| 24 | - name: Run Build | ||
| 25 | env: | ||
| 26 | ENV: "prod" | ||
| 27 | BUILD: "true" | ||
| 28 | DEPLOY: "false" | ||
| 29 | run: | | ||
| 30 | echo "Environment is ready. Running build..." | ||
| 31 | uv run build.py | ||
| 32 | |||
| 33 | - name: Upload Build Artifacts | ||
| 34 | uses: actions/upload-artifact@v4 | ||
| 35 | with: | ||
| 36 | name: build-output | ||
| 37 | path: ${{ github.workspace }}/.build/ | ||
| 38 | include-hidden-files: true | ||
| 39 | |||
| 40 | deploy-job: | ||
| 41 | runs-on: ubuntu-latest | ||
| 42 | needs: build-job | ||
| 43 | environment: production | ||
| 44 | container: | ||
| 45 | image: ghcr.io/ccleberg/cleberg.net:main | ||
| 46 | |||
| 47 | steps: | ||
| 48 | - name: Checkout code | ||
| 49 | uses: actions/checkout@v4 | ||
| 50 | |||
| 51 | - name: Download Build Artifacts | ||
| 52 | uses: actions/download-artifact@v4 | ||
| 53 | with: | ||
| 54 | name: build-output | ||
| 55 | path: ${{ github.workspace }}/.build/ | ||
| 56 | |||
| 57 | - name: Setup SSH and Deploy | ||
| 58 | env: | ||
| 59 | SERVER_IP: ${{ secrets.SERVER_IP }} | ||
| 60 | SERVER_USER: ${{ secrets.SERVER_USER }} | ||
| 61 | SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} | ||
| 62 | run: | | ||
| 63 | eval $(ssh-agent -s) | ||
| 64 | echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - | ||
| 65 | rsync -avz --delete \ | ||
| 66 | -e "ssh -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" \ | ||
| 67 | .build/ \ | ||
| 68 | $SERVER_USER@$SERVER_IP:/var/www/cleberg.net/ | ||
.github/workflows/docker-build.yml added +41
| @@ -0,0 +1,41 @@ | |||
| 1 | name: Build and Push Docker Image | ||
| 2 | |||
| 3 | on: | ||
| 4 | push: | ||
| 5 | branches: [ "main" ] | ||
| 6 | paths: | ||
| 7 | - 'Dockerfile' | ||
| 8 | - 'requirements.txt' | ||
| 9 | - '.github/workflows/docker-build.yml' | ||
| 10 | |||
| 11 | jobs: | ||
| 12 | build: | ||
| 13 | runs-on: ubuntu-latest | ||
| 14 | permissions: | ||
| 15 | contents: read | ||
| 16 | packages: write | ||
| 17 | |||
| 18 | steps: | ||
| 19 | - name: Checkout repository | ||
| 20 | uses: actions/checkout@v4 | ||
| 21 | |||
| 22 | - name: Log in to GHCR | ||
| 23 | uses: docker/login-action@v3 | ||
| 24 | with: | ||
| 25 | registry: ghcr.io | ||
| 26 | username: ${{ github.actor }} | ||
| 27 | password: ${{ secrets.GITHUB_TOKEN }} | ||
| 28 | |||
| 29 | - name: Extract metadata | ||
| 30 | id: meta | ||
| 31 | uses: docker/metadata-action@v5 | ||
| 32 | with: | ||
| 33 | images: ghcr.io/${{ github.repository }} | ||
| 34 | |||
| 35 | - name: Build and push | ||
| 36 | uses: docker/build-push-action@v5 | ||
| 37 | with: | ||
| 38 | context: . | ||
| 39 | push: true | ||
| 40 | tags: ${{ steps.meta.outputs.tags }} | ||
| 41 | labels: ${{ steps.meta.outputs.labels }} | ||
.github/workflows/ruff.yml added +42
| @@ -0,0 +1,42 @@ | |||
| 1 | name: Ruff | ||
| 2 | |||
| 3 | on: | ||
| 4 | push: | ||
| 5 | branches: [ "main" ] | ||
| 6 | paths: | ||
| 7 | - '**.py' | ||
| 8 | pull_request: | ||
| 9 | branches: [ "main" ] | ||
| 10 | paths: | ||
| 11 | - '**.py' | ||
| 12 | |||
| 13 | jobs: | ||
| 14 | build: | ||
| 15 | runs-on: ubuntu-latest | ||
| 16 | strategy: | ||
| 17 | matrix: | ||
| 18 | python-version: ["3.x"] | ||
| 19 | steps: | ||
| 20 | - uses: actions/checkout@v4 | ||
| 21 | - name: Set up Python ${{ matrix.python-version }} | ||
| 22 | uses: actions/setup-python@v5 | ||
| 23 | with: | ||
| 24 | python-version: ${{ matrix.python-version }} | ||
| 25 | ref: ${{ github.event.pull_request.head.ref }} | ||
| 26 | - name: Install dependencies | ||
| 27 | run: | | ||
| 28 | python -m pip install --upgrade pip | ||
| 29 | pip install pandas dash plotly.express | ||
| 30 | - name: Install Ruff | ||
| 31 | uses: astral-sh/ruff-action@v3.2.2 | ||
| 32 | - name: Ruff Actions | ||
| 33 | run: | | ||
| 34 | ruff check --fix | ||
| 35 | ruff format | ||
| 36 | - name: Add and Commit | ||
| 37 | uses: EndBug/add-and-commit@v9 | ||
| 38 | env: | ||
| 39 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| 40 | with: | ||
| 41 | default_author: github_actions | ||
| 42 | pathspec_error_handling: ignore | ||
BRAND.md deleted −98
| @@ -1,98 +0,0 @@ | |||
| 1 | # Brand Reference — cleberg.net | ||
| 2 | |||
| 3 | Design decisions, usage rules, and porting checklist for this site and any | ||
| 4 | future sites. | ||
| 5 | |||
| 6 | --- | ||
| 7 | |||
| 8 | ## Color | ||
| 9 | |||
| 10 | All tokens live in `theme/static/tokens.css`. Import it before any other | ||
| 11 | stylesheet. | ||
| 12 | |||
| 13 | ### Palette | ||
| 14 | |||
| 15 | | Token | Light | Dark | Role | | ||
| 16 | |----------------|-------------|-------------|-------------------------------------------| | ||
| 17 | | `--bg` | `#F6F4F0` | `#161412` | Page background | | ||
| 18 | | `--bg-soft` | `#EDEAE4` | `#1F1C1A` | Subtle surfaces (code blocks, inputs) | | ||
| 19 | | `--fg` | `#111111` | `#F0EDE8` | Primary text, hard borders, table headers | | ||
| 20 | | `--fg-soft` | `#555550` | `#888580` | Secondary text, metadata | | ||
| 21 | | `--accent` | `#c0392b` | `#ee6f5c` | Interactive elements only (see below) | | ||
| 22 | | `--salmon` | `#ee6f5c` | `#ee6f5c` | Decorative only (see below) | | ||
| 23 | | `--border` | `#111111` | `#2C2825` | Hard borders (nav, tables) | | ||
| 24 | | `--border-soft`| `#DDDAD4` | `#2C2825` | Dashed or subtle dividers | | ||
| 25 | | `--code-bg` | `#E8E4DE` | `#0F0D0C` | Code blocks, blockquotes | | ||
| 26 | | `--meta` | `#555550` | `#888580` | Timestamps, labels, footnote numbers | | ||
| 27 | |||
| 28 | ### Usage Rules | ||
| 29 | |||
| 30 | **`--accent` is for interactive elements only:** links, `h2` left border, | ||
| 31 | footnote numbers, focus indicators. It is text-safe (WCAG AA: 4.6:1 on `--bg` in | ||
| 32 | light mode; ~4.5:1 on `--bg` in dark mode). | ||
| 33 | |||
| 34 | **`--salmon` is decorative only.** Never use it for body text on a light | ||
| 35 | background — it fails WCAG AA there. In dark mode, `--accent` and `--salmon` | ||
| 36 | resolve to the same value (`#ee6f5c`), which is intentional. | ||
| 37 | |||
| 38 | --- | ||
| 39 | |||
| 40 | ## Typography | ||
| 41 | |||
| 42 | - **Font stack:** `--font-mono` (ui-monospace, Cascadia Code, Source Code Pro, | ||
| 43 | Menlo, Consolas, monospace) | ||
| 44 | - **Headings:** weight 900, uppercase, `line-height: 1.1` | ||
| 45 | - **`h2` accent bar:** 10px left border in `--accent` | ||
| 46 | - **Body:** `1rem`, `line-height: 1.6` | ||
| 47 | - **Meta/labels:** `0.8–0.85rem`, uppercase, `--meta` color | ||
| 48 | - **Date format:** `YYYY-MM-DD` everywhere, no exceptions | ||
| 49 | |||
| 50 | --- | ||
| 51 | |||
| 52 | ## Logo | ||
| 53 | |||
| 54 | Files live in `~/Documents/brand/logo/`. | ||
| 55 | |||
| 56 | | Variant | Use case | | ||
| 57 | |-------------------------|--------------------------------------------------| | ||
| 58 | | `koi_light.svg/png` | Full logo on light backgrounds | | ||
| 59 | | `koi_dark.svg/png` | Full logo on dark backgrounds | | ||
| 60 | | `koi_light_minimal.svg` | Favicon, nav, small UI contexts on light | | ||
| 61 | | `koi_dark_minimal.svg` | Favicon, nav, small UI contexts on dark | | ||
| 62 | |||
| 63 | **Rule:** Use the minimal variant for anything under ~64px or in navigation | ||
| 64 | contexts. Use the full variant for headers, OG images, or anywhere it has room | ||
| 65 | to breathe. | ||
| 66 | |||
| 67 | --- | ||
| 68 | |||
| 69 | ## Signature Patterns | ||
| 70 | |||
| 71 | These are the things that make the site look like itself. Port all of them to | ||
| 72 | any new site. | ||
| 73 | |||
| 74 | 1. **Grayscale images with color on hover** — `img { filter: grayscale(1) } | ||
| 75 | img:hover { filter: grayscale(0) }`. Apply to all content images by default. | ||
| 76 | 2. **Blockquote as raw org-mode markup** — `#+begin_quote` / `#+end_quote` | ||
| 77 | pseudo-elements. Extend the "visible markup" aesthetic to other block | ||
| 78 | elements where appropriate. | ||
| 79 | 3. **Nav: uppercase, weight 900, invert on hover** — `background: var(--fg); | ||
| 80 | color: var(--bg)` on hover. No underlines in nav. | ||
| 81 | 4. **Links: underline offset** — `text-underline-offset: 3px`, invert on hover | ||
| 82 | (same as nav pattern). | ||
| 83 | 5. **Hard borders on tables** — `3px solid var(--fg)` outer border, `1px solid var(--fg)` internal. Table headers use `background: var(--fg); color: var(--bg)`. | ||
| 84 | |||
| 85 | --- | ||
| 86 | |||
| 87 | ## Porting Checklist (New Site) | ||
| 88 | |||
| 89 | - [ ] Import `tokens.css` (or copy variables and update `tokens.css` as the | ||
| 90 | source) | ||
| 91 | - [ ] Apply monospace font stack | ||
| 92 | - [ ] Apply grayscale image treatment | ||
| 93 | - [ ] Use minimal koi as favicon | ||
| 94 | - [ ] Use `YYYY-MM-DD` date format | ||
| 95 | - [ ] Confirm `--accent` WCAG contrast on new background colors if palette is | ||
| 96 | adjusted | ||
| 97 | - [ ] Build or adapt OG/social card template using koi + palette + monospace | ||
| 98 | type | ||
README.org −6
| @@ -27,12 +27,6 @@ The publishing system depends on: | |||
| 27 | - The weblorg package, available at [[https://github.com/emacs-love/weblorg][emacs-love/weblorg]], which provides advanced | 27 | - The weblorg package, available at [[https://github.com/emacs-love/weblorg][emacs-love/weblorg]], which provides advanced |
| 28 | Org publishing functionality and theming support. | 28 | Org publishing functionality and theming support. |
| 29 | 29 | ||
| 30 | ** Screenshots | ||
| 31 | |||
| 32 | | Light Mode | Dark Mode | | ||
| 33 | |-------------------------+------------------------| | ||
| 34 | | [[./screenshots/light.png]] | [[./screenshots/dark.png]] | | ||
| 35 | |||
| 36 | ** Configuration | 30 | ** Configuration |
| 37 | 31 | ||
| 38 | You can customize site settings can within the ~publish.el~ file. This file | 32 | You can customize site settings can within the ~publish.el~ file. This file |
build.py +23 −38
| @@ -185,13 +185,9 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 185 | lines = [] | 185 | lines = [] |
| 186 | current_year = None | 186 | current_year = None |
| 187 | for post in recent: | 187 | for post in recent: |
| 188 | year = post["date_obj"].year | ||
| 189 | if year != current_year: | ||
| 190 | current_year = year | ||
| 191 | lines.append(f'\t<li class="post-list-year">{year}</li>') | ||
| 192 | lines.append('\t<li class="post-list-item">') | 188 | lines.append('\t<li class="post-list-item">') |
| 193 | lines.append(f'\t\t<a href="/blog/{post["slug"]}.html">{post["title"]}</a>') | ||
| 194 | lines.append(f'\t\t<time datetime="{post["date_str"]}">{post["date_full"]}</time>') | 189 | lines.append(f'\t\t<time datetime="{post["date_str"]}">{post["date_full"]}</time>') |
| 190 | lines.append(f'\t\t<a href="/blog/{post["slug"]}.html">{post["title"]}</a>') | ||
| 195 | lines.append("\t</li>") | 191 | lines.append("\t</li>") |
| 196 | 192 | ||
| 197 | return "\n".join(lines) | 193 | return "\n".join(lines) |
| @@ -454,58 +450,47 @@ def generate_tags_page(content_dir="./content/blog", build_dir="./.build"): | |||
| 454 | posts = tag_map[tag] | 450 | posts = tag_map[tag] |
| 455 | items = "\n".join( | 451 | items = "\n".join( |
| 456 | f'<li class="post-list-item">' | 452 | f'<li class="post-list-item">' |
| 457 | f'<a href="/blog/{p["slug"]}.html">{p["title"]}</a>' | ||
| 458 | f'<time datetime="{p["date_str"]}">{p["date_str"]}</time>' | 453 | f'<time datetime="{p["date_str"]}">{p["date_str"]}</time>' |
| 454 | f'<a href="/blog/{p["slug"]}.html">{p["title"]}</a>' | ||
| 459 | f'</li>' | 455 | f'</li>' |
| 460 | for p in posts | 456 | for p in posts |
| 461 | ) | 457 | ) |
| 462 | sections.append(f'<h2 id="{tag}">{tag}</h2>\n<ul class="post-list">\n{items}\n</ul>') | 458 | sections.append(f'<h2 id="{tag}">{tag}</h2>\n<ul class="post-list">\n{items}\n</ul>') |
| 463 | 459 | ||
| 464 | html = f"""<!doctype html> | 460 | html = f"""<!doctype html> |
| 465 | <html lang="en-us"> | 461 | <html lang=en-us> |
| 466 | <head> | 462 | <head> |
| 467 | <meta charset="utf-8"> | 463 | <meta charset=utf-8> |
| 468 | <title>tags - seijaku</title> | 464 | <title>cleberg.net</title> |
| 469 | <meta name="viewport" content="width=device-width, initial-scale=1"> | 465 | <meta name=viewport content="width=device-width,initial-scale=1"> |
| 470 | <link rel="stylesheet" href="/styles.min.css" type="text/css"> | 466 | <meta name=author content="Christian Cleberg <hello@cleberg.net>"> |
| 471 | <link rel="icon" href="/favicon.svg" type="image/svg+xml"> | 467 | <meta name=description content="Stillness amidst the chaos."> |
| 468 | <link rel=stylesheet href=http://localhost:8000/styles.min.css> | ||
| 469 | <link rel=icon href=data:,> | ||
| 472 | </head> | 470 | </head> |
| 473 | <body> | 471 | <body> |
| 474 | <a href="#main-content" class="skip-link">Skip to content</a> | 472 | <a href=#main-content class=skip-link>Skip to content</a> |
| 475 | <header class="masthead"> | ||
| 476 | <a href="/" class="masthead-title">seijaku</a> | ||
| 477 | <p class="masthead-subtitle"><i>stillness amidst the chaos</i></p> | ||
| 478 | <nav aria-label="Site Navigation"> | 473 | <nav aria-label="Site Navigation"> |
| 479 | <ul> | 474 | <ul> |
| 480 | <li><a href="/blog/">Blog</a></li> | 475 | <li><a href=/>Home</a> |
| 481 | <li><a href="/tags/">Tags</a></li> | 476 | <li><a href=/apps/>Apps</a> |
| 482 | <li><a href="/guides/index.html">Guides</a></li> | 477 | <li><a href=/blog/>Blog</a> |
| 483 | <li><a href="/apps/">Apps</a></li> | 478 | <li><a href=/garden/>Garden</a> |
| 484 | <li><a href="/garden/">Garden</a></li> | 479 | <li><a href=/guides/>Guides</a> |
| 485 | <li><a href="/salary/">Salary</a></li> | 480 | <li><a href=/salary/>Salary</a> |
| 481 | <li><a href=/tags/>Tags</a> | ||
| 486 | </ul> | 482 | </ul> |
| 487 | </nav> | 483 | </nav> |
| 488 | </header> | 484 | <main id=main-content> |
| 489 | <main id="main-content"> | ||
| 490 | <h1>Tags</h1> | 485 | <h1>Tags</h1> |
| 491 | <ul class="tag-toc">{toc_items}</ul> | 486 | <ul class="tag-toc">{toc_items}</ul> |
| 492 | {"".join(f"<section>{s}</section>" for s in sections)} | 487 | {"".join(f"<section>{s}</section>" for s in sections)} |
| 493 | </main> | 488 | </main> |
| 494 | <hr> | ||
| 495 | <footer> | 489 | <footer> |
| 496 | <div> | 490 | <a href=https://github.com/ccleberg/cleberg.net>Source</a>· |
| 497 | <a href="https://github.com/ccleberg/cleberg.net">Source</a> · | 491 | <a href=/feed.xml>RSS</a>· |
| 498 | <a href="/feed.xml">RSS</a> · | 492 | <a href=http://paske4urhs6nttrtlkuwa5cowum3fjkc6yv6kl4ncx3mjxcd77764nqd.onion/>Onion</a>· |
| 499 | <a href="http://paske4urhs6nttrtlkuwa5cowum3fjkc6yv6kl4ncx3mjxcd77764nqd.onion/">Onion</a> · | 493 | <a href=/tips/>Tips</a> |
| 500 | <a href="/now/">Now</a> · | ||
| 501 | <a href="/uses/">Uses</a> · | ||
| 502 | <a href="/tips/">Tips</a> · | ||
| 503 | <a href="https://cv.cleberg.net">CV</a> | ||
| 504 | </div> | ||
| 505 | <div> | ||
| 506 | <a href="mailto:hello@cleberg.net">hello@cleberg.net</a> [<a href="/gpg.txt">PGP</a>] · | ||
| 507 | Signal: @cmc.01 | ||
| 508 | </div> | ||
| 509 | </footer> | 494 | </footer> |
| 510 | </body> | 495 | </body> |
| 511 | </html>""" | 496 | </html>""" |
content/apps/index.org +10 −37
| @@ -1,4 +1,4 @@ | |||
| 1 | #+title: apps | 1 | #+title: Apps |
| 2 | #+slug: index | 2 | #+slug: index |
| 3 | #+options: toc:nil | 3 | #+options: toc:nil |
| 4 | 4 | ||
| @@ -7,43 +7,16 @@ | |||
| 7 | Small apps I've built for iOS. Fully offline. No ads, no accounts, no data | 7 | Small apps I've built for iOS. Fully offline. No ads, no accounts, no data |
| 8 | collection. | 8 | collection. |
| 9 | 9 | ||
| 10 | #+begin_export html | 10 | #+begin_quote |
| 11 | <div class="app-card"> | 11 | All 3 apps are currently in Apple's review queue and are not available on the |
| 12 | <a href="https://apps.apple.com/app/daybyday"><img class="app-icon" src="https://img.cleberg.net/apps/daybyday.png" alt="DayByDay icon"></a> | 12 | App Store yet. I will update the links here as soon as Apple publishes them. |
| 13 | <div class="app-info"> | 13 | #+end_quote |
| 14 | <span class="app-title">Day By Day</span> | ||
| 15 | <span class="app-subtitle">Learn days, months & seasons!</span> | ||
| 16 | <div class="app-links"> | ||
| 17 | <a href="https://apps.apple.com/app/daybyday">App Store</a> · | ||
| 18 | <a href="https://github.com/ccleberg/DayByDay">GitHub</a> | ||
| 19 | </div> | ||
| 20 | </div> | ||
| 21 | </div> | ||
| 22 | 14 | ||
| 23 | <div class="app-card"> | 15 | | App | Description | GitHub | |
| 24 | <a href="https://apps.apple.com/app/space-explorers"><img class="app-icon" src="https://img.cleberg.net/apps/spaceexplorers.png" alt="Space Explorers icon"></a> | 16 | |-----------------+--------------------------------------+--------| |
| 25 | <div class="app-info"> | 17 | | Day By Day | Learn days, months & seasons! | [[https://github.com/ccleberg/DayByDay][GitHub]] | |
| 26 | <span class="app-title">Space Explorers</span> | 18 | | Domain Dig | DNS lookup & SSL certificate checker | [[https://github.com/ccleberg/DomainDig][GitHub]] | |
| 27 | <span class="app-subtitle">Explore the galaxy and learn!</span> | 19 | | Space Explorers | Explore the galaxy and learn! | [[https://github.com/ccleberg/SpaceExplorers][GitHub]] | |
| 28 | <div class="app-links"> | ||
| 29 | <a href="https://apps.apple.com/app/space-explorers">App Store</a> · | ||
| 30 | <a href="https://github.com/ccleberg/SpaceExplorers">GitHub</a> | ||
| 31 | </div> | ||
| 32 | </div> | ||
| 33 | </div> | ||
| 34 | |||
| 35 | <div class="app-card"> | ||
| 36 | <a href="https://apps.apple.com/app/domaindig"><img class="app-icon" src="https://img.cleberg.net/apps/domaindig.png" alt="DomainDig icon"></a> | ||
| 37 | <div class="app-info"> | ||
| 38 | <span class="app-title">Domain Dig</span> | ||
| 39 | <span class="app-subtitle">DNS lookup & SSL certificate checker</span> | ||
| 40 | <div class="app-links"> | ||
| 41 | <a href="https://apps.apple.com/app/domaindig">App Store</a> · | ||
| 42 | <a href="https://github.com/ccleberg/DomainDig">GitHub</a> | ||
| 43 | </div> | ||
| 44 | </div> | ||
| 45 | </div> | ||
| 46 | #+end_export | ||
| 47 | 20 | ||
| 48 | * Web Projects | 21 | * Web Projects |
| 49 | 22 | ||
content/blog/2018-11-28-aes-encryption.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2018-11-28 Wed 00:00:00] | 1 | #+date: [2018-11-28 Wed 00:00:00] |
| 2 | #+title: aes encryption: what the math actually does | 2 | #+title: AES Encryption |
| 3 | #+description: Detailed explanation of AES encryption, including key handling, encryption modes, algorithm structure, and implementation considerations for secure data protection. | 3 | #+description: Let's learn about AES encryption, its method, and how it can be used. |
| 4 | #+slug: aes-encryption | 4 | #+slug: aes-encryption |
| 5 | #+filetags: :security: | 5 | #+filetags: :security: |
| 6 | 6 | ||
| 7 | * Basic AES | 7 | * Basic AES |
| 8 | 8 | ||
content/blog/2018-11-28-cpp-compiler.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2018-11-28 Wed 00:00:00] | 1 | #+date: [2018-11-28 Wed 00:00:00] |
| 2 | #+title: inside the c++ compiler | 2 | #+title: The C++ Compiler |
| 3 | #+description: Systematic presentation of the C++ compilation phases including preprocessing, compilation, assembly, and linking, with technical insights into each stage's function. | 3 | #+description: A brief trip into the C++ compilation process. |
| 4 | #+slug: cpp-compiler | 4 | #+slug: cpp-compiler |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * A Brief Introduction | 7 | * A Brief Introduction |
| 8 | 8 | ||
content/blog/2019-01-07-useful-css.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2019-01-07 Mon 00:00:00] | 1 | #+date: [2019-01-07 Mon 00:00:00] |
| 2 | #+title: css notes: flexbox, shadows, variables | 2 | #+title: CSS Tips: Flexbox, Shadows, Variables |
| 3 | #+description: Practical guide on applying CSS rules and constructs such as flexbox, box shadows, and variable usage to achieve standard web styling and layout objectives. | 3 | #+description: A few quick tips on modern CSS features. |
| 4 | #+slug: useful-css | 4 | #+slug: useful-css |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | * Introduction to CSS | 7 | * Introduction to CSS |
| 8 | 8 | ||
content/blog/2019-09-09-audit-analytics.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2019-09-09 Mon 00:00:00] | 1 | #+date: [2019-09-09 Mon 00:00:00] |
| 2 | #+title: audit analytics: pandas instead of pivot tables | 2 | #+title: Internal Audit Analytics |
| 3 | #+description: Examination of data analytical approaches applied within internal audit functions to improve risk evaluation, process efficiency, and decision support. | 3 | #+description: Let's talk about data analytics and its use cases within the Internal Audit function. |
| 4 | #+slug: audit-analytics | 4 | #+slug: audit-analytics |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * What Are Data Analytics? | 7 | * What Are Data Analytics? |
| 8 | 8 | ||
content/blog/2019-12-03-the-ansoff-matrix.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2019-12-03 Tue 00:00:00] | 1 | #+date: [2019-12-03 Tue 00:00:00] |
| 2 | #+title: ansoff matrix: business school diagram, limited shelf life | 2 | #+title: The Ansoff Matrix |
| 3 | #+description: Analytical description of the Ansoff Matrix, detailing market and product development strategies for measured business expansion and competitive positioning. | 3 | #+description: A detailed description of the Ansoff Matrix business model. |
| 4 | #+slug: the-ansoff-matrix | 4 | #+slug: the-ansoff-matrix |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2019-12-16-password-security.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2019-12-16 Mon 00:00:00] | 1 | #+date: [2019-12-16 Mon 00:00:00] |
| 2 | #+title: nist passwords: the guidelines nobody implements | 2 | #+title: NIST Password Security |
| 3 | #+description: Compilation of guidelines for password generation, storage, protection, and compliance with established standards such as NIST for maintaining digital security. | 3 | #+description: Let's look at what NIST currently recommends for passwords and secrets. |
| 4 | #+slug: password-security | 4 | #+slug: password-security |
| 5 | #+filetags: :security: | 5 | #+filetags: :security: |
| 6 | 6 | ||
| 7 | * Users | 7 | * Users |
| 8 | 8 | ||
content/blog/2020-01-25-linux-software.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-01-25 Sat 00:00:00] | 1 | #+date: [2020-01-25 Sat 00:00:00] |
| 2 | #+title: linux software: what i actually install first | 2 | #+title: My Favorite Linux Software |
| 3 | #+description: Inventory and description of key Linux applications including graphical and command-line tools, with installation instructions for various distributions. | 3 | #+description: A quick list of my favorite apps on Linux. |
| 4 | #+slug: linux-software | 4 | #+slug: linux-software |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Graphical Applications | 7 | * Graphical Applications |
| 8 | 8 | ||
content/blog/2020-01-26-steam-on-ntfs.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-01-26 Sun 00:00:00] | 1 | #+date: [2020-01-26 Sun 00:00:00] |
| 2 | #+title: steam ntfs linux: it works, mostly | 2 | #+title: Steam NTFS Fix on Linux |
| 3 | #+description: Procedures for mounting NTFS drives using ntfs-3g to enable reliable execution of Steam gaming software on Linux environments. | 3 | #+description: Procedures for mounting NTFS drives using ntfs-3g for Steam on Linux. |
| 4 | #+slug: steam-on-ntfs | 4 | #+slug: steam-on-ntfs |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Auto-Mount Steam Drives | 7 | * Auto-Mount Steam Drives |
| 8 | 8 | ||
content/blog/2020-02-09-cryptography-basics.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-02-09 Sunday 00:00:00] | 1 | #+date: [2020-02-09 Sunday 00:00:00] |
| 2 | #+title: cryptography basics: keys, certs, and why it matters | 2 | #+title: Cryptography Basics |
| 3 | #+description: Systematic overview of encryption methodologies, key categories, algorithmic frameworks, and their applications in data confidentiality and integrity. | 3 | #+description: An introduction to cryptographic methods for encryption. |
| 4 | #+slug: cryptography | 4 | #+slug: cryptography |
| 5 | #+filetags: :security: | 5 | #+filetags: :security: |
| 6 | 6 | ||
| 7 | * Similar Article Available | 7 | * Similar Article Available |
| 8 | 8 | ||
content/blog/2020-03-25-session-messenger.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-03-25 Wed 00:00:00] | 1 | #+date: [2020-03-25 Wed 00:00:00] |
| 2 | #+title: session messenger: is it secure? | 2 | #+title: Review: Session Messenger |
| 3 | #+description: Technical description of the Session messaging protocol, including end-to-end encryption, metadata minimization, multi-device synchronization, and privacy-centric design. | 3 | #+description: A user review of the Session Messenger app on Linux, macOS, and iOS. |
| 4 | #+slug: session-messenger | 4 | #+slug: session-messenger |
| 5 | #+filetags: :privacy: | 5 | #+filetags: :privacy: |
| 6 | 6 | ||
| 7 | * Privacy Warning | 7 | * Privacy Warning |
| 8 | 8 | ||
content/blog/2020-05-03-homelab.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-05-03 Sun 00:00:00] | 1 | #+date: [2020-05-03 Sun 00:00:00] |
| 2 | #+title: homelab: rack, network, what broke | 2 | #+title: A Look Inside My Homelab |
| 3 | #+description: Comprehensive instructions on assembling and configuring a homelab environment, emphasizing hardware selection, software deployment, and network setup for operational efficiency. | 3 | #+description: A retrospective guide after throwing together the first iteration of my home lab. |
| 4 | #+slug: homelab | 4 | #+slug: homelab |
| 5 | #+filetags: :self-hosting: | 5 | #+filetags: :self-hosting: |
| 6 | 6 | ||
| 7 | * What is a Homelab? | 7 | * What is a Homelab? |
| 8 | 8 | ||
content/blog/2020-05-19-customizing-ubuntu.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-05-19 Tue 00:00:00] | 1 | #+date: [2020-05-19 Tue 00:00:00] |
| 2 | #+title: ubuntu gnome customization: making it not look terrible | 2 | #+title: Ubuntu GNOME Customization |
| 3 | #+description: Detailed instructions for modifying system appearance and interface elements in Ubuntu 20.04, including setting themes, icon packs, font adjustments, terminal configurations, and related customization parameters. | 3 | #+description: Some tips and tricks to customize GNOME on Ubuntu 20.04. |
| 4 | #+slug: customizing-ubuntu | 4 | #+slug: customizing-ubuntu |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * More Information | 7 | * More Information |
| 8 | 8 | ||
content/blog/2020-07-20-video-game-sales.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-07-20 Mon 00:00:00] | 1 | #+date: [2020-07-20 Mon 00:00:00] |
| 2 | #+title: video game sales data: 40 years of numbers | 2 | #+title: Data Analysis: Video Games Sales Data |
| 3 | #+description: Presentation of analyzed data regarding global video game sales, covering platform distributions, genre classifications, and geographic market performance metrics. | 3 | #+description: A simple data analysis of the video games sales dataset. |
| 4 | #+slug: video-game-sales | 4 | #+slug: video-game-sales |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Background Information | 7 | * Background Information |
| 8 | 8 | ||
content/blog/2020-07-26-business-analysis.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-07-26 Sun 00:00:00] | 1 | #+date: [2020-07-26 Sun 00:00:00] |
| 2 | #+title: business location analysis: python maps, urban data | 2 | #+title: Data Analysis: Finding the Best Location for a Business |
| 3 | #+description: Methodology for utilizing data science techniques and Foursquare API data to analyze and select promising business sites within urban environments. | 3 | #+description: Part of my data analysis course, I built an algorithm to find the best location for a new business in Lincoln. |
| 4 | #+slug: business-analysis | 4 | #+slug: business-analysis |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * Background Information | 7 | * Background Information |
| 8 | 8 | ||
content/blog/2020-08-22-redirect-github-pages.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-08-22 Sat 00:00:00] | 1 | #+date: [2020-08-22 Sat 00:00:00] |
| 2 | #+title: github pages root domain: drop the www | 2 | #+title: GitHub Pages Redirect Subdomain to TLD |
| 3 | #+description: Stepwise instructions for configuring redirection of GitHub Pages sites from the www subdomain to the apex domain to improve domain resolution and access consistency. | 3 | #+description: A quick recap of a Stack Overflow answer that I want to exist in perpetuity. |
| 4 | #+slug: redirect-github-pages | 4 | #+slug: redirect-github-pages |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | * Short answer | 7 | * Short answer |
| 8 | 8 | ||
content/blog/2020-08-29-php-auth-flow.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-08-29 Sat 00:00:00] | 1 | #+date: [2020-08-29 Sat 00:00:00] |
| 2 | #+title: php auth: sessions from scratch | 2 | #+title: Learning PHP Auth |
| 3 | #+description: Comprehensive guide to developing a secure user login system in PHP, including account creation, session management, and logout procedures. | 3 | #+description: A quick recap of my recent learning experience with PHP Auth. |
| 4 | #+slug: php-auth-flow | 4 | #+slug: php-auth-flow |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | * Introduction | 7 | * Introduction |
| 8 | 8 | ||
content/blog/2020-09-01-visual-recognition.org +3 −3
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-09-01 Tue 00:00:00] | 1 | #+date: [2020-09-01 Tue 00:00:00] |
| 2 | #+title: ibm watson vision api: before they killed it | 2 | #+title: IBM Watson Vision API |
| 3 | #+description: Technical overview and application instructions for using IBM Watson Visual Recognition service, with focus on API configuration, image input processing, and classification output handling. | 3 | #+description: Technical overview and application instructions for using IBM Watson Visual Recognition service, with focus on API configuration, image input processing, and classification output handling. |
| 4 | #+slug: visual-recognition | 4 | #+slug: visual-recognition |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * What is IBM Watson? | 7 | * What is IBM Watson? |
| 8 | 8 | ||
content/blog/2020-09-22-internal-audit.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-09-22 Tue 00:00:00] | 1 | #+date: [2020-09-22 Tue 00:00:00] |
| 2 | #+title: internal audit: what it does vs. what management thinks it does | 2 | #+title: Internal Audit: Who Are They? |
| 3 | #+description: Analysis of internal audit processes, their contribution to risk management, governance frameworks, and compliance monitoring within corporate structures. | 3 | #+description: Learn who your Internal Audit partners actually are. |
| 4 | #+slug: internal-audit | 4 | #+slug: internal-audit |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * Definitions | 7 | * Definitions |
| 8 | 8 | ||
content/blog/2020-09-25-happiness-map.org +3 −3
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-09-25 Fri 00:00:00] | 1 | #+date: [2020-09-25 Fri 00:00:00] |
| 2 | #+title: happiness choropleth: folium map, world data | 2 | #+title: Data Analysis: World Happiness Choropleth Map |
| 3 | #+description: Instructions for creating an interactive choropleth map visualizing international happiness data based on metrics such as GDP, social support, health indicators, freedom indices, generosity, and corruption levels. | 3 | #+description: A quick dive into choropleth maps. |
| 4 | #+slug: happiness-map | 4 | #+slug: happiness-map |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Background Information | 7 | * Background Information |
| 8 | 8 | ||
content/blog/2020-10-12-mediocrity.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-10-12 Mon 00:00:00] | 1 | #+date: [2020-10-12 Mon 00:00:00] |
| 2 | #+title: when good is good enough—and when it isn't | 2 | #+title: On Mediocrity |
| 3 | #+description: Examination of decision-making principles relating to achieving sufficient quality levels, including trade-offs between perfection and adequacy in professional and operational contexts. | 3 | #+description: Thoughts on mediocrity and when perfect is the enemy of good. |
| 4 | #+slug: mediocrity | 4 | #+slug: mediocrity |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Perfect is the Enemy of Good | 7 | * Perfect is the Enemy of Good |
| 8 | 8 | ||
content/blog/2020-12-27-website-redesign.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-12-27 Sun 00:00:00] | 1 | #+date: [2020-12-27 Sun 00:00:00] |
| 2 | #+title: website redesign: 5kb, 100s on lighthouse, no framework | 2 | #+title: Minimalist Website Redesign (5kb) |
| 3 | #+description: Detailed process outlining methods for reducing website page size to approximately 5 kilobytes, enhancing loading speed, search engine indexing efficiency, and user interface responsiveness. | 3 | #+description: A retrospective summary of recent changes to minimize my site. |
| 4 | #+slug: website-redesign | 4 | #+slug: website-redesign |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | * A Brief History | 7 | * A Brief History |
| 8 | 8 | ||
content/blog/2020-12-28-neon-drive.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-12-28 Mon 00:00:00] | 1 | #+date: [2020-12-28 Mon 00:00:00] |
| 2 | #+title: neon drive: review | 2 | #+title: Neon Drive |
| 3 | #+description: Description of game mechanics, graphical style, and level design in Neon Drive, an arcade racing game inspired by 1980s synthwave aesthetics. | 3 | #+description: My thoughts on Neon Drive, a synthwave-inspired arcade racer. |
| 4 | #+slug: neon-drive | 4 | #+slug: neon-drive |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Game Description | 7 | * Game Description |
| 8 | 8 | ||
content/blog/2020-12-29-zork.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2020-12-29 Tue 00:00:00] | 1 | #+date: [2020-12-29 Tue 00:00:00] |
| 2 | #+title: zork: the text adventure that started it all | 2 | #+title: The Zork Anthology |
| 3 | #+description: Detailed operational guide for navigating Zork, a text-based interactive fiction game from the 1980s. Includes instructions for exploration, puzzle resolution, and item collection. | 3 | #+description: My thoughts on Zork (plus, some tips and a map). |
| 4 | #+slug: zork | 4 | #+slug: zork |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Download (Free) | 7 | * Download (Free) |
| 8 | 8 | ||
content/blog/2021-01-01-seum.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-01-01 Fri 00:00:00] | 1 | #+date: [2021-01-01 Fri 00:00:00] |
| 2 | #+title: seum: speedrunners from hell | 2 | #+title: SEUM: Speedrunners from Hell |
| 3 | #+description: Technical overview for utilizing the game SEUM, focusing on speedrunning techniques, gravity manipulation, teleportation functions, and level completion criteria. | 3 | #+description: A quick look at one of my favorite speedrunning games. |
| 4 | #+slug: seum | 4 | #+slug: seum |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Game Description | 7 | * Game Description |
| 8 | 8 | ||
content/blog/2021-01-04-fediverse.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-01-04 Mon 00:00:00] | 1 | #+date: [2021-01-04 Mon 00:00:00] |
| 2 | #+title: fediverse: decentralized social, minus the algorithm | 2 | #+title: Fediverse: Decentralized Social |
| 3 | #+description: Detailed introduction to the Fediverse network architecture, user registration procedures, platform navigation, and protocols ensuring content decentralization and censorship resistance. | 3 | #+description: A primer on the fediverse, how it works, and why I use it. |
| 4 | #+slug: fediverse | 4 | #+slug: fediverse |
| 5 | #+filetags: :privacy: | 5 | #+filetags: :privacy: |
| 6 | 6 | ||
| 7 | * What is the Fediverse? | 7 | * What is the Fediverse? |
| 8 | 8 | ||
content/blog/2021-01-07-ufw.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-01-07 Thu 00:00:00] | 1 | #+date: [2021-01-07 Thu 00:00:00] |
| 2 | #+title: ufw hardening: firewall config you should have set up already | 2 | #+title: UFW: Firewall Setup on Ubuntu |
| 3 | #+description: Stepwise instructions for installation, configuration, enabling, and management of the Uncomplicated Firewall utility to secure network interfaces on Ubuntu server environments. | 3 | #+description: How to install and configure UFW on Ubuntu. |
| 4 | #+slug: ufw | 4 | #+slug: ufw |
| 5 | #+filetags: :linux:security: | 5 | #+filetags: :linux:security: |
| 6 | 6 | ||
| 7 | * Uncomplicated Firewall | 7 | * Uncomplicated Firewall |
| 8 | 8 | ||
content/blog/2021-02-19-macos.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-02-19 Fri 00:00:00] | 1 | #+date: [2021-02-19 Fri 00:00:00] |
| 2 | #+title: macos for linux users: what to fix first | 2 | #+title: macOS for Linux Users |
| 3 | #+description: Comprehensive overview for first-time macOS users transitioning from other OS platforms, including system setup, terminal usage, and user interface customization. | 3 | #+description: First steps for Linux users switching to macOS. |
| 4 | #+slug: macos | 4 | #+slug: macos |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Diving into macOS | 7 | * Diving into macOS |
| 8 | 8 | ||
content/blog/2021-03-19-clone-github-repos.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-03-19 Fri 00:00:00] | 1 | #+date: [2021-03-19 Fri 00:00:00] |
| 2 | #+title: github and sourcehut: scripting mass clones and remote updates | 2 | #+title: Scripting Mass Clones from GitHub and Sourcehut |
| 3 | #+description: Script-based methodology for cloning multiple repositories from GitHub and Sourcehut accounts. Includes automation techniques to streamline repository management and backups. | 3 | #+description: Scripts to clone all your repos from GitHub or Sourcehut at once. |
| 4 | #+slug: clone-github-repos | 4 | #+slug: clone-github-repos |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Cloning from GitHub | 7 | * Cloning from GitHub |
| 8 | 8 | ||
content/blog/2021-03-28-gemini-capsule.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-03-28 Sun 00:00:00] | 1 | #+date: [2021-03-28 Sun 00:00:00] |
| 2 | #+title: gemini capsule: deploy it, own your content | 2 | #+title: Gemini Capsule: Deploy and Own Your Content |
| 3 | #+description: Incremental procedural guide to initiate and maintain a Gemini capsule server. Covers installation, deployment, and operational best practices for beginners. | 3 | #+description: How to set up and run your own Gemini capsule. |
| 4 | #+slug: gemini-capsule | 4 | #+slug: gemini-capsule |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * What is Gemini? | 7 | * What is Gemini? |
| 8 | 8 | ||
content/blog/2021-03-28-vaporwave-vs-outrun.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-03-28 Sun 00:00:00] | 1 | #+date: [2021-03-28 Sun 00:00:00] |
| 2 | #+title: vaporwave vs outrun: the aesthetic breakdown | 2 | #+title: Vaporwave vs. Outrun |
| 3 | #+description: Systematic examination of Vaporwave and Outrun aesthetic frameworks, focusing on graphical elements, chromatic schemes, musical associations, and period-specific cultural influences. | 3 | #+description: Breaking down the differences between vaporwave and outrun aesthetics. |
| 4 | #+slug: vaporwave-vs-outrun | 4 | #+slug: vaporwave-vs-outrun |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2021-03-30-vps-web-server.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-03-30 Tue 00:00:00] | 1 | #+date: [2021-03-30 Tue 00:00:00] |
| 2 | #+title: vps web server: get off shared hosting | 2 | #+title: VPS Web Server: Get Off Shared Hosting |
| 3 | #+description: Instructional outline for setting up and maintaining a VPS environment configured for secure and scalable web hosting applications. | 3 | #+description: How to set up a VPS and host your own website. |
| 4 | #+slug: vps-web-server | 4 | #+slug: vps-web-server |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Shared Hosting vs. VPS (Virtual Private Server) | 7 | * Shared Hosting vs. VPS (Virtual Private Server) |
| 8 | 8 | ||
content/blog/2021-04-17-gemini-server.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-04-17 Sat 00:00:00] | 1 | #+date: [2021-04-17 Sat 00:00:00] |
| 2 | #+title: agate gemini server installation and firewall configuration | 2 | #+title: Agate Gemini Server Setup |
| 3 | #+description: Detailed directives for installation and configuration of a Gemini protocol server on Ubuntu, including network security and firewall setup. | 3 | #+description: Installing Agate and configuring a firewall for a Gemini server on Ubuntu. |
| 4 | #+slug: gemini-server | 4 | #+slug: gemini-server |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * Similar Article Available | 7 | * Similar Article Available |
| 8 | 8 | ||
content/blog/2021-04-23-php-comment-system.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-04-23 Fri 00:00:00] | 1 | #+date: [2021-04-23 Fri 00:00:00] |
| 2 | #+title: building a lightweight php static commenting system without javascript | 2 | #+title: A Lightweight, Static PHP Comment System |
| 3 | #+description: Technical walkthrough for constructing a lightweight, privacy-oriented static comment system using PHP, with no client-side scripting or external dependencies. | 3 | #+description: Building a simple PHP comment system with no JavaScript and no external dependencies. |
| 4 | #+slug: php-comment-system | 4 | #+slug: php-comment-system |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * The Terrible-ness of Commenting Systems | 7 | * The Terrible-ness of Commenting Systems |
| 8 | 8 | ||
content/blog/2021-04-28-photography.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-04-28 Wed 00:00:00] | 1 | #+date: [2021-04-28 Wed 00:00:00] |
| 2 | #+title: photography: gear and what actually matters | 2 | #+title: My Photography Gear |
| 3 | #+description: Instructional document covering basic techniques in photography, including equipment selection, operational best practices, and methods for capturing high-quality images. | 3 | #+description: My approach to photography and the gear I use. |
| 4 | #+slug: photography | 4 | #+slug: photography |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Why Photography? | 7 | * Why Photography? |
| 8 | 8 | ||
content/blog/2021-05-30-changing-git-authors.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-05-30 Sun 00:00:00] | 1 | #+date: [2021-05-30 Sun 00:00:00] |
| 2 | #+title: automated script for correcting git author details in multiple projects | 2 | #+title: Correcting Git Author Details Across Multiple Repos |
| 3 | #+description: Detailed instructions for systematically updating the Git author name and email information in multiple repositories using command-line tools and scripts. | 3 | #+description: A script to update the git author name and email across multiple repos. |
| 4 | #+slug: changing-git-authors | 4 | #+slug: changing-git-authors |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Changing Git Author/Email Based on Previously Committed Email | 7 | * Changing Git Author/Email Based on Previously Committed Email |
| 8 | 8 | ||
content/blog/2021-07-15-delete-gitlab-repos.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-07-15 Thu 00:00:00] | 1 | #+date: [2021-07-15 Thu 00:00:00] |
| 2 | #+title: automated deletion of all gitlab repositories using python | 2 | #+title: Deleting All GitLab Repositories with Python |
| 3 | #+description: Stepwise instructions for executing a Python script to delete all repositories associated with a GitLab account. Includes authentication and error handling procedures. | 3 | #+description: A Python script to delete all your GitLab repositories at once. |
| 4 | #+slug: delete-gitlab-repos | 4 | #+slug: delete-gitlab-repos |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Background | 7 | * Background |
| 8 | 8 | ||
content/blog/2021-08-25-audit-sampling.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-08-25 Wed 00:00:00] | 1 | #+date: [2021-08-25 Wed 00:00:00] |
| 2 | #+title: audit sampling: pandas for random and stratified samples | 2 | #+title: Audit Sampling with Pandas |
| 3 | #+description: Presentation of methods for implementing audit sampling techniques including simple random, stratified, and systematic sampling using Python's Pandas library for precise audit outcomes. | 3 | #+description: Using Python and Pandas to run random and stratified audit samples. |
| 4 | #+slug: audit-sampling | 4 | #+slug: audit-sampling |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * Introduction | 7 | * Introduction |
| 8 | 8 | ||
content/blog/2021-10-09-apache-redirect.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-10-09 Sat 00:00:00] | 1 | #+date: [2021-10-09 Sat 00:00:00] |
| 2 | #+title: setting up apache rewrite rules for extensionless urls | 2 | #+title: Apache Rewrite Rules for Extensionless URLs |
| 3 | #+description: Technical guide to applying Apache mod_rewrite directives for transforming .html file requests into clean directory-style URL structures to enhance website navigation and indexing. | 3 | #+description: Using mod_rewrite to serve clean, extensionless URLs in Apache. |
| 4 | #+slug: apache-redirect | 4 | #+slug: apache-redirect |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | * The Problem | 7 | * The Problem |
| 8 | 8 | ||
content/blog/2021-12-04-cisa.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2021-12-04 Sat 00:00:00] | 1 | #+date: [2021-12-04 Sat 00:00:00] |
| 2 | #+title: cisa exam: what the test measures vs. what the job requires | 2 | #+title: I Passed the CISA Exam |
| 3 | #+description: Comprehensive outline of study materials, preparation strategies, and procedural advice for passing the CISA examination on the initial attempt. | 3 | #+description: My take on the CISA exam: what it covers, and what it doesn't. |
| 4 | #+slug: cisa | 4 | #+slug: cisa |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * What is the CISA? | 7 | * What is the CISA? |
| 8 | 8 | ||
content/blog/2022-02-10-leaving-the-office.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-02-10 Thu 00:00:00] | 1 | #+date: [2022-02-10 Thu 00:00:00] |
| 2 | #+title: leaving the office: remote work without the linkedin take | 2 | #+title: Leaving the Office |
| 3 | #+description: Examination of factors influencing the shift from traditional office environments to remote work, including benefits, constraints, and implementation recommendations. | 3 | #+description: My honest thoughts on leaving the office and working remotely. |
| 4 | #+slug: leaving-the-office | 4 | #+slug: leaving-the-office |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * The Working World is Changing | 7 | * The Working World is Changing |
| 8 | 8 | ||
content/blog/2022-02-10-njalla-dns-api.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-02-10 Thu 00:00:00] | 1 | #+date: [2022-02-10 Thu 00:00:00] |
| 2 | #+title: automating dynamic dns record updates via njalla api using python | 2 | #+title: Dynamic DNS Updates via the Njalla API |
| 3 | #+description: Instructional material detailing automation of DNS record updates by interfacing with Njalla's API, suitable for environments with frequently changing IP addresses. | 3 | #+description: A Python script to update DNS records automatically via the Njalla API. |
| 4 | #+slug: njalla-dns-api | 4 | #+slug: njalla-dns-api |
| 5 | #+filetags: :security: | 5 | #+filetags: :security: |
| 6 | 6 | ||
| 7 | * Njalla's API | 7 | * Njalla's API |
| 8 | 8 | ||
content/blog/2022-02-16-debian-and-nginx.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-02-16 Wed 00:00:00] | 1 | #+date: [2022-02-16 Wed 00:00:00] |
| 2 | #+title: debian nginx migration: ditch ubuntu, move the stack | 2 | #+title: Migrating from Ubuntu to Debian with Nginx |
| 3 | #+description: Step-by-step protocol for transitioning web server infrastructure to Debian operating system, including installation, configuration, and security hardening of Nginx and Agate services. | 3 | #+description: Moving my web server from Ubuntu to Debian and reconfiguring Nginx. |
| 4 | #+slug: debian-and-nginx | 4 | #+slug: debian-and-nginx |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * Server Operating System (OS): Debian | 7 | * Server Operating System (OS): Debian |
| 8 | 8 | ||
content/blog/2022-02-17-exiftool.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-02-17 Thu 00:00:00] | 1 | #+date: [2022-02-17 Thu 00:00:00] |
| 2 | #+title: exiftool metadata: strip it before you post it | 2 | #+title: ExifTool: Strip Metadata Before You Post |
| 3 | #+description: Technical instructions for utilizing Exiftool to systematically strip metadata from image files to ensure privacy and reduce file size. | 3 | #+description: How to use ExifTool to strip metadata from images before sharing them. |
| 4 | #+slug: exiftool | 4 | #+slug: exiftool |
| 5 | #+filetags: :linux:privacy: | 5 | #+filetags: :linux:privacy: |
| 6 | 6 | ||
| 7 | ** Why Strip Metadata? | 7 | ** Why Strip Metadata? |
| 8 | 8 | ||
content/blog/2022-02-20-nginx-caching.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-02-20 Sun 00:00:00] | 1 | #+date: [2022-02-20 Sun 00:00:00] |
| 2 | #+title: nginx caching: static content, cache config | 2 | #+title: Nginx Caching for Static Content |
| 3 | #+description: Detailed methods for configuring Nginx to cache static resources such as CSS, JavaScript, and images to improve website loading times and resource efficiency. | 3 | #+description: Configuring Nginx to cache static assets like CSS, JS, and images. |
| 4 | #+slug: nginx-caching | 4 | #+slug: nginx-caching |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * Update Your Nginx Config to Cache Static Files | 7 | * Update Your Nginx Config to Cache Static Files |
| 8 | 8 | ||
content/blog/2022-02-22-tuesday.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-02-22 Tue 00:00:00] | 1 | #+date: [2022-02-22 Tue 00:00:00] |
| 2 | #+title: twosday: 2 22 22 was a real date | 2 | #+title: Twosday: 2/22/22 |
| 3 | #+description: Examination of the date Tuesday, February 22, 2022, highlighting the palindromic properties and expected observations on this specific calendar occurrence. | 3 | #+description: A brief note on Tuesday, February 22nd, 2022. |
| 4 | #+slug: tuesday | 4 | #+slug: tuesday |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Tuesday, Twosday | 7 | * Tuesday, Twosday |
| 8 | 8 | ||
content/blog/2022-03-02-reliable-notes.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-03-02 Wed 00:00:00] | 1 | #+date: [2022-03-02 Wed 00:00:00] |
| 2 | #+title: notes in plaintext: portable, no app dependency | 2 | #+title: Create Reliable Notes with Plaintext |
| 3 | #+description: Instructions on applying standardized note-taking procedures with Markdown format, including synchronization and cross-platform compatibility considerations. | 3 | #+description: Why I keep my notes in plaintext Markdown, synced across devices. |
| 4 | #+slug: reliable-notes | 4 | #+slug: reliable-notes |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Choosing Durable File Formats | 7 | * Choosing Durable File Formats |
| 8 | 8 | ||
content/blog/2022-03-03-financial-database.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-03-03 Thu 00:00:00] | 1 | #+date: [2022-03-03 Thu 00:00:00] |
| 2 | #+title: financial tracker: sqlite over spreadsheets | 2 | #+title: Personal Finance Tracker with SQLite |
| 3 | #+description: Procedures for creating and maintaining a personal financial database utilizing SQLite, Python programming language, and Jupyter Notebook interface. | 3 | #+description: Building a personal finance tracker with SQLite, Python, and Jupyter. |
| 4 | #+slug: financial-database | 4 | #+slug: financial-database |
| 5 | #+filetags: :self-hosting: | 5 | #+filetags: :self-hosting: |
| 6 | 6 | ||
| 7 | * Personal Financial Tracking | 7 | * Personal Financial Tracking |
| 8 | 8 | ||
content/blog/2022-03-08-plex-migration.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-03-08 Tue 00:00:00] | 1 | #+date: [2022-03-08 Tue 00:00:00] |
| 2 | #+title: migrating plex media server to new hardware with nvidia gpu setup | 2 | #+title: Migrating Plex to New Hardware with Nvidia GPU |
| 3 | #+description: Stepwise instructions for transferring Plex Media Server to new hardware and enabling Nvidia GPU transcoding to optimize media processing performance. | 3 | #+description: Moving Plex to new hardware and setting up Nvidia GPU transcoding. |
| 4 | #+slug: plex-migration | 4 | #+slug: plex-migration |
| 5 | #+filetags: :self-hosting: | 5 | #+filetags: :self-hosting: |
| 6 | 6 | ||
| 7 | * Migration Phases | 7 | * Migration Phases |
| 8 | 8 | ||
content/blog/2022-03-23-cloudflare-dns-api.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-03-23 Wed 00:00:00] | 1 | #+date: [2022-03-23 Wed 00:00:00] |
| 2 | #+title: dynamic dns record updates via cloudflare api | 2 | #+title: Dynamic DNS Updates via the Cloudflare API |
| 3 | #+description: Command-line procedures to automate updating of DNS A and AAAA records by interfacing with the Cloudflare API, suitable for environments with variable IP addresses. | 3 | #+description: Automatically updating DNS A and AAAA records via the Cloudflare API. |
| 4 | #+slug: cloudflare-dns-api | 4 | #+slug: cloudflare-dns-api |
| 5 | #+filetags: :security: | 5 | #+filetags: :security: |
| 6 | 6 | ||
| 7 | * DDNS: Dynamic DNS | 7 | * DDNS: Dynamic DNS |
| 8 | :PROPERTIES: | 8 | :PROPERTIES: |
content/blog/2022-03-23-nextcloud-on-ubuntu.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-03-23 Wed 00:00:00] | 1 | #+date: [2022-03-23 Wed 00:00:00] |
| 2 | #+title: self hosting guide: nextcloud | 2 | #+title: Self-Hosting Guide: Nextcloud |
| 3 | #+description: Comprehensive guide for implementing Nextcloud as a self-hosted solution on an Ubuntu server, including installation steps, configuration parameters, and basic security measures. | 3 | #+description: How to install and configure Nextcloud on Ubuntu. |
| 4 | #+slug: nextcloud-on-ubuntu | 4 | #+slug: nextcloud-on-ubuntu |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * What is Nextcloud? | 7 | * What is Nextcloud? |
| 8 | :PROPERTIES: | 8 | :PROPERTIES: |
content/blog/2022-03-24-server-hardening.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-03-24 Thu 00:00:00] | 1 | #+date: [2022-03-24 Thu 00:00:00] |
| 2 | #+title: server hardening: firewalls, ssh, vlans | 2 | #+title: Server Hardening: Firewalls, SSH, VLANs |
| 3 | #+description: Detailed instructions to enhance the security posture of home servers exposed to public networks, including firewall setup, secure SSH configuration, fail2ban deployment, and network segmentation. | 3 | #+description: Hardening a home server with UFW, SSH config, fail2ban, and VLANs. |
| 4 | #+slug: server-hardening | 4 | #+slug: server-hardening |
| 5 | #+filetags: :linux:security: | 5 | #+filetags: :linux:security: |
| 6 | 6 | ||
| 7 | * Planning Data Flows & Security | 7 | * Planning Data Flows & Security |
| 8 | 8 | ||
content/blog/2022-03-26-ssh-mfa.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-03-26 Sat 00:00:00] | 1 | #+date: [2022-03-26 Sat 00:00:00] |
| 2 | #+title: ssh mfa: totp on top of keys | 2 | #+title: SSH MFA: TOTP on Top of Keys |
| 3 | #+description: Step-by-step deployment guide for enabling TOTP multi-factor authentication on SSH services using Google Authenticator and Pluggable Authentication Module (PAM) integration. | 3 | #+description: Adding TOTP two-factor authentication on top of SSH key auth. |
| 4 | #+slug: ssh-mfa | 4 | #+slug: ssh-mfa |
| 5 | #+filetags: :security: | 5 | #+filetags: :security: |
| 6 | 6 | ||
| 7 | * Why Do I Need Multi-Factor Authentication (MFA) for SSH (Secure Shell Protocol)? | 7 | * Why Do I Need Multi-Factor Authentication (MFA) for SSH (Secure Shell Protocol)? |
| 8 | 8 | ||
content/blog/2022-04-02-nginx-reverse-proxy.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-04-02 Sat 00:00:00] | 1 | #+date: [2022-04-02 Sat 00:00:00] |
| 2 | #+title: nginx reverse proxy: config and nothing else | 2 | #+title: Nginx Reverse Proxy Config |
| 3 | #+description: Technical guide for setting up Nginx server to operate as a reverse proxy on Ubuntu systems, including configuration files setup and operational parameters. | 3 | #+description: Setting up Nginx as a reverse proxy on Ubuntu. |
| 4 | #+slug: nginx-reverse-proxy | 4 | #+slug: nginx-reverse-proxy |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * What is a Reverse Proxy? | 7 | * What is a Reverse Proxy? |
| 8 | 8 | ||
content/blog/2022-04-09-pinetime.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-04-09 Sat 00:00:00] | 1 | #+date: [2022-04-09 Sat 00:00:00] |
| 2 | #+title: pinetime smartwatch: an open source hardware & software overview | 2 | #+title: PineTime: Open Source Smartwatch Overview |
| 3 | #+description: Technical description of PineTime smartwatch capabilities, including heart rate measurement, step counting, sleep monitoring, and smartphone connectivity functions. | 3 | #+description: An overview of the PineTime open-source smartwatch and what it can do. |
| 4 | #+slug: pinetime | 4 | #+slug: pinetime |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * PineTime Product Information | 7 | * PineTime Product Information |
| 8 | 8 | ||
content/blog/2022-06-01-ditching-cloudflare.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-06-01 Wed 00:00:00] | 1 | #+date: [2022-06-01 Wed 00:00:00] |
| 2 | #+title: ditching cloudflare: dns under your own name, not theirs | 2 | #+title: Ditching Cloudflare |
| 3 | #+description: Evaluation and procedural explanation for migrating DNS management services from Cloudflare to Njalla, with emphasis on privacy controls and domain registration mechanics. | 3 | #+description: Why I moved my DNS away from Cloudflare, and how I did it. |
| 4 | #+slug: ditching-cloudflare | 4 | #+slug: ditching-cloudflare |
| 5 | #+filetags: :privacy:security: | 5 | #+filetags: :privacy:security: |
| 6 | 6 | ||
| 7 | * Registrar | 7 | * Registrar |
| 8 | 8 | ||
content/blog/2022-06-07-self-hosting-freshrss.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-06-07 Tue 00:00:00] | 1 | #+date: [2022-06-07 Tue 00:00:00] |
| 2 | #+title: self hosting guide: freshrss | 2 | #+title: Self-Hosting Guide: FreshRSS |
| 3 | #+description: Stepwise instructions for installing FreshRSS using Docker and configuring Nginx as a reverse proxy to enable secure and synchronized RSS feed access. | 3 | #+description: How to install FreshRSS with Docker and Nginx. |
| 4 | #+slug: self-hosting-freshrss | 4 | #+slug: self-hosting-freshrss |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Why Use Really Simple Syndication (RSS)? | 7 | * Why Use Really Simple Syndication (RSS)? |
| 8 | 8 | ||
content/blog/2022-06-16-terminal-lifestyle.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-06-16 Thu 00:00:00] | 1 | #+date: [2022-06-16 Thu 00:00:00] |
| 2 | #+title: terminal first: why the gui is optional | 2 | #+title: Terminal First: Why the GUI Is Optional |
| 3 | #+description: Detailed procedures for reducing digital interruptions and increasing efficiency through terminal-based utilities for web browsing, communication, electronic mail, RSS feeds, and programming tasks. | 3 | #+description: My setup for handling email, browsing, IRC, and RSS from the terminal. |
| 4 | #+slug: terminal-lifestyle | 4 | #+slug: terminal-lifestyle |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Text-Based Simplicity | 7 | * Text-Based Simplicity |
| 8 | 8 | ||
content/blog/2022-06-22-daily-poetry.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-06-22 Wed 00:00:00] | 1 | #+date: [2022-06-22 Wed 00:00:00] |
| 2 | #+title: daily poetry: cron job, no subscription required | 2 | #+title: Daily Poetry via Cron |
| 3 | #+description: Instructional guide for scheduling and automating the distribution of classic and contemporary poetry in plaintext format to an electronic mail inbox using Python scripting and SMTP protocol. | 3 | #+description: A Python script that emails you a poem every morning via cron. |
| 4 | #+slug: daily-poetry | 4 | #+slug: daily-poetry |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * Source Code | 7 | * Source Code |
| 8 | 8 | ||
content/blog/2022-06-24-fedora-i3.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-06-24 Fri 00:00:00] | 1 | #+date: [2022-06-24 Fri 00:00:00] |
| 2 | #+title: fedora i3: back on linux, tiling wm | 2 | #+title: Fedora and i3: Back on Linux |
| 3 | #+description: Examination of the transition from macOS to Linux, including a detailed description of Fedora operating system installation and i3 window manager configuration. | 3 | #+description: Moving back to Linux: installing Fedora and setting up i3. |
| 4 | #+slug: fedora-i3 | 4 | #+slug: fedora-i3 |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Leaving macOS | 7 | * Leaving macOS |
| 8 | 8 | ||
content/blog/2022-07-01-git-server.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-07-01 Fri 00:00:00] | 1 | #+date: [2022-07-01 Fri 00:00:00] |
| 2 | #+title: self hosting guide: git & cgit | 2 | #+title: Self-Hosting Guide: Git and cgit |
| 3 | #+description: Comprehensive instructions for secure and efficient setup, hosting, and management of personal Git repositories to facilitate collaborative development and remote access. | 3 | #+description: How to self-host Git repos and browse them with cgit. |
| 4 | #+slug: git-server | 4 | #+slug: git-server |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * My Approach to Self-Hosting Git | 7 | * My Approach to Self-Hosting Git |
| 8 | 8 | ||
content/blog/2022-07-14-gnupg.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-07-14 Thu 00:00:00] | 1 | #+date: [2022-07-14 Thu 00:00:00] |
| 2 | #+title: gnupg: encryption, signing, web of trust | 2 | #+title: GnuPG: Encryption, Signing, Web of Trust |
| 3 | #+description: Technical manual covering the architecture, cryptographic algorithms, vulnerability considerations, key management, and typical applications of GNU Privacy Guard for secure data and email encryption. | 3 | #+description: How GnuPG works and how I use it for encryption and signing. |
| 4 | #+slug: gnupg | 4 | #+slug: gnupg |
| 5 | #+filetags: :linux:security: | 5 | #+filetags: :linux:security: |
| 6 | 6 | ||
| 7 | * The History of GPG | 7 | * The History of GPG |
| 8 | 8 | ||
content/blog/2022-07-25-curseradio.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-07-25 Mon 00:00:00] | 1 | #+date: [2022-07-25 Mon 00:00:00] |
| 2 | #+title: curseradio: a lightweight command line internet radio player for linux | 2 | #+title: Curseradio: Internet Radio from the Terminal |
| 3 | #+description: Stepwise instructions for installing and utilizing Curseradio, a lightweight command-line program for streaming radio stations within Linux environments. | 3 | #+description: Installing and using Curseradio to stream internet radio from the terminal. |
| 4 | #+slug: curseradio | 4 | #+slug: curseradio |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2022-07-30-flac-to-opus.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-07-30 Sat 00:00:00] | 1 | #+date: [2022-07-30 Sat 00:00:00] |
| 2 | #+title: automating recursive flac to opus conversion with a bash script | 2 | #+title: Recursive FLAC to Opus Conversion |
| 3 | #+description: Instructions for automating the conversion of audio files from FLAC to Opus format recursively within directory structures, including performance considerations and script usage. | 3 | #+description: A bash script to convert FLAC files to Opus recursively. |
| 4 | #+slug: flac-to-opus | 4 | #+slug: flac-to-opus |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Converting FLAC to OPUS | 7 | * Converting FLAC to OPUS |
| 8 | 8 | ||
content/blog/2022-07-31-bash-it.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-07-31 Sun 00:00:00] | 1 | #+date: [2022-07-31 Sun 00:00:00] |
| 2 | #+title: bash it: plugins and autosuggestions for zsh refugees | 2 | #+title: Bash-It: Plugins and Autosuggestions |
| 3 | #+description: Guide to augmenting Bash shell features by integrating Bash-It framework along with ble.sh for input autosuggestions, improving command-line efficiency on Linux systems. | 3 | #+description: Setting up Bash-It with ble.sh for a better shell experience. |
| 4 | #+slug: bash-it | 4 | #+slug: bash-it |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Bash | 7 | * Bash |
| 8 | 8 | ||
content/blog/2022-08-31-privacy-com-changes.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-08-31 Wed 00:00:00] | 1 | #+date: [2022-08-31 Wed 00:00:00] |
| 2 | #+title: privacy com changes: they changed the product, not the name | 2 | #+title: Privacy.com Changed the Product, Not the Name |
| 3 | #+description: Detailed examination of modifications to Privacy.com service terms and their implications on user privacy and payment security protocols. | 3 | #+description: Privacy.com changed their terms. Here's what that means. |
| 4 | #+slug: privacy-com-changes | 4 | #+slug: privacy-com-changes |
| 5 | #+filetags: :privacy: | 5 | #+filetags: :privacy: |
| 6 | 6 | ||
| 7 | * Privacy.com Changes Their Terms | 7 | * Privacy.com Changes Their Terms |
| 8 | 8 | ||
content/blog/2022-09-17-serenity-os.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-09-17 Sat 00:00:00] | 1 | #+date: [2022-09-17 Sat 00:00:00] |
| 2 | #+title: building and exploring serenityos: a retro inspired unix like desktop | 2 | #+title: Building and Exploring SerenityOS |
| 3 | #+description: Technical overview of Serenity OS including system architecture, building procedures, and operational instructions for this Unix-like operating system with a 1990s user interface style. | 3 | #+description: Building and running SerenityOS, a retro Unix-like desktop OS. |
| 4 | #+slug: serenity-os | 4 | #+slug: serenity-os |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2022-09-21-graphene-os.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-09-21 Wed 00:00:00] | 1 | #+date: [2022-09-21 Wed 00:00:00] |
| 2 | #+title: installing grapheneos on pixel 6 pro | 2 | #+title: Installing GrapheneOS on Pixel 6 Pro |
| 3 | #+description: Step-by-step instructions to perform secure installation of the GrapheneOS operating system on Google Pixel 6 Pro hardware platform. | 3 | #+description: How to install GrapheneOS on a Pixel 6 Pro. |
| 4 | #+slug: graphene-os | 4 | #+slug: graphene-os |
| 5 | #+filetags: :linux:privacy: | 5 | #+filetags: :linux:privacy: |
| 6 | 6 | ||
| 7 | * Introduction | 7 | * Introduction |
| 8 | 8 | ||
content/blog/2022-10-04-mtp-linux.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-10-04 Tue 00:00:00] | 1 | #+date: [2022-10-04 Tue 00:00:00] |
| 2 | #+title: mtp linux: mount your phone without a file manager | 2 | #+title: MTP on Linux: Mount Your Phone Without a File Manager |
| 3 | #+description: Instructions for mounting and accessing Media Transfer Protocol (MTP) compatible mobile devices on Fedora Linux using jmtpfs for file transfer and management. | 3 | #+description: Mounting Android phones on Fedora Linux with jmtpfs. |
| 4 | #+slug: mtp-linux | 4 | #+slug: mtp-linux |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | I recently ran into trouble attempting to mount my GrapheneOS phone to my laptop | 7 | I recently ran into trouble attempting to mount my GrapheneOS phone to my laptop |
| 8 | running Fedora Linux via the [[https://en.wikipedia.org/wiki/Media_transfer_protocol][Media Transfer Protocol]] (MTP) and discovered a | 8 | running Fedora Linux via the [[https://en.wikipedia.org/wiki/Media_transfer_protocol][Media Transfer Protocol]] (MTP) and discovered a |
content/blog/2022-10-04-syncthing.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-10-04 Tue 00:00:00] | 1 | #+date: [2022-10-04 Tue 00:00:00] |
| 2 | #+title: self hosting guide: syncthing | 2 | #+title: Self-Hosting Guide: Syncthing |
| 3 | #+description: Technical instructions for setting up Syncthing as a peer-to-peer self-hosted file synchronization system that preserves data privacy by eliminating third-party intermediaries. | 3 | #+description: How to set up Syncthing for private, peer-to-peer file sync. |
| 4 | #+slug: syncthing | 4 | #+slug: syncthing |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * An Overview of Syncthing | 7 | * An Overview of Syncthing |
| 8 | 8 | ||
content/blog/2022-10-22-alpine-linux.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-10-22 Sat 00:00:00] | 1 | #+date: [2022-10-22 Sat 00:00:00] |
| 2 | #+title: alpine linux: minimal install, minimal attack surface | 2 | #+title: Alpine Linux: Minimal Install, Minimal Attack Surface |
| 3 | #+description: Detailed procedure for deploying Alpine Linux to achieve a secure, lightweight server environment optimized for web hosting and containerization. | 3 | #+description: Installing Alpine Linux as a lightweight, secure server OS. |
| 4 | #+slug: alpine-linux | 4 | #+slug: alpine-linux |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Alpine Linux | 7 | * Alpine Linux |
| 8 | 8 | ||
content/blog/2022-10-30-linux-display-manager.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-10-30 Sun 00:00:00] | 1 | #+date: [2022-10-30 Sun 00:00:00] |
| 2 | #+title: managing display managers in void linux: disable, enable, and configure | 2 | #+title: Void Linux: Remove the Display Manager |
| 3 | #+description: Stepwise instructions to manage and replace the display manager on a Void Linux installation, including service control and configuration editing. | 3 | #+description: Disabling the display manager on Void Linux and starting i3 manually. |
| 4 | #+slug: linux-display-manager | 4 | #+slug: linux-display-manager |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Display Manager Services | 7 | * Display Manager Services |
| 8 | 8 | ||
content/blog/2022-11-07-self-hosting-matrix.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-11-07 Mon 00:00:00] | 1 | #+date: [2022-11-07 Mon 00:00:00] |
| 2 | #+title: self hosting guide: matrix synapse | 2 | #+title: Self-Hosting Guide: Matrix Synapse |
| 3 | #+description: Systematic guide for deploying Matrix Synapse on Alpine Linux, covering dependency installation, reverse proxy setup, TLS certificate application, and user account management. | 3 | #+description: How to deploy Matrix Synapse on Alpine Linux with Nginx. |
| 4 | #+slug: self-hosting-matrix | 4 | #+slug: self-hosting-matrix |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Synapse | 7 | * Synapse |
| 8 | 8 | ||
content/blog/2022-11-11-nginx-tmp-errors.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-11-11 Fri 00:00:00] | 1 | #+date: [2022-11-11 Fri 00:00:00] |
| 2 | #+title: troubleshooting and fixing nginx permission denied errors on /var/lib/nginx | 2 | #+title: Fixing Nginx Permission Denied Errors on /var/lib/nginx |
| 3 | #+description: Step-by-step remediation for addressing permission denied errors encountered by Nginx in the /var/lib/nginx directory to restore temporary file caching functionality. | 3 | #+description: Fixing permission denied errors on /var/lib/nginx in Nginx. |
| 4 | #+slug: nginx-tmp-errors | 4 | #+slug: nginx-tmp-errors |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | /This is a brief post so that I personally remember the solution as it | 7 | /This is a brief post so that I personally remember the solution as it |
| 8 | has occurred multiple times for me./ | 8 | has occurred multiple times for me./ |
content/blog/2022-11-27-server-build.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-11-27 Sun 00:00:00] | 1 | #+date: [2022-11-27 Sun 00:00:00] |
| 2 | #+title: server build: rack hardware, consumer parts, no enterprise markup | 2 | #+title: Server Build: Rack Hardware, Consumer Parts |
| 3 | #+description: Detailed instructions on selecting components, assembling, and configuring a rack-mounted server suitable for advanced computing tasks in a professional or laboratory setting. | 3 | #+description: How I built a rack-mounted server with consumer parts. |
| 4 | #+slug: server-build | 4 | #+slug: server-build |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * The Dilemma | 7 | * The Dilemma |
| 8 | 8 | ||
content/blog/2022-11-29-nginx-referrer-ban-list.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-11-29 Tue 00:00:00] | 1 | #+date: [2022-11-29 Tue 00:00:00] |
| 2 | #+title: nginx referrer ban: block the scrapers | 2 | #+title: Nginx Referrer Ban List |
| 3 | #+description: Technical guide to implementing a referrer ban list in Nginx configurations to prevent access from undesired domains and improve web server security. | 3 | #+description: Blocking unwanted referrers in Nginx with a simple ban list. |
| 4 | #+slug: nginx-referrer-ban-list | 4 | #+slug: nginx-referrer-ban-list |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * Creating the Ban List | 7 | * Creating the Ban List |
| 8 | 8 | ||
content/blog/2022-12-01-nginx-compression.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-12-01 Thu 00:00:00] | 1 | #+date: [2022-12-01 Thu 00:00:00] |
| 2 | #+title: nginx gzip: compress text, nothing else | 2 | #+title: Nginx Gzip: Compress Text, Nothing Else |
| 3 | #+description: Procedures for activating and configuring GZIP compression in Nginx to decrease data transmission size, reduce bandwidth consumption, and accelerate page load times. | 3 | #+description: Enabling and configuring GZIP compression in Nginx. |
| 4 | #+slug: nginx-compression | 4 | #+slug: nginx-compression |
| 5 | #+filetags: :linux:web: | 5 | #+filetags: :linux:web: |
| 6 | 6 | ||
| 7 | * Text Compression | 7 | * Text Compression |
| 8 | 8 | ||
content/blog/2022-12-07-nginx-wildcard-redirect.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-12-07 Wed 00:00:00] | 1 | #+date: [2022-12-07 Wed 00:00:00] |
| 2 | #+title: nginx wildcard redirect: domains, subdomains, trailing paths | 2 | #+title: Nginx Wildcard Redirects |
| 3 | #+description: Instructional steps for applying regex-based redirects in Nginx to manage subdomain routing and trailing path modifications effectively. | 3 | #+description: Using regex-based redirects in Nginx for subdomain and path routing. |
| 4 | #+slug: nginx-wildcard-redirect | 4 | #+slug: nginx-wildcard-redirect |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | * Problem | 7 | * Problem |
| 8 | 8 | ||
content/blog/2022-12-17-st.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-12-17 Sat 00:00:00] | 1 | #+date: [2022-12-17 Sat 00:00:00] |
| 2 | #+title: installing and customizing the suckless simple terminal (st) on fedora linux | 2 | #+title: Suckless Simple Terminal on Fedora |
| 3 | #+description: Comprehensive instructions to obtain source code, compile, apply patches, and install the Simple Terminal application on Fedora Linux systems. | 3 | #+description: Compiling and patching the Suckless Simple Terminal on Fedora. |
| 4 | #+slug: st | 4 | #+slug: st |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * st | 7 | * st |
| 8 | 8 | ||
content/blog/2022-12-23-alpine-desktop.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2022-12-23 Fri 00:00:00] | 1 | #+date: [2022-12-23 Fri 00:00:00] |
| 2 | #+title: alpine desktop: sway on alpine, minimal by default | 2 | #+title: Alpine Desktop with Sway |
| 3 | #+description: Stepwise procedures for installing and setting up Alpine Linux as a desktop operating system, including window manager setup and relevant system adjustments. | 3 | #+description: Setting up Alpine Linux as a desktop with Sway as the window manager. |
| 4 | #+slug: alpine-desktop | 4 | #+slug: alpine-desktop |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Isn't Alpine Linux for Servers? | 7 | * Isn't Alpine Linux for Servers? |
| 8 | 8 | ||
content/blog/2023-01-03-recent-website-changes.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-01-03 Tue 00:00:00] | 1 | #+date: [2023-01-03 Tue 00:00:00] |
| 2 | #+title: website updates 2023: what changed and why | 2 | #+title: Website Updates 2023 |
| 3 | #+description: Documentation of significant changes applied to site design, layout, and accessibility features to enhance navigability and content clarity. | 3 | #+description: A rundown of recent changes to the site design and structure. |
| 4 | #+slug: recent-website-changes | 4 | #+slug: recent-website-changes |
| 5 | #+filetags: :personal:web: | 5 | #+filetags: :personal:web: |
| 6 | 6 | ||
| 7 | * The State of This Website | 7 | * The State of This Website |
| 8 | 8 | ||
content/blog/2023-01-05-mass-unlike-tumblr-posts.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-01-05 Thu 00:00:00] | 1 | #+date: [2023-01-05 Thu 00:00:00] |
| 2 | #+title: tumblr unlike all: script, done, get out | 2 | #+title: Mass Unlike All Tumblr Posts |
| 3 | #+description: Instructions for executing a JavaScript script to automate the mass unlike operation for Tumblr posts without requiring additional software. | 3 | #+description: A JavaScript snippet to mass-unlike all your Tumblr posts. |
| 4 | #+slug: mass-unlike-tumblr-posts | 4 | #+slug: mass-unlike-tumblr-posts |
| 5 | #+filetags: :linux:personal: | 5 | #+filetags: :linux:personal: |
| 6 | 6 | ||
| 7 | * The Dilemma | 7 | * The Dilemma |
| 8 | 8 | ||
content/blog/2023-01-08-fedora-login-manager.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-01-08 Sun 00:00:00] | 1 | #+date: [2023-01-08 Sun 00:00:00] |
| 2 | #+title: fedora i3 no login manager: remove it, start manually | 2 | #+title: Fedora i3: Remove the Login Manager |
| 3 | #+description: Step-by-step guide for uninstalling the default Fedora i3 login manager and configuring system to launch i3 window manager manually. | 3 | #+description: Removing the Fedora login manager and launching i3 manually. |
| 4 | #+slug: fedora-login-manager | 4 | #+slug: fedora-login-manager |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Fedora i3's Login Manager | 7 | * Fedora i3's Login Manager |
| 8 | 8 | ||
content/blog/2023-01-21-flatpak-symlinks.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-01-21 Sat 00:00:00] | 1 | #+date: [2023-01-21 Sat 00:00:00] |
| 2 | #+title: flatpak symlinks: shorten the command | 2 | #+title: Flatpak Symlinks: Shorten the Command |
| 3 | #+description: Detailed instructions for establishing symbolic links for Flatpak applications to facilitate faster execution from terminal or application launcher environments. | 3 | #+description: Creating symlinks for Flatpak apps to make them easier to launch. |
| 4 | #+slug: flatpak-symlinks | 4 | #+slug: flatpak-symlinks |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Running Flatpak Apps Should Be Faster | 7 | * Running Flatpak Apps Should Be Faster |
| 8 | 8 | ||
content/blog/2023-01-23-random-wireguard.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-01-23 Mon 00:00:00] | 1 | #+date: [2023-01-23 Mon 00:00:00] |
| 2 | #+title: automate random mullvad wireguard vpn connection on startup | 2 | #+title: Random Mullvad WireGuard on Startup |
| 3 | #+description: Stepwise method to configure system startup scripts for automatic connection to a randomly chosen Mullvad Wireguard VPN server to maintain privacy. | 3 | #+description: A startup script to connect to a random Mullvad WireGuard server. |
| 4 | #+slug: random-wireguard | 4 | #+slug: random-wireguard |
| 5 | #+filetags: :linux:security:self-hosting: | 5 | #+filetags: :linux:security:self-hosting: |
| 6 | 6 | ||
| 7 | * Mullvad Wireguard | 7 | * Mullvad Wireguard |
| 8 | 8 | ||
content/blog/2023-01-28-self-hosting-wger.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-01-28 Sat 00:00:00] | 1 | #+date: [2023-01-28 Sat 00:00:00] |
| 2 | #+title: self hosting guide: wger | 2 | #+title: Self-Hosting Guide: wger |
| 3 | #+description: Comprehensive steps for installing, configuring, and operating the Wger workout management application on a dedicated server platform. | 3 | #+description: How to self-host wger, an open-source workout manager. |
| 4 | #+slug: self-hosting-wger | 4 | #+slug: self-hosting-wger |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Wger: The Self-Hosted Workout Manager | 7 | * Wger: The Self-Hosted Workout Manager |
| 8 | 8 | ||
content/blog/2023-02-02-exploring-hare.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-02-02 Thu 00:00:00] | 1 | #+date: [2023-02-02 Thu 00:00:00] |
| 2 | #+title: hare lang: notes from first contact | 2 | #+title: Hare Lang: Notes from First Contact |
| 3 | #+description: Overview of the Hare programming language features, installation procedure, and elementary programming examples targeting system-level development. | 3 | #+description: First impressions of the Hare programming language. |
| 4 | #+slug: exploring-hare | 4 | #+slug: exploring-hare |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * A Quick Note | 7 | * A Quick Note |
| 8 | 8 | ||
content/blog/2023-05-22-burnout.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-05-22 Mon 00:00:00] | 1 | #+date: [2023-05-22 Mon 00:00:00] |
| 2 | #+title: burnout: audit and consulting will take everything you let them | 2 | #+title: Burnout |
| 3 | #+description: Examination of burnout phenomena accompanied by strategies and practical approaches for workload management and restoration of optimal functioning. | 3 | #+description: Honest thoughts on burning out in audit and consulting. |
| 4 | #+slug: burnout | 4 | #+slug: burnout |
| 5 | #+filetags: :personal: | 5 | #+filetags: :personal: |
| 6 | 6 | ||
| 7 | * RE: Burnout | 7 | * RE: Burnout |
| 8 | 8 | ||
content/blog/2023-06-08-goaccess-geoip.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-08 Thu 00:00:00] | 1 | #+date: [2023-06-08 Thu 00:00:00] |
| 2 | #+title: real time traffic insights from nginx logs using goaccess + geoip | 2 | #+title: Nginx Traffic Analysis with GoAccess and GeoIP |
| 3 | #+description: Step-by-step instructions to utilize GoAccess tool incorporating MaxMind GeoIP integration for real-time geographic and traffic analysis of Nginx log files. | 3 | #+description: Using GoAccess with MaxMind GeoIP to analyze Nginx traffic in real time. |
| 4 | #+slug: goaccess-geoip | 4 | #+slug: goaccess-geoip |
| 5 | #+filetags: :self-hosting:web: | 5 | #+filetags: :self-hosting:web: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-06-08-self-hosting-baikal.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-08 Thu 00:00:00] | 1 | #+date: [2023-06-08 Thu 00:00:00] |
| 2 | #+title: self hosting guide: baikal | 2 | #+title: Self-Hosting Guide: Baikal |
| 3 | #+description: Detailed procedure for deploying the Baikal server software to provide CalDAV and CardDAV services, including security considerations and Docker deployment. | 3 | #+description: How to deploy Baikal for self-hosted CalDAV and CardDAV. |
| 4 | #+slug: self-hosting-baikal | 4 | #+slug: self-hosting-baikal |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * What is Baikal? | 7 | * What is Baikal? |
| 8 | 8 | ||
content/blog/2023-06-18-unifi-ip-blocklist.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-18 Sun 00:00:00] | 1 | #+date: [2023-06-18 Sun 00:00:00] |
| 2 | #+title: blocking malicious ips on unifi: manual firewall rule setup | 2 | #+title: Blocking Malicious IPs on Unifi |
| 3 | #+description: Instructions to identify and block harmful IP addresses and subnets through Unifi firewall settings to improve network security posture. | 3 | #+description: Manually blocking malicious IPs via Unifi firewall rules. |
| 4 | #+slug: unifi-ip-blocklist | 4 | #+slug: unifi-ip-blocklist |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Identifying Abusive IPs | 7 | * Identifying Abusive IPs |
| 8 | 8 | ||
content/blog/2023-06-20-audit-review-template.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-20 Tue 00:00:00] | 1 | #+date: [2023-06-20 Tue 00:00:00] |
| 2 | #+title: audit testing review checklist | 2 | #+title: Audit Testing Review Checklist |
| 3 | #+description: Practical audit testing review template with detailed steps to support comprehensive evaluation of financial audits and SOC reports. | 3 | #+description: A practical checklist for reviewing audit testing on financial and SOC engagements. |
| 4 | #+slug: audit-review-template | 4 | #+slug: audit-review-template |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-06-23-byobu.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-23 Fri 00:00:00] | 1 | #+date: [2023-06-23 Fri 00:00:00] |
| 2 | #+title: byobu: tmux with less configuration overhead | 2 | #+title: Byobu: tmux with Less Configuration Overhead |
| 3 | #+description: Detailed overview of Byobu terminal multiplexer features, configuration settings, session management, and keybindings to enhance command-line efficiency. | 3 | #+description: Using Byobu as a tmux wrapper with sane defaults out of the box. |
| 4 | #+slug: byobu | 4 | #+slug: byobu |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Byobu | 7 | * Byobu |
| 8 | 8 | ||
content/blog/2023-06-23-self-hosting-convos.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-23 Fri 00:00:00] | 1 | #+date: [2023-06-23 Fri 00:00:00] |
| 2 | #+title: self hosting guide: convos | 2 | #+title: Self-Hosting Guide: Convos |
| 3 | #+description: Stepwise instructions for installation, Docker Compose configuration, Nginx reverse proxy setup, and IRC nickname registration for Convos web client hosting. | 3 | #+description: How to self-host Convos, a web-based IRC client. |
| 4 | #+slug: self-hosting-convos | 4 | #+slug: self-hosting-convos |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Convos | 7 | * Convos |
| 8 | 8 | ||
content/blog/2023-06-28-backblaze-b2.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-28 Wed 00:00:00] | 1 | #+date: [2023-06-28 Wed 00:00:00] |
| 2 | #+title: backblaze b2 backups: before i moved off it | 2 | #+title: Backblaze B2 Backups |
| 3 | #+description: Methodical guide for configuring and utilizing Backblaze B2 cloud storage services to perform reliable and secure offsite data backups. | 3 | #+description: Setting up Backblaze B2 for offsite backups before I moved on. |
| 4 | #+slug: backblaze-b2 | 4 | #+slug: backblaze-b2 |
| 5 | #+filetags: :self-hosting: | 5 | #+filetags: :self-hosting: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-06-30-self-hosting-voyager.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-06-30 Fri 00:00:00] | 1 | #+date: [2023-06-30 Fri 00:00:00] |
| 2 | #+title: self hosting guide: voyager for lemmy | 2 | #+title: Self-Hosting Guide: Voyager for Lemmy |
| 3 | #+description: Instructions for building, running, and reverse proxying Voyager, a Lemmy web client, on a server environment utilizing Docker and Nginx components. | 3 | #+description: How to self-host Voyager, a web client for Lemmy. |
| 4 | #+slug: self-hosting-voyager | 4 | #+slug: self-hosting-voyager |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Installation Guide | 7 | * Installation Guide |
| 8 | 8 | ||
content/blog/2023-07-12-wireguard-lan.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-07-12 Wed 00:00:00] | 1 | #+date: [2023-07-12 Wed 00:00:00] |
| 2 | #+title: enabling local network access with mullvad wireguard configs | 2 | #+title: Mullvad WireGuard with LAN Access |
| 3 | #+description: Detailed procedure to modify Mullvad Wireguard VPN configuration files and iptables rules to allow Local Area Network access while maintaining VPN connectivity. | 3 | #+description: Modifying Mullvad WireGuard configs to allow LAN access while connected. |
| 4 | #+slug: wireguard-lan | 4 | #+slug: wireguard-lan |
| 5 | #+filetags: :security:self-hosting: | 5 | #+filetags: :security:self-hosting: |
| 6 | 6 | ||
| 7 | * Download Configuration Files from Mullvad | 7 | * Download Configuration Files from Mullvad |
| 8 | 8 | ||
content/blog/2023-07-19-plex-transcoder-errors.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-07-19 Wed 00:00:00] | 1 | #+date: [2023-07-19 Wed 00:00:00] |
| 2 | #+title: plex subtitle error: transcoder fails to start | 2 | #+title: Plex Transcoder Errors: Subtitle Fix |
| 3 | #+description: Technical procedures to identify and correct Plex transcoder failures at startup to maintain uninterrupted media conversion and playback. | 3 | #+description: Fixing Plex transcoder startup failures caused by subtitle errors. |
| 4 | #+slug: plex-transcoder-errors | 4 | #+slug: plex-transcoder-errors |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Plex Transcoder Error | 7 | * Plex Transcoder Error |
| 8 | 8 | ||
content/blog/2023-08-18-agile-auditing.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-08-18 Fri 00:00:00] | 1 | #+date: [2023-08-18 Fri 00:00:00] |
| 2 | #+title: agile auditing: consultants cosplaying as engineers | 2 | #+title: Agile Auditing |
| 3 | #+description: Detailed examination of Agile auditing methodologies, including Scrum and Kanban frameworks, with practical steps for application in audit processes. | 3 | #+description: My take on agile auditing: what it is and how it actually plays out. |
| 4 | #+slug: agile-auditing | 4 | #+slug: agile-auditing |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * What is Agile Auditing? | 7 | * What is Agile Auditing? |
| 8 | 8 | ||
content/blog/2023-09-15-self-hosting-gitweb.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-09-15 Fri 00:00:00] | 1 | #+date: [2023-09-15 Fri 00:00:00] |
| 2 | #+title: self hosting guide: gitweb | 2 | #+title: Self-Hosting Guide: GitWeb |
| 3 | #+description: Stepwise instructions for deploying GitWeb on Linux servers using Nginx, configuring fastcgi, and managing git repositories effectively. | 3 | #+description: Deploying GitWeb on Linux with Nginx and FastCGI. |
| 4 | #+slug: self-hosting-gitweb | 4 | #+slug: self-hosting-gitweb |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-09-19-audit-sql-scripts.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-09-19 Tue 00:00:00] | 1 | #+date: [2023-09-19 Tue 00:00:00] |
| 2 | #+title: auditing user privileges in oracle, sql server, and mysql | 2 | #+title: SQL Scripts for Auditing User Privileges |
| 3 | #+description: Collection of SQL queries designed for auditing user access parameters on Oracle, Microsoft SQL Server, and MySQL database systems. | 3 | #+description: SQL queries for auditing user access in Oracle, SQL Server, and MySQL. |
| 4 | #+slug: audit-sql-scripts | 4 | #+slug: audit-sql-scripts |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-10-04-digital-minimalism.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-10-04 Wed 00:00:00] | 1 | #+date: [2023-10-04 Wed 00:00:00] |
| 2 | #+title: digital minimalism: fewer inputs, more signal | 2 | #+title: Digital Minimalism: Fewer Inputs, More Signal |
| 3 | #+description: Practical guide for minimizing digital clutter and optimizing work focus by applying digital minimalism tactics. | 3 | #+description: How I reduce digital noise and stay focused. |
| 4 | #+slug: digital-minimalism | 4 | #+slug: digital-minimalism |
| 5 | #+filetags: :linux:privacy: | 5 | #+filetags: :linux:privacy: |
| 6 | 6 | ||
| 7 | I've written [[https://cleberg.net/wiki/#digital-garden][a note about minimalism]] | 7 | I've written [[https://cleberg.net/wiki/#digital-garden][a note about minimalism]] |
| 8 | before, but I wanted to dedicate some time to reflect on digital | 8 | before, but I wanted to dedicate some time to reflect on digital |
content/blog/2023-10-11-self-hosting-authelia.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-10-11 Wed 00:00:00] | 1 | #+date: [2023-10-11 Wed 00:00:00] |
| 2 | #+title: self hosting guide: authelia | 2 | #+title: Self-Hosting Guide: Authelia |
| 3 | #+description: Instructional guide for setting up Authelia to provide secure two-factor authentication and access control in self-hosted environments. | 3 | #+description: Setting up Authelia for two-factor auth and access control on self-hosted apps. |
| 4 | #+slug: self-hosting-authelia | 4 | #+slug: self-hosting-authelia |
| 5 | #+filetags: :linux:security:self-hosting: | 5 | #+filetags: :linux:security:self-hosting: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-10-15-alpine-ssh-hardening.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-10-15 Sun 00:00:00] | 1 | #+date: [2023-10-15 Sun 00:00:00] |
| 2 | #+title: alpine linux ssh hardening guide | 2 | #+title: Alpine Linux SSH Hardening |
| 3 | #+description: Detailed guide to enhance Alpine Linux SSH server security through configuration adjustments and vulnerability mitigation. | 3 | #+description: Hardening SSH on Alpine Linux with config changes and key-only auth. |
| 4 | #+slug: alpine-ssh-hardening | 4 | #+slug: alpine-ssh-hardening |
| 5 | #+filetags: :linux:security: | 5 | #+filetags: :linux:security: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-10-17-self-hosting-anonymousoverflow.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-10-17 Tue 00:00:00] | 1 | #+date: [2023-10-17 Tue 00:00:00] |
| 2 | #+title: self hosting guide: anonymousoverflow | 2 | #+title: Self-Hosting Guide: AnonymousOverflow |
| 3 | #+description: Detailed installation and setup instructions for the AnonymousOverflow application using Docker Compose and Nginx reverse proxy. | 3 | #+description: How to self-host AnonymousOverflow with Docker Compose and Nginx. |
| 4 | #+slug: self-hosting-anonymousoverflow | 4 | #+slug: self-hosting-anonymousoverflow |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2023-11-08-scli.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-11-08 Wed 00:00:00] | 1 | #+date: [2023-11-08 Wed 00:00:00] |
| 2 | #+title: signal cli (scli) installation on alpine | 2 | #+title: Signal CLI (scli) on Alpine |
| 3 | #+description: Step-by-step instructions for installing the Signal messenger command-line client scli on Alpine Linux with musl libc, including dependencies and configuration. | 3 | #+description: Installing the Signal CLI client on Alpine Linux. |
| 4 | #+slug: scli | 4 | #+slug: scli |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | [[https://github.com/isamert/scli][scli]] is a command-line tool that | 7 | [[https://github.com/isamert/scli][scli]] is a command-line tool that |
| 8 | allows you to connect to your Signal messenger account. This program | 8 | allows you to connect to your Signal messenger account. This program |
content/blog/2023-12-03-unifi-nextdns.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2023-12-03 Sun 00:00:00] | 1 | #+date: [2023-12-03 Sun 00:00:00] |
| 2 | #+title: installing and configuring nextdns on unifi dream machine routers | 2 | #+title: NextDNS on Unifi Dream Machine |
| 3 | #+description: Procedural guide for installation and configuration of NextDNS on Unifi Dream Machine devices for network DNS filtering. | 3 | #+description: Installing and configuring NextDNS on a Unifi Dream Machine. |
| 4 | #+slug: unifi-nextdns | 4 | #+slug: unifi-nextdns |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2024-01-08-dont-say-hello.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-01-08 Mon 00:00:00] | 1 | #+date: [2024-01-08 Mon 00:00:00] |
| 2 | #+title: don't say hello | 2 | #+title: Don't Say Hello |
| 3 | #+description: Technical recommendations for improving professional communication by eliminating non-essential introductory phrases to enhance message clarity. | 3 | #+description: Stop leading messages with 'hello' and nothing else. |
| 4 | #+slug: dont-say-hello | 4 | #+slug: dont-say-hello |
| 5 | #+filetags: :privacy: | 5 | #+filetags: :privacy: |
| 6 | 6 | ||
| 7 | I recently came back from a winter break and have started working again... only | 7 | I recently came back from a winter break and have started working again... only |
| 8 | to immediately run into the dilemma of people sending me cliffhanger messages | 8 | to immediately run into the dilemma of people sending me cliffhanger messages |
content/blog/2024-01-09-macos-customization.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-01-09 Tue 00:00:00] | 1 | #+date: [2024-01-09 Tue 00:00:00] |
| 2 | #+title: macos customization: terminal, tiling wm, widgets | 2 | #+title: macOS Customization: Terminal, Tiling WM, Widgets |
| 3 | #+description: Detailed overview of methods and tools for modifying macOS system settings, including terminal usage, window management, and interface customization. | 3 | #+description: How I've customized macOS with a terminal, tiling WM, and widgets. |
| 4 | #+slug: macos-customization | 4 | #+slug: macos-customization |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | I have been using macOS more than Linux lately, so I wrote this post to describe | 7 | I have been using macOS more than Linux lately, so I wrote this post to describe |
| 8 | some simple options to customize macOS beyond the normal built-in settings menu. | 8 | some simple options to customize macOS beyond the normal built-in settings menu. |
content/blog/2024-01-13-local-llm.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-01-13 Sat 00:00:00] | 1 | #+date: [2024-01-13 Sat 00:00:00] |
| 2 | #+title: local llm: run the model, keep the data | 2 | #+title: Local LLM: Run the Model, Keep the Data |
| 3 | #+description: Technical guide to deploying and running local large language models on macOS and iOS devices focusing on open-source implementations and privacy considerations. | 3 | #+description: Running local language models on macOS and iOS with open-source tools. |
| 4 | #+slug: local-llm | 4 | #+slug: local-llm |
| 5 | #+filetags: :linux:privacy: | 5 | #+filetags: :linux:privacy: |
| 6 | 6 | ||
| 7 | * Requirements | 7 | * Requirements |
| 8 | 8 | ||
content/blog/2024-01-26-audit-dashboard.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-01-26 Fri 00:00:00] | 1 | #+date: [2024-01-26 Fri 00:00:00] |
| 2 | #+title: audit dashboard: alteryx + power bi, the corporate stack | 2 | #+title: Audit Dashboard: Alteryx and Power BI |
| 3 | #+description: Instructions for transforming audit data into dynamic dashboards via data preparation with Alteryx and visualization using Microsoft Power BI. | 3 | #+description: Building an audit dashboard with Alteryx for data prep and Power BI for visuals. |
| 4 | #+slug: audit-dashboard | 4 | #+slug: audit-dashboard |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | Alteryx and Power BI are powerful tools that can help turn your old-school audit | 7 | Alteryx and Power BI are powerful tools that can help turn your old-school audit |
| 8 | trackers into interactive tools that provide useful insights and potential | 8 | trackers into interactive tools that provide useful insights and potential |
content/blog/2024-01-27-tableau-dashboard.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-01-27 Sat 00:00:00] | 1 | #+date: [2024-01-27 Sat 00:00:00] |
| 2 | #+title: omaha crime data: tableau, 8 years of numbers | 2 | #+title: Omaha Crime Data: 8 Years in Tableau |
| 3 | #+description: Detailed procedure for data preparation and interactive visualization of crime trends in Omaha, using Tableau software from 2015 through 2023 data. | 3 | #+description: Visualizing 8 years of Omaha crime data in Tableau. |
| 4 | #+slug: tableau-dashboard | 4 | #+slug: tableau-dashboard |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | In this project, I am going to show you how to use Tableau Public for free to | 7 | In this project, I am going to show you how to use Tableau Public for free to |
| 8 | create simple dashboards. | 8 | create simple dashboards. |
content/blog/2024-02-06-zfs.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-02-06 Tue 00:00:00] | 1 | #+date: [2024-02-06 Tue 00:00:00] |
| 2 | #+title: creating and managing zfs storage pools on ubuntu linux | 2 | #+title: ZFS Storage Pools on Ubuntu |
| 3 | #+description: Stepwise guide to setting up ZFS storage pools on Ubuntu, including initial installation, pool creation, expansion, and maintenance. | 3 | #+description: Setting up and managing ZFS storage pools on Ubuntu. |
| 4 | #+slug: zfs | 4 | #+slug: zfs |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | This post details the process I used to create ZFS pools, datasets, and | 7 | This post details the process I used to create ZFS pools, datasets, and |
| 8 | snapshots on Ubuntu Server. | 8 | snapshots on Ubuntu Server. |
content/blog/2024-02-13-ubuntu-emergency-mode.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-02-13 Tue 00:00:00] | 1 | #+date: [2024-02-13 Tue 00:00:00] |
| 2 | #+title: resolving ubuntu boot issues caused by invalid /etc/fstab mounts | 2 | #+title: Ubuntu Emergency Mode: Bad /etc/fstab Fix |
| 3 | #+description: Detailed instructions to identify errors in the /etc/fstab file causing Ubuntu to enter emergency mode and steps to edit and restore normal boot operations. | 3 | #+description: Fixing an invalid /etc/fstab that put Ubuntu into emergency mode. |
| 4 | #+slug: ubuntu-emergency-mode | 4 | #+slug: ubuntu-emergency-mode |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * The Problem | 7 | * The Problem |
| 8 | 8 | ||
content/blog/2024-02-21-self-hosting-otter-wiki.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-02-21 Wed 00:00:00] | 1 | #+date: [2024-02-21 Wed 00:00:00] |
| 2 | #+title: self hosting guide: an otter wiki | 2 | #+title: Self-Hosting Guide: Otter Wiki |
| 3 | #+description: Stepwise directions for installing Otter Wiki, configuring Docker Compose environment, and setting up Nginx reverse proxy for secure access. | 3 | #+description: How to self-host Otter Wiki with Docker Compose and Nginx. |
| 4 | #+slug: self-hosting-otter-wiki | 4 | #+slug: self-hosting-otter-wiki |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * An Otter Wiki | 7 | * An Otter Wiki |
| 8 | 8 | ||
content/blog/2024-03-13-doom-emacs.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-03-13 Wed 00:00:00] | 1 | #+date: [2024-03-13 Wed 00:00:00] |
| 2 | #+title: doom emacs & org mode setup | 2 | #+title: Doom Emacs and Org Mode Setup |
| 3 | #+description: Technical manual covering installation, configuration files, and usage procedures for Doom Emacs and Org-Mode targeting note management and task organization. | 3 | #+description: How I set up Doom Emacs and Org Mode for notes and task management. |
| 4 | #+slug: doom-emacs | 4 | #+slug: doom-emacs |
| 5 | #+filetags: :emacs: | 5 | #+filetags: :emacs: |
| 6 | 6 | ||
| 7 | ** Screenshots | 7 | ** Screenshots |
| 8 | 8 | ||
content/blog/2024-03-15-self-hosting-ddns-updater.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-03-15 Fri 00:00:00] | 1 | #+date: [2024-03-15 Fri 00:00:00] |
| 2 | #+title: self hosting guide: ddns updater | 2 | #+title: Self-Hosting Guide: DDNS Updater |
| 3 | #+description: Step-by-step configuration guide for deploying a Dynamic DNS updater using Docker Compose, integrating with Cloudflare API, and securing with Nginx reverse proxy. | 3 | #+description: Deploying a DDNS updater with Docker Compose and Cloudflare. |
| 4 | #+slug: self-hosting-ddns-updater | 4 | #+slug: self-hosting-ddns-updater |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | #+caption: DDNS Updater Web View | 7 | #+caption: DDNS Updater Web View |
| 8 | #+attr_html: :alt An example of the DDNS Updater app running and showing that cleberg.net's IP has been updated on Cloudflare. | 8 | #+attr_html: :alt An example of the DDNS Updater app running and showing that cleberg.net's IP has been updated on Cloudflare. |
content/blog/2024-03-29-org-blog.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-03-29 Fri 00:00:00] | 1 | #+date: [2024-03-29 Fri 00:00:00] |
| 2 | #+title: blogging with emacs org mode and weblorg | 2 | #+title: Blogging with Emacs Org Mode and weblorg |
| 3 | #+description: Instructional content for preparing and publishing blogs using Emacs Org-Mode, including setup of static site generators and content management workflows. | 3 | #+description: How I set up this blog using Emacs Org Mode and weblorg. |
| 4 | #+slug: org-blog | 4 | #+slug: org-blog |
| 5 | #+filetags: :emacs:web: | 5 | #+filetags: :emacs:web: |
| 6 | 6 | ||
| 7 | First and foremost, apologies to those who subscribe via RSS as I know that my | 7 | First and foremost, apologies to those who subscribe via RSS as I know that my |
| 8 | feed duplicated itself when I moved this blog over to org-mode last night. | 8 | feed duplicated itself when I moved this blog over to org-mode last night. |
content/blog/2024-04-06-convert-onenote-to-markdown.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-04-06 Sat 00:00:00] | 1 | #+date: [2024-04-06 Sat 00:00:00] |
| 2 | #+title: onenote to org: escape the microsoft format | 2 | #+title: OneNote to Org: Escape the Microsoft Format |
| 3 | #+description: Detailed conversion instructions to transform OneNote document files into Markdown or Org-Mode formats using Pandoc command-line utility on Windows systems. | 3 | #+description: Converting OneNote files to Markdown or Org Mode with Pandoc. |
| 4 | #+slug: convert-onenote-to-markdown | 4 | #+slug: convert-onenote-to-markdown |
| 5 | #+filetags: :emacs: | 5 | #+filetags: :emacs: |
| 6 | 6 | ||
| 7 | If you're looking to convert your OneNote content to another format, such as | 7 | If you're looking to convert your OneNote content to another format, such as |
| 8 | Markdown or Org-Mode, you're in luck. I use a solution that doesn't require | 8 | Markdown or Org-Mode, you're in luck. I use a solution that doesn't require |
content/blog/2024-04-08-docker-local-web-server.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-04-08 Mon 00:00:00] | 1 | #+date: [2024-04-08 Mon 00:00:00] |
| 2 | #+title: local web dev server setup with docker & nginx | 2 | #+title: Local Web Dev Server with Docker and Nginx |
| 3 | #+description: Instructions for setting up a local web development environment employing Docker Desktop and Nginx web server to facilitate development and testing workflows. | 3 | #+description: Setting up a local web server for development with Docker and Nginx. |
| 4 | #+slug: docker-local-web-server | 4 | #+slug: docker-local-web-server |
| 5 | #+filetags: :self-hosting:web: | 5 | #+filetags: :self-hosting:web: |
| 6 | 6 | ||
| 7 | When developing websites locally, I often use a simple Python web server to | 7 | When developing websites locally, I often use a simple Python web server to |
| 8 | observe the changes. | 8 | observe the changes. |
content/blog/2024-04-18-mu4e.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-04-18 Thu 00:00:00] | 1 | #+date: [2024-04-18 Thu 00:00:00] |
| 2 | #+title: configuring mu4e with doom emacs on macos | 2 | #+title: mu4e with Doom Emacs on macOS |
| 3 | #+description: Stepwise procedure for installing, configuring, and using Mu4e email client within Doom Emacs on macOS for organized email management. | 3 | #+description: Setting up mu4e for email inside Doom Emacs on macOS. |
| 4 | #+slug: mu4e | 4 | #+slug: mu4e |
| 5 | #+filetags: :emacs:linux: | 5 | #+filetags: :emacs:linux: |
| 6 | 6 | ||
| 7 | This post was heavily inspired by [[https://macowners.club/posts/email-emacs-mu4e-macos/][Email setup in Emacs with Mu4e on macOS]], but | 7 | This post was heavily inspired by [[https://macowners.club/posts/email-emacs-mu4e-macos/][Email setup in Emacs with Mu4e on macOS]], but |
| 8 | with my own tweaks for a single-account configuration and some Doom-specific | 8 | with my own tweaks for a single-account configuration and some Doom-specific |
content/blog/2024-05-03-ubuntu-on-macos.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-05-03 Fri 00:00:00] | 1 | #+date: [2024-05-03 Fri 00:00:00] |
| 2 | #+title: orbstack on macos: running a full ubuntu linux environment | 2 | #+title: OrbStack on macOS: Running Ubuntu |
| 3 | #+description: Technical guide outlining the installation and operation of OrbStack to run Ubuntu Linux containers natively on macOS systems with performance considerations. | 3 | #+description: Running a full Ubuntu environment on macOS using OrbStack. |
| 4 | #+slug: ubuntu-on-macos | 4 | #+slug: ubuntu-on-macos |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | Being a macOS user who previously used Linux for many years, I often find myself | 7 | Being a macOS user who previously used Linux for many years, I often find myself |
| 8 | searching for alternatives to the Linux-native tools and methods that I had | 8 | searching for alternatives to the Linux-native tools and methods that I had |
content/blog/2024-06-19-deprecated-trusted-gpg-fix.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-06-19 Wednesday 08:00:00] | 1 | #+date: [2024-06-19 Wed 08:00:00] |
| 2 | #+title: migrating ubuntu gpg keys to trusted.gpg.d | 2 | #+title: Ubuntu: Migrate GPG Keys to trusted.gpg.d |
| 3 | #+description: Technical instructions to relocate GPG keys from the deprecated trusted.gpg keyring to the supported trusted.gpg.d directory for system security maintenance. | 3 | #+description: Moving Ubuntu GPG keys from the deprecated trusted.gpg to trusted.gpg.d. |
| 4 | #+slug: deprecated-trusted-gpg-fix | 4 | #+slug: deprecated-trusted-gpg-fix |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | ** System Warning | 7 | ** System Warning |
| 8 | 8 | ||
content/blog/2024-07-11-emacs-on-ipad.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-07-11 Thursday 20:24:02] | 1 | #+date: [2024-07-11 Thu 20:24:02] |
| 2 | #+title: running emacs natively on apple silicon ipad | 2 | #+title: Running Emacs Natively on an Apple Silicon iPad |
| 3 | #+description: Procedural instructions for installing Emacs on iPadOS devices with Apple Silicon architecture, including configuration and operational guidance. | 3 | #+description: Installing and running Emacs natively on an iPad with Apple Silicon. |
| 4 | #+slug: emacs-on-ipad | 4 | #+slug: emacs-on-ipad |
| 5 | #+filetags: :emacs: | 5 | #+filetags: :emacs: |
| 6 | 6 | ||
| 7 | This post describes the process to install and use Emacs on the iPad Air 13-inch | 7 | This post describes the process to install and use Emacs on the iPad Air 13-inch |
| 8 | (M2). The iPad used in this post is running iPadOS 17.6. | 8 | (M2). The iPad used in this post is running iPadOS 17.6. |
content/blog/2024-08-11-org-mode-features.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-08-11 Sun 12:48:00] | 1 | #+date: [2024-08-11 Sun 12:48:00] |
| 2 | #+title: org mode features: what i actually use | 2 | #+title: Org Mode Features: What I Actually Use |
| 3 | #+description: Detailed overview of essential Org-Mode functionalities focusing on task organization, note-taking, and workflow optimization. | 3 | #+description: The Org Mode features I actually reach for, and how I use them. |
| 4 | #+slug: org-mode-features | 4 | #+slug: org-mode-features |
| 5 | #+filetags: :emacs: | 5 | #+filetags: :emacs: |
| 6 | 6 | ||
| 7 | * Cycling (Folding) | 7 | * Cycling (Folding) |
| 8 | 8 | ||
content/blog/2024-08-25-n8n-sentiment-analysis.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-08-25 Sunday 09:45:30] | 1 | #+date: [2024-08-25 Sun 09:45:30] |
| 2 | #+title: automate email sentiment analysis with n8n | 2 | #+title: Email Sentiment Analysis with n8n |
| 3 | #+description: Detailed procedural steps for configuring an n8n workflow to perform sentiment analysis on incoming email messages, enabling automated classification based on sentiment. | 3 | #+description: Using n8n to automatically classify incoming emails by sentiment. |
| 4 | #+slug: n8n-sentiment-analysis | 4 | #+slug: n8n-sentiment-analysis |
| 5 | #+filetags: :self-hosting: | 5 | #+filetags: :self-hosting: |
| 6 | 6 | ||
| 7 | * n8n | 7 | * n8n |
| 8 | 8 | ||
content/blog/2024-09-20-prometheus-grafana-cloud.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-09-20 Friday 13:38:52] | 1 | #+date: [2024-09-20 Fri 13:38:52] |
| 2 | #+title: prometheus grafana: monitoring without paying for the cloud tier | 2 | #+title: Prometheus and Grafana Cloud for Server Monitoring |
| 3 | #+description: Stepwise method for deploying Prometheus with Docker to monitor Linux servers and integrating Grafana Cloud for visualization and analysis of collected metrics. | 3 | #+description: Monitoring Linux servers with Prometheus and visualizing in Grafana Cloud. |
| 4 | #+slug: prometheus-grafana-cloud | 4 | #+slug: prometheus-grafana-cloud |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | This tutorial will guide you through the process of: | 7 | This tutorial will guide you through the process of: |
| 8 | 8 | ||
content/blog/2024-09-23-self-hosting-transmission.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-09-23 Monday 19:52:20] | 1 | #+date: [2024-09-23 Mon 19:52:20] |
| 2 | #+title: self hosting guide: transmission bittorrent client | 2 | #+title: Self-Hosting Guide: Transmission |
| 3 | #+description: Comprehensive setup instructions for installing and configuring the Transmission BitTorrent client on a Linux server, including securing remote access through Nginx reverse proxy. | 3 | #+description: Setting up Transmission on a Linux server with Nginx for remote access. |
| 4 | #+slug: self-hosting-transmission | 4 | #+slug: self-hosting-transmission |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | #+begin_quote | 7 | #+begin_quote |
| 8 | If you're torrenting anything sensitive, I *highly* recommend you use a VPN. | 8 | If you're torrenting anything sensitive, I *highly* recommend you use a VPN. |
content/blog/2024-10-31-continue-ollama-code-assistant.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-10-31 Thursday 11:01:05] | 1 | #+date: [2024-10-31 Thu 11:01:05] |
| 2 | #+title: ollama code assistant setup in vs codium | 2 | #+title: Ollama Code Assistant in VS Codium |
| 3 | #+description: Technical overview and configuration guide for incorporating Ollama as a code assistance tool within VS Codium and VS Code editors to enhance development workflows. | 3 | #+description: Setting up Ollama as a local code assistant in VS Codium. |
| 4 | #+slug: continue-ollama-code-assistant | 4 | #+slug: continue-ollama-code-assistant |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Background | 7 | * Background |
| 8 | 8 | ||
content/blog/2024-12-27-self-hosting-the-lounge.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2024-12-29 Sun 17:45:00] | 1 | #+date: [2024-12-29 Sun 17:45:00] |
| 2 | #+title: self hosting guide: the lounge (irc) | 2 | #+title: Self-Hosting Guide: The Lounge (IRC) |
| 3 | #+description: Step-by-step instructions for installing and configuring The Lounge IRC web client on Linux systems utilizing Docker Compose to provide persistent and secure chat access. | 3 | #+description: How to self-host The Lounge IRC client with Docker Compose. |
| 4 | #+slug: self-hosting-the-lounge | 4 | #+slug: self-hosting-the-lounge |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * The Lounge | 7 | * The Lounge |
| 8 | 8 | ||
content/blog/2025-01-23-self-hosting-tandoor.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-01-23 Thursday 20:44:45] | 1 | #+date: [2025-01-23 Thu 20:44:45] |
| 2 | #+title: self hosting guide: tandoor recipe manager | 2 | #+title: Self-Hosting Guide: Tandoor |
| 3 | #+description: Detailed tutorial on deploying Tandoor, an open-source recipe management application, including installation steps and configuration for self-hosted operation. | 3 | #+description: Self-hosting Tandoor, an open-source recipe manager. |
| 4 | #+slug: self-hosting-tandoor | 4 | #+slug: self-hosting-tandoor |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2025-02-11-obscura-vpn.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-02-11 Tuesday 11:40:00] | 1 | #+date: [2025-02-11 Tue 11:40:00] |
| 2 | #+title: obscura vpn: a two party protocol review | 2 | #+title: Obscura VPN: A Two-Party Protocol Review |
| 3 | #+description: Analytical review outlining the features, implementation, and security aspects of Obscura VPN's two-party protocol in conjunction with Mullvad VPN. | 3 | #+description: A review of Obscura VPN and its two-party protocol with Mullvad. |
| 4 | #+slug: obscura-vpn | 4 | #+slug: obscura-vpn |
| 5 | #+filetags: :security: | 5 | #+filetags: :security: |
| 6 | 6 | ||
| 7 | #+begin_quote | 7 | #+begin_quote |
| 8 | This review is written at a high-level for users, not a technical deep-dive of | 8 | This review is written at a high-level for users, not a technical deep-dive of |
content/blog/2025-02-24-email-migration.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-02-25 Mon 19:20:05] | 1 | #+date: [2025-02-25 Mon 19:20:05] |
| 2 | #+title: email migration: 5000+ emails, proton to migadu | 2 | #+title: Email Migration: 5,000+ Emails, Proton to Migadu |
| 3 | #+description: Detailed instructions describing the process and considerations involved in transferring email data securely from Proton Mail to Migadu email hosting. | 3 | #+description: Moving 5,000+ emails from Proton Mail to Migadu. |
| 4 | #+slug: email-migration | 4 | #+slug: email-migration |
| 5 | #+filetags: :privacy: | 5 | #+filetags: :privacy: |
| 6 | 6 | ||
| 7 | * The Setup | 7 | * The Setup |
| 8 | 8 | ||
content/blog/2025-04-05-git-mirror.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-04-05 Saturday 23:04:54] | 1 | #+date: [2025-04-05 Sat 23:04:54] |
| 2 | #+title: automating github to gitlab repository sync | 2 | #+title: Automating GitHub to GitLab Repository Sync |
| 3 | #+description: Technical steps for setting up automated synchronization and mirroring of source code repositories from GitHub to GitLab for redundancy and repository management. | 3 | #+description: Automatically mirroring GitHub repos to GitLab for redundancy. |
| 4 | #+slug: git-mirror | 4 | #+slug: git-mirror |
| 5 | #+filetags: :self-hosting: | 5 | #+filetags: :self-hosting: |
| 6 | 6 | ||
| 7 | This is a short post detailing how I maintained repositories on GitHub and | 7 | This is a short post detailing how I maintained repositories on GitHub and |
| 8 | mirrors on GitLab - including both public and private repositories. | 8 | mirrors on GitLab - including both public and private repositories. |
content/blog/2025-05-02-asahi-linux.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-05-02 Friday 21:10:00] | 1 | #+date: [2025-05-02 Fri 21:10:00] |
| 2 | #+title: asahi linux: linux on apple silicon, current state | 2 | #+title: Asahi Linux: Linux on Apple Silicon |
| 3 | #+description: Documented analysis of installation procedure, system performance, and software compatibility for running Asahi Linux on the Apple M2 MacBook Pro 16-inch model. | 3 | #+description: What it's actually like to run Asahi Linux on an Apple M2. |
| 4 | #+slug: asahi-linux | 4 | #+slug: asahi-linux |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | * Trying out Asahi Linux | 7 | * Trying out Asahi Linux |
| 8 | 8 | ||
content/blog/2025-05-30-it-audit-career.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-05-30 Friday 10:53:28] | 1 | #+date: [2025-05-30 Fri 10:53:28] |
| 2 | #+title: it audit career: skills that matter vs. skills that look good | 2 | #+title: IT Audit Career: Skills That Matter |
| 3 | #+description: Instructional content detailing actionable knowledge areas including artificial intelligence, blockchain, cloud computing, DevOps, and automation relevant for audit professionals. | 3 | #+description: What skills actually matter in IT audit vs. what just looks good on paper. |
| 4 | #+slug: it-audit-career | 4 | #+slug: it-audit-career |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * Introduction | 7 | * Introduction |
| 8 | 8 | ||
content/blog/2025-06-02-private-ios-apps.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-06-03 Tue 11:38:40] | 1 | #+date: [2025-06-03 Tue 11:38:40] |
| 2 | #+title: private ios apps: what i actually use | 2 | #+title: Private iOS Apps: What I Actually Use |
| 3 | #+description: Curated listing of iOS applications prioritized for privacy preservation and data security, targeted at users requiring minimal data exposure. | 3 | #+description: The iOS apps I use that prioritize privacy. |
| 4 | #+slug: private-ios-apps | 4 | #+slug: private-ios-apps |
| 5 | #+filetags: :linux:privacy: | 5 | #+filetags: :linux:privacy: |
| 6 | 6 | ||
| 7 | The world is evolving into a privacy nightmare, where our own devices are being | 7 | The world is evolving into a privacy nightmare, where our own devices are being |
| 8 | used by numerous parties to constantly track and report on our activities. This | 8 | used by numerous parties to constantly track and report on our activities. This |
content/blog/2025-09-04-website-redesign.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-09-05 Fri 10:21:00] | 1 | #+date: [2025-09-05 Fri 10:21:00] |
| 2 | #+title: website redesign 2025: what changed | 2 | #+title: Website Redesign 2025 |
| 3 | #+description: Read this post to understand my latest website redesign and the context for the refresh. | 3 | #+description: An overview of the 2025 redesign of this site. |
| 4 | #+slug: human-website-design | 4 | #+slug: human-website-design |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | #+begin_quote | 7 | #+begin_quote |
| 8 | /Please note that this redesign is a work-in-progress and is not complete. The | 8 | /Please note that this redesign is a work-in-progress and is not complete. The |
content/blog/2025-09-25-minimalist-website-redesign.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-09-25 Thu 21:08:00] | 1 | #+date: [2025-09-25 Thu 21:08:00] |
| 2 | #+title: minimalist site: strip it down | 2 | #+title: Minimalist Site: Strip It Down |
| 3 | #+description: This post details a complete redesign of a blog post, stripping away extraneous CSS and HTML elements to prioritize readability and user experience. | 3 | #+description: A complete redesign stripping away extraneous CSS and HTML for readability. |
| 4 | #+slug: minimalist-website-redesign | 4 | #+slug: minimalist-website-redesign |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | I know what you're thinking: "ANOTHER blog post about redesigning the website?" | 7 | I know what you're thinking: "ANOTHER blog post about redesigning the website?" |
| 8 | 8 | ||
content/blog/2025-10-03-privacy-toolkit.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-10-03 Fri 4:23:00] | 1 | #+date: [2025-10-03 Fri 4:23:00] |
| 2 | #+title: my privacy toolkit | 2 | #+title: My Privacy Toolkit |
| 3 | #+description: Learn about the tools I use to keep my life private and data secure. | 3 | #+description: The tools I use to keep my data private. |
| 4 | #+slug: privacy-toolkit | 4 | #+slug: privacy-toolkit |
| 5 | #+filetags: :privacy: | 5 | #+filetags: :privacy: |
| 6 | 6 | ||
| 7 | * VPN | 7 | * VPN |
| 8 | 8 | ||
content/blog/2025-10-06-rocket-league-macos.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-10-06 Mon 13:11:00] | 1 | #+date: [2025-10-06 Mon 13:11:00] |
| 2 | #+title: playing rocket league on macos via crossover | 2 | #+title: Rocket League on macOS via CrossOver |
| 3 | #+description: Learn how to play Rocket League on macOS via CrossOver. | 3 | #+description: Getting Rocket League running on macOS through CrossOver. |
| 4 | #+slug: rocket-league-macos | 4 | #+slug: rocket-league-macos |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | #+caption: Rocket League on macOS | 7 | #+caption: Rocket League on macOS |
| 8 | #+attr_html: :alt The Rocket League launch screen on macOS. | 8 | #+attr_html: :alt The Rocket League launch screen on macOS. |
content/blog/2025-10-24-digital-garden.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-10-24 Fri 19:41:41] | 1 | #+date: [2025-10-24 Fri 19:41:41] |
| 2 | #+title: digital garden | 2 | #+title: Digital Garden |
| 3 | #+description: A post dedicated to digital gardens, an online space for personal knowledge management, creative exploration, and reflection. | 3 | #+description: What a digital garden is and how I think about mine. |
| 4 | #+slug: digital-garden | 4 | #+slug: digital-garden |
| 5 | #+filetags: :web: | 5 | #+filetags: :web: |
| 6 | 6 | ||
| 7 | * What's a Digital Garden? | 7 | * What's a Digital Garden? |
| 8 | 8 | ||
content/blog/2025-11-02-aerc-macos.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-11-02 Sun 10:07:14] | 1 | #+date: [2025-11-02 Sun 10:07:14] |
| 2 | #+title: using aerc on macos | 2 | #+title: Using aerc on macOS |
| 3 | #+description: Learn how I use aerc, a TUI email client, on macOS. | 3 | #+description: How I use aerc, a TUI email client, on macOS. |
| 4 | #+slug: aerc-macos | 4 | #+slug: aerc-macos |
| 5 | #+filetags: :linux: | 5 | #+filetags: :linux: |
| 6 | 6 | ||
| 7 | #+caption: aerc-mail | 7 | #+caption: aerc-mail |
| 8 | #+attr_html: :alt An image of aerc with an email opened in the reader window. | 8 | #+attr_html: :alt An image of aerc with an email opened in the reader window. |
content/blog/2025-11-13-wcag.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-11-14 Fri 19:46:30] | 1 | #+date: [2025-11-14 Fri 19:46:30] |
| 2 | #+title: wcag compliance: accessibility as a real constraint, not a checkbox | 2 | #+title: WCAG Compliance: Accessibility as a Real Constraint |
| 3 | #+description: Read on to learn more about how I've ensured my humble site is compliant with WCAG 2. | 3 | #+description: How I've made this site compliant with WCAG 2. |
| 4 | #+slug: wcag | 4 | #+slug: wcag |
| 5 | #+filetags: :audit:web: | 5 | #+filetags: :audit:web: |
| 6 | 6 | ||
| 7 | * WCAG 2 | 7 | * WCAG 2 |
| 8 | 8 | ||
content/blog/2025-11-23-it-audit-ai.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-11-23 17:43:57] | 1 | #+date: [2025-11-23 Sun 17:43:57] |
| 2 | #+title: it audit ai: where it helps and where it's theater | 2 | #+title: IT Audit and AI: Where It Helps and Where It's Theater |
| 3 | #+description: Learn how I'm currently using AI in my role in Technology Assurance (i.e., IT Audit) at KPMG. | 3 | #+description: How I'm currently using AI in my Technology Assurance role at KPMG. |
| 4 | #+slug: it-audit-ai | 4 | #+slug: it-audit-ai |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | * My AI Toolkit | 7 | * My AI Toolkit |
| 8 | 8 | ||
content/blog/2025-12-06-self-hosting-tor.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-12-06 Sat 14:13:00] | 1 | #+date: [2025-12-06 Sat 14:13:00] |
| 2 | #+title: self hosting guide: tor websites | 2 | #+title: Self-Hosting Guide: Tor Websites |
| 3 | #+description: Learn how to host your own website on Tor with an Onion Address in a few short steps! | 3 | #+description: How to host a website on Tor with an onion address. |
| 4 | #+slug: self-hosting-tor | 4 | #+slug: self-hosting-tor |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Installation | 7 | * Installation |
| 8 | 8 | ||
content/blog/2025-12-20-self-hosting-home-assistant.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2025-12-20 Sat 20:27:08] | 1 | #+date: [2025-12-20 Sat 20:27:08] |
| 2 | #+title: self hosting guide: home assistant | 2 | #+title: Self-Hosting Guide: Home Assistant |
| 3 | #+description: A guide to configuring and customizing Home Assistant. | 3 | #+description: Configuring and customizing Home Assistant. |
| 4 | #+slug: self-hosting-home-assistant | 4 | #+slug: self-hosting-home-assistant |
| 5 | #+filetags: :linux:self-hosting: | 5 | #+filetags: :linux:self-hosting: |
| 6 | 6 | ||
| 7 | * Overview | 7 | * Overview |
| 8 | 8 | ||
content/blog/2026-01-31-emacs-carnival-2026-01-this-year-i-will.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-01-31 Sat 20:32:11] | 1 | #+date: [2026-01-31 Sat 20:32:11] |
| 2 | #+title: emacs carnival: “this year, i will...” | 2 | #+title: Emacs Carnival: This Year, I Will... |
| 3 | #+description: My response to the Emacs Carnival post for January 2026. | 3 | #+description: My response to the Emacs Carnival prompt for January 2026. |
| 4 | #+slug: emacs-carnival-2026-01-this-year-i-will | 4 | #+slug: emacs-carnival-2026-01-this-year-i-will |
| 5 | #+filetags: :emacs:personal: | 5 | #+filetags: :emacs:personal: |
| 6 | 6 | ||
| 7 | This year in Emacs, I expect to do a lot. However, here are some actionable | 7 | This year in Emacs, I expect to do a lot. However, here are some actionable |
| 8 | goals for myself that should have a positive impact as I start out 2026. | 8 | goals for myself that should have a positive impact as I start out 2026. |
content/blog/2026-02-02-emacs-carnival-2026-02-completion.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-02-02 18:40:21] | 1 | #+date: [2026-02-02 Mon 18:40:21] |
| 2 | #+title: emacs carnival: "completion" | 2 | #+title: Emacs Carnival: Completion |
| 3 | #+description: My response to the Emacs Carnival post for February 2026. | 3 | #+description: My response to the Emacs Carnival prompt for February 2026. |
| 4 | #+slug: emacs-carnival-2026-02-completion | 4 | #+slug: emacs-carnival-2026-02-completion |
| 5 | #+filetags: :emacs:personal: | 5 | #+filetags: :emacs:personal: |
| 6 | 6 | ||
| 7 | I'm having a great time with the Emacs Carnival, as it has inspired me to write | 7 | I'm having a great time with the Emacs Carnival, as it has inspired me to write |
| 8 | two posts in such a short time. It's been a much needed inspiration to write | 8 | two posts in such a short time. It's been a much needed inspiration to write |
content/blog/2026-02-07-indieweb-carnival-2026-02-intersecting-interests.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-02-07 Sat 17:46:00] | 1 | #+date: [2026-02-07 Sat 17:46:00] |
| 2 | #+title: indieweb carnival: "intersecting interests" | 2 | #+title: IndieWeb Carnival: Intersecting Interests |
| 3 | #+description: Contrasting my passions with technology vs. natural hobbies. | 3 | #+description: Contrasting my passion for technology with my interest in natural hobbies. |
| 4 | #+slug: indiweb-carnival-2026-02-intersecting-interests | 4 | #+slug: indiweb-carnival-2026-02-intersecting-interests |
| 5 | #+filetags: :personal:web: | 5 | #+filetags: :personal:web: |
| 6 | 6 | ||
| 7 | I thought about this topic for a long time today before starting to write this | 7 | I thought about this topic for a long time today before starting to write this |
| 8 | post, as I don't think of myself as someone with intersecting interests. I | 8 | post, as I don't think of myself as someone with intersecting interests. I |
content/blog/2026-02-08-gnu-stow.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-02-08 Sun 12:17:42] | 1 | #+date: [2026-02-08 Sun 12:17:42] |
| 2 | #+title: managing my dotfiles with gnu stow and git | 2 | #+title: Managing Dotfiles with GNU Stow and Git |
| 3 | #+description: Learn how I use GNU Stow to manage my user dotfiles and configurations. | 3 | #+description: How I use GNU Stow to manage my dotfiles and configs across machines. |
| 4 | #+slug: gnu-stow | 4 | #+slug: gnu-stow |
| 5 | #+filetags: :emacs:linux: | 5 | #+filetags: :emacs:linux: |
| 6 | 6 | ||
| 7 | * What is GNU Stow? | 7 | * What is GNU Stow? |
| 8 | 8 | ||
content/blog/2026-02-12-automating-weblorg-deployments.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-02-12 Thu 20:26:32] | 1 | #+date: [2026-02-12 Thu 20:26:32] |
| 2 | #+title: weblorg deployments: automated, no github actions dependency | 2 | #+title: Automating weblorg Deployments |
| 3 | #+description: Learn how I've automated all deployment for my org-mode blog with GitHub Actions and a custom Docker image. | 3 | #+description: How I automated deployment for this org-mode blog without GitHub Actions. |
| 4 | #+slug: automating-weblorg-deployments | 4 | #+slug: automating-weblorg-deployments |
| 5 | #+filetags: :self-hosting:web: | 5 | #+filetags: :self-hosting:web: |
| 6 | 6 | ||
| 7 | As I've mentioned in previous posts, I utilize a unique pipeline to draft posts, | 7 | As I've mentioned in previous posts, I utilize a unique pipeline to draft posts, |
| 8 | compose my website, and to build and deploy the static files. | 8 | compose my website, and to build and deploy the static files. |
content/blog/2026-02-21-auditing-aws-iam.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-02-21 Sat 18:58:39] | 1 | #+date: [2026-02-21 Sat 18:58:39] |
| 2 | #+title: auditing aws iam users | 2 | #+title: Auditing AWS IAM Users |
| 3 | #+description: Learn how to audit IAM user assignments in AWS. | 3 | #+description: How to audit IAM user assignments in AWS. |
| 4 | #+slug: auditing-aws-iam | 4 | #+slug: auditing-aws-iam |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | If you've ever asked an IT team for a list of who has access to an AWS account, | 7 | If you've ever asked an IT team for a list of who has access to an AWS account, |
| 8 | you've probably received a spreadsheet that was already out of date. Or worse, | 8 | you've probably received a spreadsheet that was already out of date. Or worse, |
content/blog/2026-02-21-auditing-aws-passwords.org +4 −4
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-02-21 Sat 21:13:45] | 1 | #+date: [2026-02-21 Sat 21:13:45] |
| 2 | #+title: auditing aws passwords | 2 | #+title: Auditing AWS Passwords |
| 3 | #+description: Learn how to audit passwords in AWS. | 3 | #+description: How to audit password policies and usage in AWS. |
| 4 | #+slug: auditing-aws-passwords | 4 | #+slug: auditing-aws-passwords |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | One of the first controls an IT Auditor learns is how to audit passwords in any | 7 | One of the first controls an IT Auditor learns is how to audit passwords in any |
| 8 | number of IT systems. However, things have changed with the introduction of | 8 | number of IT systems. However, things have changed with the introduction of |
content/blog/2026-03-03-auditing-aws-s3.org +5 −5
| @@ -1,8 +1,8 @@ | |||
| 1 | #+date: [2026-03-03 Tue 18:50:23] | 1 | #+date: [2026-03-03 Tue 18:50:23] |
| 2 | #+title: auditing aws s3 buckets | 2 | #+title: Auditing AWS S3 Buckets |
| 3 | #+description: Learn how to audit AWS S3 buckets for public access. | 3 | #+description: How to audit AWS S3 buckets for public access and misconfigurations. |
| 4 | #+slug: auditing-aws-s3 | 4 | #+slug: auditing-aws-s3 |
| 5 | #+filetags: :audit: | 5 | #+filetags: :audit: |
| 6 | 6 | ||
| 7 | This is the latest in my series of posts on auditing AWS, a cloud platform that | 7 | This is the latest in my series of posts on auditing AWS, a cloud platform that |
| 8 | has existed for around two decades but can still be a mystery to auditors who | 8 | has existed for around two decades but can still be a mystery to auditors who |
| @@ -79,7 +79,7 @@ The reverse is also true. A bucket with no public policy and no public ACLs is | |||
| 79 | still at risk if PAB is missing or incomplete, because nothing is in place to | 79 | still at risk if PAB is missing or incomplete, because nothing is in place to |
| 80 | prevent a future policy or ACL change from exposing it. | 80 | prevent a future policy or ACL change from exposing it. |
| 81 | 81 | ||
| 82 | M* What the Script Does | 82 | * What the Script Does |
| 83 | 83 | ||
| 84 | The script lists every bucket in the account, determines each bucket's region, | 84 | The script lists every bucket in the account, determines each bucket's region, |
| 85 | runs all three checks against it, and appends the results to a CSV file. | 85 | runs all three checks against it, and appends the results to a CSV file. |
content/guides/index.org +1 −1
| @@ -1,4 +1,4 @@ | |||
| 1 | #+title: guides | 1 | #+title: Guides |
| 2 | #+slug: index | 2 | #+slug: index |
| 3 | #+options: toc:nil | 3 | #+options: toc:nil |
| 4 | 4 | ||
content/salary/index.org +1 −1
| @@ -1,4 +1,4 @@ | |||
| 1 | #+title: salary | 1 | #+title: Salary |
| 2 | #+slug: index | 2 | #+slug: index |
| 3 | #+options: toc:nil | 3 | #+options: toc:nil |
| 4 | 4 | ||
screenshots/dark.png deleted
Binary file not shown.
screenshots/light.png deleted
Binary file not shown.
tag_preview.py deleted −177
| @@ -1,177 +0,0 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | """ | ||
| 3 | Preview tag assignments for all blog posts. | ||
| 4 | Run with --write to actually add #+filetags to org files. | ||
| 5 | """ | ||
| 6 | import re | ||
| 7 | import sys | ||
| 8 | from pathlib import Path | ||
| 9 | |||
| 10 | CONTENT_DIR = Path("./content/blog") | ||
| 11 | |||
| 12 | # Explicit overrides take priority over rules | ||
| 13 | OVERRIDES = { | ||
| 14 | "2018-11-28-cpp-compiler": ["linux"], | ||
| 15 | "2019-12-16-password-security": ["security"], | ||
| 16 | "2020-07-26-business-analysis": ["audit"], | ||
| 17 | "2020-08-22-redirect-github-pages": ["web"], | ||
| 18 | "2020-09-22-internal-audit": ["audit"], | ||
| 19 | "2020-12-28-neon-drive": ["personal"], | ||
| 20 | "2020-12-29-zork": ["personal"], | ||
| 21 | "2021-08-25-audit-sampling": ["audit"], | ||
| 22 | "2021-12-04-cisa": ["audit"], | ||
| 23 | "2023-05-22-burnout": ["personal"], | ||
| 24 | "2023-06-20-audit-review-template": ["audit"], | ||
| 25 | "2023-08-18-agile-auditing": ["audit"], | ||
| 26 | "2025-05-30-it-audit-career": ["audit"], | ||
| 27 | "2025-11-13-wcag": ["audit", "web"], | ||
| 28 | "2025-11-23-it-audit-ai": ["audit"], | ||
| 29 | "2026-02-21-auditing-aws-iam": ["audit"], | ||
| 30 | "2026-02-21-auditing-aws-passwords": ["audit"], | ||
| 31 | "2026-03-03-auditing-aws-s3": ["audit"], | ||
| 32 | "2020-09-01-visual-recognition": ["linux"], | ||
| 33 | "2024-01-26-audit-dashboard": ["audit"], | ||
| 34 | "2023-09-19-audit-sql-scripts": ["audit"], | ||
| 35 | "2021-04-28-photography": ["personal"], | ||
| 36 | "2022-06-22-daily-poetry": ["personal"], | ||
| 37 | "2020-09-25-happiness-map": ["personal"], | ||
| 38 | "2022-03-03-financial-database": ["self-hosting"], | ||
| 39 | "2023-01-03-recent-website-changes": ["personal", "web"], | ||
| 40 | "2025-09-25-minimalist-website-redesign": ["web"], | ||
| 41 | "2026-02-07-indieweb-carnival-2026-02-intersecting-interests": ["personal", "web"], | ||
| 42 | } | ||
| 43 | |||
| 44 | TAG_RULES = { | ||
| 45 | "audit": [ | ||
| 46 | "audit", "cisa", "ansoff", | ||
| 47 | ], | ||
| 48 | "emacs": [ | ||
| 49 | "emacs", "org-mode", "org-blog", "mu4e", "doom-emacs", | ||
| 50 | "emacs-carnival", "gnu-stow", | ||
| 51 | ], | ||
| 52 | "linux": [ | ||
| 53 | "linux", "ubuntu", "debian", "fedora", "alpine", | ||
| 54 | "customizing-ubuntu", "linux-software", "linux-display", | ||
| 55 | "mtp-linux", "serenity-os", "fedora-i3", "fedora-login", | ||
| 56 | "flatpak", "zfs", "ubuntu-emergency", "ubuntu-on-macos", | ||
| 57 | "steam-on-ntfs", "bash-it", "byobu", "scli", | ||
| 58 | "terminal-lifestyle", "curseradio", "st", "flac-to-opus", | ||
| 59 | "pinetime", "server-build", "macos", "macos-customization", | ||
| 60 | "deprecated-trusted-gpg", "exiftool", "graphene", | ||
| 61 | "asahi", "aerc", "rocket-league", | ||
| 62 | ], | ||
| 63 | "self-hosting": [ | ||
| 64 | "self-hosting", "homelab", "vps-web-server", "git-server", | ||
| 65 | "plex", "nextcloud", "wireguard", "backblaze", "syncthing", | ||
| 66 | "docker", "n8n", "prometheus-grafana", "transmission", | ||
| 67 | "goaccess", "unifi", "git-mirror", "automating-weblorg", | ||
| 68 | ], | ||
| 69 | "security": [ | ||
| 70 | "aes-encryption", "cryptography", "gnupg", "password", | ||
| 71 | "server-hardening", "ssh-mfa", "ufw", "hardening", | ||
| 72 | "authelia", "wireguard", "njalla-dns", "cloudflare-dns", | ||
| 73 | "ditching-cloudflare", "obscura-vpn", | ||
| 74 | ], | ||
| 75 | "privacy": [ | ||
| 76 | "privacy", "graphene-os", "session-messenger", "fediverse", | ||
| 77 | "digital-minimalism", "privacy-com", "local-llm", | ||
| 78 | "email-migration", "dont-say-hello", | ||
| 79 | ], | ||
| 80 | "web": [ | ||
| 81 | "nginx", "apache", "php", "css", "redirect", "website-redesign", | ||
| 82 | "gemini", "indieweb", "weblorg", "html", "digital-garden", | ||
| 83 | "tableau", | ||
| 84 | ], | ||
| 85 | "personal": [ | ||
| 86 | "mediocrity", "burnout", "tuesday", "leaving-the-office", | ||
| 87 | "vaporwave", "video-game-sales", "reliable-notes", | ||
| 88 | "mass-unlike-tumblr", "changing-git-authors", "delete-gitlab", | ||
| 89 | "clone-github", "this-year-i-will", "completion", | ||
| 90 | "seum", "neon-drive", "zork", | ||
| 91 | ], | ||
| 92 | } | ||
| 93 | |||
| 94 | def assign_tags(slug: str, title: str) -> list[str]: | ||
| 95 | if slug in OVERRIDES: | ||
| 96 | return OVERRIDES[slug] | ||
| 97 | slug_lower = slug.lower() | ||
| 98 | title_lower = title.lower() | ||
| 99 | tags = [] | ||
| 100 | for tag, patterns in TAG_RULES.items(): | ||
| 101 | for pattern in patterns: | ||
| 102 | if pattern in slug_lower or pattern in title_lower: | ||
| 103 | if tag not in tags: | ||
| 104 | tags.append(tag) | ||
| 105 | break | ||
| 106 | return sorted(tags) | ||
| 107 | |||
| 108 | def get_title(path: Path) -> str: | ||
| 109 | title_pat = re.compile(r"^#\+title:\s*(.+)$", re.IGNORECASE) | ||
| 110 | with path.open("r", encoding="utf-8") as f: | ||
| 111 | for line in f: | ||
| 112 | m = title_pat.match(line) | ||
| 113 | if m: | ||
| 114 | return m.group(1).strip() | ||
| 115 | return path.stem | ||
| 116 | |||
| 117 | def has_filetags(path: Path) -> bool: | ||
| 118 | with path.open("r", encoding="utf-8") as f: | ||
| 119 | for line in f: | ||
| 120 | if re.match(r"^#\+filetags:", line, re.IGNORECASE): | ||
| 121 | return True | ||
| 122 | return False | ||
| 123 | |||
| 124 | def write_filetags(path: Path, tags: list[str]): | ||
| 125 | tag_str = ":" + ":".join(tags) + ":" | ||
| 126 | content = path.read_text(encoding="utf-8") | ||
| 127 | slug_pat = re.compile(r"(#\+slug:\s*.+\n)", re.IGNORECASE) | ||
| 128 | m = slug_pat.search(content) | ||
| 129 | if m: | ||
| 130 | insert_at = m.end() | ||
| 131 | new_content = content[:insert_at] + f"#+filetags: {tag_str}\n" + content[insert_at:] | ||
| 132 | path.write_text(new_content, encoding="utf-8") | ||
| 133 | return True | ||
| 134 | return False | ||
| 135 | |||
| 136 | write_mode = "--write" in sys.argv | ||
| 137 | |||
| 138 | untagged = [] | ||
| 139 | rows = [] | ||
| 140 | for org_path in sorted(CONTENT_DIR.glob("*.org")): | ||
| 141 | slug = org_path.stem | ||
| 142 | title = get_title(org_path) | ||
| 143 | tags = assign_tags(slug, title) | ||
| 144 | if not tags: | ||
| 145 | untagged.append((slug, title)) | ||
| 146 | rows.append((slug, title, tags)) | ||
| 147 | |||
| 148 | print(f"{'SLUG':<50} {'TAGS'}") | ||
| 149 | print("-" * 85) | ||
| 150 | for slug, title, tags in rows: | ||
| 151 | tag_str = ", ".join(tags) if tags else "-- UNTAGGED --" | ||
| 152 | print(f"{slug:<50} {tag_str}") | ||
| 153 | |||
| 154 | print(f"\nTotal: {len(rows)} posts | Untagged: {len(untagged)}") | ||
| 155 | if untagged: | ||
| 156 | print("\nUntagged posts:") | ||
| 157 | for slug, title in untagged: | ||
| 158 | print(f" {slug}") | ||
| 159 | |||
| 160 | if write_mode: | ||
| 161 | written = 0 | ||
| 162 | skipped = 0 | ||
| 163 | for org_path in sorted(CONTENT_DIR.glob("*.org")): | ||
| 164 | slug = org_path.stem | ||
| 165 | title = get_title(org_path) | ||
| 166 | tags = assign_tags(slug, title) | ||
| 167 | if not tags: | ||
| 168 | skipped += 1 | ||
| 169 | continue | ||
| 170 | if has_filetags(org_path): | ||
| 171 | skipped += 1 | ||
| 172 | continue | ||
| 173 | if write_filetags(org_path, tags): | ||
| 174 | written += 1 | ||
| 175 | print(f"\nWrote filetags to {written} files, skipped {skipped}.") | ||
| 176 | else: | ||
| 177 | print("\nRun with --write to apply filetags to org files.") | ||
theme/static/favicon.svg deleted −14
| @@ -1,14 +0,0 @@ | |||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1500 1499.999933"> | ||
| 2 | <style> | ||
| 3 | path { fill: #111111; } | ||
| 4 | @media (prefers-color-scheme: dark) { path { fill: #ffffff; } } | ||
| 5 | </style> | ||
| 6 | <defs> | ||
| 7 | <clipPath id="c"> | ||
| 8 | <path d="M 246.484375 243.425781 L 1253.730469 243.425781 L 1253.730469 1256.457031 L 246.484375 1256.457031 Z" clip-rule="nonzero"/> | ||
| 9 | </clipPath> | ||
| 10 | </defs> | ||
| 11 | <g clip-path="url(#c)"> | ||
| 12 | <path fill-rule="nonzero" d="M 562.695312 907.28125 C 514.085938 881.21875 396.300781 818.089844 368.757812 795.410156 C 351.777344 781.4375 345.167969 771.671875 345.152344 765.117188 C 345.152344 762.648438 346.535156 760.578125 348.84375 758.890625 C 352.042969 756.558594 356.808594 754.898438 362.398438 753.796875 C 381.738281 750.015625 408.554688 753.210938 419.015625 759.636719 C 433.589844 783.507812 445.734375 801.542969 451.113281 804.4375 C 442.617188 780.46875 429.820312 749.761719 426.273438 724.375 C 422.824219 699.628906 421.839844 674.320312 423.527344 648.550781 C 424.203125 638.359375 425.214844 628.765625 426.183594 619.714844 C 431 574.277344 434.464844 541.792969 390.460938 495.28125 C 384.738281 489.226562 377.890625 482.316406 370.613281 474.960938 C 321.140625 424.960938 250.707031 353.765625 261.152344 267.800781 C 315.074219 306.644531 342.925781 327.1875 407.71875 334.761719 C 431.320312 337.511719 456.527344 336.820312 478.058594 329.164062 C 516.382812 315.507812 544.5625 284.574219 556.761719 269.183594 C 585.796875 331.273438 570.703125 413.90625 557.585938 485.699219 C 555.382812 497.800781 553.21875 509.597656 551.347656 520.890625 L 550.988281 518.554688 C 548.242188 492 533.292969 467.066406 523.683594 458.480469 C 543.953125 487.382812 544.246094 547.246094 546.410156 585.914062 C 548.929688 630.609375 564.742188 669.382812 589.390625 702.851562 C 598.3125 714.96875 608.402344 726.378906 619.417969 737.101562 C 631.074219 748.449219 648.730469 762.6875 668.375 775.730469 C 694.527344 793.078125 719.457031 807.15625 744.265625 818.808594 C 813.890625 851.503906 901.886719 873.054688 977.726562 889.058594 C 1010.898438 896.054688 1096.996094 920.363281 1158.511719 953.554688 C 1194.910156 973.207031 1222.335938 995.527344 1223.371094 1018.152344 C 1224.523438 1043.605469 1204.757812 1067.1875 1177.46875 1086.679688 C 1137.429688 1115.277344 1081.878906 1134.636719 1050.003906 1139.148438 C 1031.6875 1141.75 1013.195312 1143.371094 994.636719 1144.058594 C 982.558594 1144.5 970.476562 1144.539062 958.371094 1144.191406 C 968.617188 1130.5 979.1875 1114.320312 979.929688 1104.875 C 941.871094 1141.261719 909.90625 1170.003906 864.242188 1199.265625 C 825.28125 1224.238281 781.023438 1245.164062 744.679688 1242.683594 C 727.714844 1241.515625 717.398438 1236.394531 712.25 1228.964844 C 708.503906 1223.5625 707.335938 1216.6875 708.210938 1209.125 C 709.167969 1200.882812 712.5 1191.832031 717.585938 1182.796875 C 731.828125 1157.542969 759.238281 1133.378906 786.851562 1127.394531 C 807.09375 1134.054688 858.996094 1138.113281 869.710938 1127.019531 C 850.992188 1126.398438 825.226562 1126.160156 785.628906 1112.675781 C 726.160156 1092.4375 669.730469 1062.9375 619.5 1025.476562 C 570.769531 989.117188 527.917969 945.246094 493.855469 895.03125 C 490.457031 890.042969 487.257812 885.117188 484.230469 880.289062 C 512.519531 895.828125 553.472656 909.324219 562.695312 907.28125 Z M 849.492188 843.15625 C 822.199219 835.515625 746.46875 809.984375 712.699219 787.941406 C 727.59375 784.449219 741.570312 775.574219 755.640625 766.617188 C 778.648438 751.992188 801.984375 737.167969 827.550781 750.769531 C 865.59375 771.007812 855.625 821.660156 849.492188 843.15625 Z M 1187.714844 1095.996094 C 1193.289062 1108.085938 1206.632812 1127.722656 1213.546875 1132.421875 C 1206.738281 1121.804688 1197.832031 1107.753906 1195.359375 1090.117188 C 1220.78125 1069.574219 1238.171875 1044.957031 1236.910156 1017.554688 C 1236.273438 1003.515625 1228.519531 990.085938 1215.964844 977.492188 C 1227.179688 964.300781 1238.597656 955.117188 1253.757812 947.238281 C 1236.328125 950.964844 1222.746094 958.582031 1210.03125 971.890625 C 1197.898438 961.117188 1182.367188 950.980469 1165.015625 941.609375 C 1102.1875 907.703125 1014.351562 882.890625 980.527344 875.761719 C 940.914062 867.402344 901.410156 858.167969 862.488281 846.980469 C 869.40625 822.773438 880.914062 763.816406 833.9375 738.800781 C 801.347656 721.457031 774.664062 738.429688 748.339844 755.164062 C 714.078125 776.953125 704.867188 785.246094 675.054688 764.835938 C 645.808594 744.8125 620.042969 721.589844 600.316406 694.808594 C 569.453125 652.917969 553.351562 602.132812 561.96875 541.046875 C 564.328125 524.25 567.570312 506.546875 570.925781 488.140625 C 585.132812 410.402344 601.589844 320.296875 563.734375 253.046875 L 558.328125 243.4375 L 552.183594 252.632812 C 552.089844 252.765625 521.253906 299.34375 473.464844 316.371094 C 454.113281 323.269531 431.039062 323.839844 409.285156 321.292969 C 344.542969 313.730469 305.648438 285.066406 251.222656 245.695312 L 249.367188 255.355469 C 230.609375 352.796875 307.546875 430.535156 360.976562 484.542969 C 367.878906 491.511719 374.386719 498.078125 380.570312 504.636719 C 420.316406 546.636719 417.140625 576.492188 412.707031 618.253906 C 411.726562 627.359375 410.703125 637.019531 410.011719 647.636719 C 408.25 674.414062 409.269531 700.664062 412.839844 726.246094 C 413.664062 732.140625 414.621094 738.003906 415.707031 743.84375 C 400.136719 739 377.105469 737.089844 359.808594 740.472656 C 352.363281 741.933594 345.738281 744.363281 340.839844 747.929688 C 335.050781 752.152344 331.585938 757.804688 331.585938 765.128906 C 331.613281 775.546875 339.617188 789.015625 360.15625 805.921875 C 375.710938 818.742188 417.804688 843.34375 460.855469 867.351562 C 464.039062 873.097656 467.453125 878.921875 471.089844 884.828125 C 474.886719 890.996094 478.734375 896.941406 482.613281 902.675781 C 517.539062 954.148438 561.460938 999.121094 611.414062 1036.371094 C 658.433594 1071.457031 710.828125 1099.710938 766.101562 1120.132812 C 741.265625 1131.347656 718.578125 1153.363281 705.757812 1176.121094 C 699.824219 1186.632812 695.921875 1197.433594 694.738281 1207.558594 C 693.503906 1218.375 695.347656 1228.417969 701.085938 1236.699219 C 708.519531 1247.433594 722.175781 1254.761719 743.75 1256.234375 C 810.464844 1260.796875 899.523438 1194.117188 943.382812 1157.15625 C 960.628906 1158.085938 977.910156 1158.246094 995.15625 1157.621094 C 1014.125 1156.917969 1033.054688 1155.246094 1051.890625 1152.578125 C 1095.21875 1146.4375 1152.65625 1121.753906 1187.714844 1095.996094"/> | ||
| 13 | </g> | ||
| 14 | </svg>\ No newline at end of file | ||
theme/static/koi-hr.svg deleted −7
| @@ -1,7 +0,0 @@ | |||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1500 1500"> | ||
| 2 | <style> | ||
| 3 | path { fill: #111111; } | ||
| 4 | @media (prefers-color-scheme: dark) { path { fill: #F0EDE8; } } | ||
| 5 | </style> | ||
| 6 | <path fill-rule="nonzero" d="M 562.695312 907.28125 C 514.085938 881.21875 396.300781 818.089844 368.757812 795.410156 C 351.777344 781.4375 345.167969 771.671875 345.152344 765.117188 C 345.152344 762.648438 346.535156 760.578125 348.84375 758.890625 C 352.042969 756.558594 356.808594 754.898438 362.398438 753.796875 C 381.738281 750.015625 408.554688 753.210938 419.015625 759.636719 C 433.589844 783.507812 445.734375 801.542969 451.113281 804.4375 C 442.617188 780.46875 429.820312 749.761719 426.273438 724.375 C 422.824219 699.628906 421.839844 674.320312 423.527344 648.550781 C 424.203125 638.359375 425.214844 628.765625 426.183594 619.714844 C 431 574.277344 434.464844 541.792969 390.460938 495.28125 C 384.738281 489.226562 377.890625 482.316406 370.613281 474.960938 C 321.140625 424.960938 250.707031 353.765625 261.152344 267.800781 C 315.074219 306.644531 342.925781 327.1875 407.71875 334.761719 C 431.320312 337.511719 456.527344 336.820312 478.058594 329.164062 C 516.382812 315.507812 544.5625 284.574219 556.761719 269.183594 C 585.796875 331.273438 570.703125 413.90625 557.585938 485.699219 C 555.382812 497.800781 553.21875 509.597656 551.347656 520.890625 L 550.988281 518.554688 C 548.242188 492 533.292969 467.066406 523.683594 458.480469 C 543.953125 487.382812 544.246094 547.246094 546.410156 585.914062 C 548.929688 630.609375 564.742188 669.382812 589.390625 702.851562 C 598.3125 714.96875 608.402344 726.378906 619.417969 737.101562 C 631.074219 748.449219 648.730469 762.6875 668.375 775.730469 C 694.527344 793.078125 719.457031 807.15625 744.265625 818.808594 C 813.890625 851.503906 901.886719 873.054688 977.726562 889.058594 C 1010.898438 896.054688 1096.996094 920.363281 1158.511719 953.554688 C 1194.910156 973.207031 1222.335938 995.527344 1223.371094 1018.152344 C 1224.523438 1043.605469 1204.757812 1067.1875 1177.46875 1086.679688 C 1137.429688 1115.277344 1081.878906 1134.636719 1050.003906 1139.148438 C 1031.6875 1141.75 1013.195312 1143.371094 994.636719 1144.058594 C 982.558594 1144.5 970.476562 1144.539062 958.371094 1144.191406 C 968.617188 1130.5 979.1875 1114.320312 979.929688 1104.875 C 941.871094 1141.261719 909.90625 1170.003906 864.242188 1199.265625 C 825.28125 1224.238281 781.023438 1245.164062 744.679688 1242.683594 C 727.714844 1241.515625 717.398438 1236.394531 712.25 1228.964844 C 708.503906 1223.5625 707.335938 1216.6875 708.210938 1209.125 C 709.167969 1200.882812 712.5 1191.832031 717.585938 1182.796875 C 731.828125 1157.542969 759.238281 1133.378906 786.851562 1127.394531 C 807.09375 1134.054688 858.996094 1138.113281 869.710938 1127.019531 C 850.992188 1126.398438 825.226562 1126.160156 785.628906 1112.675781 C 726.160156 1092.4375 669.730469 1062.9375 619.5 1025.476562 C 570.769531 989.117188 527.917969 945.246094 493.855469 895.03125 C 490.457031 890.042969 487.257812 885.117188 484.230469 880.289062 C 512.519531 895.828125 553.472656 909.324219 562.695312 907.28125 Z M 849.492188 843.15625 C 822.199219 835.515625 746.46875 809.984375 712.699219 787.941406 C 727.59375 784.449219 741.570312 775.574219 755.640625 766.617188 C 778.648438 751.992188 801.984375 737.167969 827.550781 750.769531 C 865.59375 771.007812 855.625 821.660156 849.492188 843.15625 Z M 1187.714844 1095.996094 C 1193.289062 1108.085938 1206.632812 1127.722656 1213.546875 1132.421875 C 1206.738281 1121.804688 1197.832031 1107.753906 1195.359375 1090.117188 C 1220.78125 1069.574219 1238.171875 1044.957031 1236.910156 1017.554688 C 1236.273438 1003.515625 1228.519531 990.085938 1215.964844 977.492188 C 1227.179688 964.300781 1238.597656 955.117188 1253.757812 947.238281 C 1236.328125 950.964844 1222.746094 958.582031 1210.03125 971.890625 C 1197.898438 961.117188 1182.367188 950.980469 1165.015625 941.609375 C 1102.1875 907.703125 1014.351562 882.890625 980.527344 875.761719 C 940.914062 867.402344 901.410156 858.167969 862.488281 846.980469 C 869.40625 822.773438 880.914062 763.816406 833.9375 738.800781 C 801.347656 721.457031 774.664062 738.429688 748.339844 755.164062 C 714.078125 776.953125 704.867188 785.246094 675.054688 764.835938 C 645.808594 744.8125 620.042969 721.589844 600.316406 694.808594 C 569.453125 652.917969 553.351562 602.132812 561.96875 541.046875 C 564.328125 524.25 567.570312 506.546875 570.925781 488.140625 C 585.132812 410.402344 601.589844 320.296875 563.734375 253.046875 L 558.328125 243.4375 L 552.183594 252.632812 C 552.089844 252.765625 521.253906 299.34375 473.464844 316.371094 C 454.113281 323.269531 431.039062 323.839844 409.285156 321.292969 C 344.542969 313.730469 305.648438 285.066406 251.222656 245.695312 L 249.367188 255.355469 C 230.609375 352.796875 307.546875 430.535156 360.976562 484.542969 C 367.878906 491.511719 374.386719 498.078125 380.570312 504.636719 C 420.316406 546.636719 417.140625 576.492188 412.707031 618.253906 C 411.726562 627.359375 410.703125 637.019531 410.011719 647.636719 C 408.25 674.414062 409.269531 700.664062 412.839844 726.246094 C 413.664062 732.140625 414.621094 738.003906 415.707031 743.84375 C 400.136719 739 377.105469 737.089844 359.808594 740.472656 C 352.363281 741.933594 345.738281 744.363281 340.839844 747.929688 C 335.050781 752.152344 331.585938 757.804688 331.585938 765.128906 C 331.613281 775.546875 339.617188 789.015625 360.15625 805.921875 C 375.710938 818.742188 417.804688 843.34375 460.855469 867.351562 C 464.039062 873.097656 467.453125 878.921875 471.089844 884.828125 C 474.886719 890.996094 478.734375 896.941406 482.613281 902.675781 C 517.539062 954.148438 561.460938 999.121094 611.414062 1036.371094 C 658.433594 1071.457031 710.828125 1099.710938 766.101562 1120.132812 C 741.265625 1131.347656 718.578125 1153.363281 705.757812 1176.121094 C 699.824219 1186.632812 695.921875 1197.433594 694.738281 1207.558594 C 693.503906 1218.375 695.347656 1228.417969 701.085938 1236.699219 C 708.519531 1247.433594 722.175781 1254.761719 743.75 1256.234375 C 810.464844 1260.796875 899.523438 1194.117188 943.382812 1157.15625 C 960.628906 1158.085938 977.910156 1158.246094 995.15625 1157.621094 C 1014.125 1156.917969 1033.054688 1155.246094 1051.890625 1152.578125 C 1095.21875 1146.4375 1152.65625 1121.753906 1187.714844 1095.996094"/> | ||
| 7 | </svg> | ||
theme/static/styles.css +11 −596
| @@ -1,597 +1,12 @@ | |||
| 1 | @import url('tokens.css'); | 1 | body { max-width: 800px; margin: 0 auto; } |
| 2 | 2 | nav ul { list-style: none; padding: 0; display: flex; flex-direction: row; } | |
| 3 | /* ============================================================ | 3 | nav ul li { padding-right: 0.5rem;} |
| 4 | HOMEPAGE INTRO | 4 | img { max-width: 100%; } |
| 5 | ============================================================ */ | 5 | .post-list-item { display: flexbox; list-style: none; } |
| 6 | .homepage-intro { | 6 | .post-list-item time { padding-right: 0.5rem; } |
| 7 | max-width: var(--prose-w); | 7 | .post-list-year { list-style: none; margin-top: 1rem; margin-bottom: 0.5rem; font-weight: bold; } |
| 8 | margin: 3rem 0; | 8 | .skip-link { display: none; } |
| 9 | margin-top: 1rem; | 9 | footer { margin: 2rem 0;} |
| 10 | font-family: var(--font-serif); | 10 | pre, blockquote { margin: 1rem 0; padding: 0.5rem; background-color: lightgrey; } |
| 11 | font-size: var(--text-body); | ||
| 12 | line-height: var(--lh-body); | ||
| 13 | } | ||
| 14 | .homepage-intro p { margin-bottom: 1.1rem; } | ||
| 15 | .homepage-intro p:first-child { | ||
| 16 | font-size: 0.9rem; | ||
| 17 | text-transform: uppercase; | ||
| 18 | letter-spacing: 0.1em; | ||
| 19 | font-family: var(--font-sans); | ||
| 20 | color: var(--meta); | ||
| 21 | margin-bottom: 0.5rem; | ||
| 22 | } | ||
| 23 | .homepage-intro p:nth-child(2) { | ||
| 24 | font-size: 1.3rem; | ||
| 25 | font-weight: 700; | ||
| 26 | letter-spacing: -0.01em; | ||
| 27 | color: var(--fg); | ||
| 28 | margin-bottom: 1.5rem; | ||
| 29 | } | ||
| 30 | |||
| 31 | /* ============================================================ | ||
| 32 | RESET & BASE | ||
| 33 | ============================================================ */ | ||
| 34 | *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } | ||
| 35 | |||
| 36 | body { | ||
| 37 | background: var(--bg); | ||
| 38 | color: var(--fg); | ||
| 39 | font-family: var(--font-sans); | ||
| 40 | font-size: var(--text-body); | ||
| 41 | line-height: var(--lh-body); | ||
| 42 | -webkit-font-smoothing: antialiased; | ||
| 43 | text-rendering: optimizeLegibility; | ||
| 44 | } | ||
| 45 | |||
| 46 | /* Full-bleed header — border and nav span 100vw */ | ||
| 47 | header { | ||
| 48 | width: 100%; | ||
| 49 | } | ||
| 50 | |||
| 51 | /* Centered content column */ | ||
| 52 | main, | ||
| 53 | footer, | ||
| 54 | header { | ||
| 55 | max-width: var(--outer-w); | ||
| 56 | margin: 0 auto; | ||
| 57 | padding-left: var(--pad); | ||
| 58 | padding-right: var(--pad); | ||
| 59 | } | ||
| 60 | footer { padding-bottom: 3rem; } | ||
| 61 | |||
| 62 | /* Prose constraint — applied to article/page body text only */ | ||
| 63 | .prose { | ||
| 64 | max-width: var(--prose-w); | ||
| 65 | } | ||
| 66 | |||
| 67 | /* ============================================================ | ||
| 68 | MASTHEAD | ||
| 69 | ============================================================ */ | ||
| 70 | .masthead { | ||
| 71 | border-top: 2px solid var(--fg); | ||
| 72 | padding-top: 1.5rem; | ||
| 73 | padding-bottom: 0; | ||
| 74 | padding-left: var(--pad); | ||
| 75 | padding-right: var(--pad); | ||
| 76 | } | ||
| 77 | |||
| 78 | .masthead-title { | ||
| 79 | display: block; | ||
| 80 | font-family: var(--font-serif); | ||
| 81 | font-size: var(--text-display); | ||
| 82 | font-weight: 700; | ||
| 83 | line-height: var(--lh-display); | ||
| 84 | letter-spacing: -0.03em; | ||
| 85 | text-decoration: none; | ||
| 86 | color: var(--fg); | ||
| 87 | margin-bottom: 1.25rem; | ||
| 88 | } | ||
| 89 | .masthead-title:hover { color: var(--accent); background: none; } | ||
| 90 | |||
| 91 | .masthead-subtitle { | ||
| 92 | font-family: var(--font-sans); | ||
| 93 | font-size: var(--text-xs); | ||
| 94 | letter-spacing: 0.12em; | ||
| 95 | color: var(--meta); | ||
| 96 | text-transform: lowercase; | ||
| 97 | margin-bottom: 1rem; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* ============================================================ | ||
| 101 | NAV STRIP — full outer width, equal cells | ||
| 102 | ============================================================ */ | ||
| 103 | .masthead nav ul { | ||
| 104 | list-style: none; | ||
| 105 | display: flex; | ||
| 106 | } | ||
| 107 | .masthead nav li { flex: 1; } | ||
| 108 | .masthead nav a { | ||
| 109 | display: block; | ||
| 110 | text-align: center; | ||
| 111 | padding: 0.55rem 0; | ||
| 112 | font-size: var(--text-xs); | ||
| 113 | font-weight: 700; | ||
| 114 | text-transform: uppercase; | ||
| 115 | letter-spacing: 0.16em; | ||
| 116 | text-decoration: none; | ||
| 117 | color: var(--meta); | ||
| 118 | border: 1px solid var(--border-soft); | ||
| 119 | transition: color 0.1s, background 0.1s; | ||
| 120 | } | ||
| 121 | .masthead nav a:hover { color: var(--bg); background: var(--fg); } | ||
| 122 | |||
| 123 | /* ============================================================ | ||
| 124 | MAIN CONTENT AREA | ||
| 125 | ============================================================ */ | ||
| 126 | main { padding-top: 2rem; } | ||
| 127 | |||
| 128 | /* ============================================================ | ||
| 129 | KOI HR | ||
| 130 | ============================================================ */ | ||
| 131 | hr { | ||
| 132 | border: none; | ||
| 133 | height: 2.5rem; | ||
| 134 | position: relative; | ||
| 135 | display: flex; | ||
| 136 | align-items: center; | ||
| 137 | justify-content: center; | ||
| 138 | background-image: url('koi-hr.svg'); | ||
| 139 | background-repeat: no-repeat; | ||
| 140 | background-position: center; | ||
| 141 | background-size: auto 100%; | ||
| 142 | margin: 3rem 0; | ||
| 143 | } | ||
| 144 | hr::before, hr::after { | ||
| 145 | content: ''; | ||
| 146 | position: absolute; | ||
| 147 | top: 50%; | ||
| 148 | transform: translateY(-50%); | ||
| 149 | width: calc(50% - 2rem); | ||
| 150 | height: 1px; | ||
| 151 | background: var(--border-soft); | ||
| 152 | } | ||
| 153 | hr::before { left: 0; } | ||
| 154 | hr::after { right: 0; } | ||
| 155 | |||
| 156 | /* ============================================================ | ||
| 157 | FOOTER | ||
| 158 | ============================================================ */ | ||
| 159 | footer { | ||
| 160 | font-size: var(--text-xs); | ||
| 161 | text-transform: uppercase; | ||
| 162 | letter-spacing: 0.14em; | ||
| 163 | color: var(--meta); | ||
| 164 | display: flex; | ||
| 165 | flex-direction: column; | ||
| 166 | gap: 0.4rem; | ||
| 167 | } | ||
| 168 | footer a { color: var(--meta); text-decoration: none; transition: color 0.1s; } | ||
| 169 | footer a:hover { color: var(--fg); background: none; } | ||
| 170 | |||
| 171 | /* ============================================================ | ||
| 172 | TYPOGRAPHY | ||
| 173 | ============================================================ */ | ||
| 174 | h1, h2, h3, h4 { | ||
| 175 | font-family: var(--font-serif); | ||
| 176 | font-weight: 700; | ||
| 177 | letter-spacing: -0.02em; | ||
| 178 | line-height: 1.1; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* Page-level h1 (blog list, garden, guides) */ | ||
| 182 | h1 { | ||
| 183 | font-size: var(--text-h1); | ||
| 184 | margin-bottom: 0.5rem; | ||
| 185 | } | ||
| 186 | |||
| 187 | /* Article display title — larger, tighter */ | ||
| 188 | .article-title { | ||
| 189 | font-family: var(--font-serif); | ||
| 190 | font-size: clamp(2.4rem, 5vw, 3.6rem); | ||
| 191 | font-weight: 700; | ||
| 192 | line-height: 1.05; | ||
| 193 | letter-spacing: -0.03em; | ||
| 194 | margin: 0.4rem 0 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | h2 { | ||
| 198 | font-size: var(--text-h2); | ||
| 199 | border-left: 1px solid var(--accent); | ||
| 200 | padding-left: 0.75rem; | ||
| 201 | margin-top: 2.5rem; | ||
| 202 | margin-bottom: 0.4rem; | ||
| 203 | } | ||
| 204 | h3 { font-size: 1.05rem; margin-top: 2rem; margin-bottom: 0.3rem; } | ||
| 205 | |||
| 206 | p { margin-bottom: 1.2rem; } | ||
| 207 | |||
| 208 | /* Accent ONLY on links and h2 bar — nowhere else */ | ||
| 209 | a { | ||
| 210 | color: var(--accent); | ||
| 211 | text-decoration: underline; | ||
| 212 | text-underline-offset: 3px; | ||
| 213 | transition: background 0.1s, color 0.1s; | ||
| 214 | } | ||
| 215 | a:hover { background: var(--accent); color: var(--bg); text-decoration: none; } | ||
| 216 | |||
| 217 | /* ============================================================ | ||
| 218 | SECTION LABEL — uppercase eyebrow text | ||
| 219 | ============================================================ */ | ||
| 220 | .label { | ||
| 221 | display: block; | ||
| 222 | font-size: var(--text-xs); | ||
| 223 | font-weight: 700; | ||
| 224 | text-transform: uppercase; | ||
| 225 | letter-spacing: 0.16em; | ||
| 226 | color: var(--meta); | ||
| 227 | border-bottom: 1px solid var(--fg); | ||
| 228 | padding-bottom: 0.5rem; | ||
| 229 | margin-bottom: 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* ============================================================ | ||
| 233 | INFO STRIP — homepage identity block | ||
| 234 | ============================================================ */ | ||
| 235 | |||
| 236 | |||
| 237 | /* ============================================================ | ||
| 238 | POST LIST — numbered, full outer width | ||
| 239 | ============================================================ */ | ||
| 240 | .post-list { | ||
| 241 | list-style: none; | ||
| 242 | counter-reset: posts; | ||
| 243 | } | ||
| 244 | .post-list-item { | ||
| 245 | counter-increment: posts; | ||
| 246 | display: grid; | ||
| 247 | grid-template-columns: 2.5rem 1fr 7rem; | ||
| 248 | align-items: baseline; | ||
| 249 | gap: 0 1rem; | ||
| 250 | padding: 0.75rem 0; | ||
| 251 | border-bottom: 1px solid var(--border-soft); | ||
| 252 | } | ||
| 253 | .post-list-item:first-child { border-top: 1px solid var(--border-soft); } | ||
| 254 | .post-list-item::before { | ||
| 255 | content: counter(posts, decimal-leading-zero); | ||
| 256 | font-family: var(--font-mono); | ||
| 257 | font-size: var(--text-xs); | ||
| 258 | color: var(--meta); | ||
| 259 | letter-spacing: 0.04em; | ||
| 260 | grid-column: 1; | ||
| 261 | } | ||
| 262 | .post-list-item a { | ||
| 263 | font-size: var(--text-sm); | ||
| 264 | justify-self: start; | ||
| 265 | } | ||
| 266 | .post-list-item time { | ||
| 267 | font-size: var(--text-xs); | ||
| 268 | font-family: var(--font-mono); | ||
| 269 | color: var(--meta); | ||
| 270 | text-align: right; | ||
| 271 | white-space: nowrap; | ||
| 272 | letter-spacing: 0.04em; | ||
| 273 | } | ||
| 274 | |||
| 275 | /* Year separator — full-width label, resets counter display */ | ||
| 276 | .post-list-year { | ||
| 277 | display: block; | ||
| 278 | font-family: var(--font-sans); | ||
| 279 | font-size: var(--text-xs); | ||
| 280 | font-weight: 700; | ||
| 281 | text-transform: uppercase; | ||
| 282 | letter-spacing: 0.14em; | ||
| 283 | color: var(--meta); | ||
| 284 | padding: 1.5rem 0 0.4rem; | ||
| 285 | counter-increment: none; | ||
| 286 | } | ||
| 287 | |||
| 288 | .all-posts-link { | ||
| 289 | display: inline-block; | ||
| 290 | margin-top: 1.5rem; | ||
| 291 | font-size: var(--text-xs); | ||
| 292 | font-weight: 700; | ||
| 293 | text-transform: uppercase; | ||
| 294 | letter-spacing: 0.12em; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* ============================================================ | ||
| 298 | ARTICLE — post page | ||
| 299 | ============================================================ */ | ||
| 300 | .article-dateline { | ||
| 301 | font-family: var(--font-mono); | ||
| 302 | font-size: var(--text-xs); | ||
| 303 | text-transform: uppercase; | ||
| 304 | letter-spacing: 0.14em; | ||
| 305 | color: var(--meta); | ||
| 306 | margin-bottom: 0.35rem; | ||
| 307 | } | ||
| 308 | |||
| 309 | .article-standfirst { | ||
| 310 | font-family: var(--font-serif); | ||
| 311 | font-size: 1.15rem; | ||
| 312 | line-height: 1.55; | ||
| 313 | color: var(--fg-soft); | ||
| 314 | padding: 1.25rem 0; | ||
| 315 | border-top: 1px solid var(--border-soft); | ||
| 316 | border-bottom: 1px solid var(--fg); | ||
| 317 | margin-top: 1rem; | ||
| 318 | max-width: var(--prose-w); | ||
| 319 | } | ||
| 320 | |||
| 321 | .article-body { | ||
| 322 | font-family: var(--font-serif); | ||
| 323 | font-size: var(--text-body); | ||
| 324 | line-height: var(--lh-body); | ||
| 325 | max-width: var(--prose-w); | ||
| 326 | margin-top: 2.5rem; | ||
| 327 | } | ||
| 328 | .article-body p { margin-bottom: 1.3rem; } | ||
| 329 | |||
| 330 | .reply-link { | ||
| 331 | max-width: var(--prose-w); | ||
| 332 | margin-top: 4rem; | ||
| 333 | padding-top: 1.5rem; | ||
| 334 | border-top: 1px solid var(--border-soft); | ||
| 335 | font-size: var(--text-xs); | ||
| 336 | font-family: var(--font-sans); | ||
| 337 | text-transform: uppercase; | ||
| 338 | letter-spacing: 0.12em; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* ============================================================ | ||
| 342 | GENERIC PAGE (about, uses, etc.) | ||
| 343 | ============================================================ */ | ||
| 344 | .page-body { | ||
| 345 | font-family: var(--font-serif); | ||
| 346 | font-size: var(--text-body); | ||
| 347 | line-height: var(--lh-body); | ||
| 348 | max-width: var(--prose-w); | ||
| 349 | margin-top: 2rem; | ||
| 350 | } | ||
| 351 | .page-body p { margin-bottom: 1.3rem; } | ||
| 352 | |||
| 353 | /* ============================================================ | ||
| 354 | BLOG ARCHIVE | ||
| 355 | ============================================================ */ | ||
| 356 | .blog-meta { | ||
| 357 | font-size: var(--text-sm); | ||
| 358 | color: var(--meta); | ||
| 359 | margin: 0.75rem 0 2rem; | ||
| 360 | } | ||
| 361 | .blog-meta code { | ||
| 362 | font-size: var(--text-xs); | ||
| 363 | background: var(--code-bg); | ||
| 364 | padding: 0.1rem 0.35rem; | ||
| 365 | font-family: var(--font-mono); | ||
| 366 | } | ||
| 367 | |||
| 368 | /* Year separators in post list */ | ||
| 369 | .post-list-year { | ||
| 370 | font-family: var(--font-serif); | ||
| 371 | font-size: var(--text-xs); | ||
| 372 | font-weight: 700; | ||
| 373 | text-transform: uppercase; | ||
| 374 | letter-spacing: 0.14em; | ||
| 375 | color: var(--meta); | ||
| 376 | padding: 1.25rem 0 0.5rem; | ||
| 377 | list-style: none; | ||
| 378 | grid-column: 1 / -1; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* Restore list styling inside content areas */ | ||
| 382 | .article-body ul, | ||
| 383 | .article-body ol, | ||
| 384 | .page-body ul, | ||
| 385 | .page-body ol { | ||
| 386 | padding-left: 1.5rem; | ||
| 387 | margin-bottom: 1.2rem; | ||
| 388 | } | ||
| 389 | .article-body li, | ||
| 390 | .page-body li { | ||
| 391 | margin-bottom: 0.3rem; | ||
| 392 | } | ||
| 393 | .article-body ul ul, | ||
| 394 | .article-body ol ol, | ||
| 395 | .page-body ul ul, | ||
| 396 | .page-body ol ol { | ||
| 397 | margin-bottom: 0; | ||
| 398 | } | ||
| 399 | |||
| 400 | /* ============================================================ | ||
| 401 | GARDEN | ||
| 402 | ============================================================ */ | ||
| 403 | .garden-index { list-style: none; } | ||
| 404 | .garden-index li { | ||
| 405 | display: flex; | ||
| 406 | flex-direction: column; | ||
| 407 | gap: 0.15rem; | ||
| 408 | padding: 0.8rem 0; | ||
| 409 | border-bottom: 1px solid var(--border-soft); | ||
| 410 | } | ||
| 411 | .garden-index li:first-child { border-top: 1px solid var(--border-soft); } | ||
| 412 | .garden-index a { font-size: var(--text-sm); } | ||
| 413 | .garden-desc { font-size: var(--text-xs); color: var(--meta); } | ||
| 414 | |||
| 415 | /* ============================================================ | ||
| 416 | APP CARDS | ||
| 417 | ============================================================ */ | ||
| 418 | .app-card { | ||
| 419 | display: flex; | ||
| 420 | gap: 1.25rem; | ||
| 421 | align-items: flex-start; | ||
| 422 | padding: 1.25rem 0; | ||
| 423 | border-bottom: 1px solid var(--border-soft); | ||
| 424 | } | ||
| 425 | .app-card:first-of-type { border-top: 1px solid var(--border-soft); } | ||
| 426 | .app-icon { width: 52px; height: 52px; border-radius: 12px; flex-shrink: 0; filter: none !important; margin: 0; display: block; } | ||
| 427 | .app-card a:has(.app-icon):hover { background: none; } | ||
| 428 | .app-info { display: flex; flex-direction: column; gap: 0.2rem; } | ||
| 429 | .app-title { font-family: var(--font-sans); font-weight: 700; font-size: var(--text-sm); } | ||
| 430 | .app-subtitle { font-size: var(--text-xs); color: var(--meta); } | ||
| 431 | .app-links { font-size: var(--text-xs); margin-top: 0.3rem; } | ||
| 432 | |||
| 433 | /* ============================================================ | ||
| 434 | CODE & PRE | ||
| 435 | ============================================================ */ | ||
| 436 | pre { | ||
| 437 | padding: 1.25rem; | ||
| 438 | border-left: 1px solid var(--border-soft); | ||
| 439 | background: var(--code-bg); | ||
| 440 | overflow-x: auto; | ||
| 441 | font-size: var(--text-sm); | ||
| 442 | margin: 1.75rem 0; | ||
| 443 | line-height: 1.6; | ||
| 444 | } | ||
| 445 | code { | ||
| 446 | font-family: var(--font-mono); | ||
| 447 | background: var(--code-bg); | ||
| 448 | padding: 0.15rem 0.4rem; | ||
| 449 | font-size: 0.875em; | ||
| 450 | } | ||
| 451 | pre code { background: none; padding: 0; font-size: inherit; } | ||
| 452 | |||
| 453 | /* ============================================================ | ||
| 454 | BLOCKQUOTE — intentional Org-mode delimiters | ||
| 455 | ============================================================ */ | ||
| 456 | blockquote { | ||
| 457 | font-style: italic; | ||
| 458 | margin: 1.75rem 0; | ||
| 459 | padding: 0.75rem 1rem; | ||
| 460 | border-left: 1px solid var(--border-soft); | ||
| 461 | background: var(--code-bg); | ||
| 462 | } | ||
| 463 | blockquote p:last-child { margin-bottom: 0; } | ||
| 464 | blockquote p { margin: 0; } | 11 | blockquote p { margin: 0; } |
| 465 | blockquote::before { | 12 | code { color: darkred; }\ No newline at end of file |
| 466 | content: "#+begin_quote"; | ||
| 467 | display: block; | ||
| 468 | color: var(--meta); | ||
| 469 | font-style: normal; | ||
| 470 | font-size: var(--text-xs); | ||
| 471 | font-family: var(--font-mono); | ||
| 472 | letter-spacing: 0.04em; | ||
| 473 | margin-bottom: 0.5rem; | ||
| 474 | } | ||
| 475 | blockquote::after { | ||
| 476 | content: "#+end_quote"; | ||
| 477 | display: block; | ||
| 478 | color: var(--meta); | ||
| 479 | font-style: normal; | ||
| 480 | font-size: var(--text-xs); | ||
| 481 | font-family: var(--font-mono); | ||
| 482 | letter-spacing: 0.04em; | ||
| 483 | margin-top: 0.5rem; | ||
| 484 | } | ||
| 485 | |||
| 486 | /* ============================================================ | ||
| 487 | TABLES | ||
| 488 | ============================================================ */ | ||
| 489 | table { | ||
| 490 | display: block; | ||
| 491 | width: 100%; | ||
| 492 | max-width: 100%; | ||
| 493 | overflow-x: auto; | ||
| 494 | border: none; | ||
| 495 | border-collapse: collapse; | ||
| 496 | margin: 2rem 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | table td, table th { | ||
| 500 | white-space: nowrap; | ||
| 501 | padding: 0.5rem 1rem; | ||
| 502 | } | ||
| 503 | th, td { | ||
| 504 | border-bottom: 1px solid var(--border-soft); | ||
| 505 | padding: 0.65rem 0.75rem; | ||
| 506 | text-align: left; | ||
| 507 | font-size: var(--text-sm); | ||
| 508 | } | ||
| 509 | th { | ||
| 510 | border-bottom: 1px solid var(--fg); | ||
| 511 | font-size: var(--text-xs); | ||
| 512 | text-transform: uppercase; | ||
| 513 | letter-spacing: 0.1em; | ||
| 514 | font-weight: 700; | ||
| 515 | } | ||
| 516 | tr:last-child td { border-bottom: none; } | ||
| 517 | |||
| 518 | /* ============================================================ | ||
| 519 | IMAGES | ||
| 520 | ============================================================ */ | ||
| 521 | img { | ||
| 522 | max-width: 100%; | ||
| 523 | height: auto; | ||
| 524 | filter: grayscale(1); | ||
| 525 | transition: filter 0.25s; | ||
| 526 | display: block; | ||
| 527 | margin: 2rem 0; | ||
| 528 | } | ||
| 529 | img:hover { filter: grayscale(0); } | ||
| 530 | |||
| 531 | /* ============================================================ | ||
| 532 | FOOTNOTES | ||
| 533 | ============================================================ */ | ||
| 534 | .footdef { display: flex; align-items: flex-start; gap: 1rem; margin-bottom: 0.5rem; } | ||
| 535 | .footpara { margin: 0; flex: 1; font-size: var(--text-sm); } | ||
| 536 | .footnum { | ||
| 537 | font-weight: 700; | ||
| 538 | min-width: 1.5rem; | ||
| 539 | text-align: right; | ||
| 540 | text-decoration: none; | ||
| 541 | font-size: var(--text-xs); | ||
| 542 | color: var(--meta); | ||
| 543 | font-family: var(--font-mono); | ||
| 544 | } | ||
| 545 | |||
| 546 | /* ============================================================ | ||
| 547 | SKIP LINK | ||
| 548 | ============================================================ */ | ||
| 549 | .skip-link { | ||
| 550 | position: absolute; | ||
| 551 | top: -100px; | ||
| 552 | left: 50%; | ||
| 553 | transform: translateX(-50%); | ||
| 554 | background: var(--fg); | ||
| 555 | color: var(--bg); | ||
| 556 | padding: 0.75rem 1.5rem; | ||
| 557 | z-index: 999; | ||
| 558 | font-weight: 700; | ||
| 559 | font-size: var(--text-xs); | ||
| 560 | text-transform: uppercase; | ||
| 561 | letter-spacing: 0.12em; | ||
| 562 | text-decoration: none; | ||
| 563 | transition: top 0.2s; | ||
| 564 | } | ||
| 565 | .skip-link:focus { top: 0; outline: none; } | ||
| 566 | #main-content:focus { outline: none; } | ||
| 567 | |||
| 568 | /* ============================================================ | ||
| 569 | RESPONSIVE | ||
| 570 | ============================================================ */ | ||
| 571 | @media (max-width: 700px) { | ||
| 572 | .masthead-title { font-size: clamp(3rem, 14vw, 5rem); } | ||
| 573 | .masthead nav ul { flex-wrap: wrap; } | ||
| 574 | .masthead nav li { flex: none; width: 50%; } | ||
| 575 | .masthead nav a { border-bottom: 1px solid var(--border-soft); } | ||
| 576 | .post-list-item { grid-template-columns: 2.25rem 1fr; } | ||
| 577 | .post-list-item time { display: none; } | ||
| 578 | .article-title { font-size: clamp(2rem, 9vw, 2.8rem); } | ||
| 579 | } | ||
| 580 | |||
| 581 | @media (max-width: 480px) { | ||
| 582 | .masthead nav li { width: 33.333%; } | ||
| 583 | } | ||
| 584 | |||
| 585 | /* Tags page */ | ||
| 586 | .tag-toc { | ||
| 587 | display: flex; | ||
| 588 | flex-wrap: wrap; | ||
| 589 | gap: 0.5rem 1.5rem; | ||
| 590 | list-style: none; | ||
| 591 | padding: 0; | ||
| 592 | margin: 0 0 3rem; | ||
| 593 | } | ||
| 594 | .tag-count { | ||
| 595 | color: var(--meta); | ||
| 596 | font-size: var(--text-xs); | ||
| 597 | } | ||
theme/static/tokens.css deleted −51
| @@ -1,51 +0,0 @@ | |||
| 1 | /* ============================================================================= | ||
| 2 | BRAND TOKENS — cleberg.net | ||
| 3 | ============================================================================= */ | ||
| 4 | :root { | ||
| 5 | color-scheme: light dark; | ||
| 6 | |||
| 7 | /* Light */ | ||
| 8 | --bg: #ffffff; | ||
| 9 | --bg-soft: #f5f5f5; | ||
| 10 | --fg: #0a0a0a; | ||
| 11 | --fg-soft: #444444; | ||
| 12 | --accent: #c0392b; | ||
| 13 | --border: #0a0a0a; | ||
| 14 | --border-soft: #dedede; | ||
| 15 | --code-bg: #f3f3f3; | ||
| 16 | --meta: #999999; | ||
| 17 | |||
| 18 | /* Fonts */ | ||
| 19 | --font-serif: Georgia, 'Times New Roman', serif; | ||
| 20 | --font-sans: system-ui, -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif; | ||
| 21 | --font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospace; | ||
| 22 | |||
| 23 | /* Type scale */ | ||
| 24 | --text-display: clamp(4rem, 8vw, 6.5rem); | ||
| 25 | --text-h1: clamp(2.2rem, 4vw, 3rem); | ||
| 26 | --text-h2: 1.2rem; | ||
| 27 | --text-body: 1.0625rem; | ||
| 28 | --text-sm: 0.875rem; | ||
| 29 | --text-xs: 0.6875rem; /* 11px — label tier */ | ||
| 30 | --lh-display: 0.95; | ||
| 31 | --lh-body: 1.75; | ||
| 32 | |||
| 33 | /* Layout */ | ||
| 34 | --outer-w: 1000px; | ||
| 35 | --prose-w: 720px; | ||
| 36 | --pad: clamp(1.25rem, 4vw, 2.5rem); | ||
| 37 | } | ||
| 38 | |||
| 39 | @media (prefers-color-scheme: dark) { | ||
| 40 | :root { | ||
| 41 | --bg: #080808; | ||
| 42 | --bg-soft: #111111; | ||
| 43 | --fg: #eeebe6; | ||
| 44 | --fg-soft: #aaa8a3; | ||
| 45 | --accent: #e05a48; | ||
| 46 | --border: #eeebe6; | ||
| 47 | --border-soft: #1e1e1e; | ||
| 48 | --code-bg: #0d0d0d; | ||
| 49 | --meta: #555555; | ||
| 50 | } | ||
| 51 | } | ||
theme/templates/base.html +20 −29
| @@ -9,45 +9,36 @@ | |||
| 9 | {% if site_description is defined %}<meta name="description" content="{{ site_description }}">{% endif %} | 9 | {% if site_description is defined %}<meta name="description" content="{{ site_description }}">{% endif %} |
| 10 | {% if site_keywords is defined %}<meta name="keywords" content="{{ site_keywords }}">{% endif %} | 10 | {% if site_keywords is defined %}<meta name="keywords" content="{{ site_keywords }}">{% endif %} |
| 11 | <link rel="stylesheet" href="{{ url_for("static", file="styles.min.css") }}" type="text/css"> | 11 | <link rel="stylesheet" href="{{ url_for("static", file="styles.min.css") }}" type="text/css"> |
| 12 | <link rel="icon" href="{{ url_for("static", file="favicon.svg") }}" type="image/svg+xml"> | 12 | <link rel="icon" href="data:,"> |
| 13 | {% block meta %}{% endblock %} | 13 | {% block meta %}{% endblock %} |
| 14 | {% endblock %} | 14 | {% endblock %} |
| 15 | </head> | 15 | </head> |
| 16 | <body> | 16 | <body> |
| 17 | <a href="#main-content" class="skip-link">Skip to content</a> | 17 | <a href="#main-content" class="skip-link">Skip to content</a> |
| 18 | <header class="masthead"> | 18 | |
| 19 | <a href="/" class="masthead-title">seijaku</a> | 19 | <nav aria-label="Site Navigation"> |
| 20 | <p class="masthead-subtitle"><i>stillness amidst the chaos</i></p> | 20 | <ul> |
| 21 | <nav aria-label="Site Navigation"> | 21 | <li><a href="/">Home</a></li> |
| 22 | <ul> | 22 | <li><a href="/apps/">Apps</a></li> |
| 23 | <li><a href="/blog/">Blog</a></li> | 23 | <li><a href="/blog/">Blog</a></li> |
| 24 | <li><a href="/tags/">Tags</a></li> | 24 | <li><a href="/garden/">Garden</a></li> |
| 25 | <li><a href="/guides/index.html">Guides</a></li> | 25 | <li><a href="/guides/">Guides</a></li> |
| 26 | <li><a href="/apps/">Apps</a></li> | 26 | <li><a href="/salary/">Salary</a></li> |
| 27 | <li><a href="/garden/">Garden</a></li> | 27 | <li><a href="/tags/">Tags</a></li> |
| 28 | <li><a href="/salary/">Salary</a></li> | 28 | </ul> |
| 29 | </ul> | 29 | </nav> |
| 30 | </nav> | 30 | |
| 31 | </header> | ||
| 32 | <main id="main-content"> | 31 | <main id="main-content"> |
| 33 | {% block main %}{% endblock %} | 32 | {% block main %}{% endblock %} |
| 34 | </main> | 33 | </main> |
| 35 | <hr> | 34 | |
| 36 | <footer> | 35 | <footer> |
| 37 | <div> | 36 | <a href="https://github.com/ccleberg/cleberg.net">Source</a> · |
| 38 | <a href="https://github.com/ccleberg/cleberg.net">Source</a> · | 37 | <a href="/feed.xml">RSS</a> · |
| 39 | <a href="/feed.xml">RSS</a> · | 38 | <a href="http://paske4urhs6nttrtlkuwa5cowum3fjkc6yv6kl4ncx3mjxcd77764nqd.onion/">Onion</a> · |
| 40 | <a href="http://paske4urhs6nttrtlkuwa5cowum3fjkc6yv6kl4ncx3mjxcd77764nqd.onion/">Onion</a> · | 39 | <a href="/tips/">Tips</a> |
| 41 | <a href="/now/">Now</a> · | ||
| 42 | <a href="/uses/">Uses</a> · | ||
| 43 | <a href="/tips/">Tips</a> · | ||
| 44 | <a href="https://cv.cleberg.net">CV</a> | ||
| 45 | </div> | ||
| 46 | <div> | ||
| 47 | <a href="mailto:hello@cleberg.net">hello@cleberg.net</a> [<a href="/gpg.txt">PGP</a>] · | ||
| 48 | Signal: @cmc.01 | ||
| 49 | </div> | ||
| 50 | </footer> | 40 | </footer> |
| 41 | |||
| 51 | <section class="indieweb-links" style="display:none"> | 42 | <section class="indieweb-links" style="display:none"> |
| 52 | <link href="https://github.com/ccleberg" rel="me"> | 43 | <link href="https://github.com/ccleberg" rel="me"> |
| 53 | <link href="https://gitlab.com/ccleberg" rel="me"> | 44 | <link href="https://gitlab.com/ccleberg" rel="me"> |
theme/templates/blog.html +8 −8
| @@ -1,13 +1,13 @@ | |||
| 1 | {% extends "base.html" %} {% block subtitle %}blog - {% endblock %} {% block main %} | 1 | {% extends "base.html" %} {% block subtitle %}blog - {% endblock %} {% block main %} |
| 2 | <h1>Blog</h1> | 2 | <h1>Blog</h1> |
| 3 | <p class="blog-meta">Use <code>⌘ F</code> / <code>Ctrl F</code> to search · <a href="/feed.xml">RSS Feed</a></p> | 3 | <p>Use <code>⌘ F</code> / <code>Ctrl F</code> to search · <a href="/feed.xml">RSS Feed</a></p> |
| 4 | <p class="label">All Posts</p> | 4 | <p>All Posts</p> |
| 5 | <ul class="post-list"> | 5 | <ul class="post-list"> |
| 6 | {% for post in posts %} | 6 | {% for post in posts %} |
| 7 | <li class="post-list-item"> | 7 | <li class="post-list-item"> |
| 8 | <a href='{{ url_for("blog", slug=post.slug) }}'>{{ post.title }}</a> | 8 | <time datetime='{{ post.date | strftime("%Y-%m-%d") }}'>{{ post.date|strftime("%Y-%m-%d") }}</time> |
| 9 | <time datetime='{{ post.date | strftime("%Y-%m-%d") }}'>{{ post.date|strftime("%Y-%m-%d") }}</time> | 9 | <a href='{{ url_for("blog", slug=post.slug) }}'>{{ post.title }}</a> |
| 10 | </li> | 10 | </li> |
| 11 | {% endfor %} | 11 | {% endfor %} |
| 12 | </ul> | 12 | </ul> |
| 13 | {% endblock %} | 13 | {% endblock %} |
theme/templates/garden.html +9 −9
| @@ -14,14 +14,14 @@ around.</p> | |||
| 14 | <span><strong>🍂 Compost:</strong> Ideas you no longer agree with but want to | 14 | <span><strong>🍂 Compost:</strong> Ideas you no longer agree with but want to |
| 15 | keep for historical context.</span><br><br> | 15 | keep for historical context.</span><br><br> |
| 16 | </section> | 16 | </section> |
| 17 | <ul class="garden-index"> | 17 | <ul> |
| 18 | {% for post in posts %} | 18 | {% for post in posts %} |
| 19 | <li> | 19 | <li> |
| 20 | <a href='{{ url_for("garden", slug=post.slug) }}'>{{ post.title }}</a> | 20 | <a href='{{ url_for("garden", slug=post.slug) }}'>{{ post.title }}</a> |
| 21 | {% if post.description %} | 21 | {% if post.description %} |
| 22 | <span class="garden-desc">{{ post.description }}</span> | 22 | <span>{{ post.description }}</span> |
| 23 | {% endif %} | 23 | {% endif %} |
| 24 | </li> | 24 | </li> |
| 25 | {% endfor %} | 25 | {% endfor %} |
| 26 | </ul> | 26 | </ul> |
| 27 | {% endblock %} | 27 | {% endblock %} |
theme/templates/index.html +19 −19
| @@ -1,22 +1,22 @@ | |||
| 1 | {% extends "base.html" %} {% block main %} | 1 | {% extends "base.html" %} {% block main %} |
| 2 | <div class="homepage-intro"> | 2 | <section> |
| 3 | <p>My name is Christian.</p> | 3 | <p><b>Hi, I'm Christian.</b></p> |
| 4 | <p>I’m a technology auditor who doesn’t trust technology companies.</p> | 4 | <p>I'm a Technology Assurance Manager @ KPMG.</p> |
| 5 | <p>I run my own infrastructure. I audit everyone else's.</p> | 5 | <p>I use this site as a place to think out loud (see my <a href="/blog/">blog</a>, <a href="/garden/">garden</a>, or |
| 6 | <p>The infrastructure is the point. Self-hosted, self-managed, minimal | 6 | <a href="/guides/">guides</a>), a place to publish information (see |
| 7 | dependencies. This site is part of it: plaintext, no trackers, no | 7 | my <a href="https://cv.cleberg.net">CV</a> and <a href="/salary/">salary</a> |
| 8 | frameworks, no corporate CDN.</p> | 8 | pages), and a foundational URI to use for my projects (see |
| 9 | <p>The audit job funds it. KPMG. Technology Assurance. I spend 50-80 hours a | 9 | my <a href="/apps/">apps</a>).</p> |
| 10 | week inside the systems I refuse to use personally. The irony is the | 10 | <p>If you want to chat, you can find me in the following spaces:</p> |
| 11 | business model.</p> | 11 | <ul> |
| 12 | <p>GPG key, salary, and server stack are all public. That's the whole | 12 | <li>hello [at] cleberg.net (<a href="/gpg.txt">PGP Key</a>)</li> |
| 13 | introduction.</p> | 13 | <li>@cmc.01 on <a href="https://signal.org">Signal</a></li> |
| 14 | </div> | 14 | </ul> |
| 15 | <p>Curious about the technology behind this website? Check out my <a href="/uses/">/uses</a> page.</p> | ||
| 16 | <p>Curious about what I've been up to lately in my personal life? Check out my <a href="/now/">/now</a> page.</p> | ||
| 17 | </section> | ||
| 15 | 18 | ||
| 16 | <p class="section-label">Recent Posts</p> | 19 | <p>Recent Posts</p> |
| 17 | <ul class="post-list"> | 20 | <!-- BEGIN_POSTS --><!-- END_POSTS --> |
| 18 | <!-- BEGIN_POSTS --> | 21 | <p><a href="/blog/">All Posts →</a></p> |
| 19 | <!-- END_POSTS --> | ||
| 20 | </ul> | ||
| 21 | <a class="all-posts-link" href="/blog/">All Posts →</a> | ||
| 22 | {% endblock %} | 22 | {% endblock %} |
theme/templates/page.html +1 −1
| @@ -3,6 +3,6 @@ | |||
| 3 | {% block main %} | 3 | {% block main %} |
| 4 | <article> | 4 | <article> |
| 5 | <h1>{{ post.title }}</h1> | 5 | <h1>{{ post.title }}</h1> |
| 6 | <div class="page-body">{{ post.html | safe }}</div> | 6 | <div>{{ post.html | safe }}</div> |
| 7 | </article> | 7 | </article> |
| 8 | {% endblock %} | 8 | {% endblock %} |
theme/templates/post.html +5 −5
| @@ -10,12 +10,12 @@ | |||
| 10 | {% endblock %} | 10 | {% endblock %} |
| 11 | {% block main %} | 11 | {% block main %} |
| 12 | <article> | 12 | <article> |
| 13 | <p class="article-dateline"><time datetime='{{ post.date|strftime("%Y-%m-%d") }}'>{{ post.date|strftime("%Y-%m-%d") }}</time></p> | 13 | <p><time datetime='{{ post.date|strftime("%Y-%m-%d") }}'>{{ post.date|strftime("%Y-%m-%d") }}</time></p> |
| 14 | <h1 class="article-title">{{ post.title }}</h1> | 14 | <h1>{{ post.title }}</h1> |
| 15 | {% if post.description is defined %} | 15 | {% if post.description is defined %} |
| 16 | <p class="article-standfirst">{{ post.description }}</p> | 16 | <p>{{ post.description }}</p> |
| 17 | {% endif %} | 17 | {% endif %} |
| 18 | <div class="article-body">{{ post.html | safe }}</div> | 18 | <div>{{ post.html | safe }}</div> |
| 19 | <div class="reply-link"><a href="mailto:hello@cleberg.net">Reply via email →</a></div> | 19 | <div><a href="mailto:hello@cleberg.net">Reply via email →</a></div> |
| 20 | </article> | 20 | </article> |
| 21 | {% endblock %} | 21 | {% endblock %} |
utils/nginx-dev.conf deleted −17
| @@ -1,17 +0,0 @@ | |||
| 1 | server { | ||
| 2 | server_name cleberg.net www.cleberg.net; | ||
| 3 | |||
| 4 | root /usr/share/nginx/html; | ||
| 5 | index index.html; | ||
| 6 | autoindex on; | ||
| 7 | |||
| 8 | access_log /var/log/nginx/cleberg.net.access.log; | ||
| 9 | error_log /var/log/nginx/cleberg.net.error.log; | ||
| 10 | |||
| 11 | location / { | ||
| 12 | try_files $uri $uri/ =404; | ||
| 13 | } | ||
| 14 | |||
| 15 | listen [::]:80; | ||
| 16 | listen 80; | ||
| 17 | } | ||