Compare commits

..

46 Commits

Author SHA1 Message Date
Quartz Syncer
fe0581e423 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 27s
2026-02-05 12:24:25 -07:00
Quartz Syncer
125a9b1752 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 26s
2026-02-05 09:53:27 -07:00
Quartz Syncer
536652b5b6 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 22s
2026-01-21 22:48:48 -07:00
Quartz Syncer
a1b2e10668 Deleted multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 22s
2026-01-21 14:01:10 -07:00
Quartz Syncer
d5f0ffc320 Published multiple files
Some checks failed
Build and Deploy Quartz / build (push) Has been cancelled
2026-01-21 14:01:08 -07:00
Quartz Syncer
fcd2176c78 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 20s
2026-01-20 14:54:30 -07:00
Quartz Syncer
30dd2ec6c1 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 20s
2026-01-20 13:38:56 -07:00
Quartz Syncer
d60dc27dac Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 20s
2026-01-20 13:30:42 -07:00
Quartz Syncer
f0712ba561 Deleted multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 21s
2026-01-20 13:18:44 -07:00
Quartz Syncer
c41334f82c Deleted multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 18s
2026-01-19 18:40:24 -07:00
Quartz Syncer
f07306498f Published multiple files
Some checks failed
Build and Deploy Quartz / build (push) Has been cancelled
2026-01-19 18:40:22 -07:00
Quartz Syncer
b4c9d16c55 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 20s
2026-01-19 18:37:25 -07:00
Quartz Syncer
184c93e274 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 20s
2026-01-19 18:35:59 -07:00
Quartz Syncer
c48cc488f0 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 19s
2026-01-19 17:58:36 -07:00
Quartz Syncer
2888961e0b Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 20s
2026-01-19 17:56:44 -07:00
Quartz Syncer
abad0348a7 Deleted multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 19s
2026-01-19 17:55:55 -07:00
Quartz Syncer
c8dcdf904b Published multiple files
Some checks failed
Build and Deploy Quartz / build (push) Has been cancelled
2026-01-19 17:55:52 -07:00
Quartz Syncer
d7e0591641 Published multiple files
All checks were successful
Build and Deploy Quartz / build (push) Successful in 19s
2026-01-19 15:39:40 -07:00
Quartz Syncer
435f5bba6a Published multiple files
Some checks failed
Build and Deploy Quartz / build (push) Has been cancelled
2026-01-19 15:39:24 -07:00
b9d4649a2c fix: add coreutils for env -S support
All checks were successful
Build and Deploy Quartz / build (push) Successful in 19s
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 15:35:36 -07:00
e19f3597d7 chore: remove test workflow
Some checks failed
Build and Deploy Quartz / build (push) Failing after 12s
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 15:34:23 -07:00
f593b02e7e add workflow_dispatch trigger
Some checks failed
Build and Deploy Quartz / build (push) Failing after 26s
Test Push Trigger / test (push) Successful in 0s
2026-01-19 15:33:35 -07:00
b66d4e744f Update .gitea/workflows/deploy.yaml 2026-01-19 23:24:57 +01:00
78a4fec36b test: push trigger 2026-01-19 15:16:03 -07:00
d368c8926e added branch to workflow 2026-01-19 15:12:02 -07:00
bec3786e69 test: push trigger after actions toggle 2026-01-19 15:06:54 -07:00
b8aef1145c test: push trigger after actions toggle 2026-01-19 15:06:34 -07:00
e0fdbefcaa test: minimal workflow to debug push trigger 2026-01-19 15:02:17 -07:00
b0b3506ef4 test: trigger workflow on push 2026-01-19 14:54:25 -07:00
48a3dbfd6f fix: add workflow_dispatch trigger
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 14:45:35 -07:00
a5b8fdd90d fix: add rsync to workflow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 14:44:09 -07:00
Quartz Syncer
bd60a1ca15 Published multiple files 2026-01-19 14:39:10 -07:00
1eeec043e5 publish workflow 2026-01-19 14:34:36 -07:00
2e5198e290 Quartz sync: Jan 19, 2026, 2:33 PM 2026-01-19 14:34:35 -07:00
Quartz Syncer
0b70ce24df Published multiple files 2026-01-11 16:25:00 -07:00
Quartz Syncer
863583d9db Deleted multiple files 2026-01-11 16:20:23 -07:00
701ad945a4 Quartz sync: Jan 10, 2026, 5:14 PM
Some checks failed
Docker build & push image / build (push) Has been cancelled
Build and Test / build-and-test (macos-latest) (push) Has been cancelled
Build and Test / build-and-test (ubuntu-latest) (push) Has been cancelled
Build and Test / build-and-test (windows-latest) (push) Has been cancelled
Build and Test / publish-tag (push) Has been cancelled
2026-01-10 17:14:51 -07:00
Emile Bangma
f346a01296 feat(explorer): Add active class to current folder in explorer (#2196) 2026-01-08 09:54:41 +08:00
Rahmat Ardiansyah
c2dcc63b5f feat: add scroll padding for mobile screen (#2249) 2026-01-08 09:36:02 +08:00
derfalx
c2bea8a4c4 fix(citation): Language parameter for non en-US settings (#2075)
* Fix language parameter of the citation plugin for non en-US settings

Per default the rehype-citation project only supports en-US, as
explained here: https://github.com/timlrx/rehype-citation/issues/12
For other languages one can provide a locale-file either by passing
its path or providing an URL. The following repository contains locale
files for multiple languages. So, these are used, in case a non en-US
language is used in quarzt. But this optimistically assumes there is
indeed an according locale file.

In summary this solves the problem only partially, since there are
still some languages which will not work properly.

* Fixing code style by running prettier with --write

* Excluding `en-US` locales from the new behaviour.

* Removing unnecessary `null` und `undefined` check.

* Update quartz/plugins/transformers/citations.ts

* Update quartz/plugins/transformers/citations.ts

* Update quartz/plugins/transformers/citations.ts

---------

Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
2026-01-08 09:30:42 +08:00
Jacky Zhao
fa8d87a23a docs: link fixes and cleanup 2026-01-08 09:04:56 +08:00
dependabot[bot]
65c5b27041 chore(deps): bump the production-dependencies group with 3 updates (#2270)
Bumps the production-dependencies group with 3 updates: [pixi.js](https://github.com/pixijs/pixijs), [preact-render-to-string](https://github.com/preactjs/preact-render-to-string) and [ws](https://github.com/websockets/ws).


Updates `pixi.js` from 8.14.3 to 8.15.0
- [Release notes](https://github.com/pixijs/pixijs/releases)
- [Commits](https://github.com/pixijs/pixijs/compare/v8.14.3...v8.15.0)

Updates `preact-render-to-string` from 6.6.4 to 6.6.5
- [Release notes](https://github.com/preactjs/preact-render-to-string/releases)
- [Changelog](https://github.com/preactjs/preact-render-to-string/blob/main/CHANGELOG.md)
- [Commits](https://github.com/preactjs/preact-render-to-string/compare/v6.6.4...v6.6.5)

Updates `ws` from 8.18.3 to 8.19.0
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.18.3...8.19.0)

---
updated-dependencies:
- dependency-name: pixi.js
  dependency-version: 8.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: preact-render-to-string
  dependency-version: 6.6.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: ws
  dependency-version: 8.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-07 06:02:16 -05:00
Jon Erling Hustadnes
5208a96a37 fix(build.ts/startWatching): add option awaitWriteFinish with 250ms threshold (#2235)
This makes it so that the events are not fired until the file have stabilized.
This also changes the order of the fired events.
A move / rename now results in `delete` then `add` rather than the other way around.

From `chokidar` README - https://github.com/paulmillr/chokidar?tab=readme-ov-file#performance:
```
awaitWriteFinish.stabilityThreshold (default: 2000). Amount of time in milliseconds for a file size to remain constant before emitting its event.
```

Fixes #2232
2026-01-05 19:34:45 +08:00
dependabot[bot]
31ea7852fd chore(deps): bump preact in the production-dependencies group (#2266)
Bumps the production-dependencies group with 1 update: [preact](https://github.com/preactjs/preact).


Updates `preact` from 10.28.0 to 10.28.1
- [Release notes](https://github.com/preactjs/preact/releases)
- [Commits](https://github.com/preactjs/preact/compare/10.28.0...10.28.1)

---
updated-dependencies:
- dependency-name: preact
  dependency-version: 10.28.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-05 19:28:24 +08:00
Jacky Zhao
7dc826be0a fix(css): darkmode + readermode safari height 2026-01-03 23:39:56 +08:00
dependabot[bot]
11ab6da80c chore(deps): bump the ci-dependencies group with 3 updates (#2251)
Bumps the ci-dependencies group with 3 updates: [actions/cache](https://github.com/actions/cache), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `actions/cache` from 4 to 5
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

Updates `actions/upload-artifact` from 5 to 6
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

Updates `actions/download-artifact` from 6 to 7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci-dependencies
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci-dependencies
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-25 03:09:49 -05:00
80 changed files with 5303 additions and 40 deletions

View File

@@ -0,0 +1,14 @@
name: Build and Deploy Quartz
run-name: ${{ gitea.actor }} is building Quartz site
on: [push, workflow_dispatch]
jobs:
build:
runs-on: docker
steps:
- run: apk add --no-cache nodejs npm git rsync coreutils
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: npm ci
- run: npx quartz build
- run: rsync -avz --delete ./public/ /sites/pdg/

View File

@@ -21,7 +21,7 @@ jobs:
node-version: 22
- name: Cache dependencies
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
@@ -37,7 +37,7 @@ jobs:
run: npx quartz build -d docs -v
- name: Upload build artifact
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v6
with:
name: preview-build
path: public

View File

@@ -29,7 +29,7 @@ jobs:
node-version: 22
- name: Cache dependencies
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

View File

@@ -18,7 +18,7 @@ jobs:
name: Deploy Preview to Cloudflare Pages
steps:
- name: Download build artifact
uses: actions/download-artifact@v6
uses: actions/download-artifact@v7
id: preview-build-artifact
with:
name: preview-build

View File

@@ -3,7 +3,6 @@
> “[One] who works with the door open gets all kinds of interruptions, but [they] also occasionally gets clues as to what the world is and what might be important.” — Richard Hamming
Quartz is a set of tools that helps you publish your [digital garden](https://jzhao.xyz/posts/networked-thought) and notes as a website for free.
Quartz v4 features a from-the-ground rewrite focusing on end-user extensibility and ease-of-use.
🔗 Read the documentation and get started: https://quartz.jzhao.xyz/

View File

View File

@@ -0,0 +1,12 @@
---
publish: true
permalink: /about
title: Phil Skentelbery
created: 2026-01-29T14:04:18.712-07:00
modified: 2026-02-05T12:14:05.453-07:00
cssclasses: ""
---
TODO
SOOOOON

View File

@@ -0,0 +1,11 @@
---
publish: true
permalink: /musings/fear-and-loathing-in-ai-land
title: Fear and Loathing in AI Land
created: 2026-01-29T14:04:18.780-07:00
modified: 2026-02-05T12:14:05.457-07:00
cssclasses: ""
---
In my life time I do not recall a technology quite so ubiquitous yet reviled as AI. For the purpose of this note, AI is a placeholder for generative AI, your LLMs like ChatGPT, Claude, and Grok. These products have gone from niche tools to consumer products in a few short years and are

View File

@@ -0,0 +1,22 @@
---
publish: true
permalink: /musings/social-media-isnt-social
title: Social Media Isn't Social
created: 2026-01-29T14:04:18.833-07:00
modified: 2026-02-05T12:14:05.455-07:00
cssclasses: ""
---
I grew up without social media for the most part. I was 16 (?) when I first got my hands on a [MySpace](https://en.wikipedia.org/wiki/Myspace) account and it was something absolutely magical. You actually networked, socially, with friends. A Social Network if you will. You sent messages, shared music, ranked your friends in what was frankly a brutal contest. But the thing I remember most about MySpace is that it was truly social.
Then came Facebook, and it too was social, at least to start with. You connected with friends, they posted stuff to their wall, you saw what your friends posted in their feed, and so on. Early Facebook was actually kind of nice. There were a few other social networks that came and went, but then something fundamental changed.
The networks were not social any more. Content from your friends was rapidly superseded by content fed to you by The Algorithm. It wasn't an overnight change, but it was fast enough that it was noticeable. Gone were the things you had purposefully connected to, instead you were given the things you were "interested in".
Then came a realization for The Algorithm, things that you were "interested in" were not nearly as interesting as things that angered you. So more and more you were shown things that demanded your outrage. Comments, once reserved for telling your friend how cool they looked in skinny jeans, were now aimed solely at communicating how outraged you were at The Thing that The Algorithm had shoved in your face.
And this is why I abandoned social media for a long time. I lurked, I scraped around every now and again for something I wanted to see, but I did not engage like I once did. Gone were the days where i tinkered with the HTML to impress my MySpace buddies, now social media was a chore, something i had to occasionally check on so I was not out of the loop.
I missed social media, but it did not exist anymore. Outrage media did not interest me. Then I discovered the [Fediverse](https://en.wikipedia.org/wiki/Fediverse). It is far from perfect, it still has that undertone of enragement engagement from some users, but it is far closer to the social media I remember. I run my own [[20-29 HOBBYS/22 SELF HOSTING/22.12 SERVICES/GoToSocial]] server from where I engage with folk on my nerdy passions in a way that is somewhat reminiscent of how I used to display my passions in basic HTML. My feed is only content from folks I follow, I have the power to filter it as I see fit, and it is probably the closest I will ever get to the glory days of what I remember through some very heavily rose tinted glasses.
Just do not let anyone tell you that TikTok, Facebook, Twitter (X?), or whatever else is spawned from the corporate hellscape is Social Media. It's not social, it is something nefarious. You are not some kind of degenerate for yearning for social media either, connection is important, more so today than ever before. Just do not expect to get it from a platform that needs your undivided attention in order to survive.

View File

@@ -0,0 +1,19 @@
---
publish: true
permalink: /places/us-co-fairplay
title: US - CO - Fairplay
created: 2026-01-29T14:04:18.765-07:00
modified: 2026-02-05T12:15:21.732-07:00
tags:
- travel
- city
cssclasses: ""
---
## Useful Spots
**Fairplay Depot**
- Its a co-working place
- All done by phone (720) 771-4019
- [Website](https://fairplaydepot.us/en)

View File

@@ -0,0 +1,25 @@
---
publish: true
permalink: /places/us-nv-las-vegas
title: US - NV - Las Vegas
created: 2026-01-29T14:04:18.359-07:00
modified: 2026-02-05T12:15:21.734-07:00
tags:
- travel
- city
cssclasses: ""
---
## Vegas, but not Vegas
**Gäbi Coffee & Bakery**
- Cute little coffee shop and bakery.
- Great vibe
- Solid coffice
- [Website](https://www.gabicafe.com/)
**The Writers Block**
- Book store and coffee shop
- Not a coffice
- Artificial bird sanctuary
- [Website](www.thewritersblock.com)

View File

@@ -0,0 +1,17 @@
---
publish: true
permalink: /habits/mld
title: Minimum Lovable Day
created: 2026-01-29T14:04:18.832-07:00
modified: 2026-02-05T12:15:47.051-07:00
tags:
- productivity
cssclasses: ""
---
Define your Minimum Lovable Day
- Start with the one task that you can do today that will move the needle
- Add two stretch goals
Write this somewhere that will be visible all day

View File

@@ -0,0 +1,14 @@
---
publish: true
permalink: /habits/inbox-triage
title: Inbox Triage (AM)
created: 2026-01-29T14:04:18.363-07:00
modified: 2026-02-05T12:15:47.053-07:00
cssclasses: ""
---
Morning triage of my inbox (email and teams)
- If you can respond in 2 mins or less, do it
- If it needs to be [[Email Delegation \| delegated]] do it
- If it requires deep work tag it as such and move to a dedicated folder

View File

@@ -0,0 +1,80 @@
---
publish: true
permalink: /apps/veracrypt
title: VeraCrypt
created: 2026-01-29T14:04:18.863-07:00
modified: 2026-02-05T12:16:30.767-07:00
tags:
- encryption
- security
- backup
cssclasses: ""
---
VeraCrypt is free open-source disk encryption software. I use it predominantly for encrypting data on portable devices (see [[10-19 LIFE/13 TECH SETUP/13.12 PROCESSES/Backups]] for more details).
## Installation
**Arch Linux:**
```bash
sudo pacman -S veracrypt
```
**Other distributions:**
Download from https://veracrypt.io/en/Downloads.html
## Usage
### Create an encrypted volume
```bash
veracrypt -c
```
Follow the interactive prompts to:
1. Choose volume type (normal or hidden)
2. Select volume location (file or device)
3. Pick encryption algorithm (AES recommended)
4. Set volume size
5. Create password
### Mount a volume
```bash
# Mount to /mnt/veracrypt1 (default slot 1)
veracrypt /path/to/volume /mnt/veracrypt1
# Mount with specific slot
veracrypt --slot=2 /path/to/volume /mnt/veracrypt2
```
### Dismount
```bash
# Dismount specific volume
veracrypt -d /mnt/veracrypt1
# Dismount all
veracrypt -d
```
## Common Options
| Option | Description |
|--------|-------------|
| `-c` | Create new volume |
| `-d` | Dismount |
| `--slot=N` | Use slot N (1-64) |
| `-t` | Text mode (no GUI) |
| `--non-interactive` | For scripts |
| `-p PASSWORD` | Provide password (insecure, avoid) |
## Portable Drive Setup
For encrypted USB drives:
1. Create a file-hosted volume on the drive
2. Copy the portable VeraCrypt binary to the drive
3. Now usable on any machine without installation
## Tips
- Use keyfiles for additional security (combine with password)
- For full disk encryption on Linux, consider LUKS instead
- Hidden volumes provide plausible deniability
- Always safely eject before removing portable drives

View File

@@ -0,0 +1,105 @@
---
publish: true
permalink: /apps/aerc
title: aerc
created: 2026-01-30T08:09:11.034-07:00
modified: 2026-02-05T12:16:17.106-07:00
tags:
- email
- terminal
cssclasses: ""
---
aerc is a terminal email client with vim-like keybindings. It's lightweight, fast, and highly configurable. Works well with [[10-19 LIFE/13 TECH SETUP/13.11 APPS/isync]] for offline IMAP sync.
## Installation
**Arch Linux:**
```bash
sudo pacman -S aerc
```
**Dependencies for full functionality:**
```bash
# HTML rendering
sudo pacman -S w3m
# or: dante (for socksify), pandoc (markdown)
```
## Configuration
Config files live in `~/.config/aerc/`:
### accounts.conf
```ini
[Proton]
source = maildir://~/.local/share/mail/proton
outgoing = smtp+plain://127.0.0.1:1025
default = INBOX
from = Your Name <you@proton.me>
copy-to = Sent
```
### aerc.conf
```ini
[ui]
index-columns = date<20,name<25,flags>4,subject<*
timestamp-format = 2006-01-02 15:04
this-day-time-format = 15:04
this-year-time-format = Jan 02
[compose]
editor = nvim
reply-to-self = false
[filters]
text/plain = colorize
text/html = w3m -T text/html -cols $(tput cols) -dump -o display_image=false
```
### binds.conf
```ini
[messages]
q = :quit<Enter>
j = :next<Enter>
k = :prev<Enter>
Enter = :view<Enter>
c = :compose<Enter>
r = :reply<Enter>
R = :reply -a<Enter>
d = :move Trash<Enter>
```
## Usage
### Navigation
| Key | Action |
|-----|--------|
| `j/k` | Next/prev message |
| `J/K` | Next/prev folder |
| `Enter` | Open message |
| `q` | Back/quit |
| `/` | Search |
### Composing
| Key | Action |
|-----|--------|
| `c` | Compose new |
| `r` | Reply |
| `R` | Reply all |
| `f` | Forward |
| `Ctrl+x` | Send (in editor) |
### Actions
| Key | Action |
|-----|--------|
| `d` | Delete/move to trash |
| `m` | Move to folder |
| `C` | Copy to folder |
| `A` | Archive |
## Tips
- Run `:help` or `:help tutorial` for built-in documentation
- Use with [[10-19 LIFE/13 TECH SETUP/13.11 APPS/isync]] for offline access and faster sync
- Pipe messages through scripts with `:pipe`

View File

@@ -0,0 +1,113 @@
---
publish: true
permalink: /apps/atuin
title: atuin
created: 2026-01-30T08:29:14.283-07:00
modified: 2026-02-05T12:16:17.109-07:00
tags:
- shell
- history
- sync
cssclasses: ""
---
Atuin replaces your shell history with a SQLite database, providing better search, sync across machines, and detailed statistics. It's magical for finding that command you ran three weeks ago.
## Installation
**Quick install (recommended):**
```bash
curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh
```
**Arch Linux:**
```bash
sudo pacman -S atuin
```
## Shell Integration
Add to your shell config:
**Bash** (`~/.bashrc`):
```bash
eval "$(atuin init bash)"
```
**Zsh** (`~/.zshrc`):
```bash
eval "$(atuin init zsh)"
```
**Fish** (`~/.config/fish/config.fish`):
```fish
atuin init fish | source
```
## Usage
### Interactive search
Press `Ctrl+r` (or `Up` with config) to open the interactive search:
- Type to filter
- `Enter` to execute
- `Tab` to edit before running
- `Ctrl+r` to cycle through filter modes
### Filter modes
| Mode | Description |
|------|-------------|
| Global | All history across machines |
| Host | Current machine only |
| Session | Current shell session |
| Directory | Commands run in this directory |
### Commands
```bash
# Search from CLI
atuin search "docker"
# Show stats
atuin stats
# Manual sync
atuin sync
```
## Sync Setup (Optional)
Register for free sync:
```bash
atuin register -u <username> -e <email>
atuin login -u <username>
atuin sync
```
Or self-host the sync server.
## Configuration
`~/.config/atuin/config.toml`:
```toml
[settings]
# Use up arrow for atuin instead of ctrl+r
keymap_mode = "vim-normal"
# Search mode: prefix, fulltext, fuzzy
search_mode = "fuzzy"
# Filter by default
filter_mode = "host"
# Show preview of full command
show_preview = true
# Sync settings
auto_sync = true
sync_frequency = "5m"
```
## Tips
- Atuin stores history in `~/.local/share/atuin/history.db`
- Use `atuin history list` to export/inspect
- Prefix sensitive commands with a space to exclude from history

View File

@@ -0,0 +1,116 @@
---
publish: true
permalink: /apps/impala
title: impala
created: 2026-02-05T09:36:55.334-07:00
modified: 2026-02-05T12:16:17.110-07:00
tags:
- wifi
- network
- terminal
cssclasses: ""
---
impala is a TUI for managing WiFi on Linux using iwd as the backend. Much nicer than `iwctl` for day-to-day WiFi management.
## Installation
**Arch Linux:**
```bash
sudo pacman -S impala
```
**Cargo:**
```bash
cargo install impala
```
## Prerequisites
- **iwd** must be running (not wpa_supplicant)
- NetworkManager should use iwd backend (see [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Network]])
- Nerd Fonts (optional) for icons
## Usage
```bash
impala
```
### Key Bindings
| Key | Action |
|-----|--------|
| `j/k` | Navigate up/down |
| `Enter` | Connect to network |
| `d` | Disconnect |
| `r` | Refresh networks |
| `s` | Scan for networks |
| `a` | Toggle Access Point mode |
| `q` | Quit |
### Connecting to Networks
1. Launch `impala`
2. Navigate to network with `j/k`
3. Press `Enter` to connect
4. Enter password if prompted
### Hidden Networks
Press `/` to search/enter a hidden network SSID.
### WPA Enterprise (802.1X)
impala supports enterprise authentication. Select the network and follow prompts for username/password or certificate.
### QR Code Sharing
Press `Q` on a connected network to display a QR code for sharing credentials.
## Configuration
Config file: `~/.config/impala/config.toml`
```toml
[keybindings]
quit = "q"
scan = "s"
connect = "Enter"
disconnect = "d"
[appearance]
# Uses terminal colors by default
```
## Integration
### Ashell
In ashell config, use impala for WiFi management:
```toml
[settings]
wifi_more_cmd = 'kitty -e bash -c "impala"'
```
### Hyprland keybind
```bash
bind = $mainMod, W, exec, kitty -e impala
```
## Troubleshooting
### "iwd not running"
```bash
sudo systemctl enable --now iwd
```
### Conflicts with NetworkManager
NetworkManager must use iwd as backend, not wpa_supplicant. See [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Network#NetworkManager + iwd]].
## Resources
- GitHub: https://github.com/pythops/impala

View File

@@ -0,0 +1,118 @@
---
publish: true
permalink: /apps/isync
title: isync (mbsync)
created: 2026-01-30T08:09:43.461-07:00
modified: 2026-02-05T12:16:17.112-07:00
tags:
- email
- sync
- imap
cssclasses: ""
---
isync (command: `mbsync`) is a tool for synchronizing IMAP mailboxes with local Maildir folders. Essential for offline email access with clients like [[10-19 LIFE/13 TECH SETUP/13.11 APPS/aerc]] or mutt.
## Installation
**Arch Linux:**
```bash
sudo pacman -S isync
```
## ProtonMail Integration
ProtonMail requires the Proton Bridge app for IMAP access. See the [Arch Wiki guide](https://wiki.archlinux.org/title/Isync#Integration_with_ProtonMail) for details.
### Setup with Proton Bridge
1. Install and run Proton Bridge
2. Get credentials from Bridge (it generates local IMAP/SMTP credentials)
3. Configure mbsync as below
## Configuration
`~/.mbsyncrc`:
```ini
# Global settings
Create Both
Remove Both
Expunge Both
SyncState *
# ProtonMail via Proton Bridge
IMAPAccount proton
Host 127.0.0.1
Port 1143
User your-email@proton.me
PassCmd "cat ~/.config/proton-bridge/password"
SSLType STARTTLS
CertificateFile ~/.config/proton-bridge/cert.pem
IMAPStore proton-remote
Account proton
MaildirStore proton-local
Path ~/.local/share/mail/proton/
Inbox ~/.local/share/mail/proton/INBOX
SubFolders Verbatim
Channel proton
Far :proton-remote:
Near :proton-local:
Patterns *
```
## Usage
```bash
# Sync all configured channels
mbsync -a
# Sync specific channel
mbsync proton
# Verbose output
mbsync -V proton
# Dry run (show what would happen)
mbsync -n proton
```
## Automation
### systemd timer
`~/.config/systemd/user/mbsync.timer`:
```ini
[Unit]
Description=Sync mail periodically
[Timer]
OnBootSec=1m
OnUnitActiveSec=5m
[Install]
WantedBy=timers.target
```
`~/.config/systemd/user/mbsync.service`:
```ini
[Unit]
Description=Sync mail
[Service]
Type=oneshot
ExecStart=/usr/bin/mbsync -a
```
Enable:
```bash
systemctl --user enable --now mbsync.timer
```
## Tips
- Create the local maildir first: `mkdir -p ~/.local/share/mail/proton`
- Use `PassCmd` to avoid storing passwords in config
- The `Patterns *` line syncs all folders; use specific patterns to limit
- Check sync status with `mbsync -V` for verbose output

View File

@@ -0,0 +1,115 @@
---
publish: true
permalink: /apps/nvim
title: nvim (Neovim)
created: 2026-01-30T08:08:10.433-07:00
modified: 2026-02-05T12:16:17.114-07:00
tags:
- editor
- terminal
- development
cssclasses: ""
---
Neovim is a hyperextensible Vim-based text editor. I use [LazyVim](http://www.lazyvim.org/) as a pre-configured distribution for a batteries-included experience.
## Installation
**Arch Linux:**
```bash
sudo pacman -S neovim
```
**Dependencies for full LazyVim experience:**
```bash
sudo pacman -S git lazygit ripgrep fd nodejs npm
```
## LazyVim Setup
LazyVim provides sensible defaults, plugin management, and a curated set of plugins.
**Backup existing config:**
```bash
mv ~/.config/nvim ~/.config/nvim.bak
mv ~/.local/share/nvim ~/.local/share/nvim.bak
```
**Install LazyVim:**
```bash
git clone https://github.com/LazyVim/starter ~/.config/nvim
rm -rf ~/.config/nvim/.git
nvim
```
On first launch, LazyVim will install all plugins automatically.
## Key Bindings (LazyVim defaults)
### General
| Key | Action |
|-----|--------|
| `Space` | Leader key |
| `Space Space` | Find files |
| `Space /` | Live grep |
| `Space e` | File explorer |
| `Space gg` | LazyGit |
### Buffers
| Key | Action |
|-----|--------|
| `Space bd` | Delete buffer |
| `H` / `L` | Prev/next buffer |
| `Space bb` | Switch buffer |
### Windows
| Key | Action |
|-----|--------|
| `Ctrl+h/j/k/l` | Navigate windows |
| `Space w-` | Split horizontal |
| `Space w\|` | Split vertical |
### Code
| Key | Action |
|-----|--------|
| `gd` | Go to definition |
| `gr` | Find references |
| `K` | Hover documentation |
| `Space ca` | Code action |
| `Space cf` | Format |
## Configuration
LazyVim config lives in `~/.config/nvim/lua/`:
### Add plugins
`~/.config/nvim/lua/plugins/custom.lua`:
```lua
return {
-- Add plugins here
{ "tpope/vim-surround" },
-- Override existing plugin config
{
"nvim-treesitter/nvim-treesitter",
opts = {
ensure_installed = { "lua", "python", "typescript" },
},
},
}
```
### Options
`~/.config/nvim/lua/config/options.lua`:
```lua
vim.opt.relativenumber = true
vim.opt.wrap = true
vim.opt.tabstop = 4
```
## Resources
- LazyVim docs: http://www.lazyvim.org/
- Neovim docs: https://neovim.io/doc/
- `:Lazy` - Plugin manager UI
- `:Mason` - LSP/formatter installer

View File

@@ -0,0 +1,119 @@
---
publish: true
permalink: /apps/qutebrowser
title: qutebrowser
created: 2026-01-31T15:46:19.286-07:00
modified: 2026-02-05T12:16:30.762-07:00
tags:
- browser
- web
- keyboard
cssclasses: ""
---
qutebrowser is a keyboard-driven web browser with vim-like keybindings. Minimal UI, maximum efficiency.
## Installation
**Arch Linux:**
```bash
sudo pacman -S qutebrowser
```
## Configuration
Config file: `~/.config/qutebrowser/config.py`
```python
# Basic settings
c.content.javascript.enabled = True
c.content.autoplay = False
c.tabs.position = "top"
c.tabs.show = "multiple"
# Search engines
c.url.searchengines = {
'DEFAULT': 'https://duckduckgo.com/?q={}',
'g': 'https://google.com/search?q={}',
'w': 'https://en.wikipedia.org/wiki/{}',
'aw': 'https://wiki.archlinux.org/?search={}',
'gh': 'https://github.com/search?q={}',
'r': 'http://localhost:9873/{}', # urlref integration
}
# Dark mode
c.colors.webpage.darkmode.enabled = True
c.colors.webpage.preferred_color_scheme = "dark"
# Privacy
c.content.cookies.accept = "no-3rdparty"
c.content.headers.do_not_track = True
```
## Key Bindings
### Navigation
| Key | Action |
|-----|--------|
| `j/k` | Scroll down/up |
| `h/l` | Scroll left/right |
| `gg/G` | Top/bottom of page |
| `H/L` | Back/forward |
| `r` | Reload |
### Links & Hints
| Key | Action |
|-----|--------|
| `f` | Follow link (current tab) |
| `F` | Follow link (new tab) |
| `;i` | Hint images |
| `;y` | Yank link URL |
### Tabs
| Key | Action |
|-----|--------|
| `J/K` | Prev/next tab |
| `d` | Close tab |
| `u` | Undo close tab |
| `o` | Open URL |
| `O` | Open URL (new tab) |
| `t` | Open in new tab |
### Commands
| Key | Action |
|-----|--------|
| `:` | Command mode |
| `/` | Search in page |
| `yy` | Yank URL |
| `pp` | Open from clipboard |
## Google Login Fix
Google sometimes blocks qutebrowser. Workaround:
See: https://github.com/qutebrowser/qutebrowser/issues/8492
```python
# Set a Chrome user agent for Google sites
c.content.headers.user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
```
Or use per-domain settings:
```python
config.set('content.headers.user_agent',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'*://accounts.google.com/*')
```
## Userscripts
Store in `~/.local/share/qutebrowser/userscripts/`
See [[10-19 LIFE/13 TECH SETUP/13.11 APPS/urlref]] for an example qutebrowser userscript integration.
## Tips
- `:help` opens the comprehensive help
- Use `:set` to explore available options
- `:bind` to see/modify key bindings
- Greasemonkey scripts work via `c.content.javascript.enabled`

View File

@@ -0,0 +1,87 @@
---
publish: true
permalink: /apps/urlref
title: urlref
created: 2026-01-29T14:04:18.714-07:00
modified: 2026-02-05T12:16:30.765-07:00
tags:
- web
- note_taking
cssclasses: ""
---
As an avid user of pen and paper for note taking I have had endless trouble figuring out how to store url's without having to write them out in full. I seem to have found a solution to this issue with [urlref](https://benjaminhollon.com/musings/urlref/) from the fantastic [Benjamin Hollon](https://polymaths.social/@amin). I did have a little bit of fun setting up for myself though so I am documenting here in case it is helpful to anyone, including future me.
## Installation
### Install Nim
**Arch Linux:**
```bash
sudo pacman -S nim nimble
```
**Other distributions:**
See https://nim-lang.org/install.html
### Build
```bash
cd urlref
nimble build
```
### Install system-wide (optional)
```bash
nimble install
```
This installs the binary to `~/.nimble/bin/`. Ensure it's in your PATH:
```bash
export PATH="$HOME/.nimble/bin:$PATH"
```
## Usage
### Create a short reference
```bash
urlref create "https://example.com/some/long/url"
# Output: ABC
```
### Start the redirect server
```bash
urlref
```
The server runs on port 9873. Visiting `http://localhost:9873/ABC` redirects to the original URL.
## Examples
### systemd service
```bash
[Unit]
Description=URL Reference Redirect Server
After=network.target
[Service]
ExecStart=%h/.nimble/bin/urlref
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
```
### qutebrowser Integration
This [[10-19 LIFE/13 TECH SETUP/13.11 APPS/qutebrowser]] integration works for me, you are on your own for other browsers!
#### Userscript
Should live at `~/.local/share/qutebrowser/userscripts`
```bash
#!/bin/bash
# Qutebrowser userscript to shorten the current URL using urlref
shortcode=$(~/.nimble/bin/urlref create "$QUTE_URL")
if [ -n "$shortcode" ]; then
echo "message-info 'Shortcode: $shortcode'" >> "$QUTE_FIFO"
echo "yank inline $shortcode" >> "$QUTE_FIFO"
else
echo "message-error 'Failed to create shortcode'" >> "$QUTE_FIFO"
fi
```
Bind it to a key
```python
config.bind('ar', 'spawn --userscript urlref-shorten')
```
Add a custom search engine
```python
c.url.searchengines['r'] = 'http://localhost:9873/{}'
```

View File

@@ -0,0 +1,104 @@
---
publish: true
permalink: /apps/whosthere
title: whosthere
created: 2026-02-05T08:46:27.958-07:00
modified: 2026-02-05T12:16:30.769-07:00
tags:
- network
- lan
- discovery
cssclasses: ""
---
whosthere is a LAN discovery tool with a modern TUI. It discovers devices on your network using mDNS, SSDP, and ARP scanning—all without requiring root privileges.
## Installation
**Arch Linux (via AUR):**
```bash
yay -S whosthere-bin
```
**Homebrew:**
```bash
brew install whosthere
```
**Go:**
```bash
go install github.com/ramonvermeulen/whosthere@latest
```
## Usage
### Interactive TUI
```bash
whosthere
```
Navigate with arrow keys or vim bindings:
- `j/k` - Move up/down
- `Enter` - Select/expand
- `q` - Quit
- `r` - Refresh scan
- `p` - Port scan selected device
### Daemon Mode
Run as a background service with HTTP API:
```bash
whosthere daemon
```
Query via API:
```bash
curl http://localhost:8080/devices
```
### CLI Output
```bash
# JSON output
whosthere --json
# One-shot scan (no TUI)
whosthere --once
```
## Features
- **mDNS discovery** - Finds devices advertising services
- **SSDP scanning** - Discovers UPnP devices
- **ARP cache reading** - Catches everything else
- **OUI lookup** - Shows manufacturer from MAC address
- **Port scanning** - Optional service discovery on found hosts
## Configuration
`~/.config/whosthere/config.yaml`:
```yaml
# Theme customization
theme:
primary: "#7aa2f7"
secondary: "#bb9af7"
# Scan settings
scan:
timeout: 5s
ports: [22, 80, 443, 8080]
# Daemon settings
daemon:
port: 8080
refresh_interval: 60s
```
## Tips
- No root required—uses unprivileged scanning techniques
- Port scanning requires explicit action; only scan devices you own
- Great for finding that Raspberry Pi you forgot the IP of
- Combine with `--json` for scripting and automation
## See Also
- GitHub: https://github.com/ramonvermeulen/whosthere

View File

@@ -0,0 +1,116 @@
---
publish: true
permalink: /apps/zathura
title: zathura
created: 2026-02-05T09:08:26.899-07:00
modified: 2026-02-05T12:16:30.770-07:00
tags:
- pdf
- documents
- reader
cssclasses: ""
---
zathura is a minimalist document viewer with vim-like keybindings. Fast, keyboard-driven, and highly customizable.
## Installation
**Arch Linux:**
```bash
sudo pacman -S zathura zathura-pdf-mupdf
```
When prompted for tesseract data (for OCR), select `tesseract-data-eng` for English.
### Backend plugins
| Plugin | Formats |
|--------|---------|
| `zathura-pdf-mupdf` | PDF, EPUB, XPS (recommended) |
| `zathura-pdf-poppler` | PDF (alternative) |
| `zathura-djvu` | DjVu |
| `zathura-ps` | PostScript |
| `zathura-cb` | Comic books (CBZ/CBR) |
## Key Bindings
### Navigation
| Key | Action |
|-----|--------|
| `j/k` | Scroll down/up |
| `h/l` | Scroll left/right |
| `Ctrl+d/u` | Half page down/up |
| `gg/G` | First/last page |
| `nG` | Go to page n |
| `Space` | Next page |
### Zoom
| Key | Action |
|-----|--------|
| `+/-` | Zoom in/out |
| a` | Fit page |
| `s` | Fit width |
### View
| Key | Action |
|-----|--------|
| `d` | Toggle dual-page |
| `r` | Rotate |
| `R` | Reload |
| `Tab` | Toggle index |
| `F11` | Fullscreen |
### Other
| Key | Action |
|-----|--------|
| `/` | Search |
| `n/N` | Next/prev match |
| `y` | Copy selection |
| `o/O` | Open file |
| `q` | Quit |
## Configuration
`~/.config/zathura/zathurarc`:
```bash
# Enable clipboard
set selection-clipboard clipboard
# Recolor for dark mode
set recolor true
set recolor-darkcolor "#ebdbb2"
set recolor-lightcolor "#282828"
# Default zoom
set zoom-min 10
set adjust-open "best-fit"
# Status bar
set statusbar-home-tilde true
# Window
set window-title-basename true
set window-title-page true
```
## Make Default PDF Viewer
```bash
xdg-mime default org.pwmt.zathura.desktop application/pdf
```
## Synctex (LaTeX integration)
For LaTeX editors that support synctex:
```bash
zathura --synctex-forward <line>:<col>:<input> <pdf>
```
Configure your editor to call this for forward search.
## Tips
- `:help` or `man zathura` for full documentation
- Use `:bmark` to bookmark pages
- Use `i` to invert colors (quick dark mode)
- Index/TOC navigation with `Tab` is very useful for long documents

View File

@@ -0,0 +1,92 @@
---
publish: true
permalink: /processes/backups
title: Backups
created: 2026-01-29T14:04:18.777-07:00
modified: 2026-02-05T12:16:56.630-07:00
cssclasses: ""
---
## Local
For me local backups happen in two main ways
1. Backups to a VPS using [[20-29 HOBBYS/22 SELF HOSTING/22.12 SERVICES/Syncthing]]
2. Backups to a USB stick that lives in my emergency kit
### USB Backups
For USB backups I had a few key requirements
1. They must be encrypted
2. Decryption should be able to take place on any Windows, Mac, or Linux device
3. Decryption must be simple enough that an intermediate user should be able to manage it given instructions (this is in case someone needs this data if I am no longer around to impart my wisdom)
Given these requirements I settled on using [[10-19 LIFE/13 TECH SETUP/13.11 APPS/VeraCrypt]] to create an encrypted container formatted with exFat on a USB drive. This way someone can install the software and, given my key, decrypt the data.
I created the following helper functions to make this processes a little less cumbersome for myself on a monthly basis.
#### Mount/Unmount Container
```bash
vault() {
local mount_base="/run/media/$USER"
local mount_point="$mount_base/vault"
_vault_find() {
local container
container=$(command find "$mount_base" -maxdepth 2 -name "DataVault" -type f 2>/dev/null | head -1)
if [[ -z "$container" ]]; then
echo "Error: DataVault not found under $mount_base" >&2
return 1
fi
echo "$container"
}
case "${1:-}" in
m|mount)
local container
container=$(_vault_find) || return 1
if mountpoint -q "$mount_point" 2>/dev/null; then
echo "Already mounted at $mount_point"
return 0
fi
echo "Found: $container"
sudo mkdir -p "$mount_point"
sudo veracrypt -t --fs-options="uid=$(id -u),gid=$(id -g)" "$container" "$mount_point"
echo "Mounted at $mount_point"
;;
u|unmount)
if ! mountpoint -q "$mount_point" 2>/dev/null; then
echo "Not mounted"
return 0
fi
sudo veracrypt -t -d "$mount_point"
sudo rmdir "$mount_point" 2>/dev/null || true
echo "Unmounted"
;;
*)
echo "Usage: vault {mount|m|unmount|u}"
return 1
;;
esac
}
```
#### Sync Data
```bash
vault-sync() {
local mount_point="/run/media/$USER/vault"
local source="$HOME/DataStore"
if ! mountpoint -q "$mount_point" 2>/dev/null; then
echo "Error: Vault not mounted at $mount_point" >&2
return 1
fi
if [[ ! -d "$source" ]]; then
echo "Error: Source directory $source does not exist" >&2
return 1
fi
rsync -av --delete "$source/" "$mount_point/"
echo "Sync complete"
}
```
## Cloud
For services on my VPS's I backup docker volumes using [docker-volume-backup](https://github.com/offen/docker-volume-backup)

View File

@@ -0,0 +1,58 @@
---
publish: true
permalink: /os
title: Arch Linux Setup Guide
created: 2026-02-05T09:20:32.962-07:00
modified: 2026-02-05T12:17:52.896-07:00
tags:
- guide
- arch
- linux
cssclasses: ""
---
# Arch Linux Setup Guide
My personal Arch Linux setup for Framework Laptop 13 (AMD). Follow these guides in order for a complete system.
## Core Installation
1. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Base Install]] ← **Start here** — LUKS2 + BTRFS + Limine bootloader
2. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Plymouth]] — Boot splash screen (optional, but nice with LUKS)
## Desktop Environment
3. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Hyprland Setup]] — Wayland compositor and ecosystem
4. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/hyprlock]] — Screen lock with fingerprint support
5. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/hyprshutdown]] — Graceful shutdown animations
6. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Ashell]] — Status bar
7. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Mako]] — Notifications
## System Configuration
8. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Audio]] — PipeWire and audio fixes
9. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Network]] — NetworkManager, iwd, Tailscale
10. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Fonts]] — Font rendering improvements
11. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Printing]] — CUPS setup
## Utilities
12. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Shell]] — Starship prompt and shell config
13. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Disks]] — Automounting with udiskie
14. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/AppImage Management]] — Running and managing AppImages
15. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Keychain]] — GNOME Keyring for secrets
## Security
16. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/fprintd]] — Fingerprint authentication
17. [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Yubikey]] — Hardware key setup
---
## Quick Reference
| Category | Key Packages |
|----------|-------------|
| Base | `base linux linux-firmware btrfs-progs limine` |
| Boot | `plymouth` |
| Desktop | `hyprland hyprlock hypridle hyprpaper hyprshutdown` |
| Bar | `ashell mako` |
| Audio | `pipewire pipewire-pulse wireplumber` |
| Network | `networkmanager iwd tailscale` |
| Auth | `fprintd gnome-keyring` |
| Utils | `starship udiskie` |

View File

@@ -0,0 +1,118 @@
---
publish: true
permalink: /os/appimage
title: AppImage Management
created: 2026-01-29T15:05:11.266-07:00
modified: 2026-02-05T12:17:52.899-07:00
tags:
- appimage
- apps
cssclasses: ""
---
Managing AppImage applications on Arch Linux.
## Directory Structure
```
~/.local/bin/ # AppImage binaries
~/.local/share/applications/ # Desktop entries
```
## Installation Process
### 1. Download the AppImage
```bash
cd ~/.local/bin
wget "https://example.com/App.AppImage"
chmod +x App.AppImage
```
### 2. Create desktop entry
Create `~/.local/share/applications/app.desktop`:
```ini
[Desktop Entry]
Name=App Name
Comment=Description
Exec=/home/phil/.local/bin/App.AppImage
Icon=app-icon
Type=Application
Categories=Utility;
```
### 3. Update desktop database
```bash
update-desktop-database ~/.local/share/applications/
```
## Electron Apps on Wayland
Many Electron-based AppImages need extra flags for Wayland:
```bash
./App.AppImage --enable-features=UseOzonePlatform --ozone-platform=wayland
```
Update the desktop entry:
```ini
Exec=/home/phil/.local/bin/App.AppImage --enable-features=UseOzonePlatform --ozone-platform=wayland
```
## AppImage Tools
### appimagetool
Extract and repack AppImages:
```bash
# Extract
./App.AppImage --appimage-extract
# Creates squashfs-root/ directory
```
### AppImageLauncher
Integrates AppImages into your system automatically:
```bash
paru -S appimagelauncher
```
Features:
- Prompts to integrate on first run
- Creates desktop entries automatically
- Manages AppImages in a central location
## Helper Script
Save as `~/.local/bin/appimage-install`:
```bash
#!/bin/bash
# Usage: appimage-install App.AppImage "App Name"
APPIMAGE="$1"
NAME="$2"
DEST="$HOME/.local/bin/$(basename "$APPIMAGE")"
cp "$APPIMAGE" "$DEST"
chmod +x "$DEST"
cat > "$HOME/.local/share/applications/${NAME,,}.desktop" << EOF
[Desktop Entry]
Name=$NAME
Exec=$DEST
Type=Application
Categories=Utility;
EOF
update-desktop-database ~/.local/share/applications/
echo "Installed $NAME"
```
## Tips
- Keep AppImages in `~/.local/bin` which should be in your PATH
- Some AppImages bundle their own icon — extract with `--appimage-extract` to find it
- For system-wide install, use `/opt/` and `/usr/share/applications/`

View File

@@ -0,0 +1,122 @@
---
publish: true
permalink: /os/ashell
title: Ashell
created: 2026-01-29T15:16:18.996-07:00
modified: 2026-02-05T12:17:52.901-07:00
tags:
- hyprland
- statusbar
- wayland
cssclasses: ""
---
Ashell is a lightweight status bar for Wayland compositors like [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Hyprland Setup\|Hyprland]].
## Installation
**From AUR:**
```bash
paru -S ashell
```
**From source:**
```bash
git clone https://github.com/malpenzibo/ashell
cd ashell
cargo build --release
cp target/release/ashell ~/.local/bin/
```
## Hyprland Integration
Add to `~/.config/hypr/hyprland.conf`:
```bash
exec-once = ashell
```
## My Configuration
Config location: `~/.config/ashell/config.toml`
```toml
log_level = "warn"
outputs = { Targets = ["eDP-1"] }
position = "Top"
app_launcher_cmd = "walker"
[modules]
left = [ [ "appLauncher", "Updates", "Workspaces" ] ]
right = [ "SystemInfo", [ "Tray", "Clock", "Privacy", "Settings" ] ]
[updates]
check_cmd = "checkupdates; paru -Qua"
update_cmd = 'kitty -e bash -c "paru; echo Done - Press enter to exit; read" &'
[system_info]
indicators = ["Cpu", "Memory", "Temperature", "IpAddress", "DownloadSpeed", "UploadSpeed"]
[workspaces]
enable_workspace_filling = true
[[CustomModule]]
name = "appLauncher"
icon = "󱗼"
command = "walker"
[window_title]
truncate_title_after_length = 100
[settings]
lock_cmd = "playerctl --all-players pause; hyprlock &"
audio_sinks_more_cmd = "pavucontrol -t 3"
audio_sources_more_cmd = "pavucontrol -t 4"
wifi_more_cmd = 'kitty -e bash -c "impala"'
vpn_more_cmd = "nm-connection-editor"
bluetooth_more_cmd = 'kitty -e bash -c "bluetui"'
shutdown_cmd = "hyprshutdown -t 'Shutting down...' --post-cmd 'shutdown -P 0'"
suspend_cmd = "systemctl suspend"
hibernate_cmd = "systemctl hibernate"
reboot_cmd = "hyprshutdown -t 'Restarting...' --post-cmd 'reboot'"
logout_cmd = "loginctl kill-user $(whoami)"
[appearance]
style = "Islands"
primary_color = "#7aa2f7"
success_color = "#9ece6a"
text_color = "#a9b1d6"
workspace_colors = [ "#7aa2f7", "#9ece6a" ]
special_workspace_colors = [ "#7aa2f7", "#9ece6a" ]
[appearance.danger_color]
base = "#f7768e"
weak = "#e0af68"
[appearance.background_color]
base = "#1a1b26"
weak = "#24273a"
strong = "#414868"
[appearance.secondary_color]
base = "#0c0d14"
```
## Key Features
- **Islands style** — Floating pill-shaped modules
- **Tokyo Night theme** — Colors match my Hyprland/terminal theme
- **Custom app launcher** — Uses Walker with a custom icon
- **System info** — CPU, memory, temp, network speeds
- **Update checker** — Shows pending pacman/AUR updates
- **Integration apps:**
- `walker` — App launcher
- `pavucontrol` — Audio settings
- `impala` — WiFi TUI
- `bluetui` — Bluetooth TUI
- `hyprshutdown` — Graceful shutdown with animation
## Resources
- Documentation: https://malpenzibo.github.io/ashell/
- GitHub: https://github.com/malpenzibo/ashell

View File

@@ -0,0 +1,89 @@
---
publish: true
permalink: /os/audio
title: Audio
created: 2026-01-29T15:21:02.328-07:00
modified: 2026-02-05T12:17:52.903-07:00
tags:
- audio
- pipewire
- hyprland
cssclasses: ""
---
Audio setup using PipeWire on Arch Linux with Hyprland.
## Installation
Already included in [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Base Install]], but for reference:
```bash
sudo pacman -S \
pipewire pipewire-alsa pipewire-pulse pipewire-jack \
wireplumber sof-firmware
```
## Volume Control
### CLI
```bash
# Using wpctl (WirePlumber)
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
# Using pactl (PulseAudio compat)
pactl set-sink-volume @DEFAULT_SINK@ +5%
pactl set-sink-volume @DEFAULT_SINK@ -5%
pactl set-sink-mute @DEFAULT_SINK@ toggle
```
### GUI
```bash
sudo pacman -S pavucontrol # GTK
# or
sudo pacman -S pwvucontrol # Qt/PipeWire native
```
### Hyprland Keybinds
```bash
bind = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
bind = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bind = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
```
## Troubleshooting
### No sound
Check WirePlumber is running:
```bash
systemctl --user status wireplumber
systemctl --user status pipewire
```
Restart if needed:
```bash
systemctl --user restart wireplumber pipewire pipewire-pulse
```
### Headphone jack buzz (Framework AMD)
The AMD board has slight buzz when audio idles. Disable power saving:
Create `/etc/modprobe.d/audio-powersave.conf`:
```
options snd_hda_intel power_save=0
```
### Application-specific issues
Some apps need explicit PipeWire support. Check:
```bash
pactl info | grep "Server Name"
# Should show: PulseAudio (on PipeWire)
```
## Resources
- Detailed guide: https://dev.to/laithalenooz/resolving-audio-issues-on-arch-linux-with-hyprland-a-step-by-step-guide-2n
- Arch Wiki: https://wiki.archlinux.org/title/PipeWire

View File

@@ -0,0 +1,465 @@
---
publish: true
permalink: /os/base-install
title: Base Install
created: 2026-01-29T14:10:28.844-07:00
modified: 2026-02-05T12:17:52.905-07:00
tags:
- arch
- installation
- luks
- btrfs
cssclasses: ""
---
My Arch Linux installation guide for Framework Laptop 13 (AMD Ryzen 7040). LUKS2 encrypted BTRFS with Limine bootloader.
> Based on guides by [yovko](https://gist.github.com/yovko/512326b904d120f3280c163abfbcb787) and [mgajewskik](https://gist.github.com/mgajewskik/a9331171c31b6e8839c427210ba76730), adapted for Framework AMD hardware.
---
## Overview
- **Encryption:** LUKS2 on system partition
- **Filesystem:** BTRFS with subvolumes (snapshots, compression)
- **Bootloader:** Limine (lightweight, Snapper-friendly)
- **Hardware:** Framework Laptop 13 AMD (Ryzen 7040 series)
---
## Preparation
Boot from the [official Arch ISO](https://archlinux.org/download/).
### Connect to WiFi
```bash
iwctl station wlan0 connect <SSID>
```
### Set keymap and font
```bash
loadkeys us
setfont ter-132b
```
### Verify UEFI mode
```bash
cat /sys/firmware/efi/fw_platform_size
# Should return 64
```
### (Optional) SSH in from another machine
```bash
passwd # set root password
ip addr show # get IP
# From other machine: ssh root@<ip>
```
---
## Disk Partitioning
Assuming single-boot Arch on `/dev/nvme0n1`.
### Wipe existing partitions
```bash
sgdisk --zap-all /dev/nvme0n1
```
### Create partitions
- **ESP:** 2GB FAT32 for `/boot`
- **System:** Rest of disk, LUKS2 encrypted BTRFS
```bash
parted --script /dev/nvme0n1 \
mklabel gpt \
mkpart ESP fat32 1MiB 2049MiB \
set 1 esp on \
mkpart Linux btrfs 2050MiB 100%
```
### Format ESP
```bash
mkfs.fat -F 32 /dev/nvme0n1p1
```
---
## Encryption Setup
### Create LUKS container
```bash
cryptsetup luksFormat /dev/nvme0n1p2
```
**Save the UUID** — you'll need it for the bootloader:
```bash
cryptsetup luksUUID /dev/nvme0n1p2
```
### Open the container
```bash
cryptsetup open /dev/nvme0n1p2 root
```
---
## BTRFS Setup
### Format and mount
```bash
mkfs.btrfs /dev/mapper/root
mount /dev/mapper/root /mnt
```
### Create subvolumes
```bash
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@var_log
btrfs subvolume create /mnt/@var_cache
btrfs subvolume create /mnt/@snapshots
```
### Remount with subvolumes
```bash
umount /mnt
mount -o compress=zstd:1,noatime,subvol=@ /dev/mapper/root /mnt
mount --mkdir -o compress=zstd:1,noatime,subvol=@home /dev/mapper/root /mnt/home
mount --mkdir -o compress=zstd:1,noatime,subvol=@var_log /dev/mapper/root /mnt/var/log
mount --mkdir -o compress=zstd:1,noatime,subvol=@var_cache /dev/mapper/root /mnt/var/cache
mount --mkdir -o compress=zstd:1,noatime,subvol=@snapshots /dev/mapper/root /mnt/.snapshots
mount --mkdir /dev/nvme0n1p1 /mnt/boot
```
---
## Install Base System
```bash
pacman -Syy
pacstrap -K /mnt \
base base-devel linux linux-firmware linux-headers \
git vim neovim \
btrfs-progs efibootmgr limine cryptsetup \
networkmanager iwd wireless-regdb \
reflector bash-completion zsh \
pipewire pipewire-alsa pipewire-pulse pipewire-jack wireplumber sof-firmware \
bluez bluez-utils \
acpi acpid power-profiles-daemon \
firewalld cups avahi nss-mdns \
util-linux terminus-font openssh man sudo rsync \
amd-ucode mesa vulkan-radeon libva-mesa-driver
```
### Generate fstab
```bash
genfstab -U /mnt >> /mnt/etc/fstab
```
---
## System Configuration
### Chroot in
```bash
arch-chroot /mnt
```
### Timezone and locale
```bash
ln -sf /usr/share/zoneinfo/America/Denver /etc/localtime
hwclock --systohc
# Edit /etc/locale.gen, uncomment en_US.UTF-8 UTF-8
vim /etc/locale.gen
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
```
### Console font and keymap
```bash
cat > /etc/vconsole.conf << EOF
KEYMAP=us
FONT=ter-132b
EOF
```
### Hostname
```bash
echo "framework" > /etc/hostname
```
### Root password
```bash
passwd
```
### Create user
```bash
useradd -mG wheel phil
passwd phil
EDITOR=vim visudo # uncomment %wheel ALL=(ALL:ALL) ALL
```
### Configure mkinitcpio
Edit `/etc/mkinitcpio.conf`:
```bash
MODULES=(btrfs)
BINARIES=(/usr/bin/btrfs)
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)
```
> **Note:** Add `resume` after `filesystems` if you want hibernation support.
Regenerate:
```bash
mkinitcpio -P
```
---
## Limine Bootloader
### Install Limine
```bash
mkdir -p /boot/EFI/limine
cp /usr/share/limine/BOOTX64.EFI /boot/EFI/limine/
```
### Create NVRAM entry
```bash
efibootmgr --create --disk /dev/nvme0n1 --part 1 \
--label "Arch Linux" \
--loader '\EFI\limine\BOOTX64.EFI' \
--unicode
```
### Configure Limine
Create `/boot/EFI/limine/limine.conf`:
```
timeout: 3
/Arch Linux
protocol: linux
path: boot():/vmlinuz-linux
cmdline: quiet cryptdevice=UUID=<YOUR-LUKS-UUID>:root root=/dev/mapper/root rw rootflags=subvol=@ rootfstype=btrfs cfg80211.ieee80211_regdom=US
module_path: boot():/initramfs-linux.img
/Arch Linux (fallback)
protocol: linux
path: boot():/vmlinuz-linux
cmdline: quiet cryptdevice=UUID=<YOUR-LUKS-UUID>:root root=/dev/mapper/root rw rootflags=subvol=@ rootfstype=btrfs cfg80211.ieee80211_regdom=US
module_path: boot():/initramfs-linux-fallback.img
```
Replace `<YOUR-LUKS-UUID>` with the UUID from earlier.
---
## Enable Services
```bash
systemctl enable NetworkManager
systemctl enable iwd
systemctl enable bluetooth
systemctl enable cups
systemctl enable avahi-daemon
systemctl enable firewalld
systemctl enable acpid
systemctl enable power-profiles-daemon
systemctl enable reflector.timer
systemctl enable fstrim.timer
```
---
## Framework AMD Tweaks
### Disable PC speaker
Create `/etc/modprobe.d/nobeep.conf`:
```
blacklist pcspkr
blacklist snd_pcsp
```
### Lid behavior
Edit `/etc/systemd/logind.conf`:
```ini
HandlePowerKey=ignore
HandlePowerKeyLongPress=poweroff
HandleLidSwitch=suspend
HandleLidSwitchExternalPower=suspend
HandleLidSwitchDocked=ignore
```
### WiFi performance (MediaTek RZ616)
The AMD Framework uses MediaTek WiFi which needs some tuning.
**Set regulatory domain** — without this you're stuck on 2.4GHz:
```bash
# Add to Limine cmdline:
cfg80211.ieee80211_regdom=US
```
**Use iwd as NetworkManager backend** for better stability:
Create `/etc/NetworkManager/conf.d/wifi-backend.conf`:
```ini
[device]
wifi.backend=iwd
```
**Disable WiFi power saving** to prevent disconnects:
Create `/etc/modprobe.d/mt7921.conf`:
```
options mt7921e power_save=0
```
### Headphone jack buzz fix
The AMD board has a slight buzz when audio is idle. Disable power saving:
Create `/etc/modprobe.d/audio-powersave.conf`:
```
options snd_hda_intel power_save=0
```
### USB-A expansion card power drain
Avoid placing USB-A cards in the **two rear slots** — they cause higher idle power drain. Front slots are fine.
### HDMI/DisplayPort expansion cards
Don't use the **front-left slot** for HDMI/DP cards — may not work on AMD.
---
## Reboot
```bash
exit
umount -R /mnt
cryptsetup close root
reboot
```
Remove the USB drive.
---
## Post-Install
### Connect to WiFi
```bash
nmcli device wifi connect <SSID> password <password>
```
### Install paru (AUR helper)
```bash
sudo pacman -S --needed git base-devel
git clone https://aur.archlinux.org/paru.git
cd paru && makepkg -si
cd .. && rm -rf paru
```
### Enable pacman colors
Uncomment `Color` in `/etc/pacman.conf`.
### Time sync
```bash
timedatectl set-ntp true
```
### Pacman hook for Limine updates
Create `/etc/pacman.d/hooks/99-limine.hook`:
```ini
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = limine
[Action]
Description = Deploying Limine after upgrade...
When = PostTransaction
Exec = /usr/bin/cp /usr/share/limine/BOOTX64.EFI /boot/EFI/limine/
```
### BIOS updates
Framework AMD is well supported on LVFS. Check for updates:
```bash
sudo pacman -S fwupd
fwupdmgr refresh
fwupdmgr get-updates
fwupdmgr update
```
> **Note:** If you have a batch 1 or 2 device, make sure BIOS is at least 3.03 before updating further.
---
## Next Steps
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Hyprland Setup]] — graphical environment
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Network]] — advanced networking
- Snapper for BTRFS snapshots
- Swap/hibernation setup
---
## References
- [Arch Wiki: Framework Laptop 13](https://wiki.archlinux.org/title/Framework_Laptop_13)
- [Arch Wiki: Installation Guide](https://wiki.archlinux.org/title/Installation_guide)
- [Arch Wiki: Limine](https://wiki.archlinux.org/title/Limine)
- [Arch Wiki: BTRFS](https://wiki.archlinux.org/title/Btrfs)
- [Arch Wiki: dm-crypt](https://wiki.archlinux.org/title/Dm-crypt)

View File

@@ -0,0 +1,101 @@
---
publish: true
permalink: /os/disks
title: Disks
created: 2026-01-29T21:46:53.106-07:00
modified: 2026-02-05T12:18:02.151-07:00
tags:
- disks
- automount
- usb
cssclasses: ""
---
Automounting removable drives with udiskie.
## Installation
```bash
sudo pacman -S udiskie udisks2
```
## Usage
### Start udiskie
Run in background (auto-mounts drives):
```bash
udiskie &
```
With tray icon:
```bash
udiskie --tray &
```
### Hyprland Integration
Add to `~/.config/hypr/hyprland.conf`:
```bash
exec-once = udiskie --tray
```
## Configuration
Config location: `~/.config/udiskie/config.yml`
```yaml
program_options:
tray: true
notify: true
automount: true
device_config:
- device_file: /dev/sda1
options:
- noexec
```
## Manual Control
```bash
# Mount
udisksctl mount -b /dev/sdb1
# Unmount
udisksctl unmount -b /dev/sdb1
# Power off (safely eject)
udisksctl power-off -b /dev/sdb
# List drives
lsblk
```
## Encrypted Drives
udiskie handles LUKS-encrypted drives automatically — prompts for password when detected.
For command line:
```bash
# Unlock
udisksctl unlock -b /dev/sdb1
# Then mount
udisksctl mount -b /dev/dm-0
```
## Mount Points
By default, drives mount to `/run/media/$USER/<label>`
## Tips
- Use `--no-automount` if you prefer manual mounting
- Notifications require a notification daemon (e.g., [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Mako]])
- For NTFS support: `sudo pacman -S ntfs-3g`
## Resources
- GitHub: https://github.com/coldfix/udiskie
- Arch Wiki: https://wiki.archlinux.org/title/Udisks

View File

@@ -0,0 +1,106 @@
---
publish: true
permalink: /os/fonts
title: Fonts
created: 2026-01-29T15:24:42.068-07:00
modified: 2026-02-05T12:18:02.154-07:00
tags:
- fonts
- rendering
- appearance
cssclasses: ""
---
Font installation and rendering improvements for Arch Linux.
## Essential Fonts
```bash
sudo pacman -S \
ttf-dejavu ttf-liberation ttf-roboto \
noto-fonts noto-fonts-cjk noto-fonts-emoji \
ttf-jetbrains-mono ttf-fira-code \
ttf-font-awesome
```
### Nerd Fonts (icons in terminal)
```bash
paru -S ttf-jetbrains-mono-nerd
# or download from https://www.nerdfonts.com/
```
## Font Rendering
Arch's default font rendering can look rough. These tweaks improve it significantly.
### Enable good defaults
```bash
sudo ln -s /usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf /etc/fonts/conf.d/
sudo ln -s /usr/share/fontconfig/conf.avail/10-hinting-slight.conf /etc/fonts/conf.d/
sudo ln -s /usr/share/fontconfig/conf.avail/11-lcdfilter-default.conf /etc/fonts/conf.d/
```
### User fontconfig
Create `~/.config/fontconfig/fonts.conf`:
```xml
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<match target="font">
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
<edit name="hinting" mode="assign">
<bool>true</bool>
</edit>
<edit name="hintstyle" mode="assign">
<const>hintslight</const>
</edit>
<edit name="lcdfilter" mode="assign">
<const>lcddefault</const>
</edit>
<edit name="rgba" mode="assign">
<const>rgb</const>
</edit>
</match>
</fontconfig>
```
### Rebuild font cache
```bash
fc-cache -fv
```
## Verify Settings
```bash
fc-match -v sans | grep -E "antialias|hinting|hintstyle|rgba"
```
## Default Fonts
Set preferred defaults:
```xml
<!-- Add to fonts.conf -->
<alias>
<family>sans-serif</family>
<prefer><family>Noto Sans</family></prefer>
</alias>
<alias>
<family>serif</family>
<prefer><family>Noto Serif</family></prefer>
</alias>
<alias>
<family>monospace</family>
<prefer><family>JetBrains Mono</family></prefer>
</alias>
```
## Resources
- Detailed guide: https://github.com/davgar99/arch-linux-font-improvement-guide
- Arch Wiki: https://wiki.archlinux.org/title/Font_configuration

View File

@@ -0,0 +1,203 @@
---
publish: true
permalink: /os/hyprland
title: Hyprland Setup
created: 2026-01-29T15:09:13.502-07:00
modified: 2026-02-05T12:18:02.155-07:00
tags:
- hyprland
- wayland
- desktop
cssclasses: ""
---
Hyprland is a dynamic tiling Wayland compositor. This covers the full Hyprland ecosystem setup after [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Base Install]].
## Installation
```bash
sudo pacman -S \
hyprland \
hyprlock \
hypridle \
hyprpaper \
hyprpicker \
hyprcursor \
hyprsunset \
xdg-desktop-portal-hyprland \
hyprpolkitagent
```
### Full Package List
All Hyprland ecosystem packages I have installed:
- hyprcursor
- hyprgraphics
- hypridle
- hyprland
- hyprland-guiutils
- hyprland-protocols
- hyprland-qt-support
- hyprlang
- hyprlock
- hyprpaper
- hyprpicker
- hyprpolkitagent
- hyprpwcenter
- hyprsunset
- hyprtoolkit
- hyprutils
- hyprwayland-scanner
- hyprwire
- xdg-desktop-portal-hyprland
### AUR Packages
```bash
paru -S hyprshutdown
```
See [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/hyprshutdown]] for build instructions if the AUR version is outdated.
## Related Components
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Ashell]] — Status bar
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Mako]] — Notifications
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/hyprlock]] — Screen lock with fingerprint support
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/hyprshutdown]] — Graceful shutdown animations
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/fprintd]] — Fingerprint authentication
- [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Plymouth]] — Boot splash screen
## Configuration Structure
My config uses **includes** to keep the main file clean and modular.
### Directory Layout
```
~/.config/hypr/
├── hyprland.conf # Main config (mostly defaults + sources)
├── hyprland.conf.d/ # Modular config includes
│ ├── monitors # Display configuration
│ ├── programs # Variable definitions ($terminal, etc.)
│ ├── autostart # exec-once statements
│ ├── general # Gaps, borders, layout
│ └── keybinds # Custom keybind overrides
├── hyprlock.conf # Lock screen config
├── hypridle.conf # Idle behavior config
├── hyprpaper.conf # Wallpaper config
└── hyprsunset.conf # Night light config
```
### Using Includes
The main `hyprland.conf` uses `source` statements to pull in modular configs:
```bash
# In hyprland.conf
source = ~/.config/hypr/hyprland.conf.d/monitors
source = ~/.config/hypr/hyprland.conf.d/programs
source = ~/.config/hypr/hyprland.conf.d/autostart
source = ~/.config/hypr/hyprland.conf.d/general
source = ~/.config/hypr/hyprland.conf.d/keybinds
```
### Why Includes?
1. **Keep defaults intact** — Main config stays close to upstream defaults
2. **Easy diffing** — Can compare against new Hyprland releases
3. **Modular changes** — Edit just monitors or keybinds without touching the rest
4. **Machine-specific** — Different monitor configs per machine, same base
### Example: programs
Define variables in one place:
```bash
# ~/.config/hypr/hyprland.conf.d/programs
$terminal = kitty
$filemanager = thunar
$menu = walker
```
### Example: autostart
All startup applications:
```bash
# ~/.config/hypr/hyprland.conf.d/autostart
# Hypr ecosystem
exec-once = hyprpaper & hypridle & hyprsunset
# Status bar
exec-once = ashell &
# Services
exec-once = systemctl --user start elephant
exec-once = systemctl --user start hyprpolkitagent
# Apps
exec-once = walker --gapplication-service
exec-once = udiskie &
exec-once = wl-paste --watch cliphist store
exec-once = tailscale up
exec-once = protonmail-bridge-core
```
### Example: keybinds
Override and add custom bindings:
```bash
# ~/.config/hypr/hyprland.conf.d/keybinds
$mainModS = SUPER_SHIFT
# Unbind defaults I don't want
unbind = $mainMod, Q
unbind = $mainMod, C
unbind = $mainMod, R
# My bindings
bind = $mainMod, Return, exec, $terminal
bind = $mainMod, Q, killactive
bind = $mainModS, B, exec, qutebrowser
bind = $mainMod, Space, exec, $menu
```
## Idle Management (hypridle)
Config: `~/.config/hypr/hypridle.conf`
My idle sequence:
1. **2.5 min** — Dim screen + keyboard backlight
2. **5 min** — Lock screen
3. **5.5 min** — Turn off display
4. **30 min** — Suspend
Key settings:
```bash
general {
lock_cmd = pidof hyprlock || hyprlock # Prevent multiple instances
before_sleep_cmd = loginctl lock-session
after_sleep_cmd = hyprctl dispatch dpms on
}
```
## Brightness Control
Install `brightnessctl`:
```bash
sudo pacman -S brightnessctl
```
Framework laptop keybinds (already in default config):
```bash
bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%-
```
## Tips
- Use `hyprctl` to interact with Hyprland from scripts
- `hyprctl monitors` — list displays
- `hyprctl clients` — list windows
- `hyprctl reload` — reload config without restart

View File

@@ -0,0 +1,107 @@
---
publish: true
permalink: /os/keychain
title: Keychain
created: 2026-01-29T21:15:48.335-07:00
modified: 2026-02-05T12:18:02.157-07:00
tags:
- security
- secrets
- gnome-keyring
cssclasses: ""
---
GNOME Keyring for managing secrets, SSH keys, and application passwords.
## Installation
```bash
sudo pacman -S gnome-keyring libsecret seahorse
```
- `gnome-keyring` — The keyring daemon
- `libsecret` — Library for apps to access secrets
- `seahorse` — GUI for managing keyring
## PAM Integration
Automatically unlock keyring on login.
Edit `/etc/pam.d/login`:
```
auth optional pam_gnome_keyring.so
session optional pam_gnome_keyring.so auto_start
```
For GDM/SDDM, also edit `/etc/pam.d/passwd`:
```
password optional pam_gnome_keyring.so
```
## Hyprland Integration
Add to `~/.config/hypr/hyprland.conf`:
```bash
exec-once = gnome-keyring-daemon --start --components=secrets,ssh
```
Set environment variables in hyprland.conf:
```bash
env = SSH_AUTH_SOCK,$XDG_RUNTIME_DIR/gcr/ssh
```
Or in your shell profile:
```bash
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/gcr/ssh"
```
## SSH Key Management
### Add key to agent
```bash
ssh-add ~/.ssh/id_ed25519
```
### List keys
```bash
ssh-add -l
```
### GUI management
Launch Seahorse:
```bash
seahorse
```
## Unlocking
If keyring doesn't auto-unlock:
```bash
# Manually unlock
gnome-keyring-daemon --unlock
# Or via secret-tool
secret-tool search --unlock xdg:schema org.gnome.keyring.Note
```
## Application Support
Apps using libsecret (most modern apps) will automatically use gnome-keyring. For apps that need explicit setup:
### Git credential storage
```bash
git config --global credential.helper /usr/lib/git-core/git-credential-libsecret
```
### VS Code
VS Code uses gnome-keyring automatically for settings sync.
## Resources
- Arch Wiki: https://wiki.archlinux.org/title/GNOME/Keyring

View File

@@ -0,0 +1,106 @@
---
publish: true
permalink: /os/mako
title: Mako
created: 2026-01-29T15:18:16.265-07:00
modified: 2026-02-05T12:18:02.159-07:00
tags:
- notifications
- wayland
- hyprland
cssclasses: ""
---
Mako is a lightweight notification daemon for Wayland compositors.
## Installation
```bash
sudo pacman -S mako libnotify
```
## Configuration
Config location: `~/.config/mako/config`
```ini
# Appearance
font=monospace 11
background-color=#282828
text-color=#ebdbb2
border-color=#458588
border-size=2
border-radius=5
# Behavior
default-timeout=5000
ignore-timeout=0
max-visible=5
# Position
anchor=top-right
margin=10
# Grouping
group-by=app-name
# Actions
on-button-left=dismiss
on-button-right=dismiss-all
# Urgency-specific
[urgency=low]
background-color=#282828
[urgency=normal]
background-color=#282828
[urgency=critical]
background-color=#cc241d
default-timeout=0
```
## Hyprland Integration
Add to `~/.config/hypr/hyprland.conf`:
```bash
exec-once = mako
```
## Usage
### Test notifications
```bash
notify-send "Hello" "This is a test notification"
notify-send -u critical "Warning" "This is urgent!"
```
### Control mako
```bash
makoctl dismiss # Dismiss latest
makoctl dismiss --all # Dismiss all
makoctl restore # Restore last dismissed
makoctl list # List waiting notifications
makoctl reload # Reload config
```
## Do Not Disturb
```bash
# Enable DND
makoctl set-mode do-not-disturb
# Disable DND
makoctl set-mode default
```
Add a keybind:
```bash
bind = SUPER, N, exec, makoctl set-mode do-not-disturb
bind = SUPER SHIFT, N, exec, makoctl set-mode default
```
## Resources
- GitHub: https://github.com/emersion/mako
- Man page: `man 5 mako`

View File

@@ -0,0 +1,182 @@
---
publish: true
permalink: /os/network
title: Network
created: 2026-01-29T14:15:15.157-07:00
modified: 2026-02-05T12:18:10.583-07:00
tags:
- network
- wifi
- tailscale
cssclasses: ""
---
Network configuration using NetworkManager with iwd backend, systemd-resolved for DNS, and Tailscale for mesh networking.
## Architecture
My setup:
- **NetworkManager** — Connection management
- **iwd** — WiFi backend (replaces wpa_supplicant)
- **systemd-resolved** — DNS resolution
- **dhcpcd** — Disabled (NetworkManager handles DHCP)
## Disable dhcpcd
NetworkManager handles DHCP itself, so dhcpcd is not needed and can cause conflicts.
```bash
# Stop and disable dhcpcd
sudo systemctl stop dhcpcd
sudo systemctl disable dhcpcd
# Verify it's not running
systemctl status dhcpcd
```
If you had dhcpcd managing interfaces, NetworkManager will take over after a reboot.
## NetworkManager + iwd
Using iwd as the WiFi backend provides better stability than wpa_supplicant, especially on Framework AMD with the MediaTek WiFi card.
### Configure iwd backend
Create `/etc/NetworkManager/conf.d/wifi-backend.conf`:
```ini
[device]
wifi.backend=iwd
```
### Enable services
```bash
sudo systemctl enable --now NetworkManager
sudo systemctl enable --now iwd
```
### Disable wpa_supplicant (if installed)
```bash
sudo systemctl stop wpa_supplicant
sudo systemctl disable wpa_supplicant
```
## DNS with systemd-resolved
I use systemd-resolved for DNS instead of letting NetworkManager write to `/etc/resolv.conf` directly.
### Enable systemd-resolved
```bash
sudo systemctl enable --now systemd-resolved
```
### Link resolv.conf
```bash
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
```
### Configure NetworkManager to use it
Create `/etc/NetworkManager/conf.d/dns.conf`:
```ini
[main]
dns=systemd-resolved
```
### Verify
```bash
resolvectl status
```
## WiFi Management
### CLI (nmcli)
```bash
# List networks
nmcli device wifi list
# Connect
nmcli device wifi connect "SSID" password "password"
# Saved connections
nmcli connection show
# Disconnect
nmcli device disconnect wlan0
# Forget network
nmcli connection delete "SSID"
```
### TUI (impala)
I use [[10-19 LIFE/13 TECH SETUP/13.11 APPS/impala]] for interactive WiFi management — much nicer than `iwctl`:
```bash
impala
```
See [[10-19 LIFE/13 TECH SETUP/13.11 APPS/impala]] for keybindings and configuration.
## Tailscale
Tailscale creates a secure mesh network between all your devices.
### Installation
```bash
curl -fsSL https://tailscale.com/install.sh | sh
```
Or via pacman:
```bash
sudo pacman -S tailscale
```
### Setup
```bash
sudo systemctl enable --now tailscaled
sudo tailscale up
```
Follow the auth URL to connect to your tailnet.
### Useful commands
```bash
tailscale status # Show connected devices
tailscale ip # Show Tailscale IP
tailscale ping <host> # Ping another device
tailscale ssh <host> # SSH to another device (if enabled)
```
### Exit node (use another device as VPN)
```bash
# Enable exit node on a device
sudo tailscale up --advertise-exit-node
# Use an exit node
sudo tailscale up --exit-node=<hostname>
```
## Complete Setup Summary
1. Disable dhcpcd
2. Enable NetworkManager + iwd
3. Disable wpa_supplicant
4. Enable systemd-resolved
5. Link resolv.conf
6. Install Tailscale
7. Install [[10-19 LIFE/13 TECH SETUP/13.11 APPS/impala]] for WiFi TUI
## Resources
- Arch Wiki: https://wiki.archlinux.org/title/NetworkManager#Using_iwd_as_the_Wi-Fi_backend
- Tailscale docs: https://tailscale.com/kb/

View File

@@ -0,0 +1,131 @@
---
publish: true
permalink: /os/plymouth
title: Plymouth
created: 2026-02-05T09:31:46.739-07:00
modified: 2026-02-05T12:18:10.585-07:00
tags:
- boot
- splash
- luks
cssclasses: ""
---
Plymouth provides a graphical boot splash screen, including during LUKS password entry.
## Installation
```bash
sudo pacman -S plymouth
```
## Configuration
### mkinitcpio (systemd hooks)
I use systemd-based initramfs hooks. Edit `/etc/mkinitcpio.conf`:
```bash
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole plymouth sd-encrypt block filesystems resume fsck)
```
Key points:
- Using `systemd` not `udev`
- Using `sd-vconsole` not `keymap consolefont`
- Using `sd-encrypt` not `encrypt`
- `plymouth` comes **after** `sd-vconsole` and **before** `sd-encrypt`
Regenerate initramfs:
```bash
sudo mkinitcpio -P
```
### Kernel Parameters
Add `splash` to your bootloader config.
**For Limine** (`/boot/EFI/limine/limine.conf`):
```
cmdline: quiet splash rd.luks.uuid=<UUID> root=/dev/mapper/root ...
```
> **Note:** With systemd hooks, use `rd.luks.uuid=` instead of `cryptdevice=`
**For systemd-boot** (`/boot/loader/entries/arch.conf`):
```
options quiet splash rd.luks.uuid=<UUID> root=/dev/mapper/root ...
```
### Set Theme
```bash
# List available themes
plymouth-set-default-theme -l
# Set theme (and rebuild initramfs)
sudo plymouth-set-default-theme -R spinner
```
Popular themes:
- `spinner` — Simple spinner (default)
- `bgrt` — Uses manufacturer logo from ACPI
- `fade-in` — Fading star field
### Install more themes
```bash
paru -S plymouth-theme-arch-logo
paru -S plymouth-theme-monoarch
```
## LUKS Integration
Plymouth displays the LUKS password prompt graphically instead of the text console.
For this to work with systemd hooks:
1. `plymouth` hook must be before `sd-encrypt` hook
2. `splash` must be in kernel parameters
3. Use `rd.luks.uuid=` for LUKS device specification
## systemd vs udev Hooks
| udev-based | systemd-based |
|------------|---------------|
| `udev` | `systemd` |
| `keymap consolefont` | `sd-vconsole` |
| `encrypt` | `sd-encrypt` |
| `cryptdevice=UUID=...:name` | `rd.luks.uuid=...` |
## Testing
Test without rebooting:
```bash
sudo plymouthd
sudo plymouth --show-splash
# Press Enter to dismiss
sudo plymouth quit
```
## Troubleshooting
### No splash on boot
1. Verify `splash` is in kernel params
2. Check hook order in mkinitcpio.conf
3. Regenerate initramfs: `sudo mkinitcpio -P`
### LUKS prompt is text-only
The `plymouth` hook must come **before** `sd-encrypt`:
```bash
HOOKS=(... sd-vconsole plymouth sd-encrypt ...)
```
### View boot messages
Remove `quiet` temporarily to see boot messages if Plymouth isn't working.
## Resources
- Arch Wiki: https://wiki.archlinux.org/title/Plymouth
- Arch Wiki (mkinitcpio systemd): https://wiki.archlinux.org/title/Mkinitcpio#Common_hooks

View File

@@ -0,0 +1,95 @@
---
publish: true
permalink: /os/printing
title: Printing
created: 2026-02-05T08:52:25.911-07:00
modified: 2026-02-05T12:18:10.587-07:00
tags:
- printing
- cups
cssclasses: ""
---
CUPS printing setup for Arch Linux.
## Installation
```bash
sudo pacman -S cups cups-pdf
```
## Enable Services
```bash
sudo systemctl enable --now cups
sudo systemctl enable --now avahi-daemon
```
Avahi enables automatic network printer discovery.
## Configuration
### Web interface
Access CUPS admin at: http://localhost:631
### Add printer via CLI
```bash
# List available printers
lpinfo -v
# Add a printer
lpadmin -p PrinterName -E -v "uri" -m "driver.ppd"
# Set default printer
lpoptions -d PrinterName
```
### Network printers (auto-discovery)
With Avahi running, network printers should appear automatically. If not:
```bash
# Install nss-mdns for .local hostname resolution
sudo pacman -S nss-mdns
# Edit /etc/nsswitch.conf, add mdns_minimal before resolve:
hosts: mymachines mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] files myhostname dns
```
## Print to PDF
The `cups-pdf` package creates a virtual PDF printer:
```bash
# Print to PDF (outputs to ~/PDF/)
lp -d cups-pdf document.txt
```
## Useful Commands
```bash
lpstat -p # List printers
lpstat -t # Full status
lp -d PrinterName file # Print file
cancel <job-id> # Cancel print job
lprm <job-id> # Remove print job
```
## Troubleshooting
```bash
# Check CUPS status
systemctl status cups
# View logs
journalctl -u cups -f
# Restart CUPS
sudo systemctl restart cups
```
## Resources
- Arch Wiki: https://wiki.archlinux.org/title/CUPS

View File

@@ -0,0 +1,153 @@
---
publish: true
permalink: /os/shell
title: Shell
created: 2026-01-29T16:18:01.019-07:00
modified: 2026-02-05T12:18:10.588-07:00
tags:
- shell
- terminal
- bash
cssclasses: ""
---
Shell configuration with Bash, Starship prompt, and Atuin history.
## Starship Prompt
Starship is a fast, customizable prompt that works with any shell.
### Installation
```bash
curl -sS https://starship.rs/install.sh | sh
```
Or via pacman:
```bash
sudo pacman -S starship
```
### Bash Integration
Add to `~/.bashrc`:
```bash
eval "$(starship init bash)"
```
### Configuration
Config location: `~/.config/starship.toml`
```toml
# Minimal prompt
format = """
$directory\
$git_branch\
$git_status\
$character"""
[directory]
truncation_length = 3
truncate_to_repo = true
[git_branch]
symbol = " "
[git_status]
format = '([$all_status$ahead_behind]($style) )'
[character]
success_symbol = "[](green)"
error_symbol = "[](red)"
```
## Atuin (Shell History)
See [[10-19 LIFE/13 TECH SETUP/13.11 APPS/atuin]] for full setup. Quick integration:
```bash
# Install
curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh
# Add to ~/.bashrc
. "$HOME/.atuin/bin/env"
[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh
eval "$(atuin init bash)"
```
## My .bashrc Structure
I keep my bashrc clean by sourcing external files:
```bash
# ~/.bashrc
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
# Basic aliases
alias ls='ls --color=auto'
alias grep='grep --color=auto'
# PATH
export PATH="/home/phil/.local/bin:$PATH"
export PATH="$HOME/.npm-global/bin:$PATH"
export PATH="$PATH:$HOME/go/bin"
# Starship
eval "$(starship init bash)"
# Atuin
. "$HOME/.atuin/bin/env"
[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh
eval "$(atuin init bash)"
# Custom config (aliases, functions)
source ~/.config/dotfiles/aliases
source ~/.config/dotfiles/functions
# Completions
source <(openclaw completion --shell bash)
```
### Modular Config
Keep aliases and functions in separate files:
```
~/.config/dotfiles/
├── aliases # alias definitions
└── functions # shell functions
```
This keeps `.bashrc` clean and makes it easy to version control customizations separately.
## Useful Tools
```bash
sudo pacman -S \
fzf # Fuzzy finder
bat # Better cat
eza # Better ls
ripgrep # Better grep
fd # Better find
```
### fzf Integration
```bash
# Add to ~/.bashrc
source /usr/share/fzf/key-bindings.bash
source /usr/share/fzf/completion.bash
```
Keybindings:
- `Ctrl+R` — Search history (or use Atuin)
- `Ctrl+T` — Search files
- `Alt+C` — cd into directory
## Resources
- Starship: https://starship.rs/
- Atuin: https://atuin.sh/

View File

@@ -0,0 +1,143 @@
---
publish: true
permalink: /os/yubikey
title: Yubikey
created: 2026-01-29T21:27:17.327-07:00
modified: 2026-02-05T12:18:10.589-07:00
tags:
- security
- yubikey
- 2fa
cssclasses: ""
---
YubiKey hardware security key setup on Arch Linux.
## Installation
```bash
sudo pacman -S \
yubikey-manager \
yubico-authenticator \
pcsclite ccid
```
- `yubikey-manager` — CLI tool (`ykman`)
- `yubico-authenticator` — TOTP/HOTP GUI
- `pcsclite`, `ccid` — Smart card daemon
## Enable Services
```bash
sudo systemctl enable --now pcscd
```
## Basic Usage
### Check YubiKey
```bash
ykman info
```
### List OTP slots
```bash
ykman otp info
```
## TOTP Authenticator
Launch the GUI:
```bash
yubico-authenticator
```
Or use CLI:
```bash
# List accounts
ykman oath accounts list
# Get code
ykman oath accounts code "Account Name"
```
## FIDO2/WebAuthn
Works out of the box with modern browsers for passkeys and 2FA.
### udev rules
If YubiKey isn't detected, add udev rules:
```bash
sudo pacman -S libu2f-host
```
Or manually create `/etc/udev/rules.d/70-u2f.rules`:
```
# YubiKey
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0664", GROUP="users", ATTRS{idVendor}=="1050"
```
Reload:
```bash
sudo udevadm control --reload-rules
sudo udevadm trigger
```
## SSH Authentication
Use YubiKey for SSH keys via FIDO2:
### Generate key
```bash
ssh-keygen -t ed25519-sk -O resident -O verify-required
```
- `-t ed25519-sk` — FIDO2 key type
- `-O resident` — Store on YubiKey (discoverable)
- `-O verify-required` — Require touch + PIN
### Load resident keys
```bash
ssh-add -K # Load all resident keys from YubiKey
```
## PIV (Smart Card)
For certificate-based auth:
```bash
# Check PIV status
ykman piv info
# Generate key in slot 9a
ykman piv keys generate 9a public.pem
```
## GPG
Use YubiKey as GPG smart card:
```bash
gpg --card-status
gpg --card-edit
```
## Locking Workstation
Lock screen when YubiKey is removed:
```bash
# Install
paru -S yubikey-touch-detector
# Or use udev rule + hyprlock
```
## Resources
- Arch Wiki: https://wiki.archlinux.org/title/Smartcards
- YubiKey docs: https://docs.yubico.com/

View File

@@ -0,0 +1,120 @@
---
publish: true
permalink: /os/fprintd
title: fprintd
created: 2026-02-05T09:31:46.737-07:00
modified: 2026-02-05T12:18:16.843-07:00
tags:
- security
- fingerprint
- authentication
cssclasses: ""
---
Fingerprint authentication daemon for Linux. Works with [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/hyprlock]] and system login.
## Installation
```bash
sudo pacman -S fprintd
```
The service starts on-demand, no need to enable it.
## Enroll Fingerprints
```bash
# Enroll a finger (follow prompts)
fprintd-enroll
# Enroll specific finger
fprintd-enroll -f right-index-finger
# List enrolled fingerprints
fprintd-list $USER
```
## PAM Configuration
### For hyprlock
Create `/etc/pam.d/hyprlock`:
```
# PAM configuration file for hyprlock
auth include login
```
This inherits from the login config which includes fprintd.
### For system login
Edit `/etc/pam.d/system-local-login` — usually already configured if using default Arch PAM.
### Manual PAM setup
To add fingerprint auth to any PAM service, add before password auth:
```
auth sufficient pam_fprintd.so
```
## hyprlock Integration
Enable in `~/.config/hypr/hyprlock.conf`:
```bash
auth {
fingerprint {
enabled = true
ready_message = Scan fingerprint to unlock
present_message = Scanning...
retry_delay = 250
}
}
```
## Troubleshooting
### Check service status
```bash
systemctl status fprintd
```
### Verify device detection
```bash
fprintd-list $USER
```
Should show your fingerprint reader device.
### Re-enroll if not working
```bash
fprintd-delete $USER # Delete all prints
fprintd-enroll # Re-enroll
```
### Debug
```bash
# Run fprintd in foreground with debug
sudo /usr/libexec/fprintd -d
```
## Supported Devices
Framework Laptop 13 uses the **Goodix MOC Fingerprint Sensor** which works out of the box with fprintd.
Check if your device is supported:
```bash
lsusb | grep -i fingerprint
```
## Security Notes
- Fingerprint is "sufficient" not "required" — password always works as fallback
- Fingerprints are stored encrypted in `/var/lib/fprint/`
- Consider if fingerprint auth meets your security requirements
## Resources
- Arch Wiki: https://wiki.archlinux.org/title/Fprint

View File

@@ -0,0 +1,188 @@
---
publish: true
permalink: /os/hyprlock
title: hyprlock
created: 2026-02-05T09:31:46.736-07:00
modified: 2026-02-05T12:18:16.846-07:00
tags:
- hyprland
- lockscreen
- security
cssclasses: ""
---
hyprlock is the lock screen for Hyprland with support for fingerprint authentication.
## Installation
```bash
sudo pacman -S hyprlock
```
## My Configuration
Config: `~/.config/hypr/hyprlock.conf`
```bash
$font = Monospace
general {
hide_cursor = false
}
# Fingerprint authentication
auth {
fingerprint {
enabled = true
ready_message = Scan fingerprint to unlock
present_message = Scanning...
retry_delay = 250 # in milliseconds
}
}
animations {
enabled = true
bezier = linear, 1, 1, 0, 0
animation = fadeIn, 1, 5, linear
animation = fadeOut, 1, 5, linear
animation = inputFieldDots, 1, 2, linear
}
background {
monitor =
path = screenshot
blur_passes = 3
}
input-field {
monitor =
size = 20%, 5%
outline_thickness = 3
inner_color = rgba(0, 0, 0, 0.0) # no fill
outer_color = rgba(33ccffee) rgba(00ff99ee) 45deg
check_color = rgba(00ff99ee) rgba(ff6633ee) 120deg
fail_color = rgba(ff6633ee) rgba(ff0066ee) 40deg
font_color = rgb(143, 143, 143)
fade_on_empty = false
rounding = 15
font_family = $font
placeholder_text = Input password...
fail_text = $PAMFAIL
dots_spacing = 0.3
position = 0, -20
halign = center
valign = center
}
# TIME
label {
monitor =
text = $TIME
font_size = 90
font_family = $font
position = -30, 0
halign = right
valign = top
}
# DATE
label {
monitor =
text = cmd[update:60000] date +"%A, %d %B %Y"
font_size = 25
font_family = $font
position = -30, -150
halign = right
valign = top
}
# KEYBOARD LAYOUT
label {
monitor =
text = $LAYOUT[en,ru]
font_size = 24
onclick = hyprctl switchxkblayout all next
position = 250, -20
halign = center
valign = center
}
```
## Key Features
### Fingerprint Support
Requires [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/fprintd]] to be configured. The `auth` block enables fingerprint unlock:
```bash
auth {
fingerprint {
enabled = true
ready_message = Scan fingerprint to unlock
present_message = Scanning...
}
}
```
### Screenshot Background
Uses a screenshot of the current screen with blur:
```bash
background {
path = screenshot
blur_passes = 3
}
```
### Gradient Border
Input field has a gradient border matching Hyprland theme:
```bash
outer_color = rgba(33ccffee) rgba(00ff99ee) 45deg
```
## Integration with hypridle
hypridle triggers hyprlock on idle. See [[10-19 LIFE/13 TECH SETUP/13.13 OS SETUP/Hyprland Setup#Idle Management (hypridle)]].
Key config in `~/.config/hypr/hypridle.conf`:
```bash
general {
lock_cmd = pidof hyprlock || hyprlock # Prevent multiple instances
before_sleep_cmd = loginctl lock-session
}
listener {
timeout = 300 # 5 min
on-timeout = loginctl lock-session
}
```
## Manual Lock
```bash
hyprlock
```
Or via keybind:
```bash
bind = $mainMod, L, exec, hyprlock
```
## Shortcuts
While locked:
- `ESC` — Clear password
- `Ctrl+U` — Clear password
- `Ctrl+Backspace` — Clear password
## Resources
- Wiki: https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock

View File

@@ -0,0 +1,78 @@
---
publish: true
permalink: /os/hyprshutdown
title: hyprshutdown
created: 2026-02-05T09:31:46.735-07:00
modified: 2026-02-05T12:18:16.847-07:00
tags:
- hyprland
- shutdown
cssclasses: ""
---
hyprshutdown provides graceful shutdown/reboot with animated transitions for Hyprland.
## Installation
**From AUR:**
```bash
paru -S hyprshutdown
```
**Build from source** (if AUR is outdated):
```bash
git clone https://github.com/hyprwm/hyprshutdown
cd hyprshutdown
cmake .
make all
sudo make install
```
## Usage
```bash
# Shutdown with animation
hyprshutdown -t "Shutting down..." --post-cmd "shutdown -P 0"
# Reboot with animation
hyprshutdown -t "Restarting..." --post-cmd "reboot"
# Custom timeout (ms)
hyprshutdown -t "Goodbye!" --timeout 2000 --post-cmd "shutdown -P 0"
```
## Options
| Option | Description |
|--------|-------------|
| `-t, --text` | Message to display during animation |
| `--post-cmd` | Command to run after animation completes |
| `--timeout` | Animation duration in milliseconds |
## Integration
### Hyprland keybind
```bash
bind = $mainMod, M, exec, command -v hyprshutdown >/dev/null 2>&1 && hyprshutdown || hyprctl dispatch exit
```
### Ashell settings
In ashell config:
```toml
[settings]
shutdown_cmd = "hyprshutdown -t 'Shutting down...' --post-cmd 'shutdown -P 0'"
reboot_cmd = "hyprshutdown -t 'Restarting...' --post-cmd 'reboot'"
```
## Fallback
If hyprshutdown isn't installed, fall back to regular exit:
```bash
command -v hyprshutdown >/dev/null 2>&1 && hyprshutdown || hyprctl dispatch exit
```
## Resources
- GitHub: https://github.com/hyprwm/hyprshutdown

View File

@@ -0,0 +1,15 @@
---
publish: true
permalink: /ai/blogwatcher
title: blogwatcher
created: 2026-01-31T20:42:32.556-07:00
modified: 2026-02-05T12:18:45.700-07:00
tags:
- ai
- rss
- monitoring
cssclasses: ""
---
`go install github.com/Hyaxia/blogwatcher/cmd/blogwatcher@latest`

View File

@@ -0,0 +1,42 @@
---
publish: true
permalink: /ttrpg/daggerheart/character-creation
title: Character Creation Cheat Sheet
created: 2026-01-29T14:04:18.364-07:00
modified: 2026-02-05T12:19:54.478-07:00
tags:
- daggerheart
cssclasses: ""
---
1. Review any character creation notes from your Campaign Frame
2. Choose a class and subclass
- [Bard](https://daggerheart.su/class/bard)
- [Druid](https://daggerheart.su/class/druid)
- [Guardian](https://daggerheart.su/class/guardian)
- [Ranger](https://daggerheart.su/class/ranger)
- [Rogue](https://daggerheart.su/class/rogue)
- [Seraph](https://daggerheart.su/class/seraph)
- [Sorcerer](https://daggerheart.su/class/sorcerer)
- [Warrior](https://daggerheart.su/class/warrior)
- [Wizard](https://daggerheart.su/class/wizard)
3. Choose your heritage
- Choose your [Ancestry](https://daggerheart.su/ancestry)
- Choose your [Community](https://daggerheart.su/community)
4. Distribute trait modifiers
- You have six modifiers (+2, +1, +1, 0, 0, -1)
- These need to be distributed between the six traits (Agility, Strength, Finesse, Instinct, Presence, Knowledge)
5. Complete additional character information
- Evasion
- Hit Points
- Stress
- Hope & Fear
6. Choose starting [equipment](https://daggerheart.su/equipment)
- You will have access to tier 1 equipment only
7. Create your background
8. Create your experiences
- Each character starts with 2 experiences
9. Choose your [Domain](https://daggerheart.su/domain-card) cards
- Each class is a combination of two domains
- You may choose 2 level 1 cards total from these decks combined
10. Create your connections

View File

@@ -0,0 +1,21 @@
---
publish: true
permalink: /ttrpg/hbs
title: Holding Back Sin
created: 2026-01-29T14:04:18.607-07:00
modified: 2026-02-05T12:19:54.481-07:00
tags:
- daggerheart
- holding_back_sin
cssclasses: ""
---
## Campaign Frame
- [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/Sin Manifest]]
## Factions
- [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Church\|The Church]]
## Locations
- [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Pit\|The Pit]]
- [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/Ydrasog\|Ydrasog]]

View File

@@ -0,0 +1,61 @@
---
publish: true
permalink: /ttrpg/hbs/sin-manifest
title: "Campaign Frame: Sin Manifest"
created: 2026-01-29T14:04:18.718-07:00
modified: 2026-02-05T12:19:54.485-07:00
tags:
- daggerheart
- holding_back_sin
cssclasses: ""
---
*Designed by [[06 AUTHOR/11 METADATA/Phil Skentelbery]]*
>[!warning] Under Construction
>This page is under construction. Detail's will likely change prior to Session 0
## Pitch
Long ago, at the very edge of memory, [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Church]] imprisoned [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The First Sinner]], a fallen angel rumored to be the source of all the evil's that plague the land of [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/Ydrasog]]. In the centuries that followed The Church has held The First Sinner in a magical prison known as [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Pit]], which sits deep in the center of [[Purgatory]], a miles-wide crater that is filled with a perpetual mist.
The magic's that maintain The Pit are now beginning to fail. Evils that only existed in history books are starting to bleed into Purgatory and, unless the source of the failure can be addressed, will soon begin to spread beyond the crater and into the world. You are prisoner's of The Church and rather than risk their own, your party of Sinners has been drafted to investigate the cause of the failures and, hopefully, reverse the impacts.
### Tone & Feel
*Folk Horror, Rural Gothic, Occult, Rustic, Sinister, Supernatural*
### Themes
Apocalypse, Ends Justify Means, Redemption, Survival
### Touchstones
Hellboy: The Crooked Man, The Dark Crystal, Pointy Hat, Old Gods of Appalachia
## Character Creation
*Check the [[20-29 HOBBYS/21 TTRPG/21.11 DAGGERHEART/Character Creation\|Cheat Sheet]] for additional guidance*
### Communities
*All communities are available but some have special considerations as documented below*
**Highborne, Loreborne, Orderborne**
- In Ydrasog being a member of one of these communities most likely means being a member of The Church. Your fall from grace and designation as a Sinner means you will be frowned upon by other agents of faith. You will also struggle with the denizens of purgatory, who will see you as one of the faithful regardless.
**Ridgeborne**
- To be Ridgeborne in Ydrasog means that you belong to the communities the line the rocky terrain that makes up the rim of Purgatory. This is a harsh existence fending off the fiends that rise from the crater and the raiding parties that the scattered groups of survivors send scaling the walls looking for supplies.
**Seaborne, Wanderborne**
- Ydrasog is an insular realm that limits access to outsiders where possible. All nations however need trade and exploration and to be Seaborne or Wanderborne means you are a part of this class. Traders, explorers, and missionaries are all common in these communities.
**Underborne**
- Underborne in Ydrasog are the denizens of Purgatory. Escaping Purgatory is rare, impossible if The Church is to be believed. But stories of people escaping the crater to eek out a living in between the cities of Ydrasog persist.
### Ancestries
*All ancestries except for Infernis are available but some have special considerations as documented below*
**Clanks**
- Clanks in Ydrasog are commonly crafted from wood, stone, and occasionally flesh as opposed to metal. Metal clanks are incredibly rare and are used by The Church in their most impressive temples as servants.
**Ribbets**
- Ydrasog Ribbets are large (6-8ft tall) and have more in common with toads than frogs. They are often seen moving on all fours, standing only when needed to complete the task at hand.
### Classes
*All classes are available but some have special considerations as documented below*
**Druids, Rangers, and Sorcerers**
- These classes often worship [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Old Gods]] rather than [[The One God]] and as such often find themselves at odds with The Church.
**Seraphs and Wizards**
- Deriving their powers from The One God, these classes are often friendly with agents of The Church. Many are agents themselves and will have served in [[The Holy Militia]].
>[!warning] Syndicate Rogues
>For the purpose of this one shot Syndicate Rogues are available but will not have much use of their skills. They should be avoided unless you have a really clever plan

View File

@@ -0,0 +1,14 @@
---
publish: true
permalink: /ttrpg/hbs/the-church
title: The Church
created: 2026-01-29T14:04:18.879-07:00
modified: 2026-02-05T12:19:54.486-07:00
tags:
- daggerheart
- holding_back_sin
- faction
cssclasses: ""
---
The Church, or more accurately, The Church of [[The One God]], is the primary religion of Ydrasog. They are also the largest military power thanks to [[The Holy Militia]] as well as the most powerful political faction. The Church was not always this powerful however, prior to the imprisonment of [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The First Sinner]] in [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Pit]] they were one faith in a sea of many.

View File

@@ -0,0 +1,17 @@
---
publish: true
permalink: /ttrpg/hbs/the-first-sinner
title: The First Sinner
created: 2026-01-29T14:04:18.545-07:00
modified: 2026-02-05T12:20:02.544-07:00
tags:
- daggerheart
- holding_back_sin
cssclasses: ""
---
Little of what is known about The First Sinner can be presented as fact. [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Church]] has gone to great lengths to portray their view of the angel, their account of it's imprisonment is the only known account, their portrayal of its visage the only reference to what it may look like.
## Imprisonment
The tale of The First Sinner's imprisonment is a cornerstone of the worship of [[The One God]]. Centuries ago, after committing a sin so heinous that it had to be forgotten, The First Sinner was cast out of Paradise by The One God, but they were unable to bring themselves to destroy the angel. Instead, a brave group of heroes answered the call of The One God and vowed to end the angel's existence. They were however unable to complete their task, so great was it's power, and instead they sealed it in [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Pit]] for all eternity.
## Presentation
The First Sinner is portrayed as a beautiful, androgynous, humanoid in most literature. The Elite Guard of [[The Holy Militia]] wear helmets whose masks are purportedly casts of the angels face.

View File

@@ -0,0 +1,13 @@
---
publish: true
permalink: /ttrpg/hbs/the-old-gods
title: The Old Gods
created: 2026-01-29T14:04:18.493-07:00
modified: 2026-02-05T12:20:02.552-07:00
tags:
- daggerheart
- holding_back_sin
cssclasses: ""
---
The Old Gods is the colloquial term given to the gods that were commonly worshiped by the people of [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/Ydrasog]] prior to [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Church]] becoming the primary power in the region along with the worship of [[The One God]]. Whilst worship of The Old Gods is not illegal in Ydrasog it is frowned upon, often seen as the purview of savages and outsiders.

View File

@@ -0,0 +1,15 @@
---
publish: true
permalink: /ttrpg/hbs/the-pit
title: The Pit
created: 2026-01-29T14:04:18.361-07:00
modified: 2026-02-05T12:20:02.554-07:00
tags:
- daggerheart
- holding_back_sin
- location
cssclasses: ""
---
Little is known of The Pit by the populace of Ydrasog, save for it's purpose to contain [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The First Sinner]] and hold back the sins that spawn the ancient horrors that once plagued the land. Some claim that it is a tower of white that rises from the mists of [[Purgatory]], others say that it is a great maze of ancient stone. All that is known for sure is that it sits in the very center of Purgatory and that no one who ventures near it returns.

View File

@@ -0,0 +1,14 @@
---
publish: true
permalink: /ttrpg/hbs/ydrasog
title: Ydrasog
created: 2026-01-29T14:04:18.798-07:00
modified: 2026-02-05T12:20:02.555-07:00
tags:
- daggerheart
- holding_back_sin
- location
cssclasses: ""
---
Ydrasog is a forsaken realm where ancient curses seep from the very soil, and the boundary between the mortal world and darker realms grows thin as the magics protecting [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Pit]] grow weak. Rolling hills of sickly heath stretch between brooding forests of gnarled oak and twisted pine, their shadows harboring things that should not be. Crumbling stone circles and weathered burial mounds dot the landscape like infected wounds, while isolated hamlets huddle behind wards of iron and salt, their inhabitants speaking in hushed tones of old compacts made with entities best left unnamed. The only cities able to thrive are those protected by [[20-29 HOBBYS/21 TTRPG/21.12 HOLDING BACK SIN/The Church]], and within the walls of these metropolis' their word is law. The air itself feels heavy with malevolent intent, carrying the scent of bog water and decay, and those who venture too far into the wild places often return changed—if they return at all. Here, folklore bleeds into terrible reality, and the old ways still hold sway over a land that remembers every sin committed upon its scarred flesh.

View File

@@ -0,0 +1,56 @@
---
publish: true
permalink: /sh/garden
title: Digital Garden
created: 2026-02-05T09:58:59.613-07:00
modified: 2026-02-05T12:21:13.912-07:00
tags:
- self_hosting
- digital_gardening
- guide
cssclasses: ""
---
# Digital Garden Setup
My digital garden stack for publishing Obsidian notes to the web.
## Architecture
```
Obsidian Vault → Quartz Syncer → Quartz (build) → Caddy (serve)
Self-hosted LiveSync (multi-device editing)
```
## Components
1. [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Obsidian]] — Note-taking and editing
2. [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Quartz]] — Static site generator (Markdown → HTML)
3. [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Caddy]] — Web server with automatic HTTPS
4. [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Selfhosted Live Sync]] — Real-time sync across devices
## Setup Order
1. **[[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Obsidian]]** — Install and configure plugins
2. **[[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Selfhosted Live Sync]]** — Set up CouchDB for multi-device sync
3. **[[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Quartz]]** — Clone repo, configure, connect to vault
4. **[[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Caddy]]** — Configure reverse proxy and deploy
## Publishing Workflow
1. Write/edit notes in Obsidian (any device)
2. LiveSync keeps all devices in sync via CouchDB
3. Mark notes for publishing with `publish: true` frontmatter
4. Use Quartz Syncer plugin to push to Quartz repo
5. Build triggers (manual or CI) regenerate the site
6. Caddy serves the static files
## Quick Reference
| Component | Purpose | Tech |
|-----------|---------|------|
| Editor | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Obsidian]] | Electron app |
| Sync | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Selfhosted Live Sync]] | CouchDB |
| Generator | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Quartz]] | Node.js/TypeScript |
| Server | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Caddy]] | Go binary |

View File

@@ -0,0 +1,148 @@
---
publish: true
permalink: /sh/garden/caddy
title: Caddy
created: 2026-02-05T09:58:59.617-07:00
modified: 2026-02-05T12:21:13.914-07:00
tags:
- self_hosting
- web_server
cssclasses: ""
---
Caddy is a powerful web server with automatic HTTPS. I use it to serve my [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Quartz]] digital garden.
## Installation
**Arch Linux:**
```bash
sudo pacman -S caddy
```
**Docker:**
```bash
docker pull caddy:latest
```
**Binary:**
Download from https://caddyserver.com/download
## Basic Configuration
Caddyfile location: `/etc/caddy/Caddyfile`
### Serve Static Files
```caddyfile
garden.example.com {
root * /var/www/garden/public
file_server
# Handle SPA routing (if using Quartz SPA mode)
try_files {path} {path}/ /index.html
# Compression
encode gzip zstd
}
```
### With Reverse Proxy
If running Quartz dev server:
```caddyfile
garden.example.com {
reverse_proxy localhost:8080
}
```
## Automatic HTTPS
Caddy automatically provisions TLS certificates via Let's Encrypt. Just use a domain name and Caddy handles the rest.
Requirements:
- Domain DNS points to your server
- Ports 80 and 443 accessible
- Caddy can bind to those ports
## Running Caddy
### systemd
```bash
sudo systemctl enable --now caddy
```
### Manual
```bash
caddy run --config /etc/caddy/Caddyfile
```
### Reload config
```bash
sudo systemctl reload caddy
# or
caddy reload --config /etc/caddy/Caddyfile
```
## Digital Garden Setup
My Caddyfile for serving Quartz:
```caddyfile
garden.example.com {
root * /var/www/garden/public
file_server
# Quartz SPA routing
try_files {path} {path}.html {path}/ /index.html
# Compression for faster loads
encode gzip zstd
# Cache static assets
@static {
path *.css *.js *.woff2 *.png *.jpg *.svg
}
header @static Cache-Control "public, max-age=31536000"
# Security headers
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
}
}
```
## Deployment Workflow
1. Build Quartz: `npx quartz build`
2. Copy to server: `rsync -avz public/ server:/var/www/garden/public/`
3. Caddy automatically serves the new files
Or use a CI/CD pipeline to automate.
## Multiple Sites
```caddyfile
garden.example.com {
root * /var/www/garden/public
file_server
}
blog.example.com {
root * /var/www/blog
file_server
}
api.example.com {
reverse_proxy localhost:3000
}
```
## Resources
- Docs: https://caddyserver.com/docs/
- Caddyfile: https://caddyserver.com/docs/caddyfile

View File

@@ -0,0 +1,19 @@
---
publish: true
permalink: /sh/garden/obsidian
title: Obsidian Setup for Digital Gardening
created: 2026-01-29T14:04:18.365-07:00
modified: 2026-02-05T12:21:13.916-07:00
tags:
- self_hosting
- digital_gardening
- obsidian
cssclasses: ""
---
My current setup for digital gardening with [Obsidian](https://obsidian.md) is very lightweight by design, plugin bloat is real and detracts from the simplicity that allows me to just get things done.
## Plugins
- Harper - Great for spelling and grammar checks
- Quartz Syncer - Used to synchronize my vault contents to my [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Quartz]] repo
- Dataview - I just cannot live without this
- Self-hosted LiveSync - For editing on multiple devices

View File

@@ -0,0 +1,179 @@
---
publish: true
permalink: /sh/garden/quartz
title: Quartz
created: 2026-02-05T09:58:59.615-07:00
modified: 2026-02-05T12:21:13.918-07:00
tags:
- self_hosting
- digital_gardening
- static_site
cssclasses: ""
---
Quartz is a fast, batteries-included static-site generator that transforms Markdown content into fully functional websites. Perfect for publishing [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Obsidian]] vaults as digital gardens.
## Features
- **Obsidian compatibility** — Wikilinks, callouts, backlinks
- **Full-text search** — Client-side search
- **Graph view** — Interactive note connections
- **Popover previews** — Hover to preview linked notes
- **Fast** — SPA routing, tiny bundles
- **Customizable** — JSX components, plugin system
## Installation
Requires Node.js v22+.
```bash
git clone https://github.com/jackyzha0/quartz.git
cd quartz
npm i
npx quartz create
```
Follow the prompts to initialize with your content.
## Configuration
Main config: `quartz.config.ts`
```typescript
const config: QuartzConfig = {
configuration: {
pageTitle: "My Digital Garden",
enableSPA: true,
enablePopovers: true,
analytics: null, // or plausible, umami, etc.
locale: "en-US",
baseUrl: "garden.example.com",
ignorePatterns: ["private", ".obsidian"],
defaultDateType: "modified",
theme: {
cdnCaching: true,
typography: {
header: "Schibsted Grotesk",
body: "Source Sans Pro",
code: "IBM Plex Mono",
},
colors: {
lightMode: { /* ... */ },
darkMode: { /* ... */ },
},
},
},
plugins: { /* ... */ },
}
```
## Content
All content lives in `/content` folder. Home page is `content/index.md`.
### Frontmatter
```yaml
---
title: My Note
description: A description for previews
tags:
- example
draft: false # true = don't publish
publish: true # used by Quartz Syncer
date: 2026-02-05
---
```
### Supported Syntax
- Standard Markdown + GFM (tables, footnotes, task lists)
- Obsidian wikilinks: `[[Note Name]]`
- Obsidian callouts: `> [!info]`
- LaTeX math: `$inline$` and `$$block$$`
- Syntax highlighting
## Building
```bash
# Development (hot reload)
npx quartz build --serve
# Production build
npx quartz build
# Output goes to /public
```
## Syncing Content
### Manual
```bash
npx quartz sync
```
### Quartz Syncer Plugin (Recommended)
Install the **Quartz Syncer** plugin in [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Obsidian]]:
1. Install from Community Plugins
2. Configure Git provider (GitHub, GitLab, etc.)
3. Set Quartz repo path
4. Use plugin to selectively publish notes
Features:
- Compiles Dataview queries to static content
- Diff viewer before publishing
- Selective publish/update/remove
- Smart caching
## Hosting Options
### Self-hosted with [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Caddy]]
Build locally or via CI, serve `/public` with Caddy.
### GitHub Pages
Add `.github/workflows/deploy.yml`:
```yaml
name: Deploy Quartz
on:
push:
branches: [v4]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npx quartz build
- uses: actions/upload-pages-artifact@v3
with:
path: public
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
steps:
- uses: actions/deploy-pages@v4
```
### Cloudflare Pages
- Build command: `npx quartz build`
- Output directory: `public`
- Production branch: `v4`
## Resources
- Docs: https://quartz.jzhao.xyz/
- GitHub: https://github.com/jackyzha0/quartz
- Quartz Syncer: https://github.com/saberzero1/quartz-syncer

View File

@@ -0,0 +1,158 @@
---
publish: true
permalink: /sh/garden/livesync
title: Self-hosted LiveSync
created: 2026-02-05T09:58:59.620-07:00
modified: 2026-02-05T12:21:13.920-07:00
tags:
- self_hosting
- obsidian
- sync
cssclasses: ""
---
Self-hosted LiveSync is a community plugin for [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Obsidian]] that enables real-time synchronization across devices using CouchDB or object storage.
## Features
- **Real-time sync** — Changes sync immediately
- **Conflict resolution** — Automatic merging of simple conflicts
- **End-to-end encryption** — Data encrypted before leaving device
- **Self-hosted** — Your data on your server
- **Multi-platform** — Works on all Obsidian platforms (desktop, mobile)
## Architecture
```
Device A (Obsidian) ←→ CouchDB Server ←→ Device B (Obsidian)
```
All devices sync to a central CouchDB instance. Changes propagate in real-time.
## Server Setup (CouchDB)
### Docker (Recommended)
```yaml
# docker-compose.yml
version: "3"
services:
couchdb:
image: couchdb:latest
restart: always
ports:
- "5984:5984"
environment:
- COUCHDB_USER=admin
- COUCHDB_PASSWORD=your-secure-password
volumes:
- ./couchdb-data:/opt/couchdb/data
```
```bash
docker-compose up -d
```
### Configure CouchDB
Access Fauxton UI at `http://server:5984/_utils`
1. Create a database for your vault (e.g., `obsidian-vault`)
2. Configure CORS if accessing from different domains
### CORS Setup
In Fauxton → Configuration → CORS:
- Enable CORS
- Set origins to `app://obsidian.md` and your domain
Or via curl:
```bash
curl -X PUT http://admin:password@localhost:5984/_node/_local/_config/httpd/enable_cors -d '"true"'
curl -X PUT http://admin:password@localhost:5984/_node/_local/_config/cors/origins -d '"app://obsidian.md"'
curl -X PUT http://admin:password@localhost:5984/_node/_local/_config/cors/credentials -d '"true"'
curl -X PUT http://admin:password@localhost:5984/_node/_local/_config/cors/methods -d '"GET, PUT, POST, HEAD, DELETE"'
curl -X PUT http://admin:password@localhost:5984/_node/_local/_config/cors/headers -d '"accept, authorization, content-type, origin, referer"'
```
## Plugin Setup
1. Install **Self-hosted LiveSync** from Obsidian Community Plugins
2. Open plugin settings
3. Configure connection:
- URI: `https://couchdb.example.com`
- Username: your CouchDB user
- Password: your CouchDB password
- Database: `obsidian-vault`
4. Set up encryption passphrase (all devices must use same passphrase)
5. Test connection
6. Enable sync
## Sync Modes
| Mode | Description |
|------|-------------|
| LiveSync | Real-time sync (uses more bandwidth) |
| Periodic | Sync at intervals |
| On file save | Sync when files change |
## Customization Sync
Sync settings, themes, plugins across devices:
Settings → Customization Sync → Enable
Select what to sync:
- Settings files
- Snippets
- Themes
- Plugins (careful with this)
## Encryption
Always enable end-to-end encryption:
1. Settings → Encryption → Enable
2. Set passphrase (same on all devices)
3. All data is encrypted before upload
## Troubleshooting
### Sync not working
```bash
# Check CouchDB is running
curl http://localhost:5984
# Check database exists
curl http://admin:password@localhost:5984/obsidian-vault
```
### Conflicts
Plugin shows conflict indicator. Open note to resolve:
- View both versions
- Choose or merge manually
- Conflicts auto-resolve if possible
### Rebuild database
If sync gets corrupted:
1. Disable sync on all devices
2. Delete database in CouchDB
3. Re-create database
4. Rebuild from primary device
5. Re-enable on other devices
## Alternatives to CouchDB
LiveSync also supports:
- MinIO (S3-compatible)
- Cloudflare R2
- AWS S3
- WebRTC (peer-to-peer, experimental)
## Resources
- GitHub: https://github.com/vrtmrz/obsidian-livesync
- Docs: https://github.com/vrtmrz/obsidian-livesync/blob/main/docs/

View File

@@ -0,0 +1,31 @@
---
publish: true
permalink: /sh/garden/setup
title: Digital Garden Setup
created: 2026-01-29T14:04:18.669-07:00
modified: 2026-02-05T12:21:19.644-07:00
tags:
- self_hosting
- digital_gardening
cssclasses: ""
---
This Digital Garden is built with a self-hosted stack:
| Layer | Tool | Purpose |
|-------|------|---------|
| Editor | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Obsidian]] | Write and organize notes |
| Sync | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Selfhosted Live Sync]] | Real-time multi-device sync |
| Generator | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Quartz]] | Convert Markdown to static site |
| Server | [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Caddy]] | Serve with automatic HTTPS |
## Why Self-Hosted?
- **Privacy** — Notes stay on my infrastructure
- **Control** — No vendor lock-in
- **Learning** — Understanding the full stack
- **Cost** — Cheap VPS vs subscription services
## See Also
- [[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/00 - Start Here]] — Full setup guide with ordering

View File

@@ -0,0 +1,10 @@
---
publish: true
permalink: /sh/services/gotosocial
title: GoToSocial
created: 2026-01-29T14:04:18.591-07:00
modified: 2026-02-05T12:21:24.501-07:00
cssclasses: ""
---
I host [GoToSocial](https://gotosocial.org/) on a VPS. It is my primary [Fediverse](https://en.wikipedia.org/wiki/Fediverse) interface and it has been more than adequate for my needs. The only thing I do that is of much difference to the standard deployment is that I back up the docker volume using my standard [[10-19 LIFE/13 TECH SETUP/13.12 PROCESSES/Backups\|backup]] process for cloud services.

View File

@@ -0,0 +1,13 @@
---
publish: true
permalink: /sh/services/syncthing
title: Syncthing
created: 2026-01-29T14:04:18.802-07:00
modified: 2026-02-05T12:21:24.504-07:00
cssclasses: ""
---
Used for data synchronization and [[10-19 LIFE/13 TECH SETUP/13.12 PROCESSES/Backups\|backup]] between devices
## Knowledge Base
### Password Reset
Resetting the password for Syncthing is fairly trivial so long as you have access to the config file. Simply pop it open, find the user and password lines, delete them, and restart.

View File

@@ -0,0 +1,16 @@
---
publish: true
permalink: /security/evilginx
title: Evilginx
created: 2026-01-29T14:04:18.808-07:00
modified: 2026-02-05T12:21:58.021-07:00
tags:
- guide
- evilginx
cssclasses: ""
---
## Setup and Tutorial
- [[20-29 HOBBYS/23 SECURITY/23.11 EVILGINX/Installation of Community Edition\|Installation]]<--Start here
- [[20-29 HOBBYS/23 SECURITY/23.11 EVILGINX/configuration\|Configuration Basics]]
- [[20-29 HOBBYS/23 SECURITY/23.11 EVILGINX/phish setup\|My First Phishing Test]]

View File

@@ -0,0 +1,68 @@
---
publish: true
permalink: /security/evilginx/install
title: Installing Evilginx Community Edition
created: 2026-01-29T14:04:18.369-07:00
modified: 2026-02-05T12:21:58.024-07:00
tags:
- phishing
- evilginx
- guide
cssclasses: ""
---
With commercialization comes the enshitification of community editions, and this is equally true for Evilginx sadly. They have made it very clear in their documentation that they no longer want to make it obvious for users to install without paying so here are my installation notes for those who follow.
>[!info]
>My install was performed on a VPS running Debian 12. YMMV if you are using a different distro
>
>This guide covers software installation only. The official Evilginx documentation for domain setup is adequate
>[!note] Prior to installing Evilginx I completed some basic server setup work that you can find [[20-29 HOBBYS/23 SECURITY/23.11 EVILGINX/basic configuration\|here]]
1. Install prerequisite packages
```
apt install git make golang tmux
```
>[!note]
>The `tmux` package is not required for the install but is highly recommended for running the service so I have included it here
>
2. Clone the git repository at the latest stable tag (3.3.0 at time of writing)
```
git clone --depth 1 --branch v3.3.0 https://github.com/kgretzky/evilginx2.git
```
3. Build the software
```
cd evilginx2
make
```
4. Create a directory for the Evilginx binary and configurations
```
mkdir ~/evilginx
```
5. Copy the binary and necessary directories to the application folder
```
cp ./build/evilginx ~/evilginx
cp -r ./phishlets/ ~/evilginx
cp -r ./redirectors/ ~/evilginx
```
6. Make sure everything is executable
```
chmod 700 ~/evilginx
```
From here you can move on to [[20-29 HOBBYS/23 SECURITY/23.11 EVILGINX/configuration]]

View File

@@ -0,0 +1,45 @@
---
publish: true
permalink: /security/evilginx/basic-config
title: Server bootstrapping
created: 2026-01-29T14:04:18.492-07:00
modified: 2026-02-05T12:21:58.025-07:00
tags:
- evilginx
- guide
- self_hosting
cssclasses: ""
---
## Install and configure ufw
1. Install the ufw package
```
apt install ufw
```
2. Set the default ufw policies
```
ufw default deny incoming
ufw default allow outgoing
```
3. Allow required traffic
>[!note]
>For the purpose of a basic Evilginx setup on a remote server we will allow ssh, dns, and https but add other services as necessary for your setup
```
ufw allow ssh
ufw allow 53
ufw allow https
```
4. Enable the firewall
```
ufw enable
```
At this point your server has **BASIC** protections.

View File

@@ -0,0 +1,50 @@
---
publish: true
permalink: /security/evilginx/config
title: Evilginx Configuration
created: 2026-01-29T14:04:18.516-07:00
modified: 2026-02-05T12:21:58.027-07:00
tags:
- evilginx
- guide
- phishing
cssclasses: ""
---
>[!info]
>These are my notes on my specific steps to configure Evilginx. I have tried to highlight things that you would need to change for your deployment scenario but no guarantees!
1. Start a new tmux session for Evilginx
```
tmux new-session -A -s evilginx
```
>[!note]
>This command will attempt to attach (the `-A` argument) to an existing session called evilginx (specified by `-s evilginx`) before creating a new one
2. Launch Evilginx
```
~/evilginx/evilginx
```
3. At the Evilginx prompt set your domain and IP
```
config domain philsphishpharm.click
config ipv4 external 80.78.25.193
config ipv4 bind 80.78.25.193
```
4. You will need to restart Evilginx to apply the configuration
```
(At the Evilginx prompt)
exit
(At the system prompt)
~/evilginx/evilginx
```
At this point Evilginx should be configured at ready for you to [[20-29 HOBBYS/23 SECURITY/23.11 EVILGINX/phish setup\|start phishing]]!

View File

@@ -0,0 +1,55 @@
---
publish: true
permalink: /security/evilginx/phish-setup
title: Basic Phish Setup
created: 2026-01-29T14:04:18.366-07:00
modified: 2026-02-05T12:21:58.028-07:00
tags:
- evilginx
- guide
- phishing
cssclasses: ""
---
>[!note]
>As previously discussed the community edition of Evilginx has been kneecapped so the quickstart example in their documentation will not work. This guide will give a rough approximation of that tutorial
1. Install `curl`
```
apt install curl
```
2. Create the LinkedIn phishlet. This downloads a copy of a phishlet for my pastebin to replace the one the Evilginx team removed
```
curl -o ~/evilginx/phishlets/linkedin.yaml https://snippets.thesatelliteoflove.com/api/public/snippets/1/1/raw
```
3. Connect to your Evilginx tmux session and launch Evilginx
```
tmux new-session -A -s evilginx
~/evilginx/evilginx
```
4. Assign a hostname to the LinkedIn phishlet
```
phishlets hostname linkedin demo.philsphishpharm.click
```
5. Enable your phishlet
```
phishlets enable linkedin
```
6. Create a lure (link) for your phishlet. Once created the second command will return the link (assuming this is your first lure)
```
lures create linkedin
lures get-url 0
```
You now have a valid phising url. Good job!

View File

@@ -0,0 +1,135 @@
---
publish: true
permalink: /mtg/limited/ff-draft
title: Final Fantasy Draft Notes
created: 2026-01-29T14:04:18.666-07:00
modified: 2026-02-05T12:22:25.497-07:00
tags:
- mtg
cssclasses: ""
---
## Sign post cards
[Tier list](https://draftsim.com/FIN-pick-order.php)
Pay particular attention to BG and UR options
### A Grade Cards
- **Dion, Bahamut's Dominant // Bahamut, Warden of Light** (White)
- **Urza, Lord High Artificer*** (Blue)
- **Jill, Shiva's Dominant // Shiva, Warden of Ice** (Blue)
- **Ardyn, the Usurper** (Black)
- **Nibelheim Aflame** (Red)
- **Smuggler's Copter*** (Colorless)
- **Sazh Katzroy** (Green)
- **Sin, Spira's Punishment** (Multicolor)
- **Atraxa, Grand Unifier*** (Multicolor)
### A- Grade Cards
- **Ultima** (White)
- **Summon: Leviathan** (Blue)
- **Sephiroth, Fabled SOLDIER // Sephiroth, One-Winged Angel** (Black)
- **Summon: Primal Odin** (Black)
- **Yawgmoth, Thran Physician*** (Black)
- **Winota, Joiner of Forces*** (Multicolor)
### B+ Grade Cards
- **Machinist's Arsenal** (White)
- **Summon: Knights of Round** (White)
- **Venat, Heart of Hydaelyn // Hydaelyn, the Mothercrystal** (White)
- **Adeline, Resplendent Cathar*** (White)
- **Akroma's Will*** (White)
- **Sram, Senior Edificer*** (White)
- **The Lunar Whale** (Blue)
- **Memories Returning** (Blue)
- **Cryptic Command*** (Blue)
- **Cecil, Dark Knight // Cecil, Redeemed Paladin** (Black)
- **Zenos yae Galvus // Shinryu, Transcendent Rival** (Black)
- **Varragoth, Bloodsky Sire*** (Black)
- **Choco-Comet** (Red)
- **Gilgamesh, Master-at-Arms** (Red)
- **Buster Sword** (Colorless)
- **Esper Origins // Summon: Esper Maduin** (Green)
- **Summon: Titan** (Green)
- **Primeval Titan*** (Green)
- **Cloud of Darkness** (Multicolor)
- **Emet-Selch, Unsundered // Hades, Sorcerer of Eld** (Multicolor)
- **Jenova, Ancient Calamity** (Multicolor)
- **Joshua, Phoenix's Dominant // Phoenix, Warden of Fire** (Multicolor)
- **Kefka, Court Mage // Kefka, Ruler of Ruin** (Multicolor)
- **Kuja, Genome Sorcerer // Trance Kuja, Fate Defied** (Multicolor)
- **Yuna, Hope of Spira** (Multicolor)
- **Bruse Tarl, Boorish Herder*** (Multicolor)
- **Muldrotha, the Gravetide*** (Multicolor)
### B Grade Cards
- **Adelbert Steiner** (White)
- **Battle Menu** (White)
- **Cloud, Midgar Mercenary** (White)
- **Delivery Moogle** (White)
- **Dragoon's Lance** (White)
- **Moogles' Valor** (White)
- **Kenrith, the Returned King*** (White)
- **Loran of the Third Path*** (White)
- **Dragoon's Wyvern** (Blue)
- **Swallowed by Leviathan** (Blue)
- **Valkyrie Aerial Unit** (Blue)
- **Y'shtola Rhul** (Blue)
- **Venser, Shaper Savant*** (Blue)
- **Jecht, Reluctant Guardian // Braska's Final Aeon** (Black)
- **Ninja's Blades** (Black)
- **Overkill** (Black)
- **Fatal Push*** (Black)
- **Gix, Yawgmoth Praetor*** (Black)
- **Clive, Ifrit's Dominant // Ifrit, Warden of Inferno** (Red)
- **Firion, Wild Rose Warrior** (Red)
- **Samurai's Katana** (Red)
- **Seifer Almasy** (Red)
- **Summon: G.F. Cerberus** (Red)
- **Zell Dincht** (Red)
- **Captain Lannery Storm*** (Red)
- **Godo, Bandit Warlord*** (Red)
- **Lightning Bolt*** (Red)
- **Ragavan, Nimble Pilferer*** (Red)
- **Summon: Bahamut** (Colorless)
- **The Regalia** (Colorless)
- **Sazh's Chocobo** (Green)
- **Summon: Fenrir** (Green)
- **Traveling Chocobo** (Green)
- **Vanille, Cheerful l'Cie** (Green)
- **Zanarkand, Ancient Metropolis // Lasting Fayth** (Land)
- **Absolute Virtue** (Multicolor)
- **The Emperor of Palamecia // The Lord Master of Hell** (Multicolor)
- **Exdeath, Void Warlock // Neo Exdeath, Dimension's End** (Multicolor)
- **Garland, Knight of Cornelia // Chaos, the Endless** (Multicolor)
- **Locke Cole** (Multicolor)
- **Shantotto, Tactician Magician** (Multicolor)
- **Squall, SeeD Mercenary** (Multicolor)
- **Zidane, Tantalus Thief** (Multicolor)
- **Kraum, Ludevic's Opus*** (Multicolor)
- **Vial Smasher the Fierce*** (Multicolor)
### B- Grade Cards
- **Aerith Gainsborough** (White)
- **Magitek Armor** (White)
- **White Auracite** (White)
- **Mangara, the Diplomat*** (White)
- **Astrologian's Planisphere** (Blue)
- **Eject** (Blue)
- **Il Mheg Pixie** (Blue)
- **Summon: Shiva** (Blue)
- **Travel the Overworld** (Blue)
- **Circle of Power** (Black)
- **Dark Confidant** (Black)
- **The Final Days** (Black)
- **Sidequest: Hunt the Mark // Yiazmat, Ultimate Mark** (Black)
- **Vayne's Treachery** (Black)
- **Thunder Magic** (Red)
- **Ancient Adamantoise** (Green)
- **Summon: Fat Chocobo** (Green)
- **Torgal, A Fine Hound** (Green)
- **Balamb Garden, SeeD Academy // Balamb Garden, Airborne** (Land)
- **Gladiolus Amicitia** (Multicolor)
- **Ignis Scientia** (Multicolor)
- **Lightning, Army of One** (Multicolor)
- **Omega, Heartless Evolution** (Multicolor)
- **Rinoa Heartilly** (Multicolor)
- **Rufus Shinra** (Multicolor)
- **Terra, Magical Adept // Esper Terra** (Multicolor)
- **Vivi Ornitier** (Multicolor)

View File

@@ -0,0 +1,108 @@
---
publish: true
permalink: /mtg/commander/necrons
title: "Deck: Nasty Nasty Necrons"
created: 2026-01-29T14:04:18.368-07:00
modified: 2026-02-05T12:22:25.500-07:00
tags:
- mtg
- commander
- deck
- mono-black
cssclasses: ""
---
## Change Tracking
| Version | Date | Notes |
| ------- | -------- | ---------------------------- |
| 1.0 | 7/3/2025 | Initial version of this deck |
## Notes
Inspired by [MTGGoldfish](https://www.mtggoldfish.com/articles/warhammer-40-000-precon-upgrade-guide-necron-dynasties-30)
## Deck
### Creatures
| Card Name | Mana Cost | Notes |
| ------------------------------------------------------------------------------------------------------------- | ------------ | --------- |
| [Meteor Golem](https://api.scryfall.com/cards/e681f44b-17af-4d4b-a7fa-9445e6001a5f?format=image) | {7} | |
| [Scarecrone](https://api.scryfall.com/cards/1978400d-a8f1-4df7-8caf-b9ca81334bce?format=image) | {3} | |
| [Trazyn the Infinite](https://api.scryfall.com/cards/1ae95cfb-1c3e-43cc-acfa-68f25b0f6e52?format=image) | {4}{B}{B} | |
| [Shard of the Void Dragon](https://api.scryfall.com/cards/41dd0b55-3dbb-4b65-a949-20c2a12f7edd?format=image) | {4}{B}{B}{B} | |
| [Shard of the Nightbringer](https://api.scryfall.com/cards/21e4140e-22b3-479f-a259-0f56ed02b8ad?format=image) | {5}{B}{B}{B} | |
| [Scrap Trawler](https://api.scryfall.com/cards/68abc75f-596f-4169-96fc-ada941ef47ed?format=image) | {3} | |
| [Metalwork Colossus](https://api.scryfall.com/cards/df3e046e-ff1b-4bee-8611-229d0088f5a1?format=image) | {11} | |
| [Illuminor Szeras](https://api.scryfall.com/cards/d161a190-3c85-4207-9d88-7ff9213efea8?format=image) | {2}{B} | Commander |
| [Necron Deathmark](https://api.scryfall.com/cards/4129cb0d-eefe-4971-9db8-1196201ef353?format=image) | {3}{B}{B} | |
| [Imotekh the Stormlord](https://api.scryfall.com/cards/286ff901-1faf-4a02-a37a-fa165989112f?format=image) | {2}{B}{B} | |
| [Anrakyr the Traveller](https://api.scryfall.com/cards/6ea09406-c65e-4ee4-9c74-0553e5110837?format=image) | {4}{B} | |
| [Myr Retriever](https://api.scryfall.com/cards/7f0149d4-0731-474a-a1c3-28c25e486c14?format=image) | {2} | |
| [Workshop Assistant](https://api.scryfall.com/cards/e9387e8f-0e72-4212-81c8-e64050700c52?format=image) | {3} | |
| [Grim Haruspex](https://api.scryfall.com/cards/358ade1a-375d-44b4-910f-21d53c7498bb?format=image) | {2}{B} | |
| [Cryptek](https://api.scryfall.com/cards/ea8483a2-9135-48d1-994d-9525d5ffcabb?format=image) | {3}{B} | |
| [Psychomancer](https://api.scryfall.com/cards/780743bf-e1a0-4114-9474-319632e0c775?format=image) | {1}{B} | |
| [Chronomancer](https://api.scryfall.com/cards/a960acea-3404-4834-9296-d6715add49af?format=image) | {1}{B} | |
| [Canoptek Spyder](https://api.scryfall.com/cards/56ae1e4b-b620-480b-b6fc-66f2137d7d89?format=image) | {5} | |
| [Solemn Simulacrum](https://api.scryfall.com/cards/71ec1e1d-8c7b-40e9-b916-440f8acf3ea5?format=image) | {4} | |
| [Voltaic Construct](https://api.scryfall.com/cards/a1ca55ec-d262-40d8-b654-40e177bcfd6e?format=image) | {4} | |
| [Junk Diver](https://api.scryfall.com/cards/2fd4e90a-0b4e-431d-9265-1cd4be8592f0?format=image) | {3} | |
| [Smothering Abomination](https://api.scryfall.com/cards/cd81d0de-01a3-4f28-8a2b-c2e6f36a03c4?format=image) | {2}{B}{B} | |
| [Sojourner's Companion](https://api.scryfall.com/cards/8c6af084-eee7-4259-a58b-a866e0cf171b?format=image) | {7} | |
| [Canoptek Scarab Swarm](https://api.scryfall.com/cards/3ce2021c-1422-4901-a554-2d4fab72c8e4?format=image) | {4} | |
| [Disciple of the Vault](https://api.scryfall.com/cards/4c539843-4e3f-47a7-92e1-412eaaa2d9c5?format=image) | {B} | |
| [Technomancer](https://api.scryfall.com/cards/c160c1f7-714e-444a-ab74-c64c3a099a48?format=image) | {5}{B}{B} | |
| [Noxious Gearhulk](https://api.scryfall.com/cards/96886e7f-66b2-4f67-a5c6-c65500bcfdef?format=image) | {4}{B}{B} | |
| [Scrapyard Recombiner](https://api.scryfall.com/cards/8945f5e0-c143-47ca-910e-32ad9ac34487?format=image) | {3} | |
| [Jhoira's Familiar](https://api.scryfall.com/cards/7b89a074-9aca-4f7f-953a-b401199be1cb?format=image) | {4} | |
| [Shimmer Myr](https://api.scryfall.com/cards/8609dc53-774f-4abe-a312-0ff7133d536b?format=image) | {3} | |
| [Shadow of Mortality](https://api.scryfall.com/cards/22487ad9-c18f-4c38-9791-5dea3c322042?format=image) | {13}{B}{B} | |
| [Frogmite](https://api.scryfall.com/cards/0665de15-bfd3-4b08-9712-dfcc7907607a?format=image) | {4} | |
| [Cryptothrall](https://api.scryfall.com/cards/086d94a0-763e-495e-b952-5c13383657c9?format=image) | {4} | |
| [Skorpekh Lord](https://api.scryfall.com/cards/b768ec5f-771a-4acd-b3dd-85dea914689e?format=image) | {2}{B} | |
| [Dross Scorpion](https://api.scryfall.com/cards/27c5381c-2e79-41fa-b1d7-2cf0c6dc1808?format=image) | {4} | |
| [Lokhust Heavy Destroyer](https://api.scryfall.com/cards/4665fa5d-37ea-4898-a4a4-7bc5311075de?format=image) | {1}{B}{B}{B} | |
| [Royal Warden](https://api.scryfall.com/cards/0a968eac-2840-41ba-b7de-3182964d4913?format=image) | {3}{B}{B} | |
| [Midnight Reaper](https://api.scryfall.com/cards/33c16202-4d7f-449c-8b29-144b2a9fda9a?format=image) | {2}{B} | |
| [Triarch Praetorian](https://api.scryfall.com/cards/5ad67a79-cb13-44b8-adac-36cfd211f2d3?format=image) | {1}{B} | |
| [Foundry Inspector](https://api.scryfall.com/cards/9a0bd043-ae62-41fe-a33b-989acd89b175?format=image) | {3} | |
| [Canoptek Tomb Sentinel](https://api.scryfall.com/cards/aec9ba42-4c58-4e40-a8c5-63da81c44616?format=image) | {4} | |
| [Myr Enforcer](https://api.scryfall.com/cards/bd437677-8b07-4fa2-8691-fc65684f0efc?format=image) | {7} | |
| [Cathodion](https://api.scryfall.com/cards/13ddba34-e627-4f4c-b78c-ea0c48a22537?format=image) | {3} | |
### Other Cards
| Card Name | Mana Cost |
|-----------|-----------|
| [Staff of Domination](https://api.scryfall.com/cards/7980fc3b-71d5-427d-bd42-087256fd2059?format=image) | {3} |
| [Their Number Is Legion](https://api.scryfall.com/cards/f03c1eb4-1f47-4b65-8d8d-4057fb6997e1?format=image) | {X}{B}{B}{B}{B} |
| [Morbid Curiosity](https://api.scryfall.com/cards/03898f46-a26c-4765-8f1e-ea976fc53d7e?format=image) | {1}{B}{B} |
| [Cranial Plating](https://api.scryfall.com/cards/e1375f17-bc25-4a65-98b7-4785bbdbe974?format=image) | {2} |
| [Nim Deathmantle](https://api.scryfall.com/cards/787b1cc8-42b4-4d3e-9b8a-a252de297b1a?format=image) | {2} |
| [Arcane Signet](https://api.scryfall.com/cards/44ff370e-b72d-4a6c-b6dd-8434820559cc?format=image) | {2} |
| [Sceptre of Eternal Glory](https://api.scryfall.com/cards/bc7f3009-c852-41e7-8e62-d2ee637b3998?format=image) | {4} |
| [Ghost Ark](https://api.scryfall.com/cards/2c6865c1-8144-4b06-a599-a62382fe1124?format=image) | {4} |
| [Sol Ring](https://api.scryfall.com/cards/e07f656c-97b5-4147-821a-edbb49f34e19?format=image) | {1} |
| [Skullclamp](https://api.scryfall.com/cards/04733881-38a3-404c-837f-fad3fc5a5647?format=image) | {1} |
| [Dread Return](https://api.scryfall.com/cards/96aa9e00-e73e-4a6e-9607-77533aac4be4?format=image) | {2}{B}{B} |
| [Caged Sun](https://api.scryfall.com/cards/e828d87a-f2c7-475b-8c8f-b36474c50cf9?format=image) | {6} |
| [Wayfarer's Bauble](https://api.scryfall.com/cards/57ead261-d358-419e-b832-086439c5e793?format=image) | {1} |
| [Sculpting Steel](https://api.scryfall.com/cards/41368983-14f8-4efa-bb60-b0a7ceb3d021?format=image) | {3} |
| [Living Death](https://api.scryfall.com/cards/9e03a4fe-6ee5-423b-bc05-452e8d14507b?format=image) | {3}{B}{B} |
| [Mask of Memory](https://api.scryfall.com/cards/30acbb34-3ff5-4d38-b349-f108351f94f8?format=image) | {2} |
| [Gate to the Afterlife](https://api.scryfall.com/cards/8b544a59-86b9-447d-b54d-b94a262b6866?format=image) | {3} |
| [Mutilate](https://api.scryfall.com/cards/b931c7cb-ef83-440c-9195-ace311f4a601?format=image) | {2}{B}{B} |
| [Mystic Forge](https://api.scryfall.com/cards/cf56bef3-7f0e-47b4-96f5-325722f7708a?format=image) | {4} |
| [Mind Stone](https://api.scryfall.com/cards/52284689-f2e0-442d-80d0-9e766759e2bc?format=image) | {2} |
| [Their Name Is Death](https://api.scryfall.com/cards/ea5ddc28-dfc1-4b96-b6e2-590fcb1f83ef?format=image) | {3}{B}{B}{B} |
### Lands
| Card Name | Count |
|-----------|-------|
| [Barren Moor](https://api.scryfall.com/cards/22a7ef45-0fa0-4924-955c-27da5f6d0098?format=image) | 1 |
| [Tomb Fortress](https://api.scryfall.com/cards/5ffd1a43-5613-4058-9e51-fd3cc1585651?format=image) | 1 |
| [Desert of the Glorified](https://api.scryfall.com/cards/f9161bb7-07db-468f-b944-37a90fa0e4d9?format=image) | 1 |
| [Swamp](https://api.scryfall.com/cards/f6497c73-4bbb-4923-8151-8234c98ca6d4?format=image) | 30 |
| [Vault of Whispers](https://api.scryfall.com/cards/4dca7b45-164d-4181-9585-5d0f3b6a6927?format=image) | 1 |
| [Myriad Landscape](https://api.scryfall.com/cards/a3a12e0f-85de-440f-8a7d-230bf8c415c1?format=image) | 1 |
| [Reliquary Tower](https://api.scryfall.com/cards/fc07ad3a-982a-4bfc-b2e7-8e6e340ed32c?format=image) | 1 |

View File

@@ -0,0 +1,28 @@
---
publish: true
permalink: /mtg/commander/nids
title: 'Deck: Nid that goes "PING"'
created: 2026-01-29T14:04:18.574-07:00
modified: 2026-02-05T12:22:25.502-07:00
tags:
- mtg
- commander
- deck
cssclasses: ""
---
## Change Tracking
| Version | Date | Notes |
| ------- | -------- | ----------- |
| 0.1 | 7/3/2025 | Design mode |
## Notes
Inspired by [MTGGoldfish](https://www.mtggoldfish.com/price/Warhammer+40K+Commander+Decks/Ghyrson+Starn+Kelermorph#paper)
## Deck
### Creatures
| Card Name | Mana Cost | Notes |
| --------------------------------------------------------------------------------------- | --------- | --------- |
| [Ghyrson Starn, Kelermorph](https://scryfall.com/card/40k/124/ghyrson-starn-kelermorph) | {1}{U}{R} | Commander |
| | | |

View File

@@ -0,0 +1,12 @@
---
publish: true
permalink: /mtg/pauper/planning
title: Pauper Planning
created: 2026-01-29T14:04:18.357-07:00
modified: 2026-02-05T12:22:25.503-07:00
tags:
- mtg
cssclasses: ""
---
Section coming soon...

13
content/index.md Normal file
View File

@@ -0,0 +1,13 @@
---
publish: true
permalink: /index.md
title: Home
created: 2026-01-29T14:04:18.325-07:00
modified: 2026-01-19T17:58:25.379-07:00
cssclasses: ""
---
>[!warning] Under Construction
>This site is under construction and cannot be trusted
[[20-29 HOBBYS/22 SELF HOSTING/22.11 DIGITAL GARDEN/Setup\|Learn more about this digital garden]]

View File

@@ -5,3 +5,7 @@ You can run the below one-liner to run Quartz in Docker.
```sh
docker run --rm -itp 8080:8080 -p 3001:3001 -v ./content:/usr/src/app/content $(docker build -q .)
```
> [!warning] Not to be used for production
> Serve mode is intended for local previews only.
> For production workloads, see the page on [[hosting]].

View File

@@ -8,7 +8,7 @@ By default, Quartz only fetches previews for pages inside your vault due to [COR
When [[creating components|creating your own components]], you can include this `popover-hint` class to also include it in the popover.
Similar to Obsidian, [[quartz layout.png|images referenced using wikilinks]] can also be viewed as popups.
Similar to Obsidian, [[quartz-layout-desktop.png|images referenced using wikilinks]] can also be viewed as popups.
## Configuration

72
package-lock.json generated
View File

@@ -35,9 +35,9 @@
"mdast-util-to-string": "^4.0.0",
"micromorph": "^0.4.5",
"minimatch": "^10.1.1",
"pixi.js": "^8.14.3",
"preact": "^10.28.0",
"preact-render-to-string": "^6.6.4",
"pixi.js": "^8.15.0",
"preact": "^10.28.1",
"preact-render-to-string": "^6.6.5",
"pretty-bytes": "^7.1.0",
"pretty-time": "^1.1.0",
"reading-time": "^1.5.0",
@@ -68,7 +68,7 @@
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.3",
"workerpool": "^10.0.1",
"ws": "^8.18.3",
"ws": "^8.19.0",
"yargs": "^18.0.0"
},
"bin": {
@@ -96,13 +96,13 @@
"node_modules/@bufbuild/protobuf": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.0.tgz",
"integrity": "sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ=="
"integrity": "sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ==",
"peer": true
},
"node_modules/@citation-js/core": {
"version": "0.7.14",
"resolved": "https://registry.npmjs.org/@citation-js/core/-/core-0.7.14.tgz",
"integrity": "sha512-dgeGqYDSQmn2MtnWZkwPGpJQPh43yr1lAAr9jl1NJ9pIY1RXUQxtlAUZVur0V9PHdbfQC+kkvB1KC3VpgVV3MA==",
"peer": true,
"dependencies": {
"@citation-js/date": "^0.5.0",
"@citation-js/name": "^0.4.2",
@@ -2300,7 +2300,8 @@
"node_modules/buffer-builder": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz",
"integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="
"integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==",
"peer": true
},
"node_modules/buffer-from": {
"version": "1.1.2",
@@ -2419,7 +2420,8 @@
"node_modules/colorjs.io": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz",
"integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw=="
"integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==",
"peer": true
},
"node_modules/comma-separated-tokens": {
"version": "2.0.3",
@@ -2792,7 +2794,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"peer": true,
"engines": {
"node": ">=12"
}
@@ -2971,7 +2972,6 @@
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
"hasInstallScript": true,
"license": "MIT",
"peer": true,
"bin": {
"esbuild": "bin/esbuild"
},
@@ -3382,6 +3382,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"peer": true,
"engines": {
"node": ">=8"
}
@@ -5492,9 +5493,9 @@
}
},
"node_modules/pixi.js": {
"version": "8.14.3",
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.14.3.tgz",
"integrity": "sha512-6xGYARV8D9E/fO1c2NmYn+k2dQ5oZldVm5tNlLQJ8obTlOQXdL5QpMc217qTpRyHVDFaw5eoFCLF1gr6p5ZcjQ==",
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.15.0.tgz",
"integrity": "sha512-J/Ghze/K9fjHRlfwC2EMZ7vnMIhGo4ByKCsKMcS0AB12iT79nf9zzWKUTzMJ8QAQFqQfDOl5ULwmHMUdeih2zQ==",
"license": "MIT",
"dependencies": {
"@pixi/colord": "^2.9.6",
@@ -5521,20 +5522,19 @@
"license": "MIT"
},
"node_modules/preact": {
"version": "10.28.0",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.28.0.tgz",
"integrity": "sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==",
"version": "10.28.1",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.28.1.tgz",
"integrity": "sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw==",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/preact-render-to-string": {
"version": "6.6.4",
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.6.4.tgz",
"integrity": "sha512-Bn6eQZ5SQ5loVEcC/mZmKT7HzO5Z/+vYzxfE/W2N468oSoNMJVdFGApF0GyXq0lDthuyXKTmtZ8k20NpYjr6Rw==",
"version": "6.6.5",
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.6.5.tgz",
"integrity": "sha512-O6MHzYNIKYaiSX3bOw0gGZfEbOmlIDtDfWwN1JJdc/T3ihzRT6tGGSEWE088dWrEDGa1u7101q+6fzQnO9XCPA==",
"license": "MIT",
"peerDependencies": {
"preact": ">=10 || >= 11.0.0-0"
@@ -6082,6 +6082,7 @@
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
@@ -6166,6 +6167,7 @@
"os": [
"android"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6181,6 +6183,7 @@
"os": [
"android"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6196,6 +6199,7 @@
"os": [
"android"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6211,6 +6215,7 @@
"os": [
"android"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6226,6 +6231,7 @@
"os": [
"android"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6241,6 +6247,7 @@
"os": [
"darwin"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6256,6 +6263,7 @@
"os": [
"darwin"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6271,6 +6279,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6286,6 +6295,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6301,6 +6311,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6316,6 +6327,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6331,6 +6343,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6346,6 +6359,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6361,6 +6375,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6376,6 +6391,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6391,6 +6407,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6406,6 +6423,7 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6421,6 +6439,7 @@
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6436,6 +6455,7 @@
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6451,6 +6471,7 @@
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -6620,7 +6641,6 @@
"version": "1.26.2",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.26.2.tgz",
"integrity": "sha512-iP7u2NA9A6JwRRCkIUREEX2cMhlYV5EBmbbSlfSRvPThwca8HBRbVkWuNWW+kw9+i6BSUZqqG6YeUs5dC2SjZw==",
"peer": true,
"dependencies": {
"@shikijs/core": "1.26.2",
"@shikijs/engine-javascript": "1.26.2",
@@ -6790,6 +6810,7 @@
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"peer": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -7125,7 +7146,8 @@
"node_modules/varint": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==",
"peer": true
},
"node_modules/vfile": {
"version": "6.0.3",
@@ -7226,9 +7248,9 @@
}
},
"node_modules/ws": {
"version": "8.18.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"version": "8.19.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"

View File

@@ -61,9 +61,9 @@
"mdast-util-to-string": "^4.0.0",
"micromorph": "^0.4.5",
"minimatch": "^10.1.1",
"pixi.js": "^8.14.3",
"preact": "^10.28.0",
"preact-render-to-string": "^6.6.4",
"pixi.js": "^8.15.0",
"preact": "^10.28.1",
"preact-render-to-string": "^6.6.5",
"pretty-bytes": "^7.1.0",
"pretty-time": "^1.1.0",
"reading-time": "^1.5.0",
@@ -94,7 +94,7 @@
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.3",
"workerpool": "^10.0.1",
"ws": "^8.18.3",
"ws": "^8.19.0",
"yargs": "^18.0.0"
},
"devDependencies": {

View File

@@ -8,7 +8,7 @@ import * as Plugin from "./quartz/plugins"
*/
const config: QuartzConfig = {
configuration: {
pageTitle: "Quartz 4",
pageTitle: "Phil's Digital Garden",
pageTitleSuffix: "",
enableSPA: true,
enablePopovers: true,

View File

@@ -143,6 +143,7 @@ async function startWatching(
}
const watcher = chokidar.watch(".", {
awaitWriteFinish: { stabilityThreshold: 250 },
persistent: true,
cwd: argv.directory,
ignoreInitial: true,

View File

@@ -111,6 +111,10 @@ function createFolderNode(
const folderPath = node.slug
folderContainer.dataset.folderpath = folderPath
if (currentSlug === folderPath) {
folderContainer.classList.add("active")
}
if (opts.folderClickBehavior === "link") {
// Replace button with link for link behavior
const button = titleContainer.querySelector(".folder-button") as HTMLElement

View File

@@ -5,7 +5,7 @@
background: none;
border: none;
width: 20px;
height: 20px;
height: 32px;
margin: 0;
text-align: inherit;
flex-shrink: 0;

View File

@@ -5,7 +5,7 @@
background: none;
border: none;
width: 20px;
height: 20px;
height: 32px;
margin: 0;
text-align: inherit;
flex-shrink: 0;

View File

@@ -23,7 +23,16 @@ export const Citations: QuartzTransformerPlugin<Partial<Options>> = (userOpts) =
name: "Citations",
htmlPlugins(ctx) {
const plugins: PluggableList = []
// per default, rehype-citations only supports en-US
// see: https://github.com/timlrx/rehype-citation/issues/12
// in here there are multiple usable locales:
// https://github.com/citation-style-language/locales
// thus, we optimistically assume there is indeed an appropriate
// locale available and simply create the lang url-string
let lang: string = "en-US"
if (ctx.cfg.configuration.locale !== "en-US") {
lang = `https://raw.githubusercontent.com/citation-stylelanguage/locales/refs/heads/master/locales-${ctx.cfg.configuration.locale}.xml`
}
// Add rehype-citation to the list of plugins
plugins.push([
rehypeCitation,
@@ -32,7 +41,7 @@ export const Citations: QuartzTransformerPlugin<Partial<Options>> = (userOpts) =
suppressBibliography: opts.suppressBibliography,
linkCitations: opts.linkCitations,
csl: opts.csl,
lang: ctx.cfg.configuration.locale ?? "en-US",
lang,
},
])

View File

@@ -9,6 +9,10 @@ html {
text-size-adjust: none;
overflow-x: hidden;
width: 100vw;
@media all and ($mobile) {
scroll-padding-top: 4rem;
}
}
body {