Commit 6eb7d43fc2
Unsigned
Layout: unified · split
build.py +25 −24
| @@ -104,7 +104,6 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 104 | #+title: Post Title | 104 | #+title: Post Title |
| 105 | #+date: <YYYY-MM-DD Day HH:MM:SS> | 105 | #+date: <YYYY-MM-DD Day HH:MM:SS> |
| 106 | #+slug: post-slug | 106 | #+slug: post-slug |
| 107 | #+filetags: :tag1:tag2:tag3: | ||
| 108 | 107 | ||
| 109 | Returns a string containing the section with the three most recent posts, | 108 | Returns a string containing the section with the three most recent posts, |
| 110 | formatted like the snippet in the prompt. | 109 | formatted like the snippet in the prompt. |
| @@ -115,7 +114,6 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 115 | "title": re.compile(r"^#\+title:\s*(.+)$", re.IGNORECASE), | 114 | "title": re.compile(r"^#\+title:\s*(.+)$", re.IGNORECASE), |
| 116 | "date": re.compile(r"^#\+date:\s*<(\d{4}-\d{2}-\d{2})"), | 115 | "date": re.compile(r"^#\+date:\s*<(\d{4}-\d{2}-\d{2})"), |
| 117 | "slug": re.compile(r"^#\+slug:\s*(.+)$", re.IGNORECASE), | 116 | "slug": re.compile(r"^#\+slug:\s*(.+)$", re.IGNORECASE), |
| 118 | "filetags": re.compile(r"^#\+filetags:\s*(.+)$", re.IGNORECASE), | ||
| 119 | "draft": re.compile(r"^#\+draft:\s*(.+)$", re.IGNORECASE), | 117 | "draft": re.compile(r"^#\+draft:\s*(.+)$", re.IGNORECASE), |
| 120 | } | 118 | } |
| 121 | 119 | ||
| @@ -123,7 +121,6 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 123 | title = None | 121 | title = None |
| 124 | date_str = None | 122 | date_str = None |
| 125 | slug = None | 123 | slug = None |
| 126 | tags = [] | ||
| 127 | is_draft = False | 124 | is_draft = False |
| 128 | 125 | ||
| 129 | with org_path.open("r", encoding="utf-8") as f: | 126 | with org_path.open("r", encoding="utf-8") as f: |
| @@ -147,15 +144,6 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 147 | slug = m.group(1).strip() | 144 | slug = m.group(1).strip() |
| 148 | continue | 145 | continue |
| 149 | 146 | ||
| 150 | if not tags: | ||
| 151 | m = header_patterns["filetags"].match(line) | ||
| 152 | if m: | ||
| 153 | # filetags are in the form ":tag1:tag2:tag3:" | ||
| 154 | raw = m.group(1).strip() | ||
| 155 | # split on ":" and filter out empty strings | ||
| 156 | tags = [t for t in raw.split(":") if t] | ||
| 157 | continue | ||
| 158 | |||
| 159 | m = header_patterns["draft"].match(line) | 147 | m = header_patterns["draft"].match(line) |
| 160 | if m: | 148 | if m: |
| 161 | draft_value = m.group(1).strip().lower() | 149 | draft_value = m.group(1).strip().lower() |
| @@ -165,7 +153,7 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 165 | continue | 153 | continue |
| 166 | 154 | ||
| 167 | # Stop scanning once we have all required fields | 155 | # Stop scanning once we have all required fields |
| 168 | if title and date_str and slug and tags: | 156 | if title and date_str and slug: |
| 169 | break | 157 | break |
| 170 | 158 | ||
| 171 | if is_draft: | 159 | if is_draft: |
| @@ -186,7 +174,6 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 186 | "date_obj": date_obj, | 174 | "date_obj": date_obj, |
| 187 | "date_full": date_full, | 175 | "date_full": date_full, |
| 188 | "slug": slug, | 176 | "slug": slug, |
| 189 | "tags": tags, | ||
| 190 | } | 177 | } |
| 191 | ) | 178 | ) |
| 192 | 179 | ||
| @@ -199,21 +186,15 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3): | |||
| 199 | # Build HTML lines | 186 | # Build HTML lines |
| 200 | lines = [] | 187 | lines = [] |
| 201 | for post in recent: | 188 | for post in recent: |
| 202 | lines.append('\t<div class="post">') | 189 | lines.append('\t<div>') |
| 203 | lines.append('\t\t<div class="post-content">') | ||
| 204 | lines.append( | 190 | lines.append( |
| 205 | f'\t\t\t<a href="/blog/{post["slug"]}.html">{post["title"]}</a>' | 191 | f'\t\t<time datetime="{post["date_str"]}">{post["date_full"]}</time>' |
| 206 | ) | 192 | ) |
| 207 | if post["tags"]: | ||
| 208 | lines.append('\t\t\t<div class="post-tags">') | ||
| 209 | for tag in post["tags"]: | ||
| 210 | lines.append(f'\t\t\t\t<span class="tag">{tag}</span>') | ||
| 211 | lines.append("\t\t\t</div>") | ||
| 212 | lines.append("\t\t</div>") | ||
| 213 | lines.append( | 193 | lines.append( |
| 214 | f'\t\t<time datetime="{post["date_str"]}">{post["date_full"]}</time>' | 194 | f'\t\t\t<a href="/blog/{post["slug"]}.html">{post["title"]}</a>' |
| 215 | ) | 195 | ) |
| 216 | lines.append("\t</div>") | 196 | lines.append("\t</div>") |
| 197 | lines.append("\t<br>") | ||
| 217 | 198 | ||
| 218 | return "\n".join(lines) | 199 | return "\n".join(lines) |
| 219 | 200 | ||
| @@ -246,6 +227,20 @@ def minify_css(src_css, dest_css): | |||
| 246 | sys.exit(1) | 227 | sys.exit(1) |
| 247 | 228 | ||
| 248 | 229 | ||
| 230 | def minify_html(src_html, dest_html): | ||
| 231 | print(f"Minifying HTML: {src_html} → {dest_html}") | ||
| 232 | result = subprocess.run( | ||
| 233 | ["minify", "-o", str(dest_html), str(src_html)], | ||
| 234 | stdout=subprocess.PIPE, | ||
| 235 | stderr=subprocess.PIPE, | ||
| 236 | text=True, | ||
| 237 | ) | ||
| 238 | if result.returncode != 0: | ||
| 239 | print("Error during HTML minification:") | ||
| 240 | print(result.stderr, file=sys.stderr) | ||
| 241 | sys.exit(1) | ||
| 242 | |||
| 243 | |||
| 249 | def run_emacs_publish(dev_mode=True): | 244 | def run_emacs_publish(dev_mode=True): |
| 250 | if dev_mode: | 245 | if dev_mode: |
| 251 | print("Running Emacs publish script (development)...") | 246 | print("Running Emacs publish script (development)...") |
| @@ -378,6 +373,9 @@ def main(): | |||
| 378 | # Update index page with latest posts | 373 | # Update index page with latest posts |
| 379 | update_index_html(html_snippet) | 374 | update_index_html(html_snippet) |
| 380 | 375 | ||
| 376 | # Minify index page | ||
| 377 | minify_html("./.build/index.html", "./.build/index.html") | ||
| 378 | |||
| 381 | # Generate sitemap | 379 | # Generate sitemap |
| 382 | generate_sitemap() | 380 | generate_sitemap() |
| 383 | 381 | ||
| @@ -399,6 +397,9 @@ def main(): | |||
| 399 | # Update index page with latest posts | 397 | # Update index page with latest posts |
| 400 | update_index_html(html_snippet) | 398 | update_index_html(html_snippet) |
| 401 | 399 | ||
| 400 | # Minify index page | ||
| 401 | minify_html("./.build/index.html", "./.build/index.html") | ||
| 402 | |||
| 402 | # Generate sitemap | 403 | # Generate sitemap |
| 403 | generate_sitemap() | 404 | generate_sitemap() |
| 404 | 405 | ||
content/about/index.org +1 −1
| @@ -6,7 +6,7 @@ Hey, I'm */~cmc/*. | |||
| 6 | I'm a technology audit manager, working on financial statement audits (SOX/MAR), | 6 | I'm a technology audit manager, working on financial statement audits (SOX/MAR), |
| 7 | SOC 1-3 reports, and other attestations for KPMG. | 7 | SOC 1-3 reports, and other attestations for KPMG. |
| 8 | 8 | ||
| 9 | Read up on my [[https://cv.cleberg.net][CV]] or [[https://cleberg.net/salary/][salary]] for more information. | 9 | Read up on my [[https://cv.cleberg.net][CV]] or [[https://cleberg.net/salary/][salary]] for more information. Otherwise, feel free to read more [[https://cleberg.net/about/][about me]]. |
| 10 | 10 | ||
| 11 | In my spare time, I like to: | 11 | In my spare time, I like to: |
| 12 | 12 | ||
content/wiki/blogroll.org deleted −31
| @@ -1,31 +0,0 @@ | |||
| 1 | #+title: Blogroll | ||
| 2 | #+date: <2024-04-12> | ||
| 3 | |||
| 4 | ** Aggregators | ||
| 5 | - [[https://1mb.club/][1MB Club]] | ||
| 6 | - [[https://250kb.club/][250KB Club]] | ||
| 7 | - [[https://512kb.club/][512KB Club]] | ||
| 8 | - [[https://darktheme.club/][Darktheme Club]] | ||
| 9 | - [[https://nocss.club/][No CSS Club]] | ||
| 10 | - [[https://no-js.club/][No-JS Club]] | ||
| 11 | - [[https://blogroll.org/][Ye Olde Blogroll]] | ||
| 12 | |||
| 13 | ** Plain Text | ||
| 14 | A list of various plaintext websites and lists. | ||
| 15 | |||
| 16 | - [[https://greycoder.com/a-list-of-text-only-new-sites/][A List Of Text-Only & Minimalist News Sites]] | ||
| 17 | - [[https://harvardlawreview.org/][Harvard Law Review]] | ||
| 18 | - [[https://sjmulder.nl/en/textonly.html][Hyperlinked Text]] | ||
| 19 | - [[https://medium.com/@letsworkshop/plain-text-web-design-a78ccaf9dbc0][Plain-text web design]] | ||
| 20 | - [[https://plaintextworld.com/][Plaintext World]] | ||
| 21 | - [[https://github.com/masonarmand/txt2web][txt2web]] | ||
| 22 | - [[https://justinjackson.ca/words.html][Words]] | ||
| 23 | |||
| 24 | ** Webrings | ||
| 25 | Instead of listing my personal favorites, I'm just going to drop a link to | ||
| 26 | [[https://brisray.com/web/webring-list.htm][brisay's webring list]], which contains 237 webrings for a total of 7078 websites, | ||
| 27 | as of 2024-03-15. | ||
| 28 | |||
| 29 | ** Everything Else | ||
| 30 | - [[https://deadsimplesites.com/][Dead Simple Sites]] | ||
| 31 | - [[https://planet.emacslife.com/][Planet Emacslife]] | ||
content/wiki/hardware.org deleted −95
| @@ -1,95 +0,0 @@ | |||
| 1 | #+title: Hardware | ||
| 2 | #+date: <2024-03-16> | ||
| 3 | |||
| 4 | ** Desktop | ||
| 5 | *** macOS | ||
| 6 | Probably should have added more RAM but Macbooks are stupid expensive. | ||
| 7 | |||
| 8 | | Category | Details | | ||
| 9 | |----------+-----------------| | ||
| 10 | | Model | [[https://www.apple.com/macbook-pro/][Macbook Pro 16”]] | | ||
| 11 | | CPU | Apple M2 Pro | | ||
| 12 | | RAM | 16GB | | ||
| 13 | | Storage | 512GB SSD | | ||
| 14 | |||
| 15 | *** Linux | ||
| 16 | A beauty. | ||
| 17 | |||
| 18 | | Category | Details | | ||
| 19 | |----------+---------------------------------------------| | ||
| 20 | | Model | [[https://www.lenovo.com/us/en/p/laptops/thinkpad/thinkpade/thinkpad--e15-gen-4-(15-inch-amd)/len101t0023][Lenovo ThinkPad E15 Gen 4, model 21ED0048US]] | | ||
| 21 | | CPU | AMD Ryzen 5 5625U with Radeon Graphics | | ||
| 22 | | RAM | 16 GB | | ||
| 23 | | Storage | 256 GB SSD | | ||
| 24 | |||
| 25 | ** Mobile | ||
| 26 | Previously used a Pixel 6 & Pixel 7 with GrapheneOS. | ||
| 27 | |||
| 28 | | Category | Details | | ||
| 29 | |----------+-------------------| | ||
| 30 | | Model | [[https://www.apple.com/iphone-15-pro/][iPhone 15 Pro Max]] | | ||
| 31 | | CPU | A17 Pro | | ||
| 32 | | RAM | 8GB | | ||
| 33 | | Storage | 256GB | | ||
| 34 | |||
| 35 | ** Homelab | ||
| 36 | I run a small homelab with a mix of consumer (compute/storage) and enterprise | ||
| 37 | (network) hardware. I try to keep the lab energy efficient and quiet as my top | ||
| 38 | priorities. | ||
| 39 | |||
| 40 | *** IoT | ||
| 41 | A collection of mainly smart lights, sensors, and smart appliances. My first | ||
| 42 | preference is to disable all networking for new smart devices or simply not | ||
| 43 | connect internet in the first place (e.g. I never enable internet on my smart | ||
| 44 | TVs). If the smart device requires LAN access, I will connect the device to my | ||
| 45 | guest-restricted IoT network. As a last resort, I will set-up the internet but | ||
| 46 | monitor the DNS lookups via NextDNS and forcibly block any domains I do not want | ||
| 47 | the device to be using. If the device is egregious or shady, I'll just sell it | ||
| 48 | and either replace it or live without it. | ||
| 49 | |||
| 50 | - Other Appliances (washer, dryer, humidifier, fans, etc.) | ||
| 51 | - [[https://about.irobot.com/sitecore/content/north-america/irobot-us/home/roomba/i7-series][Roomba i7+]] | ||
| 52 | - [[https://www.philips-hue.com/en-us/p/hue-white-and-color-ambiance-a19---e26-smart-bulb---60-w--3-pack-/046677562786][Philips Hue A19 Bulbs]] x 15 | ||
| 53 | - [[https://www.philips-hue.com/en-us/p/hue-bundle-play-blk-ext/33001][Philips Hue Play Light Bars]] | ||
| 54 | - [[https://www.philips-hue.com/en-us/p/hue-bridge/046677458478][Philips Hue Smart Bridge]] + play light bars and a ton of bulbs | ||
| 55 | - [[https://store.ui.com/us/en/collections/unifi-camera-security-special-chime][UP Chime]] | ||
| 56 | - [[https://store.ui.com/us/en/collections/unifi-camera-security-special-sensor][UP-Sense]] x 2 | ||
| 57 | - [[https://store.ui.com/us/en/products/unifi-smart-power][USP-Plug]] | ||
| 58 | - [[https://store.ui.com/us/en/collections/unifi-camera-security-compact-wifi-connected][UVC G4 Instant]] x 3 | ||
| 59 | - [[https://store.ui.com/us/en/collections/unifi-camera-security-special-wifi-doorbell][UVC G4 Doorbell Pro]] | ||
| 60 | |||
| 61 | *** Network | ||
| 62 | A rack-mounted Dream Machine Pro, connected downstream to an access point, mesh | ||
| 63 | extender, and a couple ethernet switches. | ||
| 64 | |||
| 65 | - [[https://store.ui.com/us/en/collections/unifi-dream-machine/products/udm-pro][UDM-Pro]] | ||
| 66 | - [[https://store.ui.com/us/en/collections/unifi-switching-standard-power-over-ethernet/products/usw-24-poe][USW-24-PoE]] | ||
| 67 | - [[https://store.ui.com/us/en/collections/unifi-switching-utility-poe/products/usw-lite-8-poe][USW-Lite-8-PoE]] | ||
| 68 | - [[https://store.ui.com/us/en/collections/unifi-wifi-flagship-high-capacity/products/u6-pro][U6-Pro]] | ||
| 69 | - [[https://store.ui.com/us/en/collections/unifi-wifi-inwall-outlet-mesh][U6-Extender]] | ||
| 70 | - [[https://store.ui.com/us/en/products/u7-pro-wall][U7-Pro-Wall]] x 2 | ||
| 71 | - [[https://store.ui.com/us/en/collections/unifi-accessory-tech-installations-rackmount/products/uacc-rack-panel-patch-blank-24][USW 24-Port Patch Panel]] | ||
| 72 | |||
| 73 | *** Servers | ||
| 74 | 1. Rack-Mount Server | ||
| 75 | |||
| 76 | I wasn't happy with using low-powered PCs as servers and I knew I did not | ||
| 77 | want the ear-shattering enterprise rack-mounted servers, so I built my own. | ||
| 78 | |||
| 79 | | Category | Details | | ||
| 80 | |--------------------+----------------------------------------| | ||
| 81 | | Case | Rosewill RSV-R4100U 4U | | ||
| 82 | | Motherboard | NZXT B550 | | ||
| 83 | | CPU | AMD Ryzen 7 5700G with Radeon Graphics | | ||
| 84 | | RAM | 64GB RAM (2x32GB) | | ||
| 85 | | Storage (On-board) | Western Digital 500GB M.2 NVME SSD | | ||
| 86 | | Storage (HDD Bay) | 48TB HDD | | ||
| 87 | | PSU | Corsair RM850 PSU | | ||
| 88 | |||
| 89 | 2. Other | ||
| 90 | |||
| 91 | These ran as my main servers before I built the rack-mounted server above. I | ||
| 92 | have shut these down indefinitely for now as I have no use for them. | ||
| 93 | |||
| 94 | - Dell OptiPlex | ||
| 95 | - Raspberry Pi 4 | ||
content/wiki/internet.org deleted −98
| @@ -1,98 +0,0 @@ | |||
| 1 | #+title: Internet | ||
| 2 | #+date: <2024-05-02> | ||
| 3 | |||
| 4 | ** Gemini | ||
| 5 | The [[https://geminiprotocol.net/][Gemini Protocol]] is a network of interconnected plaintext documents. If | ||
| 6 | you've used [[https://en.wikipedia.org/wiki/Gopher_(protocol)][Gopher]] before, Gemini will feel very familiar. | ||
| 7 | |||
| 8 | Instead of web sites, Gemini uses the term "capsules" that can be access via | ||
| 9 | =gemini://= links. | ||
| 10 | |||
| 11 | In order to browse Gemini capsules, you will need a client capable of supporting | ||
| 12 | Gemini. The Gemini Protocol website has a [[https://geminiprotocol.net/software/][Gemini software]] page with a list of | ||
| 13 | clients for each platform. | ||
| 14 | |||
| 15 | *** Gemtext | ||
| 16 | [[https://geminiprotocol.net/docs/cheatsheet.gmi][Gemtext]] is a plaintext syntax, very similar to Markdown. | ||
| 17 | |||
| 18 | To quote the Gemini Protocol's documentation: | ||
| 19 | |||
| 20 | - Long lines get wrapped by the client to fit the screen. | ||
| 21 | - Short lines /don't/ get joined together. | ||
| 22 | - Write paragraphs as single long lines. | ||
| 23 | - Blank lines are rendered verbatim. | ||
| 24 | |||
| 25 | #+begin_src md | ||
| 26 | [//]: <> (Headings) | ||
| 27 | # Heading | ||
| 28 | ## Sub-heading | ||
| 29 | ### Sub-subheading | ||
| 30 | |||
| 31 | [//]: <> (Lists) | ||
| 32 | - Mercury | ||
| 33 | - Gemini | ||
| 34 | - Apollo | ||
| 35 | |||
| 36 | [//]: <> (Quotes) | ||
| 37 | > I contend that text-based websites should not exceed in size the major works of Russian literature. | ||
| 38 | |||
| 39 | [//]: <> (Links) | ||
| 40 | => gemini://geminiprotocol.net/docs/cheatsheet.gmi | ||
| 41 | => gemini://geminiprotocol.net/docs/cheatsheet.gmi Gemtext cheatsheet | ||
| 42 | |||
| 43 | [//]: <> (Preformatted text) | ||
| 44 | Any line starting with three backticks (```) will tell the client to toggle to | ||
| 45 | "preformatted mode", which disables the client's logical checks to render links, | ||
| 46 | headings, etc. and will render the text as-is. | ||
| 47 | #+end_src | ||
| 48 | |||
| 49 | ** Gopher | ||
| 50 | The [[https://en.wikipedia.org/wiki/Gopher_(protocol)][Gopher Protocol]] is a communication protocol, similar to Gemini, that allows | ||
| 51 | for browsing of any ones of [[https://datatracker.ietf.org/doc/html/rfc1436#section-3.8][the 14 supported item types]]: | ||
| 52 | |||
| 53 | #+begin_src txt | ||
| 54 | 0 Item is a file | ||
| 55 | 1 Item is a directory | ||
| 56 | 2 Item is a CSO phone-book server | ||
| 57 | 3 Error | ||
| 58 | 4 Item is a BinHexed Macintosh file. | ||
| 59 | 5 Item is DOS binary archive of some sort. | ||
| 60 | Client must read until the TCP connection closes. Beware. | ||
| 61 | 6 Item is a UNIX uuencoded file. | ||
| 62 | 7 Item is an Index-Search server. | ||
| 63 | 8 Item points to a text-based telnet session. | ||
| 64 | 9 Item is a binary file! | ||
| 65 | Client must read until the TCP connection closes. Beware. | ||
| 66 | + Item is a redundant server | ||
| 67 | T Item points to a text-based tn3270 session. | ||
| 68 | g Item is a GIF format graphics file. | ||
| 69 | I Item is some kind of image file. Client decides how to display. | ||
| 70 | #+end_src | ||
| 71 | |||
| 72 | *** Simplicity is Intentional | ||
| 73 | Gopher is [[https://datatracker.ietf.org/doc/html/rfc1436#section-4][meant to be simplistic]]. | ||
| 74 | |||
| 75 | #+begin_src txt | ||
| 76 | As far as possible we desire any new features to be carried as new | ||
| 77 | protocols that will be hidden behind new document-types. The | ||
| 78 | internet Gopher philosophy is: | ||
| 79 | |||
| 80 | (a) Intelligence is held by the server. Clients have the option | ||
| 81 | of being able to access new document types (different, other types | ||
| 82 | of servers) by simply recognizing the document-type character. | ||
| 83 | Further intelligence to be borne by the protocol should be | ||
| 84 | minimized. | ||
| 85 | |||
| 86 | (b) The well-tempered server ought to send "text" (unless a file | ||
| 87 | must be transferred as raw binary). Should this text include | ||
| 88 | tabs, formfeeds, frufru? Probably not, but rude servers will | ||
| 89 | probably send them anyway. Publishers of documents should be | ||
| 90 | given simple tools (filters) that will alert them if there are any | ||
| 91 | funny characters in the documents they wish to publish, and give | ||
| 92 | them the opportunity to strip the questionable characters out; the | ||
| 93 | publisher may well refuse. | ||
| 94 | |||
| 95 | (c) The well-tempered client should do something reasonable with | ||
| 96 | funny characters received in text; filter them out, leave them in, | ||
| 97 | whatever. | ||
| 98 | #+end_src | ||
content/wiki/ios.org deleted −139
| @@ -1,139 +0,0 @@ | |||
| 1 | #+title: iOS | ||
| 2 | #+date: <2024-05-01> | ||
| 3 | |||
| 4 | Related: | ||
| 5 | |||
| 6 | - [[https://cleberg.net/wiki/hardware.html][Hardware]] | ||
| 7 | |||
| 8 | My primary mobile OS. Currently running iOS 17. This wiki page contains most of | ||
| 9 | the apps I have used at one point or another across my different iPhones. | ||
| 10 | |||
| 11 | (=*=) = My favorites | ||
| 12 | |||
| 13 | ** Configuration | ||
| 14 | *** Display | ||
| 15 | - Light Mode | ||
| 16 | - 08:00 to 16:00 | ||
| 17 | - Dark Mode | ||
| 18 | - 16:00 to 08:00 | ||
| 19 | |||
| 20 | *** Focus Modes | ||
| 21 | - Personal Focus | ||
| 22 | - 06:00 to 21:00 | ||
| 23 | - Allow Notifications From: | ||
| 24 | - Alarms | ||
| 25 | - Calendar | ||
| 26 | - Contacts (1 person) | ||
| 27 | - Messages | ||
| 28 | - Phone | ||
| 29 | - Reminders | ||
| 30 | - Signal | ||
| 31 | - UniFi Protect | ||
| 32 | - Sleep Focus | ||
| 33 | - 21:00 to 06:00 | ||
| 34 | - Allow Notifications From: | ||
| 35 | - Alarms | ||
| 36 | - Contacts (1 person) | ||
| 37 | - Reminders | ||
| 38 | - Signal | ||
| 39 | |||
| 40 | *** Privacy & Security | ||
| 41 | I generally follow the [[https://en.wikipedia.org/wiki/Principle_of_least_privilege][principle of least privilege]] by only permitting the bare | ||
| 42 | minimum privileges and revoking as soon as they are no longer required. | ||
| 43 | |||
| 44 | Here's the baseline I start with: | ||
| 45 | |||
| 46 | - Disable: | ||
| 47 | - Analytics & Improvements | ||
| 48 | - Apple Advertising | ||
| 49 | - Apple ID > Sign-In & Security > Two-Factor Authentication | ||
| 50 | - Location Services > System Services > Product Improvement | ||
| 51 | - Tracking > Allow Apps to Request to Track | ||
| 52 | - Safari > Advanced > Privacy Preserving Ad Measurement | ||
| 53 | - Enable: | ||
| 54 | - Apple ID > iCloud > Advanced Data Protection | ||
| 55 | - Apple ID > Personal Information > Communication Preferences | ||
| 56 | - App Privacy Report | ||
| 57 | - Location Services only for Camera, Find My, UDisc, & WiFiman (=While Using=) | ||
| 58 | - Safari > Prevent Cross-Site Tracking | ||
| 59 | - Safari > Hide IP Address | ||
| 60 | - Safari > Advanced > Advanced Tracking and Fingerprinting Protection | ||
| 61 | |||
| 62 | ** Native Apps | ||
| 63 | *** Business | ||
| 64 | - [[https://apps.apple.com/us/app/element-messenger/id1083446067][Element]] - A cross-platform messenger, based on Matrix | ||
| 65 | - [[https://apps.apple.com/us/app/linkedin-network-job-finder/id288429040][LinkedIn]] - One of the only social media apps I use | ||
| 66 | |||
| 67 | *** Developer Tools | ||
| 68 | - [[https://testflight.apple.com/join/F2vK7xo4][Harbour]] - Easily manage your Portainer service | ||
| 69 | - [[https://apps.apple.com/us/app/ish-shell/id1436902243][iSH]] - A local shell with SSH functionality | ||
| 70 | |||
| 71 | *** Entertainment | ||
| 72 | - [[https://apps.apple.com/us/app/plex-watch-live-tv-and-movies/id383457673][Plex]] - A client for the Plex Media Server | ||
| 73 | - [[https://apps.apple.com/us/app/steam-mobile/id495369748][Steam]] - The top gaming marketplace for computers | ||
| 74 | |||
| 75 | *** Lifestyle | ||
| 76 | - [[https://apps.apple.com/us/app/home/id1110145103][Home]] (=*=) - Apple homekit powered smart home manager | ||
| 77 | - [[https://apps.apple.com/us/app/philips-hue/id1055281310][Hue]] - Philips Hue smart home manager | ||
| 78 | - [[https://apps.apple.com/us/app/irobot-home/id1012014442][iRobot]] - Manage iRobot Roomba devices | ||
| 79 | - [[https://apps.apple.com/us/app/unifi-protect/id1392492235][UniFi Protect]] - View and manage most UniFi Protect cameras and settings | ||
| 80 | |||
| 81 | *** Music | ||
| 82 | - [[https://apps.apple.com/us/app/apple-music/id1108187390][Apple Music]] (=*=) - Apple's native music streaming app | ||
| 83 | - [[https://apps.apple.com/us/app/plexamp/id1500797510][Plexamp]] (=*=) - Top-notch music app for your Plex Media Server, with a neural | ||
| 84 | network that provides excellent radio/shuffle suggestions | ||
| 85 | |||
| 86 | *** Navigation | ||
| 87 | - [[https://apps.apple.com/us/app/deedum/id1546810946][deedum]] - A Gemini Protocol browser | ||
| 88 | |||
| 89 | *** News | ||
| 90 | - [[https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210][NetNewsWire]] - A free and open source RSS reader for Mac, iPhone, and iPad | ||
| 91 | |||
| 92 | *** Photo & Video | ||
| 93 | - [[https://testflight.apple.com/join/Q6WyyEpS][Aislingeach]] - A quick way to generate and rate images from the Stable Horde | ||
| 94 | - [[https://apps.apple.com/us/app/unsplash/id1290631746][Unsplash]] - Premium images, mostly free | ||
| 95 | |||
| 96 | *** Productivity | ||
| 97 | - [[https://apps.apple.com/us/app/beorg-to-do-list-agenda/id1238649962][beorg]] (=*=) - An org-mode editor, outline, and scheduler with paid extensions | ||
| 98 | - [[https://apps.apple.com/us/app/bitwarden-password-manager/id1137397744][Bitwarden]] (=*=) - An open source password manager | ||
| 99 | - [[https://apps.apple.com/us/app/bitwarden-authenticator/id6497335175][Bitwarden Authenticator]] (=*=) - Generate 2FA on your device | ||
| 100 | - [[https://apps.apple.com/us/app/cryptomator/id1560822163][Cryptomator]] - A cross-platform encryption program | ||
| 101 | - [[https://apps.apple.com/us/app/obsidian-connected-notes/id1557175442][Obsidian]] - A nice Markdown-based editor based on a "vault" structure. | ||
| 102 | Offers a paid sync solution and community extensions | ||
| 103 | - [[https://apps.apple.com/us/app/strongbox-password-manager/id897283731][Strongbox]] - Keepass password manager for iOS & macOS | ||
| 104 | - [[https://apps.apple.com/us/app/unifi/id1057750338][UniFi Network]] - View and manage most UniFi Network settings | ||
| 105 | |||
| 106 | *** Safari Extensions | ||
| 107 | - [[https://apps.apple.com/us/app/adguard-adblock-privacy/id1047223162][AdGuard]] - Ad blocker | ||
| 108 | - [[https://apps.apple.com/us/app/dark-reader-for-safari/id1438243180][Dark Reader]] - Dark mode for all the sites | ||
| 109 | - [[https://apps.apple.com/us/app/pipifier/id1234771095][PiPifier]] - Force videos to support PiP | ||
| 110 | - [[https://apps.apple.com/us/app/privacy-redirect/id1578144015][Privacy Redirect]] - Redirect select websites to others, usually to | ||
| 111 | privacy-focused alternatives | ||
| 112 | |||
| 113 | *** Social Networking | ||
| 114 | - [[https://apps.apple.com/us/app/multitab-for-tumblr/id1071533778][MultiTab T]] (=*=) - A gallery-based Tumblr client with some unique features, | ||
| 115 | such as tab history and sync | ||
| 116 | - [[https://apps.apple.com/us/app/signal-private-messenger/id874139669][Signal]] (=*=) - A simple, powerful, and secure messenger | ||
| 117 | - [[https://testflight.apple.com/join/mpVk1qIy][Three Cheers]] - A client for Tildes.net with a design focus that matches the | ||
| 118 | intent of Tildes | ||
| 119 | - [[https://apps.apple.com/us/app/voyager-for-lemmy/id6451429762][Voyager]] - A Lemmy client | ||
| 120 | |||
| 121 | *** Sports | ||
| 122 | - [[https://apps.apple.com/us/app/apple-sports/id6446788829][Apple Sports]] - Apple's new sports app - lacks notifications and live events | ||
| 123 | - [[https://apps.apple.com/us/app/udisc-disc-golf/id1072228953][UDisc]] - Disc golf course maps, score cards, and more | ||
| 124 | |||
| 125 | *** Utilities | ||
| 126 | - [[https://apps.apple.com/us/app/backblaze/id628638330][Backblaze]] - Quickly view and manage Backblaze b2 cloud storage | ||
| 127 | - [[https://apps.apple.com/us/app/mullvad-vpn/id1488466513][Mullvad VPN]] (=*=) - A private VPN service | ||
| 128 | - [[https://apps.apple.com/us/app/otp-auth/id659877384][OTP Auth]] (=*=) - A minimalistic OTP app with support for biometrics, custom | ||
| 129 | icons, import/export, and iCloud sync | ||
| 130 | - [[https://apps.apple.com/us/app/plex-dash/id1500797677][Plex Dash]] - Stats about your Plex Media Server | ||
| 131 | - [[https://apps.apple.com/us/app/safari/id1146562112][Safari]] - iOS default browser | ||
| 132 | - [[https://apps.apple.com/us/app/ubiquiti-wifiman/id1385561119][Unifi WiFiman]] - Create visual layouts of WiFi strength and save heat maps to your phone | ||
| 133 | |||
| 134 | ** Web Apps & Shortcuts | ||
| 135 | - [[https://brutalist.report/][Brutalist Report]] - Minimal news aggregator | ||
| 136 | - [[https://cyber.report/][_Cyber.Report]] - Cybersecurity news aggregator | ||
| 137 | - [[https://news.ycombinator.com/][Hacker News]] - Mostly technical news | ||
| 138 | - [[https://nextdns.io/][NextDNS]] - NextDNS statistics dashboard | ||
| 139 | - [[https://readspike.com/][Readspike]] - Minimal news aggregator | ||
content/wiki/macos.org deleted −148
| @@ -1,148 +0,0 @@ | |||
| 1 | #+title: macOS | ||
| 2 | #+date: <2024-05-01> | ||
| 3 | |||
| 4 | Related: | ||
| 5 | |||
| 6 | - [[https://cleberg.net/wiki/hardware/][Hardware]] | ||
| 7 | |||
| 8 | My primary OS. Currently running macOS Sonoma 14. This wiki page contains most | ||
| 9 | of the apps I have used at one point or another across my different Macbooks. | ||
| 10 | |||
| 11 | (=*=) = My favorites | ||
| 12 | |||
| 13 | ** Configuration | ||
| 14 | *** Disable System Services | ||
| 15 | - [[https://developer.apple.com/documentation/security/disabling_and_enabling_system_integrity_protection][Disabling and Enabling System Integrity Protection]] | ||
| 16 | - Disable Gatekeeper: =sudo spctl --master-disable= | ||
| 17 | |||
| 18 | *** Dotfiles | ||
| 19 | These are probably out of date, but they give a general idea of how I configure | ||
| 20 | my machine. | ||
| 21 | |||
| 22 | #+begin_src conf | ||
| 23 | # ~/.zshrc | ||
| 24 | export PATH="/opt/homebrew/bin:$PATH" | ||
| 25 | export PATH="$HOME/.emacs.d/bin:$PATH" | ||
| 26 | export EDITOR="/opt/homebrew/bin/emacs -nw" | ||
| 27 | ZSH_THEME="bureau" | ||
| 28 | plugins=(git zsh-autosuggestions) | ||
| 29 | source $ZSH/oh-my-zsh.sh | ||
| 30 | #+end_src | ||
| 31 | |||
| 32 | #+begin_src conf | ||
| 33 | # ~/.zprofile eval "$(/opt/homebrew/bin/brew shellenv)" | ||
| 34 | #+end_src | ||
| 35 | |||
| 36 | #+begin_src conf | ||
| 37 | # ~/.config/skhd/skhdrc | ||
| 38 | cmd - return : /Applications/iTerm.app/Contents/MacOS/iTerm2 | ||
| 39 | cmd + shift - return : /Applications/LibreWolf.app/Contents/MacOS/librewolf | ||
| 40 | #+end_src | ||
| 41 | |||
| 42 | #+begin_src conf | ||
| 43 | # ~/.config/yabai/yabairc | ||
| 44 | yabai -m config \ | ||
| 45 | mouse_follows_focus off \ | ||
| 46 | focus_follows_mouse off \ | ||
| 47 | window_origin_display default \ | ||
| 48 | window_placement second_child \ | ||
| 49 | window_zoom_persist on \ | ||
| 50 | window_shadow on \ | ||
| 51 | window_animation_duration 0.0 \ | ||
| 52 | window_animation_frame_rate 120 \ | ||
| 53 | window_opacity_duration 0.0 \ | ||
| 54 | active_window_opacity 1.0 \ | ||
| 55 | normal_window_opacity 0.90 \ | ||
| 56 | window_opacity off \ | ||
| 57 | insert_feedback_color 0xffd75f5f \ | ||
| 58 | split_ratio 0.50 \ | ||
| 59 | split_type auto \ | ||
| 60 | auto_balance off \ | ||
| 61 | top_padding 15 \ | ||
| 62 | bottom_padding 15 \ | ||
| 63 | left_padding 15 \ | ||
| 64 | right_padding 15 \ | ||
| 65 | window_gap 10 \ | ||
| 66 | layout bsp \ | ||
| 67 | mouse_modifier fn \ | ||
| 68 | mouse_action1 move \ | ||
| 69 | mouse_action2 resize \ | ||
| 70 | mouse_drop_action swap | ||
| 71 | echo "yabai configuration loaded.." | ||
| 72 | #+end_src | ||
| 73 | |||
| 74 | ** Software | ||
| 75 | *** Browsers | ||
| 76 | - [[https://librewolf.net/][Librewolf]] (=*=) - Custom version of Firefox, focused on privacy and security | ||
| 77 | - [[https://bitwarden.com/][Bitwarden]] - An open source password manager | ||
| 78 | - [[https://darkreader.org/][Dark Reader]] - Dark mode for all the websites | ||
| 79 | - [[https://libredirect.github.io/][Libredirect]] - Automatic web redirections | ||
| 80 | - [[https://strongboxsafe.com/][Strongbox]] - Keepass password manager for iOS & macOS | ||
| 81 | - [[https://ublockorigin.com/][uBlock Origin]] - Free, open-source ad content blocker | ||
| 82 | - [[https://github.com/ungoogled-software/ungoogled-chromium][Ungoogled Chromium]] - Google Chromium, sans integration with Google | ||
| 83 | - [[https://www.gnu.org/software/emacs/manual/html_mono/eww.html][eww]] - Emacs Web Wowser, for TUI browsing | ||
| 84 | - [[https://www.torproject.org/][Tor]] - Browse privately | ||
| 85 | |||
| 86 | *** Command Line Tools | ||
| 87 | - [[https://github.com/mr-karan/doggo][doggo]] - Command-line DNS Client for Humans | ||
| 88 | - [[https://github.com/muesli/duf][duf]] - Disk Usage/Free Utility - a better 'df' alternative | ||
| 89 | - [[https://github.com/bootandy/dust][dust]] - A more intuitive version of du in rust | ||
| 90 | - [[https://github.com/eza-community/eza][eza]] - A modern alternative to ls | ||
| 91 | - [[https://github.com/Macchina-CLI/macchina][macchina]] - A system information frontend with an emphasis on performance. | ||
| 92 | - [[https://github.com/yt-dlp/yt-dlp][yt-dlp]] - A youtube-dl fork with additional features and fixes | ||
| 93 | |||
| 94 | *** Communications | ||
| 95 | - [[https://element.io/][Element]] - Matrix's default GUI client | ||
| 96 | - [[https://github.com/tulir/gomuks][gomuks]] - A terminal based Matrix client | ||
| 97 | - [[https://www.thunderbird.net/][Thunderbird]] (=*=) - An open source email client by Mozilla | ||
| 98 | - [[https://signal.org/][Signal]] (=*=) - A simple, powerful, and secure messenger | ||
| 99 | |||
| 100 | *** Development | ||
| 101 | - [[https://www.docker.com/products/docker-desktop/][Docker Desktop]] - Docker containers for your desktop | ||
| 102 | - [[https://github.com/open-webui/open-webui][open-webui]] - User-friendly WebUI for LLMs | ||
| 103 | - [[https://iterm2.com/][iTerm2]] (=*=) - The best terminal for macOS, hands down | ||
| 104 | - [[https://podman-desktop.io/][Podman Desktop]] (=*=) - Open source tool for containers and Kubernetes | ||
| 105 | - [[https://developer.apple.com/xcode/][Xcode]] - Apple's IDE | ||
| 106 | - [[https://en.wikipedia.org/wiki/Z_shell][zsh]] (=*=) - My shell preference due to its plugin and theme community | ||
| 107 | - [[https://github.com/zsh-users/zsh-autosuggestions][zsh-autosuggestions]] - Fish-like autosuggestions for zsh | ||
| 108 | - [[https://github.com/zsh-users/zsh-syntax-highlighting][zsh-syntax-highlighting]] - Fish shell like syntax highlighting for Zsh | ||
| 109 | |||
| 110 | *** Editors | ||
| 111 | - [[https://github.com/doomemacs/doomemacs][Doom Emacs]] (=*=) - An Emacs framework, great for working in org-mode | ||
| 112 | - [[https://obsidian.md/][Obsidian]] - A nice Markdown-based editor based on a "vault" structure. Offers a | ||
| 113 | paid sync solution and community extensions | ||
| 114 | - [[https://standardnotes.com/][Standard Notes]] - A simple text editor focused on privacy and security. Offers | ||
| 115 | a paid sync solution and community extensions | ||
| 116 | - [[https://vscodium.com/][VSCodium]] - VS Code without proprietary blobs | ||
| 117 | |||
| 118 | *** Media | ||
| 119 | - [[https://skylum.com/luminar][Luminar]] - Luminar offers top-notch photo editing features- [[https://www.minecraft.net/][Minecraft]] - Block mining simulator | ||
| 120 | - [[https://netnewswire.com/][NetNewsWire]] - A free and open source RSS reader for Mac, iPhone, and iPad | ||
| 121 | - [[https://www.plex.tv/][Plex]] (=*=) - Desktop client for the Plex Media Server | ||
| 122 | - [[https://store.steampowered.com/][Steam]] - The top gaming marketplace for computers | ||
| 123 | - [[https://transmissionbt.com/][Transmission]] (=*=) - A Fast, Easy and Free Bittorrent Client | ||
| 124 | - [[https://www.videolan.org/vlc/][VLC]] - A free and open source cross-platform multimedia player | ||
| 125 | |||
| 126 | *** Package Management | ||
| 127 | - [[https://brew.sh/][Homebrew]] (=*=) - The Missing Package Manager for macOS (or Linux) | ||
| 128 | - [[https://www.macports.org/][MacPorts]] - A system to compile, install, and manage open source software | ||
| 129 | |||
| 130 | *** Utilities | ||
| 131 | - [[https://betterdisplay.pro/][BetterDisplay]] - Allows you to tweak a ton of features of built-in and external | ||
| 132 | screens, such as scaling, configuration overrides, and color/brightness | ||
| 133 | upscaling | ||
| 134 | - [[https://bitwarden.com/][Bitwarden]] - An open source password manager | ||
| 135 | - [[https://icemenubar.app/][Ice]] (=*=)- A powerful menu bar management tool | ||
| 136 | - [[https://obdev.at/products/littlesnitch/index.html][LittleSnitch]] - Shows all network connections on your Macbook, including system | ||
| 137 | and privileged services | ||
| 138 | - [[https://obdev.at/products/microsnitch/index.html][MicroSnitch]] - Camera & microphone monitoring and alterting service | ||
| 139 | - [[https://mullvad.net/][Mullvad]] (=*=) - A private VPN service | ||
| 140 | - [[https://ollama.com/][Ollama]] - Run Llama 2, Code Llama, and other models locally on your machine | ||
| 141 | - [[https://github.com/kghandour/Ollama-SwiftUI][Ollama Swift]] - User Interface made for Ollama.ai using Swift | ||
| 142 | - [[https://orbstack.dev/][OrbStack]] - A fast and convenient GUI to manage Docker contains and Linux VMs | ||
| 143 | - [[https://www.raycast.com/][Raycast]] - A collection of tools and shortcuts, an alternative to Spotlight | ||
| 144 | - [[https://github.com/koekeishiya/skhd][skhd]] (=*=) - Simple hotkey daemon for macOS | ||
| 145 | - [[https://strongboxsafe.com/][Strongbox]] - Keepass password manager for iOS & macOS | ||
| 146 | - [[https://syncthing.net/][Syncthing]] (=*=) - Continuous file synchronization | ||
| 147 | - [[https://www.bresink.com/osx/TinkerTool.html][TinkerTool]] - Unlock hidden configuration options for macOS | ||
| 148 | - [[https://github.com/koekeishiya/yabai][yabai]] (=*=) - Automatic window tiling | ||
content/wiki/services.org deleted −38
| @@ -1,38 +0,0 @@ | |||
| 1 | #+title: Services & Hosting | ||
| 2 | #+date: <2025-08-22> | ||
| 3 | |||
| 4 | * Domain Registration | ||
| 5 | |||
| 6 | - [[https://njal.la][Njalla]]: Migrated all domains to Njalla. Some spare domains left on Cloudflare | ||
| 7 | until I figure out if someone wants them or if I can just delete them | ||
| 8 | outright. | ||
| 9 | |||
| 10 | * DNS | ||
| 11 | |||
| 12 | - [[https://njal.la][Njalla]]: I am using their name servers and DNS for my domain traffic. | ||
| 13 | - [[https://mullvad.net][Mullvad]]: Since I use Mullvad's VPN on most of my devices, I am using their DNS | ||
| 14 | with occasional content blockers enabled. | ||
| 15 | - [[https://nextdns.io][NextDNS]]: Lastly, I enforce NextDNS's DNS at the router level on my home | ||
| 16 | network so that any device without a VPN is still slightly protected and not | ||
| 17 | using my ISP's DNS. | ||
| 18 | |||
| 19 | * Hosting | ||
| 20 | |||
| 21 | ** Web | ||
| 22 | |||
| 23 | - N/A: I currently host all of my services on my server at home via Cox's | ||
| 24 | residential fiber network. Since I have accounts on AWS, Azure, GCP, & IBM for | ||
| 25 | my job, I use these as temporary backup solutions if I'm away from home and a | ||
| 26 | service goes down that I need to use. | ||
| 27 | |||
| 28 | |||
| 29 | |||
| 30 | - [[https://migadu.com/][Migadu]]: I've used a few different email providers over the last few years, but | ||
| 31 | keep coming back to Migadu due to their drop-dead simplicity and proven | ||
| 32 | reliability. | ||
| 33 | |||
| 34 | ** Source Code | ||
| 35 | |||
| 36 | - [[https://sourcehut.org/][Sourcehut]]: I flip back and forth between Sourcehut and GitHub, but I'm | ||
| 37 | currently using Sourcehut. I love the minimal form factor and the company's | ||
| 38 | mission, but tend to use GitHub to explore other's code. | ||
content/wiki/sh.org deleted −49
| @@ -1,49 +0,0 @@ | |||
| 1 | #+title: Shell Commands & Scripts | ||
| 2 | #+date: <2025-03-19> | ||
| 3 | |||
| 4 | * File Loop | ||
| 5 | |||
| 6 | #+begin_src shell | ||
| 7 | # All files in current directory | ||
| 8 | for file in *; do echo "${file}"; done | ||
| 9 | |||
| 10 | # Files only | ||
| 11 | for file in *; do if [ -f "$file" ]; then echo "$file"; fi; done | ||
| 12 | |||
| 13 | # Directories only | ||
| 14 | for file in *; do if [ -d "$file" ]; then echo "$file"; fi; done | ||
| 15 | #+end_src | ||
| 16 | |||
| 17 | * Exifdata | ||
| 18 | |||
| 19 | #+begin_src shell | ||
| 20 | sudo exiftool -r -all= -ext jpg -ext png . | ||
| 21 | #+end_src | ||
| 22 | |||
| 23 | * Optipng | ||
| 24 | |||
| 25 | #+begin_src shell | ||
| 26 | optipng -o7 image.png | ||
| 27 | #+end_src | ||
| 28 | |||
| 29 | * Nginx + Goaccess | ||
| 30 | |||
| 31 | #+begin_src shell | ||
| 32 | zcat /var/log/nginx/access.log.*.gz | goaccess /var/log/nginx/access.log - | ||
| 33 | #+end_src | ||
| 34 | |||
| 35 | * Distro Information | ||
| 36 | |||
| 37 | #+begin_src shell | ||
| 38 | echo /etc/*_ver* /etc/*-rel*; cat /etc/*_ver* /etc/*-rel* | ||
| 39 | #+end_src | ||
| 40 | |||
| 41 | * sed | ||
| 42 | |||
| 43 | #+begin_src shell | ||
| 44 | # Replace text within file | ||
| 45 | sed -i '' 's/SEARCH_TEXT/REPLACEMENT_TEXT/g' file.txt | ||
| 46 | |||
| 47 | # Delete empty lines | ||
| 48 | sed '/^\s*$/d' | ||
| 49 | #+end_src | ||
publish.el −18
| @@ -44,23 +44,6 @@ | |||
| 44 | :output ".build/blog/index.html" | 44 | :output ".build/blog/index.html" |
| 45 | :url "/blog/") | 45 | :url "/blog/") |
| 46 | 46 | ||
| 47 | ;; Wiki post route | ||
| 48 | (weblorg-route | ||
| 49 | :name "wiki" | ||
| 50 | :input-pattern "content/wiki/*.org" | ||
| 51 | :template "post.html" | ||
| 52 | :output ".build/wiki/{{ slug }}.html" | ||
| 53 | :url "/wiki/{{ slug }}.html") | ||
| 54 | |||
| 55 | ;; Wiki index page route | ||
| 56 | (weblorg-route | ||
| 57 | :name "wiki-index" | ||
| 58 | :input-pattern "content/wiki/*.org" | ||
| 59 | :input-aggregate #'weblorg-input-aggregate-all | ||
| 60 | :template "wiki.html" | ||
| 61 | :output ".build/wiki/index.html" | ||
| 62 | :url "/wiki/") | ||
| 63 | |||
| 64 | ;; Page post route | 47 | ;; Page post route |
| 65 | (weblorg-route | 48 | (weblorg-route |
| 66 | :name "pages" | 49 | :name "pages" |
| @@ -101,7 +84,6 @@ | |||
| 101 | :output ".build/about/{{ slug }}.html" | 84 | :output ".build/about/{{ slug }}.html" |
| 102 | :url "/about/{{ slug }}.html") | 85 | :url "/about/{{ slug }}.html") |
| 103 | 86 | ||
| 104 | |||
| 105 | ;; RSS feed route | 87 | ;; RSS feed route |
| 106 | (weblorg-route | 88 | (weblorg-route |
| 107 | :name "rss" | 89 | :name "rss" |
theme/static/favicon.ico deleted
Binary file not shown.
theme/static/styles.css +16 −293
| @@ -1,338 +1,61 @@ | |||
| 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ | ||
| 2 | html{line-height:1.15;-webkit-text-size-adjust:100%}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}template{display:none}[hidden]{display:none} | ||
| 3 | |||
| 4 | /* CUSTOM CSS */ | ||
| 5 | :root { | ||
| 6 | --bg: #EDEDE7; | ||
| 7 | --bg-bright: #E8D3BE; | ||
| 8 | --fg: #201E1D; | ||
| 9 | --link: #810208; | ||
| 10 | --code: #810208; | ||
| 11 | --border: #E8D3BE; | ||
| 12 | } | ||
| 13 | |||
| 14 | @media (prefers-reduced-motion: no-preference) { | ||
| 15 | :root { | ||
| 16 | scroll-behavior: smooth; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | body { | 1 | body { |
| 21 | background-color: var(--bg); | 2 | max-width: 50em; |
| 22 | color: var(--fg); | 3 | margin: 1.5rem; |
| 23 | font-family: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; | ||
| 24 | font-size: 1rem; | ||
| 25 | line-height: 1.5; | ||
| 26 | max-width: 50em; | ||
| 27 | margin: 0 auto; | ||
| 28 | padding: 0 clamp(1rem, 5vw, 3rem); | ||
| 29 | } | ||
| 30 | |||
| 31 | @media only screen and (min-width: 768px) { | ||
| 32 | body { | ||
| 33 | font-size: 1.2rem; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | @media (min-width: 768px) { | ||
| 38 | body { | ||
| 39 | padding: 0 2rem; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | .site-nav, | ||
| 44 | footer { | ||
| 45 | border-color: var(--fg); | ||
| 46 | } | ||
| 47 | |||
| 48 | footer { | ||
| 49 | padding-top: 1rem; | ||
| 50 | margin: 1rem 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | footer p { | ||
| 54 | margin: 0; | ||
| 55 | } | 4 | } |
| 56 | 5 | ||
| 57 | ul { | 6 | nav ul { |
| 58 | list-style-type: "- "; | ||
| 59 | } | ||
| 60 | |||
| 61 | .site-nav ul { | ||
| 62 | list-style-type: none; | 7 | list-style-type: none; |
| 63 | display: flex; | 8 | display: flex; |
| 64 | align-items: center; | ||
| 65 | padding: 0; | 9 | padding: 0; |
| 66 | } | 10 | } |
| 67 | 11 | ||
| 68 | .site-nav ul li { | 12 | nav ul li { |
| 69 | margin-right: 0.5rem; | 13 | margin-right: 0.5rem; |
| 70 | } | 14 | } |
| 71 | 15 | ||
| 72 | h1, | ||
| 73 | h2, | ||
| 74 | h3, | ||
| 75 | h4 { | ||
| 76 | color: var(--fg); | ||
| 77 | } | ||
| 78 | |||
| 79 | h1 { | ||
| 80 | font-size: 1.75rem; | ||
| 81 | font-weight: bold; | ||
| 82 | margin-top: 1rem; | ||
| 83 | margin-bottom: 0.75rem; | ||
| 84 | } | ||
| 85 | |||
| 86 | h2 { | ||
| 87 | font-size: 1.5rem; | ||
| 88 | margin-top: 1rem; | ||
| 89 | margin-bottom: 0.5rem; | ||
| 90 | } | ||
| 91 | |||
| 92 | h3 { | ||
| 93 | font-size: 1.25rem; | ||
| 94 | margin-top: 1rem; | ||
| 95 | margin-bottom: 0.25rem; | ||
| 96 | } | ||
| 97 | |||
| 98 | a, | ||
| 99 | a:visited { | ||
| 100 | color: var(--link); | ||
| 101 | text-decoration: underline; | ||
| 102 | text-decoration-skip-ink: auto; | ||
| 103 | } | ||
| 104 | |||
| 105 | a:focus-visible { | ||
| 106 | outline: 2px solid var(--link); | ||
| 107 | outline-offset: 2px; | ||
| 108 | } | ||
| 109 | |||
| 110 | a:hover { | ||
| 111 | background: var(--link); | ||
| 112 | color: var(--bg); | ||
| 113 | text-decoration: none; | ||
| 114 | } | ||
| 115 | |||
| 116 | img { | 16 | img { |
| 117 | border-style: none; | 17 | border-style: none; |
| 118 | width: 100%; | 18 | width: 100%; |
| 119 | } | 19 | } |
| 120 | 20 | ||
| 121 | table { | 21 | table { |
| 122 | border: 1px solid var(--border); | 22 | border: 1px solid #111; |
| 123 | border-collapse: collapse; | 23 | border-collapse: collapse; |
| 124 | color: var(--fg); | ||
| 125 | border-color: var(--bg-bright); | ||
| 126 | font-size: inherit; | ||
| 127 | width: 100%; | 24 | width: 100%; |
| 128 | } | 25 | } |
| 129 | 26 | ||
| 130 | thead, | ||
| 131 | th, | ||
| 132 | tr, | ||
| 133 | td { | ||
| 134 | border: 1px solid var(--border); | ||
| 135 | padding: 0.25rem; | ||
| 136 | } | ||
| 137 | |||
| 138 | pre, | 27 | pre, |
| 139 | pre>code, | 28 | pre>code, |
| 140 | code { | 29 | code { |
| 141 | font-family: | ||
| 142 | Menlo, | ||
| 143 | Consolas, | ||
| 144 | Monaco, | ||
| 145 | Liberation Mono, | ||
| 146 | Lucida Console, | ||
| 147 | monospace; | ||
| 148 | font-size: 0.9rem; | 30 | font-size: 0.9rem; |
| 149 | } | 31 | } |
| 150 | 32 | ||
| 151 | pre { | 33 | pre { |
| 152 | background-color: var(--bg-bright) !important; | 34 | border: 1px solid #111; |
| 153 | margin: 0.5rem 0; | 35 | margin: 0.5rem 0; |
| 154 | padding: 0.5rem; | 36 | padding: 0.5rem; |
| 155 | overflow-x: auto; | 37 | overflow-x: auto; |
| 156 | } | 38 | } |
| 157 | 39 | ||
| 158 | :not(pre)>code { | 40 | time { |
| 159 | color: var(--code); | ||
| 160 | } | ||
| 161 | |||
| 162 | aside { | ||
| 163 | background-color: var(--bg-bright); | ||
| 164 | padding: 1rem; | ||
| 165 | } | ||
| 166 | |||
| 167 | blockquote { | ||
| 168 | background-color: var(--bg-bright); | ||
| 169 | border-left: 5px solid var(--link); | ||
| 170 | margin: 1rem 0; | ||
| 171 | padding: 0.5rem 1rem; | ||
| 172 | } | ||
| 173 | |||
| 174 | blockquote p { | ||
| 175 | margin: 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | .post, | ||
| 179 | .wiki-post { | ||
| 180 | display: flex; | ||
| 181 | justify-content: space-between; | ||
| 182 | } | ||
| 183 | |||
| 184 | .post time { | ||
| 185 | flex-shrink: 0; | ||
| 186 | font-style: italic; | ||
| 187 | margin-right: 0.5rem; | ||
| 188 | opacity: 0.8; | ||
| 189 | } | ||
| 190 | |||
| 191 | .wiki-post { | ||
| 192 | justify-content: space-between; | ||
| 193 | } | ||
| 194 | |||
| 195 | .wiki-post:first-of-type { | ||
| 196 | border-bottom: 1px dotted var(--fg); | ||
| 197 | margin-bottom: 1rem; | ||
| 198 | } | ||
| 199 | |||
| 200 | .wiki-post p { | ||
| 201 | margin: 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | .post-metadata { | ||
| 205 | border: 1px dotted var(--border); | ||
| 206 | padding: 1rem; | ||
| 207 | } | ||
| 208 | |||
| 209 | .post-metadata h1 { | ||
| 210 | margin: 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | .post-metadata p { | ||
| 214 | margin: 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | .post-metadata time { | ||
| 218 | font-style: italic; | ||
| 219 | } | ||
| 220 | |||
| 221 | details { | ||
| 222 | display: block; | 41 | display: block; |
| 223 | margin-top: 1rem; | ||
| 224 | } | ||
| 225 | |||
| 226 | summary { | ||
| 227 | display: list-item; | ||
| 228 | font-weight: bold; | ||
| 229 | } | ||
| 230 | |||
| 231 | span.tag::before { | ||
| 232 | content: "#"; | ||
| 233 | } | ||
| 234 | |||
| 235 | .footnote-definition { | ||
| 236 | display: flex; | ||
| 237 | justify-content: flex-start; | ||
| 238 | align-items: top; | ||
| 239 | margin: 1rem 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | .footnote-definition sup { | ||
| 243 | font-size: inherit; | ||
| 244 | top: 0; | ||
| 245 | line-height: inherit; | ||
| 246 | padding-right: 0.5rem; | ||
| 247 | } | 42 | } |
| 248 | 43 | ||
| 249 | .footnote-definition sup::after { | 44 | :not(pre)>code { |
| 250 | content: "."; | 45 | color: #f00; |
| 251 | } | ||
| 252 | |||
| 253 | .footnote-definition p { | ||
| 254 | display: inline-block; | ||
| 255 | margin: 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | .hidden { | ||
| 259 | display: none; | ||
| 260 | } | ||
| 261 | |||
| 262 | .post { | ||
| 263 | display: flex; | ||
| 264 | flex-direction: row; | ||
| 265 | margin-bottom: 1rem; | ||
| 266 | } | ||
| 267 | |||
| 268 | .post-content { | ||
| 269 | display: flex; | ||
| 270 | flex-direction: column; | ||
| 271 | } | ||
| 272 | |||
| 273 | .post-tags { | ||
| 274 | font-size: 1rem; | ||
| 275 | margin-top: 0.1rem; | ||
| 276 | } | ||
| 277 | |||
| 278 | .tag { | ||
| 279 | margin-right: 0.3rem; | ||
| 280 | font-style: normal; | ||
| 281 | opacity: 0.5; | ||
| 282 | } | ||
| 283 | |||
| 284 | .tag::before { | ||
| 285 | content: "#"; | ||
| 286 | } | ||
| 287 | |||
| 288 | .skip-link { | ||
| 289 | position: absolute; | ||
| 290 | left: -999px; | ||
| 291 | top: auto; | ||
| 292 | width: 1px; | ||
| 293 | height: 1px; | ||
| 294 | overflow: hidden; | ||
| 295 | } | ||
| 296 | |||
| 297 | .skip-link:focus { | ||
| 298 | left: 1rem; | ||
| 299 | top: 1rem; | ||
| 300 | width: auto; | ||
| 301 | height: auto; | ||
| 302 | background: var(--bg-bright); | ||
| 303 | color: var(--fg); | ||
| 304 | padding: .5rem; | ||
| 305 | border: 1px solid var(--fg); | ||
| 306 | } | 46 | } |
| 307 | 47 | ||
| 308 | @media (prefers-color-scheme: dark) { | 48 | @media (prefers-color-scheme: dark) { |
| 309 | :root { | ||
| 310 | --bg: #201E1D; | ||
| 311 | --bg-bright: #2F2F2D; | ||
| 312 | --fg: #EDEDE7; | ||
| 313 | --link: #D9C2A6; | ||
| 314 | --code: #D9C2A6; | ||
| 315 | --border: #2F2F2D; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | @media print { | ||
| 320 | body { | 49 | body { |
| 321 | background: #fff; | 50 | background-color: #222; |
| 322 | color: #000; | 51 | color: #eee; |
| 323 | font-size: 12pt; | ||
| 324 | padding: 0; | ||
| 325 | max-width: none; | ||
| 326 | } | 52 | } |
| 327 | 53 | ||
| 328 | .site-nav, | 54 | a { |
| 329 | footer, | 55 | color: #add8e6; |
| 330 | aside { | ||
| 331 | display: none; | ||
| 332 | } | 56 | } |
| 333 | 57 | ||
| 334 | a::after { | 58 | pre { |
| 335 | content: " (" attr(href) ")"; | 59 | border-color: #eee; |
| 336 | font-size: 90%; | ||
| 337 | } | 60 | } |
| 338 | }\ No newline at end of file | 61 | }\ No newline at end of file |
theme/templates/base.html +7 −11
| @@ -12,29 +12,25 @@ | |||
| 12 | {% if site_description is defined %}<meta name="description" content="{{ site_description }}" >{% endif %} | 12 | {% if site_description is defined %}<meta name="description" content="{{ site_description }}" >{% endif %} |
| 13 | {% if site_keywords is defined %}<meta name="keywords" content="{{ site_keywords }}" >{% endif %} | 13 | {% if site_keywords is defined %}<meta name="keywords" content="{{ site_keywords }}" >{% endif %} |
| 14 | <link rel="stylesheet" href="{{ url_for("static", file="styles.min.css") }}" type="text/css"> | 14 | <link rel="stylesheet" href="{{ url_for("static", file="styles.min.css") }}" type="text/css"> |
| 15 | <link rel="icon" type="image/x-icon" href="{{ url_for("static", file="favicon.ico") }}"> | 15 | <link rel="icon" type="image/x-icon" href="data:,"> |
| 16 | {% block meta %}{% endblock %} | 16 | {% block meta %}{% endblock %} |
| 17 | {% endblock %} | 17 | {% endblock %} |
| 18 | </head> | 18 | </head> |
| 19 | <body> | 19 | <body> |
| 20 | <a href="#main" class="skip-link">Skip to content</a> | 20 | <nav aria-label="site-nav" role="navigation"> |
| 21 | <nav class="site-nav" aria-label="site-nav" role="navigation"> | ||
| 22 | <ul> | 21 | <ul> |
| 23 | <li><a href="/">Home</a></li> | 22 | <li><a href="/">Home</a></li> |
| 24 | <li><a href="/about/">About</a></li> | 23 | <li><a href="/about/">About</a></li> |
| 25 | <li><a href="/blog/">Blog</a></li> | 24 | <li><a href="/blog/">Blog</a></li> |
| 26 | <li><a href="/services/">Services</a></li> | 25 | <li><a href="/services/">Services</a></li> |
| 27 | <li><a href="/wiki/">Wiki</a></li> | ||
| 28 | </ul> | 26 | </ul> |
| 29 | </nav> | 27 | </nav> |
| 30 | <main id="main">{% block main %}{% endblock %}</main> | 28 | <main>{% block main %}{% endblock %}</main> |
| 31 | <footer> | 29 | <footer> |
| 32 | <p> | 30 | <a href="https://stats.uptimerobot.com/OwOWs7HU0z">Status</a> · |
| 33 | <a href="https://stats.uptimerobot.com/OwOWs7HU0z">Status</a> · | 31 | <a href="https://git.cleberg.net/cleberg.net.git" target="_blank" |
| 34 | <a href="https://git.cleberg.net/cleberg.net.git" target="_blank" | 32 | rel="noopener">Source</a> · |
| 35 | rel="noopener">Source</a> · | 33 | <a href="/feed.xml">RSS</a> |
| 36 | <a href="/feed.xml">RSS</a> | ||
| 37 | </p> | ||
| 38 | </footer> | 34 | </footer> |
| 39 | </body> | 35 | </body> |
| 40 | </html> | 36 | </html> |
theme/templates/blog.html +3 −11
| @@ -10,19 +10,11 @@ main %} | |||
| 10 | </p> | 10 | </p> |
| 11 | <br> | 11 | <br> |
| 12 | {% for post in posts %} | 12 | {% for post in posts %} |
| 13 | <div class="post"> | 13 | <div> |
| 14 | <div class="post-content"> | ||
| 15 | <a href='{{ url_for("blog", slug=post.slug) }}'>{{ post.title }}</a> | ||
| 16 | {% if post.filetags %} | ||
| 17 | <div class="post-tags"> | ||
| 18 | {% for tag in post.filetags %} | ||
| 19 | <span class="tag">{{ tag }}</span> | ||
| 20 | {% endfor %} | ||
| 21 | </div> | ||
| 22 | {% endif %} | ||
| 23 | </div> | ||
| 24 | <time datetime='{{ post.date | strftime("%Y-%m-%d") }}' | 14 | <time datetime='{{ post.date | strftime("%Y-%m-%d") }}' |
| 25 | >{{ post.date|strftime("%B %d, %Y") }}</time | 15 | >{{ post.date|strftime("%B %d, %Y") }}</time |
| 26 | > | 16 | > |
| 17 | <a href='{{ url_for("blog", slug=post.slug) }}'>{{ post.title }}</a> | ||
| 27 | </div> | 18 | </div> |
| 19 | <br> | ||
| 28 | {% endfor %} {% endblock %} | 20 | {% endfor %} {% endblock %} |
theme/templates/index.html +1 −14
| @@ -9,21 +9,8 @@ | |||
| 9 | </blockquote> | 9 | </blockquote> |
| 10 | </section> | 10 | </section> |
| 11 | <section> | 11 | <section> |
| 12 | <h2>Blog Posts</h2> | 12 | <h2>Recent Posts</h2> |
| 13 | <!-- BEGIN_POSTS --> | 13 | <!-- BEGIN_POSTS --> |
| 14 | <!-- END_POSTS --> | 14 | <!-- END_POSTS --> |
| 15 | <a href="/blog/">All Posts →</a> | ||
| 16 | </section> | ||
| 17 | |||
| 18 | <section> | ||
| 19 | <h2>Everything Else</h2> | ||
| 20 | <ul> | ||
| 21 | <li><a href="/about/">About</a></li> | ||
| 22 | <li><a href="https://cv.cleberg.net">Curriculum Vitae</a></li> | ||
| 23 | <li><a href="/now/">Now</a></li> | ||
| 24 | <li><a href="/salary/">Salary</a></li> | ||
| 25 | <li><a href="/services/">Services</a></li> | ||
| 26 | <li><a href="/wiki/">Wiki</a></li> | ||
| 27 | </ul> | ||
| 28 | </section> | 15 | </section> |
| 29 | {% endblock %} | 16 | {% endblock %} |
theme/templates/wiki.html deleted −12
| @@ -1,12 +0,0 @@ | |||
| 1 | {% extends "base.html" %} {% block subtitle %}Wiki | {% endblock %} {% block | ||
| 2 | main %} | ||
| 3 | <h1>Wiki</h1> | ||
| 4 | <p>Use <code>Ctrl + F</code> to search wiki pages for keywords.</p> | ||
| 5 | {% for post in posts %} | ||
| 6 | <div class="post"> | ||
| 7 | <a href='{{ url_for("wiki", slug=post.slug) }}'>{{ post.title }}</a> | ||
| 8 | <time datetime='{{ post.date | strftime("%Y-%m-%d") }}' | ||
| 9 | >{{ post.date|strftime("%B %d, %Y") }}</time | ||
| 10 | > | ||
| 11 | </div> | ||
| 12 | {% endfor %} {% endblock %} | ||