From 73980d9811ac352aef539d2e28b0e1df0b429ea3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:13:37 +0000 Subject: [PATCH 1/3] Initial plan From 90381dcfe780ede90bf38ba82f2bd77ad13300c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:23:52 +0000 Subject: [PATCH 2/3] Add Hugo theme with layouts and example site Co-authored-by: asimpson <1048831+asimpson@users.noreply.github.com> --- themes/cycle/assets/custom.css | 79 + themes/cycle/assets/tachyons.css | 2 + themes/cycle/exampleSite/.hugo_build.lock | 0 .../exampleSite/content/archive/_index.md | 3 + .../cycle/exampleSite/content/page/support.md | 18 + themes/cycle/exampleSite/content/page/uses.md | 37 + themes/cycle/exampleSite/content/post/0-14.md | 42 + .../content/post/8-line-firewall.md | 24 + .../cycle/exampleSite/content/post/ATR2100.md | 24 + .../content/post/a-few-bash-tips.md | 155 ++ .../content/post/a-few-posix-shell-tips.md | 76 + ...ript-that-adds-read-it-later-to-twitter.md | 14 + .../exampleSite/content/post/a-hackintosh.md | 57 + .../content/post/a-little-hydrofoil.md | 18 + .../content/post/a-new-adventure.md | 12 + .../content/post/a-new-website-for-2020.md | 16 + .../content/post/a-public-inbox.md | 20 + .../content/post/a-style-guide-guide.md | 16 + .../post/adam-versus-dropbox-and-oauth.md | 51 + .../content/post/adn-cross-poster.md | 46 + .../content/post/ajax-and-rails.md | 31 + .../post/alfred-and-web-development.md | 21 + .../content/post/amp-html-terrible-html.md | 21 + .../content/post/andy-budd-on-time.md | 12 + .../post/app_store_moment_of_clarity.md | 24 + .../apple-on-batteries-and-performance.md | 17 + .../content/post/automating-socks-proxy.md | 28 + .../content/post/balancing-devotion.md | 34 + .../bash-function-ip-address-to-clipboard.md | 18 + .../post/be-a-good-video-call-citizen.md | 27 + .../content/post/before-circles-2017.md | 37 + .../content/post/benedict-evans-in-on-fire.md | 27 + .../content/post/better-scripting-with-gh.md | 66 + .../exampleSite/content/post/blog-rewrite.md | 80 + .../post/blogs-data-and-social-networks.md | 30 + ...ree-as-renewables-edge-out-fossil-fuels.md | 14 + .../content/post/broadcast-channel.md | 10 + .../casperjs-node-and-the-raspberry-pi.md | 35 + .../content/post/command-line-notification.md | 13 + .../content/post/compose-key-and-i3.md | 35 + ...-hutchins-hacker-who-saved-the-internet.md | 14 + .../content/post/convince-the-boss.md | 18 + .../content/post/create-passion.md | 14 + .../content/post/css-reusability.md | 20 + .../content/post/cycle-v030-released.md | 13 + .../dead-cells-might-be-a-perfect-game.md | 29 + .../content/post/declining-expectations.md | 14 + .../exampleSite/content/post/diceware.md | 21 + .../exampleSite/content/post/eight-years.md | 17 + .../exampleSite/content/post/emacs-lite.md | 19 + .../exampleSite/content/post/emacs-tips.md | 34 + .../exampleSite/content/post/end-of-an-era.md | 15 + .../content/post/evening-edition.md | 12 + .../content/post/facetime-killer.md | 24 + .../exampleSite/content/post/family-first.md | 14 + .../content/post/farewell-heroku.md | 52 + ...mpeg-convert-multiple-files-using-xargs.md | 14 + .../exampleSite/content/post/five-years.md | 13 + .../exampleSite/content/post/flatkill.md | 14 + .../content/post/format-json-in-emacs.md | 21 + ...our-ways-to-approach-hacktoberfest-2020.md | 28 + .../content/post/getting-started-with-rofi.md | 72 + .../post/gists-snippets-and-sublime-text-2.md | 16 + .../content/post/git-commit-template.md | 22 + .../exampleSite/content/post/git-worktree.md | 23 + .../exampleSite/content/post/goat-counter.md | 12 + .../content/post/goodbye-sparkbox.md | 17 + .../post/google-fi-and-data-only-plans.md | 23 + .../content/post/grow-it-dont-build-it.md | 14 + .../content/post/guidelines-for-data.md | 20 + .../hacking-on-grafana-with-web-assembly.md | 146 + .../content/post/hello-micro-blog.md | 25 + .../exampleSite/content/post/hello-world.md | 66 + .../exampleSite/content/post/helm-to-ivy.md | 24 + .../content/post/heroku-and-ssh-keys.md | 10 + ...he-pacific-crest-trail-in-three-minutes.md | 10 + .../post/hosting-assets-via-github-pages.md | 31 + .../content/post/how-are-you-living.md | 12 + .../post/how-do-we-make-the-web-better.md | 53 + .../post/how-to-use-siji-font-on-polybar.md | 14 + .../exampleSite/content/post/huffduffer.md | 14 + .../content/post/i-moved-to-hover.md | 14 + .../cycle/exampleSite/content/post/ifttt.md | 34 + .../content/post/indexing-my-blogs-links.md | 10 + .../content/post/introducing-cycle.md | 117 + .../post/introducing-ivy-feedwrangler.md | 32 + .../post/ip-address-alfred-extension.md | 14 + ...iphone-checker-with-capybara-and-twilio.md | 26 + .../post/is-webp-really-better-than-jpeg.md | 14 + .../content/post/ivy-pinboard-popular.md | 40 + .../content/post/js2coffee-alfred-workflow.md | 14 + .../content/post/just-start-over.md | 16 + .../exampleSite/content/post/keeping-up.md | 26 + .../content/post/kyle-steed-on-rest.md | 14 + .../exampleSite/content/post/lambda-talk.md | 11 + .../post/learning-to-think-in-react.md | 61 + ...ating-openai-into-a-grafana-data-source.md | 10 + ...lyza-gardner-on-laying-down-our-burdens.md | 12 + .../post/macos-catalina-slow-by-design.md | 20 + .../maybe-you-shouldits-not-youmove-on.md | 19 + .../content/post/medium-isnt-permanent.md | 15 + .../messi-is-re-writing-the-record-book.md | 13 + .../exampleSite/content/post/microblogging.md | 18 + ...n-existing-build-process-to-npm-scripts.md | 111 + .../content/post/moved-to-siteleaf.md | 15 + .../content/post/moving-away-from-google.md | 15 + .../post/moving-tweetbot-beta-to-a-new-mac.md | 14 + .../content/post/my-first-bookmarklet.md | 23 + .../content/post/new-workstation.md | 83 + .../content/post/nginx-www-rewrite.md | 26 + .../content/post/nixpkgs-is-a-treasure.md | 42 + .../post/nothing-speaks-like-a-demo.md | 14 + .../post/on-diminishing-modes-in-emacs.md | 45 + .../exampleSite/content/post/on-equifax.md | 11 + .../content/post/on-george-floyd.md | 34 + .../exampleSite/content/post/on-webpack.md | 9 + .../exampleSite/content/post/openring.md | 31 + .../cycle/exampleSite/content/post/oscar.md | 14 + .../post/parsing-memory-usage-in-htoptop.md | 13 + .../post/plaintext-and-markdown-a-primer.md | 44 + .../content/post/polybar-fonts-and-ubuntu.md | 20 + .../content/post/pretty-git-log.md | 16 + .../exampleSite/content/post/psychicpaper.md | 25 + .../content/post/rands-on-email.md | 14 + .../exampleSite/content/post/recently-16.md | 46 + .../exampleSite/content/post/recently-44.md | 24 + .../content/post/rename-utility.md | 14 + .../post/rotten-tomatoes-and-launch-center.md | 20 + .../content/post/rust-module-system.md | 14 + .../content/post/rust-strings-and-str.md | 133 + .../content/post/s3-security-policy.md | 18 + ...seamless-branch-deploys-with-kubernetes.md | 12 + .../content/post/search-imessage-sql.md | 14 + .../post/second-guessing-the-modern-web.md | 12 + .../post/setting-a-default-browser-in-i3.md | 42 + .../content/post/simple-account-set-up.md | 22 + .../post/slanted-elements-with-css3.md | 10 + .../exampleSite/content/post/small-tech.md | 18 + .../exampleSite/content/post/small-things.md | 15 + ...ybox-crond-hanging-on-alpine-linux-boot.md | 33 + .../someone-is-working-harder-than-you.md | 20 + .../content/post/sparrow-and-the-app-store.md | 14 + .../exampleSite/content/post/sqlite-tips.md | 25 + .../cycle/exampleSite/content/post/story.md | 18 + .../content/post/the-era-of-the-screenshot.md | 20 + .../content/post/the-future-is-prototyping.md | 14 + .../post/the-manhattan-project-time-lapse.md | 14 + .../content/post/the-stream-hasnt-won.md | 13 + .../content/post/the-thing-about-computers.md | 15 + .../content/post/the-web-and-my-goal.md | 16 + .../content/post/the-web-is-not-print.md | 14 + .../post/the-wordpress-http-api-is-awesome.md | 14 + .../post/theme-the-chrome-dev-tools.md | 16 + .../exampleSite/content/post/thirty-five.md | 53 + .../cycle/exampleSite/content/post/thirty.md | 42 + ...fix-video-calls-while-working-from-home.md | 48 + .../exampleSite/content/post/three-years.md | 11 + .../post/tigers-and-social-networks.md | 18 + .../content/post/track-redirects-with-curl.md | 51 + .../exampleSite/content/post/tweet-stash.md | 20 + .../using-the-kindle-to-harness-the-web.md | 18 + .../exampleSite/content/post/verse-recall.md | 25 + .../exampleSite/content/post/vim-ramblings.md | 30 + .../content/post/we-all-need-a-team.md | 15 + ...formance-and-facebooks-instant-articles.md | 21 + .../content/post/web-scraper-cookbook.md | 11 + .../what-happens-when-you-remove-friction.md | 13 + .../content/post/what-is-medium.md | 17 + .../content/post/what-its-all-about.md | 16 + .../exampleSite/content/post/what-matters.md | 14 + .../content/post/what-time-is-it-in-london.md | 10 + .../post/whats-best-for-the-readers.md | 16 + .../content/post/when-the-music-stops.md | 14 + .../content/post/windows-11-as-kvm-guest.md | 60 + ...ng-with-wordpress-offset-and-pagination.md | 37 + .../content/post/youtube-subscriptions.md | 14 + .../exampleSite/content/post/zach-beane.md | 13 + .../content/post/zen-garden-part-2.md | 28 + themes/cycle/exampleSite/hugo.toml | 21 + .../exampleSite/public/archive/index.html | 2454 +++++++++++++++++ .../cycle/exampleSite/public/archive/rss.xml | 9 + .../exampleSite/public/categories/index.html | 219 ++ .../exampleSite/public/categories/rss.xml | 9 + themes/cycle/exampleSite/public/index.html | 346 +++ .../cycle/exampleSite/public/page/index.html | 243 ++ themes/cycle/exampleSite/public/page/rss.xml | 9 + .../public/page/support/index.html | 233 ++ .../exampleSite/public/page/uses/index.html | 239 ++ .../cycle/exampleSite/public/post/index.html | 2454 +++++++++++++++++ themes/cycle/exampleSite/public/post/rss.xml | 738 +++++ themes/cycle/exampleSite/public/rss.xml | 738 +++++ themes/cycle/exampleSite/public/sitemap.xml | 539 ++++ .../cycle/exampleSite/public/tags/index.html | 219 ++ themes/cycle/exampleSite/public/tags/rss.xml | 9 + .../public/writing/0-14/index.html | 267 ++ .../public/writing/8-line-firewall/index.html | 249 ++ .../public/writing/a-few-bash-tips/index.html | 347 +++ .../writing/a-few-posix-shell-tips/index.html | 288 ++ .../index.html | 241 ++ .../public/writing/a-hackintosh/index.html | 271 ++ .../writing/a-little-hydrofoil/index.html | 247 ++ .../public/writing/a-new-adventure/index.html | 240 ++ .../writing/a-new-website-for-2020/index.html | 242 ++ .../public/writing/a-public-inbox/index.html | 248 ++ .../writing/a-style-guide-guide/index.html | 244 ++ .../adam-versus-dropbox-and-oauth/index.html | 262 ++ .../writing/adn-cross-poster/index.html | 257 ++ .../public/writing/ajax-and-rails/index.html | 263 ++ .../alfred-and-web-development/index.html | 248 ++ .../writing/amp-html-terrible-html/index.html | 245 ++ .../writing/andy-budd-on-time/index.html | 242 ++ .../app_store_moment_of_clarity/index.html | 247 ++ .../index.html | 247 ++ .../public/writing/atr2100/index.html | 249 ++ .../writing/automating-socks-proxy/index.html | 253 ++ .../writing/balancing-devotion/index.html | 259 ++ .../index.html | 246 ++ .../be-a-good-video-call-citizen/index.html | 248 ++ .../writing/before-circles-2017/index.html | 253 ++ .../benedict-evans-in-on-fire/index.html | 254 ++ .../better-scripting-with-gh/index.html | 286 ++ .../public/writing/blog-rewrite/index.html | 298 ++ .../blogs-data-and-social-networks/index.html | 255 ++ .../index.html | 241 ++ .../writing/broadcast-channel/index.html | 239 ++ .../index.html | 253 ++ .../command-line-notification/index.html | 241 ++ .../writing/compose-key-and-i3/index.html | 249 ++ .../index.html | 241 ++ .../writing/convince-the-boss/index.html | 247 ++ .../public/writing/create-passion/index.html | 243 ++ .../public/writing/css-reusability/index.html | 248 ++ .../writing/cycle-v030-released/index.html | 241 ++ .../index.html | 247 ++ .../writing/declining-expectations/index.html | 243 ++ .../public/writing/diceware/index.html | 249 ++ .../public/writing/eight-years/index.html | 246 ++ .../public/writing/emacs-lite/index.html | 246 ++ .../public/writing/emacs-tips/index.html | 268 ++ .../public/writing/end-of-an-era/index.html | 242 ++ .../public/writing/evening-edition/index.html | 240 ++ .../public/writing/facetime-killer/index.html | 250 ++ .../public/writing/family-first/index.html | 243 ++ .../public/writing/farewell-heroku/index.html | 269 ++ .../index.html | 241 ++ .../public/writing/five-years/index.html | 241 ++ .../public/writing/flatkill/index.html | 241 ++ .../writing/format-json-in-emacs/index.html | 248 ++ .../index.html | 250 ++ .../getting-started-with-rofi/index.html | 282 ++ .../index.html | 242 ++ .../writing/git-commit-template/index.html | 248 ++ .../public/writing/git-worktree/index.html | 246 ++ .../public/writing/goat-counter/index.html | 238 ++ .../writing/goodbye-sparkbox/index.html | 243 ++ .../google-fi-and-data-only-plans/index.html | 246 ++ .../writing/grow-it-dont-build-it/index.html | 243 ++ .../writing/guidelines-for-data/index.html | 246 ++ .../index.html | 353 +++ .../writing/hello-micro-blog/index.html | 249 ++ .../public/writing/hello-world/index.html | 271 ++ .../public/writing/helm-to-ivy/index.html | 251 ++ .../writing/heroku-and-ssh-keys/index.html | 239 ++ .../index.html | 241 ++ .../index.html | 257 ++ .../writing/how-are-you-living/index.html | 242 ++ .../how-do-we-make-the-web-better/index.html | 277 ++ .../index.html | 239 ++ .../public/writing/huffduffer/index.html | 241 ++ .../writing/i-moved-to-hover/index.html | 241 ++ .../public/writing/ifttt/index.html | 251 ++ .../indexing-my-blogs-links/index.html | 235 ++ .../writing/introducing-cycle/index.html | 297 ++ .../introducing-ivy-feedwrangler/index.html | 258 ++ .../ip-address-alfred-extension/index.html | 241 ++ .../index.html | 246 ++ .../index.html | 241 ++ .../writing/ivy-pinboard-popular/index.html | 261 ++ .../js2coffee-alfred-workflow/index.html | 241 ++ .../public/writing/just-start-over/index.html | 244 ++ .../public/writing/keeping-up/index.html | 249 ++ .../writing/kyle-steed-on-rest/index.html | 243 ++ .../public/writing/lambda-talk/index.html | 240 ++ .../learning-to-think-in-react/index.html | 275 ++ .../index.html | 239 ++ .../index.html | 242 ++ .../macos-catalina-slow-by-design/index.html | 248 ++ .../index.html | 247 ++ .../writing/medium-isnt-permanent/index.html | 244 ++ .../index.html | 240 ++ .../public/writing/microblogging/index.html | 248 ++ .../index.html | 312 +++ .../writing/moved-to-siteleaf/index.html | 244 ++ .../moving-away-from-google/index.html | 242 ++ .../index.html | 241 ++ .../writing/my-first-bookmarklet/index.html | 246 ++ .../public/writing/new-workstation/index.html | 261 ++ .../writing/nginx-www-rewrite/index.html | 247 ++ .../writing/nixpkgs-is-a-treasure/index.html | 266 ++ .../nothing-speaks-like-a-demo/index.html | 239 ++ .../on-diminishing-modes-in-emacs/index.html | 265 ++ .../public/writing/on-equifax/index.html | 242 ++ .../public/writing/on-george-floyd/index.html | 256 ++ .../public/writing/on-webpack/index.html | 239 ++ .../public/writing/openring/index.html | 253 ++ .../public/writing/oscar/index.html | 241 ++ .../index.html | 243 ++ .../index.html | 262 ++ .../polybar-fonts-and-ubuntu/index.html | 245 ++ .../public/writing/pretty-git-log/index.html | 242 ++ .../public/writing/psychicpaper/index.html | 248 ++ .../public/writing/rands-on-email/index.html | 243 ++ .../public/writing/recently-16/index.html | 270 ++ .../public/writing/recently-44/index.html | 248 ++ .../public/writing/rename-utility/index.html | 241 ++ .../index.html | 244 ++ .../writing/rust-module-system/index.html | 239 ++ .../writing/rust-strings-and-str/index.html | 321 +++ .../writing/s3-security-policy/index.html | 243 ++ .../index.html | 238 ++ .../writing/search-imessage-sql/index.html | 239 ++ .../second-guessing-the-modern-web/index.html | 238 ++ .../index.html | 256 ++ .../writing/simple-account-set-up/index.html | 245 ++ .../slanted-elements-with-css3/index.html | 239 ++ .../public/writing/small-tech/index.html | 249 ++ .../public/writing/small-things/index.html | 244 ++ .../index.html | 256 ++ .../index.html | 246 ++ .../sparrow-and-the-app-store/index.html | 243 ++ .../public/writing/sqlite-tips/index.html | 263 ++ .../public/writing/story/index.html | 245 ++ .../the-era-of-the-screenshot/index.html | 249 ++ .../the-future-is-prototyping/index.html | 243 ++ .../index.html | 241 ++ .../writing/the-stream-hasnt-won/index.html | 243 ++ .../the-thing-about-computers/index.html | 244 ++ .../writing/the-web-and-my-goal/index.html | 244 ++ .../writing/the-web-is-not-print/index.html | 243 ++ .../index.html | 241 ++ .../theme-the-chrome-dev-tools/index.html | 242 ++ .../public/writing/thirty-five/index.html | 279 ++ .../public/writing/thirty/index.html | 272 ++ .../index.html | 264 ++ .../public/writing/three-years/index.html | 240 ++ .../tigers-and-social-networks/index.html | 245 ++ .../track-redirects-with-curl/index.html | 272 ++ .../public/writing/tweet-stash/index.html | 245 ++ .../index.html | 243 ++ .../public/writing/verse-recall/index.html | 250 ++ .../public/writing/vim-ramblings/index.html | 252 ++ .../writing/we-all-need-a-team/index.html | 244 ++ .../index.html | 247 ++ .../writing/web-scraper-cookbook/index.html | 240 ++ .../index.html | 243 ++ .../public/writing/what-is-medium/index.html | 245 ++ .../writing/what-its-all-about/index.html | 244 ++ .../public/writing/what-matters/index.html | 243 ++ .../what-time-is-it-in-london/index.html | 237 ++ .../whats-best-for-the-readers/index.html | 244 ++ .../writing/when-the-music-stops/index.html | 243 ++ .../windows-11-as-kvm-guest/index.html | 271 ++ .../index.html | 257 ++ .../writing/youtube-subscriptions/index.html | 243 ++ .../public/writing/zach-beane/index.html | 239 ++ .../writing/zen-garden-part-2/index.html | 252 ++ themes/cycle/exampleSite/themes/cycle | 1 + themes/cycle/layouts/_default/baseof.html | 9 + themes/cycle/layouts/_default/list.html | 24 + themes/cycle/layouts/_default/rss.xml | 51 + themes/cycle/layouts/_default/single.html | 14 + themes/cycle/layouts/archive/list.html | 24 + themes/cycle/layouts/index.html | 32 + themes/cycle/layouts/partials/footer.html | 4 + themes/cycle/layouts/partials/head.html | 48 + themes/cycle/layouts/partials/header.html | 11 + themes/cycle/layouts/partials/logo.html | 76 + themes/cycle/layouts/partials/post_body.html | 16 + themes/cycle/theme.toml | 12 + 379 files changed, 56775 insertions(+) create mode 100644 themes/cycle/assets/custom.css create mode 100644 themes/cycle/assets/tachyons.css create mode 100644 themes/cycle/exampleSite/.hugo_build.lock create mode 100644 themes/cycle/exampleSite/content/archive/_index.md create mode 100644 themes/cycle/exampleSite/content/page/support.md create mode 100644 themes/cycle/exampleSite/content/page/uses.md create mode 100644 themes/cycle/exampleSite/content/post/0-14.md create mode 100644 themes/cycle/exampleSite/content/post/8-line-firewall.md create mode 100644 themes/cycle/exampleSite/content/post/ATR2100.md create mode 100644 themes/cycle/exampleSite/content/post/a-few-bash-tips.md create mode 100644 themes/cycle/exampleSite/content/post/a-few-posix-shell-tips.md create mode 100644 themes/cycle/exampleSite/content/post/a-fluid-userscript-that-adds-read-it-later-to-twitter.md create mode 100644 themes/cycle/exampleSite/content/post/a-hackintosh.md create mode 100644 themes/cycle/exampleSite/content/post/a-little-hydrofoil.md create mode 100644 themes/cycle/exampleSite/content/post/a-new-adventure.md create mode 100644 themes/cycle/exampleSite/content/post/a-new-website-for-2020.md create mode 100644 themes/cycle/exampleSite/content/post/a-public-inbox.md create mode 100644 themes/cycle/exampleSite/content/post/a-style-guide-guide.md create mode 100644 themes/cycle/exampleSite/content/post/adam-versus-dropbox-and-oauth.md create mode 100644 themes/cycle/exampleSite/content/post/adn-cross-poster.md create mode 100644 themes/cycle/exampleSite/content/post/ajax-and-rails.md create mode 100644 themes/cycle/exampleSite/content/post/alfred-and-web-development.md create mode 100644 themes/cycle/exampleSite/content/post/amp-html-terrible-html.md create mode 100644 themes/cycle/exampleSite/content/post/andy-budd-on-time.md create mode 100644 themes/cycle/exampleSite/content/post/app_store_moment_of_clarity.md create mode 100644 themes/cycle/exampleSite/content/post/apple-on-batteries-and-performance.md create mode 100644 themes/cycle/exampleSite/content/post/automating-socks-proxy.md create mode 100644 themes/cycle/exampleSite/content/post/balancing-devotion.md create mode 100644 themes/cycle/exampleSite/content/post/bash-function-ip-address-to-clipboard.md create mode 100644 themes/cycle/exampleSite/content/post/be-a-good-video-call-citizen.md create mode 100644 themes/cycle/exampleSite/content/post/before-circles-2017.md create mode 100644 themes/cycle/exampleSite/content/post/benedict-evans-in-on-fire.md create mode 100644 themes/cycle/exampleSite/content/post/better-scripting-with-gh.md create mode 100644 themes/cycle/exampleSite/content/post/blog-rewrite.md create mode 100644 themes/cycle/exampleSite/content/post/blogs-data-and-social-networks.md create mode 100644 themes/cycle/exampleSite/content/post/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels.md create mode 100644 themes/cycle/exampleSite/content/post/broadcast-channel.md create mode 100644 themes/cycle/exampleSite/content/post/casperjs-node-and-the-raspberry-pi.md create mode 100644 themes/cycle/exampleSite/content/post/command-line-notification.md create mode 100644 themes/cycle/exampleSite/content/post/compose-key-and-i3.md create mode 100644 themes/cycle/exampleSite/content/post/confessions-marcus-hutchins-hacker-who-saved-the-internet.md create mode 100644 themes/cycle/exampleSite/content/post/convince-the-boss.md create mode 100644 themes/cycle/exampleSite/content/post/create-passion.md create mode 100644 themes/cycle/exampleSite/content/post/css-reusability.md create mode 100644 themes/cycle/exampleSite/content/post/cycle-v030-released.md create mode 100644 themes/cycle/exampleSite/content/post/dead-cells-might-be-a-perfect-game.md create mode 100644 themes/cycle/exampleSite/content/post/declining-expectations.md create mode 100644 themes/cycle/exampleSite/content/post/diceware.md create mode 100644 themes/cycle/exampleSite/content/post/eight-years.md create mode 100644 themes/cycle/exampleSite/content/post/emacs-lite.md create mode 100644 themes/cycle/exampleSite/content/post/emacs-tips.md create mode 100644 themes/cycle/exampleSite/content/post/end-of-an-era.md create mode 100644 themes/cycle/exampleSite/content/post/evening-edition.md create mode 100644 themes/cycle/exampleSite/content/post/facetime-killer.md create mode 100644 themes/cycle/exampleSite/content/post/family-first.md create mode 100644 themes/cycle/exampleSite/content/post/farewell-heroku.md create mode 100644 themes/cycle/exampleSite/content/post/ffmpeg-convert-multiple-files-using-xargs.md create mode 100644 themes/cycle/exampleSite/content/post/five-years.md create mode 100644 themes/cycle/exampleSite/content/post/flatkill.md create mode 100644 themes/cycle/exampleSite/content/post/format-json-in-emacs.md create mode 100644 themes/cycle/exampleSite/content/post/four-ways-to-approach-hacktoberfest-2020.md create mode 100644 themes/cycle/exampleSite/content/post/getting-started-with-rofi.md create mode 100644 themes/cycle/exampleSite/content/post/gists-snippets-and-sublime-text-2.md create mode 100644 themes/cycle/exampleSite/content/post/git-commit-template.md create mode 100644 themes/cycle/exampleSite/content/post/git-worktree.md create mode 100644 themes/cycle/exampleSite/content/post/goat-counter.md create mode 100644 themes/cycle/exampleSite/content/post/goodbye-sparkbox.md create mode 100644 themes/cycle/exampleSite/content/post/google-fi-and-data-only-plans.md create mode 100644 themes/cycle/exampleSite/content/post/grow-it-dont-build-it.md create mode 100644 themes/cycle/exampleSite/content/post/guidelines-for-data.md create mode 100644 themes/cycle/exampleSite/content/post/hacking-on-grafana-with-web-assembly.md create mode 100644 themes/cycle/exampleSite/content/post/hello-micro-blog.md create mode 100644 themes/cycle/exampleSite/content/post/hello-world.md create mode 100644 themes/cycle/exampleSite/content/post/helm-to-ivy.md create mode 100644 themes/cycle/exampleSite/content/post/heroku-and-ssh-keys.md create mode 100644 themes/cycle/exampleSite/content/post/hiking-the-pacific-crest-trail-in-three-minutes.md create mode 100644 themes/cycle/exampleSite/content/post/hosting-assets-via-github-pages.md create mode 100644 themes/cycle/exampleSite/content/post/how-are-you-living.md create mode 100644 themes/cycle/exampleSite/content/post/how-do-we-make-the-web-better.md create mode 100644 themes/cycle/exampleSite/content/post/how-to-use-siji-font-on-polybar.md create mode 100644 themes/cycle/exampleSite/content/post/huffduffer.md create mode 100644 themes/cycle/exampleSite/content/post/i-moved-to-hover.md create mode 100644 themes/cycle/exampleSite/content/post/ifttt.md create mode 100644 themes/cycle/exampleSite/content/post/indexing-my-blogs-links.md create mode 100644 themes/cycle/exampleSite/content/post/introducing-cycle.md create mode 100644 themes/cycle/exampleSite/content/post/introducing-ivy-feedwrangler.md create mode 100644 themes/cycle/exampleSite/content/post/ip-address-alfred-extension.md create mode 100644 themes/cycle/exampleSite/content/post/iphone-checker-with-capybara-and-twilio.md create mode 100644 themes/cycle/exampleSite/content/post/is-webp-really-better-than-jpeg.md create mode 100644 themes/cycle/exampleSite/content/post/ivy-pinboard-popular.md create mode 100644 themes/cycle/exampleSite/content/post/js2coffee-alfred-workflow.md create mode 100644 themes/cycle/exampleSite/content/post/just-start-over.md create mode 100644 themes/cycle/exampleSite/content/post/keeping-up.md create mode 100644 themes/cycle/exampleSite/content/post/kyle-steed-on-rest.md create mode 100644 themes/cycle/exampleSite/content/post/lambda-talk.md create mode 100644 themes/cycle/exampleSite/content/post/learning-to-think-in-react.md create mode 100644 themes/cycle/exampleSite/content/post/lessons-learned-from-integrating-openai-into-a-grafana-data-source.md create mode 100644 themes/cycle/exampleSite/content/post/lyza-gardner-on-laying-down-our-burdens.md create mode 100644 themes/cycle/exampleSite/content/post/macos-catalina-slow-by-design.md create mode 100644 themes/cycle/exampleSite/content/post/maybe-you-shouldits-not-youmove-on.md create mode 100644 themes/cycle/exampleSite/content/post/medium-isnt-permanent.md create mode 100644 themes/cycle/exampleSite/content/post/messi-is-re-writing-the-record-book.md create mode 100644 themes/cycle/exampleSite/content/post/microblogging.md create mode 100644 themes/cycle/exampleSite/content/post/migrate-an-existing-build-process-to-npm-scripts.md create mode 100644 themes/cycle/exampleSite/content/post/moved-to-siteleaf.md create mode 100644 themes/cycle/exampleSite/content/post/moving-away-from-google.md create mode 100644 themes/cycle/exampleSite/content/post/moving-tweetbot-beta-to-a-new-mac.md create mode 100644 themes/cycle/exampleSite/content/post/my-first-bookmarklet.md create mode 100644 themes/cycle/exampleSite/content/post/new-workstation.md create mode 100644 themes/cycle/exampleSite/content/post/nginx-www-rewrite.md create mode 100644 themes/cycle/exampleSite/content/post/nixpkgs-is-a-treasure.md create mode 100644 themes/cycle/exampleSite/content/post/nothing-speaks-like-a-demo.md create mode 100644 themes/cycle/exampleSite/content/post/on-diminishing-modes-in-emacs.md create mode 100644 themes/cycle/exampleSite/content/post/on-equifax.md create mode 100644 themes/cycle/exampleSite/content/post/on-george-floyd.md create mode 100644 themes/cycle/exampleSite/content/post/on-webpack.md create mode 100644 themes/cycle/exampleSite/content/post/openring.md create mode 100644 themes/cycle/exampleSite/content/post/oscar.md create mode 100644 themes/cycle/exampleSite/content/post/parsing-memory-usage-in-htoptop.md create mode 100644 themes/cycle/exampleSite/content/post/plaintext-and-markdown-a-primer.md create mode 100644 themes/cycle/exampleSite/content/post/polybar-fonts-and-ubuntu.md create mode 100644 themes/cycle/exampleSite/content/post/pretty-git-log.md create mode 100644 themes/cycle/exampleSite/content/post/psychicpaper.md create mode 100644 themes/cycle/exampleSite/content/post/rands-on-email.md create mode 100644 themes/cycle/exampleSite/content/post/recently-16.md create mode 100644 themes/cycle/exampleSite/content/post/recently-44.md create mode 100644 themes/cycle/exampleSite/content/post/rename-utility.md create mode 100644 themes/cycle/exampleSite/content/post/rotten-tomatoes-and-launch-center.md create mode 100644 themes/cycle/exampleSite/content/post/rust-module-system.md create mode 100644 themes/cycle/exampleSite/content/post/rust-strings-and-str.md create mode 100644 themes/cycle/exampleSite/content/post/s3-security-policy.md create mode 100644 themes/cycle/exampleSite/content/post/seamless-branch-deploys-with-kubernetes.md create mode 100644 themes/cycle/exampleSite/content/post/search-imessage-sql.md create mode 100644 themes/cycle/exampleSite/content/post/second-guessing-the-modern-web.md create mode 100644 themes/cycle/exampleSite/content/post/setting-a-default-browser-in-i3.md create mode 100644 themes/cycle/exampleSite/content/post/simple-account-set-up.md create mode 100644 themes/cycle/exampleSite/content/post/slanted-elements-with-css3.md create mode 100644 themes/cycle/exampleSite/content/post/small-tech.md create mode 100644 themes/cycle/exampleSite/content/post/small-things.md create mode 100644 themes/cycle/exampleSite/content/post/solving-busybox-crond-hanging-on-alpine-linux-boot.md create mode 100644 themes/cycle/exampleSite/content/post/someone-is-working-harder-than-you.md create mode 100644 themes/cycle/exampleSite/content/post/sparrow-and-the-app-store.md create mode 100644 themes/cycle/exampleSite/content/post/sqlite-tips.md create mode 100644 themes/cycle/exampleSite/content/post/story.md create mode 100644 themes/cycle/exampleSite/content/post/the-era-of-the-screenshot.md create mode 100644 themes/cycle/exampleSite/content/post/the-future-is-prototyping.md create mode 100644 themes/cycle/exampleSite/content/post/the-manhattan-project-time-lapse.md create mode 100644 themes/cycle/exampleSite/content/post/the-stream-hasnt-won.md create mode 100644 themes/cycle/exampleSite/content/post/the-thing-about-computers.md create mode 100644 themes/cycle/exampleSite/content/post/the-web-and-my-goal.md create mode 100644 themes/cycle/exampleSite/content/post/the-web-is-not-print.md create mode 100644 themes/cycle/exampleSite/content/post/the-wordpress-http-api-is-awesome.md create mode 100644 themes/cycle/exampleSite/content/post/theme-the-chrome-dev-tools.md create mode 100644 themes/cycle/exampleSite/content/post/thirty-five.md create mode 100644 themes/cycle/exampleSite/content/post/thirty.md create mode 100644 themes/cycle/exampleSite/content/post/three-easy-tuneups-to-fix-video-calls-while-working-from-home.md create mode 100644 themes/cycle/exampleSite/content/post/three-years.md create mode 100644 themes/cycle/exampleSite/content/post/tigers-and-social-networks.md create mode 100644 themes/cycle/exampleSite/content/post/track-redirects-with-curl.md create mode 100644 themes/cycle/exampleSite/content/post/tweet-stash.md create mode 100644 themes/cycle/exampleSite/content/post/using-the-kindle-to-harness-the-web.md create mode 100644 themes/cycle/exampleSite/content/post/verse-recall.md create mode 100644 themes/cycle/exampleSite/content/post/vim-ramblings.md create mode 100644 themes/cycle/exampleSite/content/post/we-all-need-a-team.md create mode 100644 themes/cycle/exampleSite/content/post/web-performance-and-facebooks-instant-articles.md create mode 100644 themes/cycle/exampleSite/content/post/web-scraper-cookbook.md create mode 100644 themes/cycle/exampleSite/content/post/what-happens-when-you-remove-friction.md create mode 100644 themes/cycle/exampleSite/content/post/what-is-medium.md create mode 100644 themes/cycle/exampleSite/content/post/what-its-all-about.md create mode 100644 themes/cycle/exampleSite/content/post/what-matters.md create mode 100644 themes/cycle/exampleSite/content/post/what-time-is-it-in-london.md create mode 100644 themes/cycle/exampleSite/content/post/whats-best-for-the-readers.md create mode 100644 themes/cycle/exampleSite/content/post/when-the-music-stops.md create mode 100644 themes/cycle/exampleSite/content/post/windows-11-as-kvm-guest.md create mode 100644 themes/cycle/exampleSite/content/post/working-with-wordpress-offset-and-pagination.md create mode 100644 themes/cycle/exampleSite/content/post/youtube-subscriptions.md create mode 100644 themes/cycle/exampleSite/content/post/zach-beane.md create mode 100644 themes/cycle/exampleSite/content/post/zen-garden-part-2.md create mode 100644 themes/cycle/exampleSite/hugo.toml create mode 100644 themes/cycle/exampleSite/public/archive/index.html create mode 100644 themes/cycle/exampleSite/public/archive/rss.xml create mode 100644 themes/cycle/exampleSite/public/categories/index.html create mode 100644 themes/cycle/exampleSite/public/categories/rss.xml create mode 100644 themes/cycle/exampleSite/public/index.html create mode 100644 themes/cycle/exampleSite/public/page/index.html create mode 100644 themes/cycle/exampleSite/public/page/rss.xml create mode 100644 themes/cycle/exampleSite/public/page/support/index.html create mode 100644 themes/cycle/exampleSite/public/page/uses/index.html create mode 100644 themes/cycle/exampleSite/public/post/index.html create mode 100644 themes/cycle/exampleSite/public/post/rss.xml create mode 100644 themes/cycle/exampleSite/public/rss.xml create mode 100644 themes/cycle/exampleSite/public/sitemap.xml create mode 100644 themes/cycle/exampleSite/public/tags/index.html create mode 100644 themes/cycle/exampleSite/public/tags/rss.xml create mode 100644 themes/cycle/exampleSite/public/writing/0-14/index.html create mode 100644 themes/cycle/exampleSite/public/writing/8-line-firewall/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-hackintosh/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-new-adventure/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-public-inbox/index.html create mode 100644 themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html create mode 100644 themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html create mode 100644 themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html create mode 100644 themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html create mode 100644 themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html create mode 100644 themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html create mode 100644 themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html create mode 100644 themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html create mode 100644 themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html create mode 100644 themes/cycle/exampleSite/public/writing/atr2100/index.html create mode 100644 themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html create mode 100644 themes/cycle/exampleSite/public/writing/balancing-devotion/index.html create mode 100644 themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html create mode 100644 themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html create mode 100644 themes/cycle/exampleSite/public/writing/before-circles-2017/index.html create mode 100644 themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html create mode 100644 themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html create mode 100644 themes/cycle/exampleSite/public/writing/blog-rewrite/index.html create mode 100644 themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html create mode 100644 themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html create mode 100644 themes/cycle/exampleSite/public/writing/broadcast-channel/index.html create mode 100644 themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html create mode 100644 themes/cycle/exampleSite/public/writing/command-line-notification/index.html create mode 100644 themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html create mode 100644 themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html create mode 100644 themes/cycle/exampleSite/public/writing/convince-the-boss/index.html create mode 100644 themes/cycle/exampleSite/public/writing/create-passion/index.html create mode 100644 themes/cycle/exampleSite/public/writing/css-reusability/index.html create mode 100644 themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html create mode 100644 themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html create mode 100644 themes/cycle/exampleSite/public/writing/declining-expectations/index.html create mode 100644 themes/cycle/exampleSite/public/writing/diceware/index.html create mode 100644 themes/cycle/exampleSite/public/writing/eight-years/index.html create mode 100644 themes/cycle/exampleSite/public/writing/emacs-lite/index.html create mode 100644 themes/cycle/exampleSite/public/writing/emacs-tips/index.html create mode 100644 themes/cycle/exampleSite/public/writing/end-of-an-era/index.html create mode 100644 themes/cycle/exampleSite/public/writing/evening-edition/index.html create mode 100644 themes/cycle/exampleSite/public/writing/facetime-killer/index.html create mode 100644 themes/cycle/exampleSite/public/writing/family-first/index.html create mode 100644 themes/cycle/exampleSite/public/writing/farewell-heroku/index.html create mode 100644 themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html create mode 100644 themes/cycle/exampleSite/public/writing/five-years/index.html create mode 100644 themes/cycle/exampleSite/public/writing/flatkill/index.html create mode 100644 themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html create mode 100644 themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html create mode 100644 themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html create mode 100644 themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html create mode 100644 themes/cycle/exampleSite/public/writing/git-commit-template/index.html create mode 100644 themes/cycle/exampleSite/public/writing/git-worktree/index.html create mode 100644 themes/cycle/exampleSite/public/writing/goat-counter/index.html create mode 100644 themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html create mode 100644 themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html create mode 100644 themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html create mode 100644 themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html create mode 100644 themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html create mode 100644 themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html create mode 100644 themes/cycle/exampleSite/public/writing/hello-world/index.html create mode 100644 themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html create mode 100644 themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html create mode 100644 themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html create mode 100644 themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html create mode 100644 themes/cycle/exampleSite/public/writing/how-are-you-living/index.html create mode 100644 themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html create mode 100644 themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html create mode 100644 themes/cycle/exampleSite/public/writing/huffduffer/index.html create mode 100644 themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html create mode 100644 themes/cycle/exampleSite/public/writing/ifttt/index.html create mode 100644 themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html create mode 100644 themes/cycle/exampleSite/public/writing/introducing-cycle/index.html create mode 100644 themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html create mode 100644 themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html create mode 100644 themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html create mode 100644 themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html create mode 100644 themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html create mode 100644 themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html create mode 100644 themes/cycle/exampleSite/public/writing/just-start-over/index.html create mode 100644 themes/cycle/exampleSite/public/writing/keeping-up/index.html create mode 100644 themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html create mode 100644 themes/cycle/exampleSite/public/writing/lambda-talk/index.html create mode 100644 themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html create mode 100644 themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html create mode 100644 themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html create mode 100644 themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html create mode 100644 themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html create mode 100644 themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html create mode 100644 themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html create mode 100644 themes/cycle/exampleSite/public/writing/microblogging/index.html create mode 100644 themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html create mode 100644 themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html create mode 100644 themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html create mode 100644 themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html create mode 100644 themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html create mode 100644 themes/cycle/exampleSite/public/writing/new-workstation/index.html create mode 100644 themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html create mode 100644 themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html create mode 100644 themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html create mode 100644 themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html create mode 100644 themes/cycle/exampleSite/public/writing/on-equifax/index.html create mode 100644 themes/cycle/exampleSite/public/writing/on-george-floyd/index.html create mode 100644 themes/cycle/exampleSite/public/writing/on-webpack/index.html create mode 100644 themes/cycle/exampleSite/public/writing/openring/index.html create mode 100644 themes/cycle/exampleSite/public/writing/oscar/index.html create mode 100644 themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html create mode 100644 themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html create mode 100644 themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html create mode 100644 themes/cycle/exampleSite/public/writing/pretty-git-log/index.html create mode 100644 themes/cycle/exampleSite/public/writing/psychicpaper/index.html create mode 100644 themes/cycle/exampleSite/public/writing/rands-on-email/index.html create mode 100644 themes/cycle/exampleSite/public/writing/recently-16/index.html create mode 100644 themes/cycle/exampleSite/public/writing/recently-44/index.html create mode 100644 themes/cycle/exampleSite/public/writing/rename-utility/index.html create mode 100644 themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html create mode 100644 themes/cycle/exampleSite/public/writing/rust-module-system/index.html create mode 100644 themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html create mode 100644 themes/cycle/exampleSite/public/writing/s3-security-policy/index.html create mode 100644 themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html create mode 100644 themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html create mode 100644 themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html create mode 100644 themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html create mode 100644 themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html create mode 100644 themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html create mode 100644 themes/cycle/exampleSite/public/writing/small-tech/index.html create mode 100644 themes/cycle/exampleSite/public/writing/small-things/index.html create mode 100644 themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html create mode 100644 themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html create mode 100644 themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html create mode 100644 themes/cycle/exampleSite/public/writing/sqlite-tips/index.html create mode 100644 themes/cycle/exampleSite/public/writing/story/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html create mode 100644 themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html create mode 100644 themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html create mode 100644 themes/cycle/exampleSite/public/writing/thirty-five/index.html create mode 100644 themes/cycle/exampleSite/public/writing/thirty/index.html create mode 100644 themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html create mode 100644 themes/cycle/exampleSite/public/writing/three-years/index.html create mode 100644 themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html create mode 100644 themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html create mode 100644 themes/cycle/exampleSite/public/writing/tweet-stash/index.html create mode 100644 themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html create mode 100644 themes/cycle/exampleSite/public/writing/verse-recall/index.html create mode 100644 themes/cycle/exampleSite/public/writing/vim-ramblings/index.html create mode 100644 themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html create mode 100644 themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html create mode 100644 themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html create mode 100644 themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html create mode 100644 themes/cycle/exampleSite/public/writing/what-is-medium/index.html create mode 100644 themes/cycle/exampleSite/public/writing/what-its-all-about/index.html create mode 100644 themes/cycle/exampleSite/public/writing/what-matters/index.html create mode 100644 themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html create mode 100644 themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html create mode 100644 themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html create mode 100644 themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html create mode 100644 themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html create mode 100644 themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html create mode 100644 themes/cycle/exampleSite/public/writing/zach-beane/index.html create mode 100644 themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html create mode 120000 themes/cycle/exampleSite/themes/cycle create mode 100644 themes/cycle/layouts/_default/baseof.html create mode 100644 themes/cycle/layouts/_default/list.html create mode 100644 themes/cycle/layouts/_default/rss.xml create mode 100644 themes/cycle/layouts/_default/single.html create mode 100644 themes/cycle/layouts/archive/list.html create mode 100644 themes/cycle/layouts/index.html create mode 100644 themes/cycle/layouts/partials/footer.html create mode 100644 themes/cycle/layouts/partials/head.html create mode 100644 themes/cycle/layouts/partials/header.html create mode 100644 themes/cycle/layouts/partials/logo.html create mode 100644 themes/cycle/layouts/partials/post_body.html create mode 100644 themes/cycle/theme.toml diff --git a/themes/cycle/assets/custom.css b/themes/cycle/assets/custom.css new file mode 100644 index 0000000..e8867ce --- /dev/null +++ b/themes/cycle/assets/custom.css @@ -0,0 +1,79 @@ +pre { + padding: 1rem; + font-size: 1rem; + font-family: "Hack", "Courier New", "monospace"; + overflow-y: scroll; +} + +.logo { + width: 88px; +} + +.logo svg .circle { + fill: #137752; +} + +.logo svg .row { + fill: #9EEBCF; +} + +p a, blockquote a, article a, ul a { + color: #137752; + opactiy: 1; + transition: opacity .15s ease-in; +} + +blockquote a:hover, blockquote a:focus, article a:hover, article a:focus { + opacity: .5; + transition: opacity .15s ease-in; +} + +blockquote a:active, article a:active { + opacity: .8; + transition: opacity .15s ease-out; +} + +article h2, article h3, article h4 { + margin: 0; + color: rgba(0,0,0,.9); +} + +.as-mw7 { + /* matches .mw7 */ + max-width: 38rem; +} + +blockquote { + border-left: 2px solid #137752; + padding-left: 1rem; + margin-left: 0; +} + +.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } +.embed-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + +figure { + margin-left: 0; + margin-right: 0; +} + +video { + width: 100%; +} + +@media(max-width: 360px) { + .nav-link { + display: block; + margin-top: .5rem; + } +} + +aside a { + color: #111111; + opactiy: 1; + transition: opacity .15s ease-in; +} + +aside h3 { + font-size: 1.3rem; +} diff --git a/themes/cycle/assets/tachyons.css b/themes/cycle/assets/tachyons.css new file mode 100644 index 0000000..3fdda3f --- /dev/null +++ b/themes/cycle/assets/tachyons.css @@ -0,0 +1,2 @@ +/*! TACHYONS v4.11.2 | http://tachyons.io */ +/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}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:.35em .75em .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}details{display:block}summary{display:list-item}[hidden],template{display:none}.border-box,a,article,aside,blockquote,body,code,dd,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,html,input[type=email],input[type=number],input[type=password],input[type=tel],input[type=text],input[type=url],legend,li,main,nav,ol,p,pre,section,table,td,textarea,th,tr,ul{box-sizing:border-box}.aspect-ratio{height:0;position:relative}.aspect-ratio--16x9{padding-bottom:56.25%}.aspect-ratio--9x16{padding-bottom:177.77%}.aspect-ratio--4x3{padding-bottom:75%}.aspect-ratio--3x4{padding-bottom:133.33%}.aspect-ratio--6x4{padding-bottom:66.6%}.aspect-ratio--4x6{padding-bottom:150%}.aspect-ratio--8x5{padding-bottom:62.5%}.aspect-ratio--5x8{padding-bottom:160%}.aspect-ratio--7x5{padding-bottom:71.42%}.aspect-ratio--5x7{padding-bottom:140%}.aspect-ratio--1x1{padding-bottom:100%}.aspect-ratio--object{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}img{max-width:100%}.cover{background-size:cover!important}.contain{background-size:contain!important}.bg-center{background-position:50%}.bg-center,.bg-top{background-repeat:no-repeat}.bg-top{background-position:top}.bg-right{background-position:100%}.bg-bottom,.bg-right{background-repeat:no-repeat}.bg-bottom{background-position:bottom}.bg-left{background-repeat:no-repeat;background-position:0}.outline{outline:1px solid}.outline-transparent{outline:1px solid transparent}.outline-0{outline:0}.ba{border-style:solid;border-width:1px}.bt{border-top-style:solid;border-top-width:1px}.br{border-right-style:solid;border-right-width:1px}.bb{border-bottom-style:solid;border-bottom-width:1px}.bl{border-left-style:solid;border-left-width:1px}.bn{border-style:none;border-width:0}.b--black{border-color:#000}.b--near-black{border-color:#111}.b--dark-gray{border-color:#333}.b--mid-gray{border-color:#555}.b--gray{border-color:#777}.b--silver{border-color:#999}.b--light-silver{border-color:#aaa}.b--moon-gray{border-color:#ccc}.b--light-gray{border-color:#eee}.b--near-white{border-color:#f4f4f4}.b--white{border-color:#fff}.b--white-90{border-color:hsla(0,0%,100%,.9)}.b--white-80{border-color:hsla(0,0%,100%,.8)}.b--white-70{border-color:hsla(0,0%,100%,.7)}.b--white-60{border-color:hsla(0,0%,100%,.6)}.b--white-50{border-color:hsla(0,0%,100%,.5)}.b--white-40{border-color:hsla(0,0%,100%,.4)}.b--white-30{border-color:hsla(0,0%,100%,.3)}.b--white-20{border-color:hsla(0,0%,100%,.2)}.b--white-10{border-color:hsla(0,0%,100%,.1)}.b--white-05{border-color:hsla(0,0%,100%,.05)}.b--white-025{border-color:hsla(0,0%,100%,.025)}.b--white-0125{border-color:hsla(0,0%,100%,.0125)}.b--black-90{border-color:rgba(0,0,0,.9)}.b--black-80{border-color:rgba(0,0,0,.8)}.b--black-70{border-color:rgba(0,0,0,.7)}.b--black-60{border-color:rgba(0,0,0,.6)}.b--black-50{border-color:rgba(0,0,0,.5)}.b--black-40{border-color:rgba(0,0,0,.4)}.b--black-30{border-color:rgba(0,0,0,.3)}.b--black-20{border-color:rgba(0,0,0,.2)}.b--black-10{border-color:rgba(0,0,0,.1)}.b--black-05{border-color:rgba(0,0,0,.05)}.b--black-025{border-color:rgba(0,0,0,.025)}.b--black-0125{border-color:rgba(0,0,0,.0125)}.b--dark-red{border-color:#e7040f}.b--red{border-color:#ff4136}.b--light-red{border-color:#ff725c}.b--orange{border-color:#ff6300}.b--gold{border-color:#ffb700}.b--yellow{border-color:gold}.b--light-yellow{border-color:#fbf1a9}.b--purple{border-color:#5e2ca5}.b--light-purple{border-color:#a463f2}.b--dark-pink{border-color:#d5008f}.b--hot-pink{border-color:#ff41b4}.b--pink{border-color:#ff80cc}.b--light-pink{border-color:#ffa3d7}.b--dark-green{border-color:#137752}.b--green{border-color:#19a974}.b--light-green{border-color:#9eebcf}.b--navy{border-color:#001b44}.b--dark-blue{border-color:#00449e}.b--blue{border-color:#357edd}.b--light-blue{border-color:#96ccff}.b--lightest-blue{border-color:#cdecff}.b--washed-blue{border-color:#f6fffe}.b--washed-green{border-color:#e8fdf5}.b--washed-yellow{border-color:#fffceb}.b--washed-red{border-color:#ffdfdf}.b--transparent{border-color:transparent}.b--inherit{border-color:inherit}.br0{border-radius:0}.br1{border-radius:.125rem}.br2{border-radius:.25rem}.br3{border-radius:.5rem}.br4{border-radius:1rem}.br-100{border-radius:100%}.br-pill{border-radius:9999px}.br--bottom{border-top-left-radius:0;border-top-right-radius:0}.br--top{border-bottom-right-radius:0}.br--right,.br--top{border-bottom-left-radius:0}.br--right{border-top-left-radius:0}.br--left{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted{border-style:dotted}.b--dashed{border-style:dashed}.b--solid{border-style:solid}.b--none{border-style:none}.bw0{border-width:0}.bw1{border-width:.125rem}.bw2{border-width:.25rem}.bw3{border-width:.5rem}.bw4{border-width:1rem}.bw5{border-width:2rem}.bt-0{border-top-width:0}.br-0{border-right-width:0}.bb-0{border-bottom-width:0}.bl-0{border-left-width:0}.shadow-1{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.pre{overflow-x:auto;overflow-y:hidden;overflow:scroll}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.top-1{top:1rem}.right-1{right:1rem}.bottom-1{bottom:1rem}.left-1{left:1rem}.top-2{top:2rem}.right-2{right:2rem}.bottom-2{bottom:2rem}.left-2{left:2rem}.top--1{top:-1rem}.right--1{right:-1rem}.bottom--1{bottom:-1rem}.left--1{left:-1rem}.top--2{top:-2rem}.right--2{right:-2rem}.bottom--2{bottom:-2rem}.left--2{left:-2rem}.absolute--fill{top:0;right:0;bottom:0;left:0}.cf:after,.cf:before{content:" ";display:table}.cf:after{clear:both}.cf{*zoom:1}.cl{clear:left}.cr{clear:right}.cb{clear:both}.cn{clear:none}.dn{display:none}.di{display:inline}.db{display:block}.dib{display:inline-block}.dit{display:inline-table}.dt{display:table}.dtc{display:table-cell}.dt-row{display:table-row}.dt-row-group{display:table-row-group}.dt-column{display:table-column}.dt-column-group{display:table-column-group}.dt--fixed{table-layout:fixed;width:100%}.flex{display:flex}.inline-flex{display:inline-flex}.flex-auto{flex:1 1 auto;min-width:0;min-height:0}.flex-none{flex:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.flex-nowrap{flex-wrap:nowrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.flex-column-reverse{flex-direction:column-reverse}.flex-row-reverse{flex-direction:row-reverse}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.self-start{align-self:flex-start}.self-end{align-self:flex-end}.self-center{align-self:center}.self-baseline{align-self:baseline}.self-stretch{align-self:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.content-start{align-content:flex-start}.content-end{align-content:flex-end}.content-center{align-content:center}.content-between{align-content:space-between}.content-around{align-content:space-around}.content-stretch{align-content:stretch}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-last{order:99999}.flex-grow-0{flex-grow:0}.flex-grow-1{flex-grow:1}.flex-shrink-0{flex-shrink:0}.flex-shrink-1{flex-shrink:1}.fl{float:left}.fl,.fr{_display:inline}.fr{float:right}.fn{float:none}.sans-serif{font-family:-apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif}.serif{font-family:georgia,times,serif}.system-sans-serif{font-family:sans-serif}.system-serif{font-family:serif}.code,code{font-family:Consolas,monaco,monospace}.courier{font-family:Courier Next,courier,monospace}.helvetica{font-family:helvetica neue,helvetica,sans-serif}.avenir{font-family:avenir next,avenir,sans-serif}.athelas{font-family:athelas,georgia,serif}.georgia{font-family:georgia,serif}.times{font-family:times,serif}.bodoni{font-family:Bodoni MT,serif}.calisto{font-family:Calisto MT,serif}.garamond{font-family:garamond,serif}.baskerville{font-family:baskerville,serif}.i{font-style:italic}.fs-normal{font-style:normal}.normal{font-weight:400}.b{font-weight:700}.fw1{font-weight:100}.fw2{font-weight:200}.fw3{font-weight:300}.fw4{font-weight:400}.fw5{font-weight:500}.fw6{font-weight:600}.fw7{font-weight:700}.fw8{font-weight:800}.fw9{font-weight:900}.input-reset{-webkit-appearance:none;-moz-appearance:none}.button-reset::-moz-focus-inner,.input-reset::-moz-focus-inner{border:0;padding:0}.h1{height:1rem}.h2{height:2rem}.h3{height:4rem}.h4{height:8rem}.h5{height:16rem}.h-25{height:25%}.h-50{height:50%}.h-75{height:75%}.h-100{height:100%}.min-h-100{min-height:100%}.vh-25{height:25vh}.vh-50{height:50vh}.vh-75{height:75vh}.vh-100{height:100vh}.min-vh-100{min-height:100vh}.h-auto{height:auto}.h-inherit{height:inherit}.tracked{letter-spacing:.1em}.tracked-tight{letter-spacing:-.05em}.tracked-mega{letter-spacing:.25em}.lh-solid{line-height:1}.lh-title{line-height:1.25}.lh-copy{line-height:1.5}.link{text-decoration:none}.link,.link:active,.link:focus,.link:hover,.link:link,.link:visited{transition:color .15s ease-in}.link:focus{outline:1px dotted currentColor}.list{list-style-type:none}.mw-100{max-width:100%}.mw1{max-width:1rem}.mw2{max-width:2rem}.mw3{max-width:4rem}.mw4{max-width:8rem}.mw5{max-width:16rem}.mw6{max-width:32rem}.mw7{max-width:48rem}.mw8{max-width:64rem}.mw9{max-width:96rem}.mw-none{max-width:none}.w1{width:1rem}.w2{width:2rem}.w3{width:4rem}.w4{width:8rem}.w5{width:16rem}.w-10{width:10%}.w-20{width:20%}.w-25{width:25%}.w-30{width:30%}.w-33{width:33%}.w-34{width:34%}.w-40{width:40%}.w-50{width:50%}.w-60{width:60%}.w-70{width:70%}.w-75{width:75%}.w-80{width:80%}.w-90{width:90%}.w-100{width:100%}.w-third{width:33.33333%}.w-two-thirds{width:66.66667%}.w-auto{width:auto}.overflow-visible{overflow:visible}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-auto{overflow:auto}.overflow-x-visible{overflow-x:visible}.overflow-x-hidden{overflow-x:hidden}.overflow-x-scroll{overflow-x:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-visible{overflow-y:visible}.overflow-y-hidden{overflow-y:hidden}.overflow-y-scroll{overflow-y:scroll}.overflow-y-auto{overflow-y:auto}.static{position:static}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.o-100{opacity:1}.o-90{opacity:.9}.o-80{opacity:.8}.o-70{opacity:.7}.o-60{opacity:.6}.o-50{opacity:.5}.o-40{opacity:.4}.o-30{opacity:.3}.o-20{opacity:.2}.o-10{opacity:.1}.o-05{opacity:.05}.o-025{opacity:.025}.o-0{opacity:0}.rotate-45{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.rotate-135{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.rotate-225{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.rotate-315{-webkit-transform:rotate(315deg);transform:rotate(315deg)}.black-90{color:rgba(0,0,0,.9)}.black-80{color:rgba(0,0,0,.8)}.black-70{color:rgba(0,0,0,.7)}.black-60{color:rgba(0,0,0,.6)}.black-50{color:rgba(0,0,0,.5)}.black-40{color:rgba(0,0,0,.4)}.black-30{color:rgba(0,0,0,.3)}.black-20{color:rgba(0,0,0,.2)}.black-10{color:rgba(0,0,0,.1)}.black-05{color:rgba(0,0,0,.05)}.white-90{color:hsla(0,0%,100%,.9)}.white-80{color:hsla(0,0%,100%,.8)}.white-70{color:hsla(0,0%,100%,.7)}.white-60{color:hsla(0,0%,100%,.6)}.white-50{color:hsla(0,0%,100%,.5)}.white-40{color:hsla(0,0%,100%,.4)}.white-30{color:hsla(0,0%,100%,.3)}.white-20{color:hsla(0,0%,100%,.2)}.white-10{color:hsla(0,0%,100%,.1)}.black{color:#000}.near-black{color:#111}.dark-gray{color:#333}.mid-gray{color:#555}.gray{color:#777}.silver{color:#999}.light-silver{color:#aaa}.moon-gray{color:#ccc}.light-gray{color:#eee}.near-white{color:#f4f4f4}.white{color:#fff}.dark-red{color:#e7040f}.red{color:#ff4136}.light-red{color:#ff725c}.orange{color:#ff6300}.gold{color:#ffb700}.yellow{color:gold}.light-yellow{color:#fbf1a9}.purple{color:#5e2ca5}.light-purple{color:#a463f2}.dark-pink{color:#d5008f}.hot-pink{color:#ff41b4}.pink{color:#ff80cc}.light-pink{color:#ffa3d7}.dark-green{color:#137752}.green{color:#19a974}.light-green{color:#9eebcf}.navy{color:#001b44}.dark-blue{color:#00449e}.blue{color:#357edd}.light-blue{color:#96ccff}.lightest-blue{color:#cdecff}.washed-blue{color:#f6fffe}.washed-green{color:#e8fdf5}.washed-yellow{color:#fffceb}.washed-red{color:#ffdfdf}.color-inherit{color:inherit}.bg-black-90{background-color:rgba(0,0,0,.9)}.bg-black-80{background-color:rgba(0,0,0,.8)}.bg-black-70{background-color:rgba(0,0,0,.7)}.bg-black-60{background-color:rgba(0,0,0,.6)}.bg-black-50{background-color:rgba(0,0,0,.5)}.bg-black-40{background-color:rgba(0,0,0,.4)}.bg-black-30{background-color:rgba(0,0,0,.3)}.bg-black-20{background-color:rgba(0,0,0,.2)}.bg-black-10{background-color:rgba(0,0,0,.1)}.bg-black-05{background-color:rgba(0,0,0,.05)}.bg-white-90{background-color:hsla(0,0%,100%,.9)}.bg-white-80{background-color:hsla(0,0%,100%,.8)}.bg-white-70{background-color:hsla(0,0%,100%,.7)}.bg-white-60{background-color:hsla(0,0%,100%,.6)}.bg-white-50{background-color:hsla(0,0%,100%,.5)}.bg-white-40{background-color:hsla(0,0%,100%,.4)}.bg-white-30{background-color:hsla(0,0%,100%,.3)}.bg-white-20{background-color:hsla(0,0%,100%,.2)}.bg-white-10{background-color:hsla(0,0%,100%,.1)}.bg-black{background-color:#000}.bg-near-black{background-color:#111}.bg-dark-gray{background-color:#333}.bg-mid-gray{background-color:#555}.bg-gray{background-color:#777}.bg-silver{background-color:#999}.bg-light-silver{background-color:#aaa}.bg-moon-gray{background-color:#ccc}.bg-light-gray{background-color:#eee}.bg-near-white{background-color:#f4f4f4}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.bg-dark-red{background-color:#e7040f}.bg-red{background-color:#ff4136}.bg-light-red{background-color:#ff725c}.bg-orange{background-color:#ff6300}.bg-gold{background-color:#ffb700}.bg-yellow{background-color:gold}.bg-light-yellow{background-color:#fbf1a9}.bg-purple{background-color:#5e2ca5}.bg-light-purple{background-color:#a463f2}.bg-dark-pink{background-color:#d5008f}.bg-hot-pink{background-color:#ff41b4}.bg-pink{background-color:#ff80cc}.bg-light-pink{background-color:#ffa3d7}.bg-dark-green{background-color:#137752}.bg-green{background-color:#19a974}.bg-light-green{background-color:#9eebcf}.bg-navy{background-color:#001b44}.bg-dark-blue{background-color:#00449e}.bg-blue{background-color:#357edd}.bg-light-blue{background-color:#96ccff}.bg-lightest-blue{background-color:#cdecff}.bg-washed-blue{background-color:#f6fffe}.bg-washed-green{background-color:#e8fdf5}.bg-washed-yellow{background-color:#fffceb}.bg-washed-red{background-color:#ffdfdf}.bg-inherit{background-color:inherit}.hover-black:focus,.hover-black:hover{color:#000}.hover-near-black:focus,.hover-near-black:hover{color:#111}.hover-dark-gray:focus,.hover-dark-gray:hover{color:#333}.hover-mid-gray:focus,.hover-mid-gray:hover{color:#555}.hover-gray:focus,.hover-gray:hover{color:#777}.hover-silver:focus,.hover-silver:hover{color:#999}.hover-light-silver:focus,.hover-light-silver:hover{color:#aaa}.hover-moon-gray:focus,.hover-moon-gray:hover{color:#ccc}.hover-light-gray:focus,.hover-light-gray:hover{color:#eee}.hover-near-white:focus,.hover-near-white:hover{color:#f4f4f4}.hover-white:focus,.hover-white:hover{color:#fff}.hover-black-90:focus,.hover-black-90:hover{color:rgba(0,0,0,.9)}.hover-black-80:focus,.hover-black-80:hover{color:rgba(0,0,0,.8)}.hover-black-70:focus,.hover-black-70:hover{color:rgba(0,0,0,.7)}.hover-black-60:focus,.hover-black-60:hover{color:rgba(0,0,0,.6)}.hover-black-50:focus,.hover-black-50:hover{color:rgba(0,0,0,.5)}.hover-black-40:focus,.hover-black-40:hover{color:rgba(0,0,0,.4)}.hover-black-30:focus,.hover-black-30:hover{color:rgba(0,0,0,.3)}.hover-black-20:focus,.hover-black-20:hover{color:rgba(0,0,0,.2)}.hover-black-10:focus,.hover-black-10:hover{color:rgba(0,0,0,.1)}.hover-white-90:focus,.hover-white-90:hover{color:hsla(0,0%,100%,.9)}.hover-white-80:focus,.hover-white-80:hover{color:hsla(0,0%,100%,.8)}.hover-white-70:focus,.hover-white-70:hover{color:hsla(0,0%,100%,.7)}.hover-white-60:focus,.hover-white-60:hover{color:hsla(0,0%,100%,.6)}.hover-white-50:focus,.hover-white-50:hover{color:hsla(0,0%,100%,.5)}.hover-white-40:focus,.hover-white-40:hover{color:hsla(0,0%,100%,.4)}.hover-white-30:focus,.hover-white-30:hover{color:hsla(0,0%,100%,.3)}.hover-white-20:focus,.hover-white-20:hover{color:hsla(0,0%,100%,.2)}.hover-white-10:focus,.hover-white-10:hover{color:hsla(0,0%,100%,.1)}.hover-inherit:focus,.hover-inherit:hover{color:inherit}.hover-bg-black:focus,.hover-bg-black:hover{background-color:#000}.hover-bg-near-black:focus,.hover-bg-near-black:hover{background-color:#111}.hover-bg-dark-gray:focus,.hover-bg-dark-gray:hover{background-color:#333}.hover-bg-mid-gray:focus,.hover-bg-mid-gray:hover{background-color:#555}.hover-bg-gray:focus,.hover-bg-gray:hover{background-color:#777}.hover-bg-silver:focus,.hover-bg-silver:hover{background-color:#999}.hover-bg-light-silver:focus,.hover-bg-light-silver:hover{background-color:#aaa}.hover-bg-moon-gray:focus,.hover-bg-moon-gray:hover{background-color:#ccc}.hover-bg-light-gray:focus,.hover-bg-light-gray:hover{background-color:#eee}.hover-bg-near-white:focus,.hover-bg-near-white:hover{background-color:#f4f4f4}.hover-bg-white:focus,.hover-bg-white:hover{background-color:#fff}.hover-bg-transparent:focus,.hover-bg-transparent:hover{background-color:transparent}.hover-bg-black-90:focus,.hover-bg-black-90:hover{background-color:rgba(0,0,0,.9)}.hover-bg-black-80:focus,.hover-bg-black-80:hover{background-color:rgba(0,0,0,.8)}.hover-bg-black-70:focus,.hover-bg-black-70:hover{background-color:rgba(0,0,0,.7)}.hover-bg-black-60:focus,.hover-bg-black-60:hover{background-color:rgba(0,0,0,.6)}.hover-bg-black-50:focus,.hover-bg-black-50:hover{background-color:rgba(0,0,0,.5)}.hover-bg-black-40:focus,.hover-bg-black-40:hover{background-color:rgba(0,0,0,.4)}.hover-bg-black-30:focus,.hover-bg-black-30:hover{background-color:rgba(0,0,0,.3)}.hover-bg-black-20:focus,.hover-bg-black-20:hover{background-color:rgba(0,0,0,.2)}.hover-bg-black-10:focus,.hover-bg-black-10:hover{background-color:rgba(0,0,0,.1)}.hover-bg-white-90:focus,.hover-bg-white-90:hover{background-color:hsla(0,0%,100%,.9)}.hover-bg-white-80:focus,.hover-bg-white-80:hover{background-color:hsla(0,0%,100%,.8)}.hover-bg-white-70:focus,.hover-bg-white-70:hover{background-color:hsla(0,0%,100%,.7)}.hover-bg-white-60:focus,.hover-bg-white-60:hover{background-color:hsla(0,0%,100%,.6)}.hover-bg-white-50:focus,.hover-bg-white-50:hover{background-color:hsla(0,0%,100%,.5)}.hover-bg-white-40:focus,.hover-bg-white-40:hover{background-color:hsla(0,0%,100%,.4)}.hover-bg-white-30:focus,.hover-bg-white-30:hover{background-color:hsla(0,0%,100%,.3)}.hover-bg-white-20:focus,.hover-bg-white-20:hover{background-color:hsla(0,0%,100%,.2)}.hover-bg-white-10:focus,.hover-bg-white-10:hover{background-color:hsla(0,0%,100%,.1)}.hover-dark-red:focus,.hover-dark-red:hover{color:#e7040f}.hover-red:focus,.hover-red:hover{color:#ff4136}.hover-light-red:focus,.hover-light-red:hover{color:#ff725c}.hover-orange:focus,.hover-orange:hover{color:#ff6300}.hover-gold:focus,.hover-gold:hover{color:#ffb700}.hover-yellow:focus,.hover-yellow:hover{color:gold}.hover-light-yellow:focus,.hover-light-yellow:hover{color:#fbf1a9}.hover-purple:focus,.hover-purple:hover{color:#5e2ca5}.hover-light-purple:focus,.hover-light-purple:hover{color:#a463f2}.hover-dark-pink:focus,.hover-dark-pink:hover{color:#d5008f}.hover-hot-pink:focus,.hover-hot-pink:hover{color:#ff41b4}.hover-pink:focus,.hover-pink:hover{color:#ff80cc}.hover-light-pink:focus,.hover-light-pink:hover{color:#ffa3d7}.hover-dark-green:focus,.hover-dark-green:hover{color:#137752}.hover-green:focus,.hover-green:hover{color:#19a974}.hover-light-green:focus,.hover-light-green:hover{color:#9eebcf}.hover-navy:focus,.hover-navy:hover{color:#001b44}.hover-dark-blue:focus,.hover-dark-blue:hover{color:#00449e}.hover-blue:focus,.hover-blue:hover{color:#357edd}.hover-light-blue:focus,.hover-light-blue:hover{color:#96ccff}.hover-lightest-blue:focus,.hover-lightest-blue:hover{color:#cdecff}.hover-washed-blue:focus,.hover-washed-blue:hover{color:#f6fffe}.hover-washed-green:focus,.hover-washed-green:hover{color:#e8fdf5}.hover-washed-yellow:focus,.hover-washed-yellow:hover{color:#fffceb}.hover-washed-red:focus,.hover-washed-red:hover{color:#ffdfdf}.hover-bg-dark-red:focus,.hover-bg-dark-red:hover{background-color:#e7040f}.hover-bg-red:focus,.hover-bg-red:hover{background-color:#ff4136}.hover-bg-light-red:focus,.hover-bg-light-red:hover{background-color:#ff725c}.hover-bg-orange:focus,.hover-bg-orange:hover{background-color:#ff6300}.hover-bg-gold:focus,.hover-bg-gold:hover{background-color:#ffb700}.hover-bg-yellow:focus,.hover-bg-yellow:hover{background-color:gold}.hover-bg-light-yellow:focus,.hover-bg-light-yellow:hover{background-color:#fbf1a9}.hover-bg-purple:focus,.hover-bg-purple:hover{background-color:#5e2ca5}.hover-bg-light-purple:focus,.hover-bg-light-purple:hover{background-color:#a463f2}.hover-bg-dark-pink:focus,.hover-bg-dark-pink:hover{background-color:#d5008f}.hover-bg-hot-pink:focus,.hover-bg-hot-pink:hover{background-color:#ff41b4}.hover-bg-pink:focus,.hover-bg-pink:hover{background-color:#ff80cc}.hover-bg-light-pink:focus,.hover-bg-light-pink:hover{background-color:#ffa3d7}.hover-bg-dark-green:focus,.hover-bg-dark-green:hover{background-color:#137752}.hover-bg-green:focus,.hover-bg-green:hover{background-color:#19a974}.hover-bg-light-green:focus,.hover-bg-light-green:hover{background-color:#9eebcf}.hover-bg-navy:focus,.hover-bg-navy:hover{background-color:#001b44}.hover-bg-dark-blue:focus,.hover-bg-dark-blue:hover{background-color:#00449e}.hover-bg-blue:focus,.hover-bg-blue:hover{background-color:#357edd}.hover-bg-light-blue:focus,.hover-bg-light-blue:hover{background-color:#96ccff}.hover-bg-lightest-blue:focus,.hover-bg-lightest-blue:hover{background-color:#cdecff}.hover-bg-washed-blue:focus,.hover-bg-washed-blue:hover{background-color:#f6fffe}.hover-bg-washed-green:focus,.hover-bg-washed-green:hover{background-color:#e8fdf5}.hover-bg-washed-yellow:focus,.hover-bg-washed-yellow:hover{background-color:#fffceb}.hover-bg-washed-red:focus,.hover-bg-washed-red:hover{background-color:#ffdfdf}.hover-bg-inherit:focus,.hover-bg-inherit:hover{background-color:inherit}.pa0{padding:0}.pa1{padding:.25rem}.pa2{padding:.5rem}.pa3{padding:1rem}.pa4{padding:2rem}.pa5{padding:4rem}.pa6{padding:8rem}.pa7{padding:16rem}.pl0{padding-left:0}.pl1{padding-left:.25rem}.pl2{padding-left:.5rem}.pl3{padding-left:1rem}.pl4{padding-left:2rem}.pl5{padding-left:4rem}.pl6{padding-left:8rem}.pl7{padding-left:16rem}.pr0{padding-right:0}.pr1{padding-right:.25rem}.pr2{padding-right:.5rem}.pr3{padding-right:1rem}.pr4{padding-right:2rem}.pr5{padding-right:4rem}.pr6{padding-right:8rem}.pr7{padding-right:16rem}.pb0{padding-bottom:0}.pb1{padding-bottom:.25rem}.pb2{padding-bottom:.5rem}.pb3{padding-bottom:1rem}.pb4{padding-bottom:2rem}.pb5{padding-bottom:4rem}.pb6{padding-bottom:8rem}.pb7{padding-bottom:16rem}.pt0{padding-top:0}.pt1{padding-top:.25rem}.pt2{padding-top:.5rem}.pt3{padding-top:1rem}.pt4{padding-top:2rem}.pt5{padding-top:4rem}.pt6{padding-top:8rem}.pt7{padding-top:16rem}.pv0{padding-top:0;padding-bottom:0}.pv1{padding-top:.25rem;padding-bottom:.25rem}.pv2{padding-top:.5rem;padding-bottom:.5rem}.pv3{padding-top:1rem;padding-bottom:1rem}.pv4{padding-top:2rem;padding-bottom:2rem}.pv5{padding-top:4rem;padding-bottom:4rem}.pv6{padding-top:8rem;padding-bottom:8rem}.pv7{padding-top:16rem;padding-bottom:16rem}.ph0{padding-left:0;padding-right:0}.ph1{padding-left:.25rem;padding-right:.25rem}.ph2{padding-left:.5rem;padding-right:.5rem}.ph3{padding-left:1rem;padding-right:1rem}.ph4{padding-left:2rem;padding-right:2rem}.ph5{padding-left:4rem;padding-right:4rem}.ph6{padding-left:8rem;padding-right:8rem}.ph7{padding-left:16rem;padding-right:16rem}.ma0{margin:0}.ma1{margin:.25rem}.ma2{margin:.5rem}.ma3{margin:1rem}.ma4{margin:2rem}.ma5{margin:4rem}.ma6{margin:8rem}.ma7{margin:16rem}.ml0{margin-left:0}.ml1{margin-left:.25rem}.ml2{margin-left:.5rem}.ml3{margin-left:1rem}.ml4{margin-left:2rem}.ml5{margin-left:4rem}.ml6{margin-left:8rem}.ml7{margin-left:16rem}.mr0{margin-right:0}.mr1{margin-right:.25rem}.mr2{margin-right:.5rem}.mr3{margin-right:1rem}.mr4{margin-right:2rem}.mr5{margin-right:4rem}.mr6{margin-right:8rem}.mr7{margin-right:16rem}.mb0{margin-bottom:0}.mb1{margin-bottom:.25rem}.mb2{margin-bottom:.5rem}.mb3{margin-bottom:1rem}.mb4{margin-bottom:2rem}.mb5{margin-bottom:4rem}.mb6{margin-bottom:8rem}.mb7{margin-bottom:16rem}.mt0{margin-top:0}.mt1{margin-top:.25rem}.mt2{margin-top:.5rem}.mt3{margin-top:1rem}.mt4{margin-top:2rem}.mt5{margin-top:4rem}.mt6{margin-top:8rem}.mt7{margin-top:16rem}.mv0{margin-top:0;margin-bottom:0}.mv1{margin-top:.25rem;margin-bottom:.25rem}.mv2{margin-top:.5rem;margin-bottom:.5rem}.mv3{margin-top:1rem;margin-bottom:1rem}.mv4{margin-top:2rem;margin-bottom:2rem}.mv5{margin-top:4rem;margin-bottom:4rem}.mv6{margin-top:8rem;margin-bottom:8rem}.mv7{margin-top:16rem;margin-bottom:16rem}.mh0{margin-left:0;margin-right:0}.mh1{margin-left:.25rem;margin-right:.25rem}.mh2{margin-left:.5rem;margin-right:.5rem}.mh3{margin-left:1rem;margin-right:1rem}.mh4{margin-left:2rem;margin-right:2rem}.mh5{margin-left:4rem;margin-right:4rem}.mh6{margin-left:8rem;margin-right:8rem}.mh7{margin-left:16rem;margin-right:16rem}.na1{margin:-.25rem}.na2{margin:-.5rem}.na3{margin:-1rem}.na4{margin:-2rem}.na5{margin:-4rem}.na6{margin:-8rem}.na7{margin:-16rem}.nl1{margin-left:-.25rem}.nl2{margin-left:-.5rem}.nl3{margin-left:-1rem}.nl4{margin-left:-2rem}.nl5{margin-left:-4rem}.nl6{margin-left:-8rem}.nl7{margin-left:-16rem}.nr1{margin-right:-.25rem}.nr2{margin-right:-.5rem}.nr3{margin-right:-1rem}.nr4{margin-right:-2rem}.nr5{margin-right:-4rem}.nr6{margin-right:-8rem}.nr7{margin-right:-16rem}.nb1{margin-bottom:-.25rem}.nb2{margin-bottom:-.5rem}.nb3{margin-bottom:-1rem}.nb4{margin-bottom:-2rem}.nb5{margin-bottom:-4rem}.nb6{margin-bottom:-8rem}.nb7{margin-bottom:-16rem}.nt1{margin-top:-.25rem}.nt2{margin-top:-.5rem}.nt3{margin-top:-1rem}.nt4{margin-top:-2rem}.nt5{margin-top:-4rem}.nt6{margin-top:-8rem}.nt7{margin-top:-16rem}.collapse{border-collapse:collapse;border-spacing:0}.striped--light-silver:nth-child(odd){background-color:#aaa}.striped--moon-gray:nth-child(odd){background-color:#ccc}.striped--light-gray:nth-child(odd){background-color:#eee}.striped--near-white:nth-child(odd){background-color:#f4f4f4}.stripe-light:nth-child(odd){background-color:hsla(0,0%,100%,.1)}.stripe-dark:nth-child(odd){background-color:rgba(0,0,0,.1)}.strike{text-decoration:line-through}.underline{text-decoration:underline}.no-underline{text-decoration:none}.tl{text-align:left}.tr{text-align:right}.tc{text-align:center}.tj{text-align:justify}.ttc{text-transform:capitalize}.ttl{text-transform:lowercase}.ttu{text-transform:uppercase}.ttn{text-transform:none}.f-6,.f-headline{font-size:6rem}.f-5,.f-subheadline{font-size:5rem}.f1{font-size:3rem}.f2{font-size:2.25rem}.f3{font-size:1.5rem}.f4{font-size:1.25rem}.f5{font-size:1rem}.f6{font-size:.875rem}.f7{font-size:.75rem}.measure{max-width:30em}.measure-wide{max-width:34em}.measure-narrow{max-width:20em}.indent{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps{font-variant:small-caps}.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.overflow-container{overflow-y:scroll}.center{margin-left:auto}.center,.mr-auto{margin-right:auto}.ml-auto{margin-left:auto}.clip{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal{white-space:normal}.nowrap{white-space:nowrap}.pre{white-space:pre}.v-base{vertical-align:baseline}.v-mid{vertical-align:middle}.v-top{vertical-align:top}.v-btm{vertical-align:bottom}.dim{opacity:1}.dim,.dim:focus,.dim:hover{transition:opacity .15s ease-in}.dim:focus,.dim:hover{opacity:.5}.dim:active{opacity:.8;transition:opacity .15s ease-out}.glow,.glow:focus,.glow:hover{transition:opacity .15s ease-in}.glow:focus,.glow:hover{opacity:1}.hide-child .child{opacity:0;transition:opacity .15s ease-in}.hide-child:active .child,.hide-child:focus .child,.hide-child:hover .child{opacity:1;transition:opacity .15s ease-in}.underline-hover:focus,.underline-hover:hover{text-decoration:underline}.grow{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;transition:transform .25s ease-out,-webkit-transform .25s ease-out}.grow:focus,.grow:hover{-webkit-transform:scale(1.05);transform:scale(1.05)}.grow:active{-webkit-transform:scale(.9);transform:scale(.9)}.grow-large{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);transition:-webkit-transform .25s ease-in-out;transition:transform .25s ease-in-out;transition:transform .25s ease-in-out,-webkit-transform .25s ease-in-out}.grow-large:focus,.grow-large:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.grow-large:active{-webkit-transform:scale(.95);transform:scale(.95)}.pointer:hover,.shadow-hover{cursor:pointer}.shadow-hover{position:relative;transition:all .5s cubic-bezier(.165,.84,.44,1)}.shadow-hover:after{content:"";box-shadow:0 0 16px 2px rgba(0,0,0,.2);border-radius:inherit;opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;transition:opacity .5s cubic-bezier(.165,.84,.44,1)}.shadow-hover:focus:after,.shadow-hover:hover:after{opacity:1}.bg-animate,.bg-animate:focus,.bg-animate:hover{transition:background-color .15s ease-in-out}.z-0{z-index:0}.z-1{z-index:1}.z-2{z-index:2}.z-3{z-index:3}.z-4{z-index:4}.z-5{z-index:5}.z-999{z-index:999}.z-9999{z-index:9999}.z-max{z-index:2147483647}.z-inherit{z-index:inherit}.z-initial{z-index:auto}.z-unset{z-index:unset}.nested-copy-line-height ol,.nested-copy-line-height p,.nested-copy-line-height ul{line-height:1.5}.nested-headline-line-height h1,.nested-headline-line-height h2,.nested-headline-line-height h3,.nested-headline-line-height h4,.nested-headline-line-height h5,.nested-headline-line-height h6{line-height:1.25}.nested-list-reset ol,.nested-list-reset ul{padding-left:0;margin-left:0;list-style-type:none}.nested-copy-indent p+p{text-indent:1em;margin-top:0;margin-bottom:0}.nested-copy-separator p+p{margin-top:1.5em}.nested-img img{width:100%;max-width:100%;display:block}.nested-links a{color:#357edd;transition:color .15s ease-in}.nested-links a:focus,.nested-links a:hover{color:#96ccff;transition:color .15s ease-in}.debug *{outline:1px solid gold}.debug-white *{outline:1px solid #fff}.debug-black *{outline:1px solid #000}.debug-grid{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAFElEQVR4AWPAC97/9x0eCsAEPgwAVLshdpENIxcAAAAASUVORK5CYII=) repeat 0 0}.debug-grid-16{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMklEQVR4AWOgCLz/b0epAa6UGuBOqQHOQHLUgFEDnAbcBZ4UGwDOkiCnkIhdgNgNxAYAiYlD+8sEuo8AAAAASUVORK5CYII=) repeat 0 0}.debug-grid-8-solid{background:#fff url(data:image/gif;base64,R0lGODdhCAAIAPEAAADw/wDx/////wAAACwAAAAACAAIAAACDZQvgaeb/lxbAIKA8y0AOw==) repeat 0 0}.debug-grid-16-solid{background:#fff url(data:image/gif;base64,R0lGODdhEAAQAPEAAADw/wDx/xXy/////ywAAAAAEAAQAAACIZyPKckYDQFsb6ZqD85jZ2+BkwiRFKehhqQCQgDHcgwEBQA7) repeat 0 0}@media screen and (min-width:30em){.aspect-ratio-ns{height:0;position:relative}.aspect-ratio--16x9-ns{padding-bottom:56.25%}.aspect-ratio--9x16-ns{padding-bottom:177.77%}.aspect-ratio--4x3-ns{padding-bottom:75%}.aspect-ratio--3x4-ns{padding-bottom:133.33%}.aspect-ratio--6x4-ns{padding-bottom:66.6%}.aspect-ratio--4x6-ns{padding-bottom:150%}.aspect-ratio--8x5-ns{padding-bottom:62.5%}.aspect-ratio--5x8-ns{padding-bottom:160%}.aspect-ratio--7x5-ns{padding-bottom:71.42%}.aspect-ratio--5x7-ns{padding-bottom:140%}.aspect-ratio--1x1-ns{padding-bottom:100%}.aspect-ratio--object-ns{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}.cover-ns{background-size:cover!important}.contain-ns{background-size:contain!important}.bg-center-ns{background-position:50%}.bg-center-ns,.bg-top-ns{background-repeat:no-repeat}.bg-top-ns{background-position:top}.bg-right-ns{background-position:100%}.bg-bottom-ns,.bg-right-ns{background-repeat:no-repeat}.bg-bottom-ns{background-position:bottom}.bg-left-ns{background-repeat:no-repeat;background-position:0}.outline-ns{outline:1px solid}.outline-transparent-ns{outline:1px solid transparent}.outline-0-ns{outline:0}.ba-ns{border-style:solid;border-width:1px}.bt-ns{border-top-style:solid;border-top-width:1px}.br-ns{border-right-style:solid;border-right-width:1px}.bb-ns{border-bottom-style:solid;border-bottom-width:1px}.bl-ns{border-left-style:solid;border-left-width:1px}.bn-ns{border-style:none;border-width:0}.br0-ns{border-radius:0}.br1-ns{border-radius:.125rem}.br2-ns{border-radius:.25rem}.br3-ns{border-radius:.5rem}.br4-ns{border-radius:1rem}.br-100-ns{border-radius:100%}.br-pill-ns{border-radius:9999px}.br--bottom-ns{border-top-left-radius:0;border-top-right-radius:0}.br--top-ns{border-bottom-right-radius:0}.br--right-ns,.br--top-ns{border-bottom-left-radius:0}.br--right-ns{border-top-left-radius:0}.br--left-ns{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted-ns{border-style:dotted}.b--dashed-ns{border-style:dashed}.b--solid-ns{border-style:solid}.b--none-ns{border-style:none}.bw0-ns{border-width:0}.bw1-ns{border-width:.125rem}.bw2-ns{border-width:.25rem}.bw3-ns{border-width:.5rem}.bw4-ns{border-width:1rem}.bw5-ns{border-width:2rem}.bt-0-ns{border-top-width:0}.br-0-ns{border-right-width:0}.bb-0-ns{border-bottom-width:0}.bl-0-ns{border-left-width:0}.shadow-1-ns{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-ns{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-ns{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-ns{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-ns{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.top-0-ns{top:0}.left-0-ns{left:0}.right-0-ns{right:0}.bottom-0-ns{bottom:0}.top-1-ns{top:1rem}.left-1-ns{left:1rem}.right-1-ns{right:1rem}.bottom-1-ns{bottom:1rem}.top-2-ns{top:2rem}.left-2-ns{left:2rem}.right-2-ns{right:2rem}.bottom-2-ns{bottom:2rem}.top--1-ns{top:-1rem}.right--1-ns{right:-1rem}.bottom--1-ns{bottom:-1rem}.left--1-ns{left:-1rem}.top--2-ns{top:-2rem}.right--2-ns{right:-2rem}.bottom--2-ns{bottom:-2rem}.left--2-ns{left:-2rem}.absolute--fill-ns{top:0;right:0;bottom:0;left:0}.cl-ns{clear:left}.cr-ns{clear:right}.cb-ns{clear:both}.cn-ns{clear:none}.dn-ns{display:none}.di-ns{display:inline}.db-ns{display:block}.dib-ns{display:inline-block}.dit-ns{display:inline-table}.dt-ns{display:table}.dtc-ns{display:table-cell}.dt-row-ns{display:table-row}.dt-row-group-ns{display:table-row-group}.dt-column-ns{display:table-column}.dt-column-group-ns{display:table-column-group}.dt--fixed-ns{table-layout:fixed;width:100%}.flex-ns{display:flex}.inline-flex-ns{display:inline-flex}.flex-auto-ns{flex:1 1 auto;min-width:0;min-height:0}.flex-none-ns{flex:none}.flex-column-ns{flex-direction:column}.flex-row-ns{flex-direction:row}.flex-wrap-ns{flex-wrap:wrap}.flex-nowrap-ns{flex-wrap:nowrap}.flex-wrap-reverse-ns{flex-wrap:wrap-reverse}.flex-column-reverse-ns{flex-direction:column-reverse}.flex-row-reverse-ns{flex-direction:row-reverse}.items-start-ns{align-items:flex-start}.items-end-ns{align-items:flex-end}.items-center-ns{align-items:center}.items-baseline-ns{align-items:baseline}.items-stretch-ns{align-items:stretch}.self-start-ns{align-self:flex-start}.self-end-ns{align-self:flex-end}.self-center-ns{align-self:center}.self-baseline-ns{align-self:baseline}.self-stretch-ns{align-self:stretch}.justify-start-ns{justify-content:flex-start}.justify-end-ns{justify-content:flex-end}.justify-center-ns{justify-content:center}.justify-between-ns{justify-content:space-between}.justify-around-ns{justify-content:space-around}.content-start-ns{align-content:flex-start}.content-end-ns{align-content:flex-end}.content-center-ns{align-content:center}.content-between-ns{align-content:space-between}.content-around-ns{align-content:space-around}.content-stretch-ns{align-content:stretch}.order-0-ns{order:0}.order-1-ns{order:1}.order-2-ns{order:2}.order-3-ns{order:3}.order-4-ns{order:4}.order-5-ns{order:5}.order-6-ns{order:6}.order-7-ns{order:7}.order-8-ns{order:8}.order-last-ns{order:99999}.flex-grow-0-ns{flex-grow:0}.flex-grow-1-ns{flex-grow:1}.flex-shrink-0-ns{flex-shrink:0}.flex-shrink-1-ns{flex-shrink:1}.fl-ns{float:left}.fl-ns,.fr-ns{_display:inline}.fr-ns{float:right}.fn-ns{float:none}.i-ns{font-style:italic}.fs-normal-ns{font-style:normal}.normal-ns{font-weight:400}.b-ns{font-weight:700}.fw1-ns{font-weight:100}.fw2-ns{font-weight:200}.fw3-ns{font-weight:300}.fw4-ns{font-weight:400}.fw5-ns{font-weight:500}.fw6-ns{font-weight:600}.fw7-ns{font-weight:700}.fw8-ns{font-weight:800}.fw9-ns{font-weight:900}.h1-ns{height:1rem}.h2-ns{height:2rem}.h3-ns{height:4rem}.h4-ns{height:8rem}.h5-ns{height:16rem}.h-25-ns{height:25%}.h-50-ns{height:50%}.h-75-ns{height:75%}.h-100-ns{height:100%}.min-h-100-ns{min-height:100%}.vh-25-ns{height:25vh}.vh-50-ns{height:50vh}.vh-75-ns{height:75vh}.vh-100-ns{height:100vh}.min-vh-100-ns{min-height:100vh}.h-auto-ns{height:auto}.h-inherit-ns{height:inherit}.tracked-ns{letter-spacing:.1em}.tracked-tight-ns{letter-spacing:-.05em}.tracked-mega-ns{letter-spacing:.25em}.lh-solid-ns{line-height:1}.lh-title-ns{line-height:1.25}.lh-copy-ns{line-height:1.5}.mw-100-ns{max-width:100%}.mw1-ns{max-width:1rem}.mw2-ns{max-width:2rem}.mw3-ns{max-width:4rem}.mw4-ns{max-width:8rem}.mw5-ns{max-width:16rem}.mw6-ns{max-width:32rem}.mw7-ns{max-width:48rem}.mw8-ns{max-width:64rem}.mw9-ns{max-width:96rem}.mw-none-ns{max-width:none}.w1-ns{width:1rem}.w2-ns{width:2rem}.w3-ns{width:4rem}.w4-ns{width:8rem}.w5-ns{width:16rem}.w-10-ns{width:10%}.w-20-ns{width:20%}.w-25-ns{width:25%}.w-30-ns{width:30%}.w-33-ns{width:33%}.w-34-ns{width:34%}.w-40-ns{width:40%}.w-50-ns{width:50%}.w-60-ns{width:60%}.w-70-ns{width:70%}.w-75-ns{width:75%}.w-80-ns{width:80%}.w-90-ns{width:90%}.w-100-ns{width:100%}.w-third-ns{width:33.33333%}.w-two-thirds-ns{width:66.66667%}.w-auto-ns{width:auto}.overflow-visible-ns{overflow:visible}.overflow-hidden-ns{overflow:hidden}.overflow-scroll-ns{overflow:scroll}.overflow-auto-ns{overflow:auto}.overflow-x-visible-ns{overflow-x:visible}.overflow-x-hidden-ns{overflow-x:hidden}.overflow-x-scroll-ns{overflow-x:scroll}.overflow-x-auto-ns{overflow-x:auto}.overflow-y-visible-ns{overflow-y:visible}.overflow-y-hidden-ns{overflow-y:hidden}.overflow-y-scroll-ns{overflow-y:scroll}.overflow-y-auto-ns{overflow-y:auto}.static-ns{position:static}.relative-ns{position:relative}.absolute-ns{position:absolute}.fixed-ns{position:fixed}.rotate-45-ns{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.rotate-90-ns{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.rotate-135-ns{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.rotate-180-ns{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.rotate-225-ns{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.rotate-270-ns{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.rotate-315-ns{-webkit-transform:rotate(315deg);transform:rotate(315deg)}.pa0-ns{padding:0}.pa1-ns{padding:.25rem}.pa2-ns{padding:.5rem}.pa3-ns{padding:1rem}.pa4-ns{padding:2rem}.pa5-ns{padding:4rem}.pa6-ns{padding:8rem}.pa7-ns{padding:16rem}.pl0-ns{padding-left:0}.pl1-ns{padding-left:.25rem}.pl2-ns{padding-left:.5rem}.pl3-ns{padding-left:1rem}.pl4-ns{padding-left:2rem}.pl5-ns{padding-left:4rem}.pl6-ns{padding-left:8rem}.pl7-ns{padding-left:16rem}.pr0-ns{padding-right:0}.pr1-ns{padding-right:.25rem}.pr2-ns{padding-right:.5rem}.pr3-ns{padding-right:1rem}.pr4-ns{padding-right:2rem}.pr5-ns{padding-right:4rem}.pr6-ns{padding-right:8rem}.pr7-ns{padding-right:16rem}.pb0-ns{padding-bottom:0}.pb1-ns{padding-bottom:.25rem}.pb2-ns{padding-bottom:.5rem}.pb3-ns{padding-bottom:1rem}.pb4-ns{padding-bottom:2rem}.pb5-ns{padding-bottom:4rem}.pb6-ns{padding-bottom:8rem}.pb7-ns{padding-bottom:16rem}.pt0-ns{padding-top:0}.pt1-ns{padding-top:.25rem}.pt2-ns{padding-top:.5rem}.pt3-ns{padding-top:1rem}.pt4-ns{padding-top:2rem}.pt5-ns{padding-top:4rem}.pt6-ns{padding-top:8rem}.pt7-ns{padding-top:16rem}.pv0-ns{padding-top:0;padding-bottom:0}.pv1-ns{padding-top:.25rem;padding-bottom:.25rem}.pv2-ns{padding-top:.5rem;padding-bottom:.5rem}.pv3-ns{padding-top:1rem;padding-bottom:1rem}.pv4-ns{padding-top:2rem;padding-bottom:2rem}.pv5-ns{padding-top:4rem;padding-bottom:4rem}.pv6-ns{padding-top:8rem;padding-bottom:8rem}.pv7-ns{padding-top:16rem;padding-bottom:16rem}.ph0-ns{padding-left:0;padding-right:0}.ph1-ns{padding-left:.25rem;padding-right:.25rem}.ph2-ns{padding-left:.5rem;padding-right:.5rem}.ph3-ns{padding-left:1rem;padding-right:1rem}.ph4-ns{padding-left:2rem;padding-right:2rem}.ph5-ns{padding-left:4rem;padding-right:4rem}.ph6-ns{padding-left:8rem;padding-right:8rem}.ph7-ns{padding-left:16rem;padding-right:16rem}.ma0-ns{margin:0}.ma1-ns{margin:.25rem}.ma2-ns{margin:.5rem}.ma3-ns{margin:1rem}.ma4-ns{margin:2rem}.ma5-ns{margin:4rem}.ma6-ns{margin:8rem}.ma7-ns{margin:16rem}.ml0-ns{margin-left:0}.ml1-ns{margin-left:.25rem}.ml2-ns{margin-left:.5rem}.ml3-ns{margin-left:1rem}.ml4-ns{margin-left:2rem}.ml5-ns{margin-left:4rem}.ml6-ns{margin-left:8rem}.ml7-ns{margin-left:16rem}.mr0-ns{margin-right:0}.mr1-ns{margin-right:.25rem}.mr2-ns{margin-right:.5rem}.mr3-ns{margin-right:1rem}.mr4-ns{margin-right:2rem}.mr5-ns{margin-right:4rem}.mr6-ns{margin-right:8rem}.mr7-ns{margin-right:16rem}.mb0-ns{margin-bottom:0}.mb1-ns{margin-bottom:.25rem}.mb2-ns{margin-bottom:.5rem}.mb3-ns{margin-bottom:1rem}.mb4-ns{margin-bottom:2rem}.mb5-ns{margin-bottom:4rem}.mb6-ns{margin-bottom:8rem}.mb7-ns{margin-bottom:16rem}.mt0-ns{margin-top:0}.mt1-ns{margin-top:.25rem}.mt2-ns{margin-top:.5rem}.mt3-ns{margin-top:1rem}.mt4-ns{margin-top:2rem}.mt5-ns{margin-top:4rem}.mt6-ns{margin-top:8rem}.mt7-ns{margin-top:16rem}.mv0-ns{margin-top:0;margin-bottom:0}.mv1-ns{margin-top:.25rem;margin-bottom:.25rem}.mv2-ns{margin-top:.5rem;margin-bottom:.5rem}.mv3-ns{margin-top:1rem;margin-bottom:1rem}.mv4-ns{margin-top:2rem;margin-bottom:2rem}.mv5-ns{margin-top:4rem;margin-bottom:4rem}.mv6-ns{margin-top:8rem;margin-bottom:8rem}.mv7-ns{margin-top:16rem;margin-bottom:16rem}.mh0-ns{margin-left:0;margin-right:0}.mh1-ns{margin-left:.25rem;margin-right:.25rem}.mh2-ns{margin-left:.5rem;margin-right:.5rem}.mh3-ns{margin-left:1rem;margin-right:1rem}.mh4-ns{margin-left:2rem;margin-right:2rem}.mh5-ns{margin-left:4rem;margin-right:4rem}.mh6-ns{margin-left:8rem;margin-right:8rem}.mh7-ns{margin-left:16rem;margin-right:16rem}.na1-ns{margin:-.25rem}.na2-ns{margin:-.5rem}.na3-ns{margin:-1rem}.na4-ns{margin:-2rem}.na5-ns{margin:-4rem}.na6-ns{margin:-8rem}.na7-ns{margin:-16rem}.nl1-ns{margin-left:-.25rem}.nl2-ns{margin-left:-.5rem}.nl3-ns{margin-left:-1rem}.nl4-ns{margin-left:-2rem}.nl5-ns{margin-left:-4rem}.nl6-ns{margin-left:-8rem}.nl7-ns{margin-left:-16rem}.nr1-ns{margin-right:-.25rem}.nr2-ns{margin-right:-.5rem}.nr3-ns{margin-right:-1rem}.nr4-ns{margin-right:-2rem}.nr5-ns{margin-right:-4rem}.nr6-ns{margin-right:-8rem}.nr7-ns{margin-right:-16rem}.nb1-ns{margin-bottom:-.25rem}.nb2-ns{margin-bottom:-.5rem}.nb3-ns{margin-bottom:-1rem}.nb4-ns{margin-bottom:-2rem}.nb5-ns{margin-bottom:-4rem}.nb6-ns{margin-bottom:-8rem}.nb7-ns{margin-bottom:-16rem}.nt1-ns{margin-top:-.25rem}.nt2-ns{margin-top:-.5rem}.nt3-ns{margin-top:-1rem}.nt4-ns{margin-top:-2rem}.nt5-ns{margin-top:-4rem}.nt6-ns{margin-top:-8rem}.nt7-ns{margin-top:-16rem}.strike-ns{text-decoration:line-through}.underline-ns{text-decoration:underline}.no-underline-ns{text-decoration:none}.tl-ns{text-align:left}.tr-ns{text-align:right}.tc-ns{text-align:center}.tj-ns{text-align:justify}.ttc-ns{text-transform:capitalize}.ttl-ns{text-transform:lowercase}.ttu-ns{text-transform:uppercase}.ttn-ns{text-transform:none}.f-6-ns,.f-headline-ns{font-size:6rem}.f-5-ns,.f-subheadline-ns{font-size:5rem}.f1-ns{font-size:3rem}.f2-ns{font-size:2.25rem}.f3-ns{font-size:1.5rem}.f4-ns{font-size:1.25rem}.f5-ns{font-size:1rem}.f6-ns{font-size:.875rem}.f7-ns{font-size:.75rem}.measure-ns{max-width:30em}.measure-wide-ns{max-width:34em}.measure-narrow-ns{max-width:20em}.indent-ns{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-ns{font-variant:small-caps}.truncate-ns{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.center-ns{margin-left:auto}.center-ns,.mr-auto-ns{margin-right:auto}.ml-auto-ns{margin-left:auto}.clip-ns{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal-ns{white-space:normal}.nowrap-ns{white-space:nowrap}.pre-ns{white-space:pre}.v-base-ns{vertical-align:baseline}.v-mid-ns{vertical-align:middle}.v-top-ns{vertical-align:top}.v-btm-ns{vertical-align:bottom}}@media screen and (min-width:30em) and (max-width:60em){.aspect-ratio-m{height:0;position:relative}.aspect-ratio--16x9-m{padding-bottom:56.25%}.aspect-ratio--9x16-m{padding-bottom:177.77%}.aspect-ratio--4x3-m{padding-bottom:75%}.aspect-ratio--3x4-m{padding-bottom:133.33%}.aspect-ratio--6x4-m{padding-bottom:66.6%}.aspect-ratio--4x6-m{padding-bottom:150%}.aspect-ratio--8x5-m{padding-bottom:62.5%}.aspect-ratio--5x8-m{padding-bottom:160%}.aspect-ratio--7x5-m{padding-bottom:71.42%}.aspect-ratio--5x7-m{padding-bottom:140%}.aspect-ratio--1x1-m{padding-bottom:100%}.aspect-ratio--object-m{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}.cover-m{background-size:cover!important}.contain-m{background-size:contain!important}.bg-center-m{background-position:50%}.bg-center-m,.bg-top-m{background-repeat:no-repeat}.bg-top-m{background-position:top}.bg-right-m{background-position:100%}.bg-bottom-m,.bg-right-m{background-repeat:no-repeat}.bg-bottom-m{background-position:bottom}.bg-left-m{background-repeat:no-repeat;background-position:0}.outline-m{outline:1px solid}.outline-transparent-m{outline:1px solid transparent}.outline-0-m{outline:0}.ba-m{border-style:solid;border-width:1px}.bt-m{border-top-style:solid;border-top-width:1px}.br-m{border-right-style:solid;border-right-width:1px}.bb-m{border-bottom-style:solid;border-bottom-width:1px}.bl-m{border-left-style:solid;border-left-width:1px}.bn-m{border-style:none;border-width:0}.br0-m{border-radius:0}.br1-m{border-radius:.125rem}.br2-m{border-radius:.25rem}.br3-m{border-radius:.5rem}.br4-m{border-radius:1rem}.br-100-m{border-radius:100%}.br-pill-m{border-radius:9999px}.br--bottom-m{border-top-left-radius:0;border-top-right-radius:0}.br--top-m{border-bottom-right-radius:0}.br--right-m,.br--top-m{border-bottom-left-radius:0}.br--right-m{border-top-left-radius:0}.br--left-m{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted-m{border-style:dotted}.b--dashed-m{border-style:dashed}.b--solid-m{border-style:solid}.b--none-m{border-style:none}.bw0-m{border-width:0}.bw1-m{border-width:.125rem}.bw2-m{border-width:.25rem}.bw3-m{border-width:.5rem}.bw4-m{border-width:1rem}.bw5-m{border-width:2rem}.bt-0-m{border-top-width:0}.br-0-m{border-right-width:0}.bb-0-m{border-bottom-width:0}.bl-0-m{border-left-width:0}.shadow-1-m{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-m{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-m{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-m{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-m{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.top-0-m{top:0}.left-0-m{left:0}.right-0-m{right:0}.bottom-0-m{bottom:0}.top-1-m{top:1rem}.left-1-m{left:1rem}.right-1-m{right:1rem}.bottom-1-m{bottom:1rem}.top-2-m{top:2rem}.left-2-m{left:2rem}.right-2-m{right:2rem}.bottom-2-m{bottom:2rem}.top--1-m{top:-1rem}.right--1-m{right:-1rem}.bottom--1-m{bottom:-1rem}.left--1-m{left:-1rem}.top--2-m{top:-2rem}.right--2-m{right:-2rem}.bottom--2-m{bottom:-2rem}.left--2-m{left:-2rem}.absolute--fill-m{top:0;right:0;bottom:0;left:0}.cl-m{clear:left}.cr-m{clear:right}.cb-m{clear:both}.cn-m{clear:none}.dn-m{display:none}.di-m{display:inline}.db-m{display:block}.dib-m{display:inline-block}.dit-m{display:inline-table}.dt-m{display:table}.dtc-m{display:table-cell}.dt-row-m{display:table-row}.dt-row-group-m{display:table-row-group}.dt-column-m{display:table-column}.dt-column-group-m{display:table-column-group}.dt--fixed-m{table-layout:fixed;width:100%}.flex-m{display:flex}.inline-flex-m{display:inline-flex}.flex-auto-m{flex:1 1 auto;min-width:0;min-height:0}.flex-none-m{flex:none}.flex-column-m{flex-direction:column}.flex-row-m{flex-direction:row}.flex-wrap-m{flex-wrap:wrap}.flex-nowrap-m{flex-wrap:nowrap}.flex-wrap-reverse-m{flex-wrap:wrap-reverse}.flex-column-reverse-m{flex-direction:column-reverse}.flex-row-reverse-m{flex-direction:row-reverse}.items-start-m{align-items:flex-start}.items-end-m{align-items:flex-end}.items-center-m{align-items:center}.items-baseline-m{align-items:baseline}.items-stretch-m{align-items:stretch}.self-start-m{align-self:flex-start}.self-end-m{align-self:flex-end}.self-center-m{align-self:center}.self-baseline-m{align-self:baseline}.self-stretch-m{align-self:stretch}.justify-start-m{justify-content:flex-start}.justify-end-m{justify-content:flex-end}.justify-center-m{justify-content:center}.justify-between-m{justify-content:space-between}.justify-around-m{justify-content:space-around}.content-start-m{align-content:flex-start}.content-end-m{align-content:flex-end}.content-center-m{align-content:center}.content-between-m{align-content:space-between}.content-around-m{align-content:space-around}.content-stretch-m{align-content:stretch}.order-0-m{order:0}.order-1-m{order:1}.order-2-m{order:2}.order-3-m{order:3}.order-4-m{order:4}.order-5-m{order:5}.order-6-m{order:6}.order-7-m{order:7}.order-8-m{order:8}.order-last-m{order:99999}.flex-grow-0-m{flex-grow:0}.flex-grow-1-m{flex-grow:1}.flex-shrink-0-m{flex-shrink:0}.flex-shrink-1-m{flex-shrink:1}.fl-m{float:left}.fl-m,.fr-m{_display:inline}.fr-m{float:right}.fn-m{float:none}.i-m{font-style:italic}.fs-normal-m{font-style:normal}.normal-m{font-weight:400}.b-m{font-weight:700}.fw1-m{font-weight:100}.fw2-m{font-weight:200}.fw3-m{font-weight:300}.fw4-m{font-weight:400}.fw5-m{font-weight:500}.fw6-m{font-weight:600}.fw7-m{font-weight:700}.fw8-m{font-weight:800}.fw9-m{font-weight:900}.h1-m{height:1rem}.h2-m{height:2rem}.h3-m{height:4rem}.h4-m{height:8rem}.h5-m{height:16rem}.h-25-m{height:25%}.h-50-m{height:50%}.h-75-m{height:75%}.h-100-m{height:100%}.min-h-100-m{min-height:100%}.vh-25-m{height:25vh}.vh-50-m{height:50vh}.vh-75-m{height:75vh}.vh-100-m{height:100vh}.min-vh-100-m{min-height:100vh}.h-auto-m{height:auto}.h-inherit-m{height:inherit}.tracked-m{letter-spacing:.1em}.tracked-tight-m{letter-spacing:-.05em}.tracked-mega-m{letter-spacing:.25em}.lh-solid-m{line-height:1}.lh-title-m{line-height:1.25}.lh-copy-m{line-height:1.5}.mw-100-m{max-width:100%}.mw1-m{max-width:1rem}.mw2-m{max-width:2rem}.mw3-m{max-width:4rem}.mw4-m{max-width:8rem}.mw5-m{max-width:16rem}.mw6-m{max-width:32rem}.mw7-m{max-width:48rem}.mw8-m{max-width:64rem}.mw9-m{max-width:96rem}.mw-none-m{max-width:none}.w1-m{width:1rem}.w2-m{width:2rem}.w3-m{width:4rem}.w4-m{width:8rem}.w5-m{width:16rem}.w-10-m{width:10%}.w-20-m{width:20%}.w-25-m{width:25%}.w-30-m{width:30%}.w-33-m{width:33%}.w-34-m{width:34%}.w-40-m{width:40%}.w-50-m{width:50%}.w-60-m{width:60%}.w-70-m{width:70%}.w-75-m{width:75%}.w-80-m{width:80%}.w-90-m{width:90%}.w-100-m{width:100%}.w-third-m{width:33.33333%}.w-two-thirds-m{width:66.66667%}.w-auto-m{width:auto}.overflow-visible-m{overflow:visible}.overflow-hidden-m{overflow:hidden}.overflow-scroll-m{overflow:scroll}.overflow-auto-m{overflow:auto}.overflow-x-visible-m{overflow-x:visible}.overflow-x-hidden-m{overflow-x:hidden}.overflow-x-scroll-m{overflow-x:scroll}.overflow-x-auto-m{overflow-x:auto}.overflow-y-visible-m{overflow-y:visible}.overflow-y-hidden-m{overflow-y:hidden}.overflow-y-scroll-m{overflow-y:scroll}.overflow-y-auto-m{overflow-y:auto}.static-m{position:static}.relative-m{position:relative}.absolute-m{position:absolute}.fixed-m{position:fixed}.rotate-45-m{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.rotate-90-m{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.rotate-135-m{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.rotate-180-m{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.rotate-225-m{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.rotate-270-m{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.rotate-315-m{-webkit-transform:rotate(315deg);transform:rotate(315deg)}.pa0-m{padding:0}.pa1-m{padding:.25rem}.pa2-m{padding:.5rem}.pa3-m{padding:1rem}.pa4-m{padding:2rem}.pa5-m{padding:4rem}.pa6-m{padding:8rem}.pa7-m{padding:16rem}.pl0-m{padding-left:0}.pl1-m{padding-left:.25rem}.pl2-m{padding-left:.5rem}.pl3-m{padding-left:1rem}.pl4-m{padding-left:2rem}.pl5-m{padding-left:4rem}.pl6-m{padding-left:8rem}.pl7-m{padding-left:16rem}.pr0-m{padding-right:0}.pr1-m{padding-right:.25rem}.pr2-m{padding-right:.5rem}.pr3-m{padding-right:1rem}.pr4-m{padding-right:2rem}.pr5-m{padding-right:4rem}.pr6-m{padding-right:8rem}.pr7-m{padding-right:16rem}.pb0-m{padding-bottom:0}.pb1-m{padding-bottom:.25rem}.pb2-m{padding-bottom:.5rem}.pb3-m{padding-bottom:1rem}.pb4-m{padding-bottom:2rem}.pb5-m{padding-bottom:4rem}.pb6-m{padding-bottom:8rem}.pb7-m{padding-bottom:16rem}.pt0-m{padding-top:0}.pt1-m{padding-top:.25rem}.pt2-m{padding-top:.5rem}.pt3-m{padding-top:1rem}.pt4-m{padding-top:2rem}.pt5-m{padding-top:4rem}.pt6-m{padding-top:8rem}.pt7-m{padding-top:16rem}.pv0-m{padding-top:0;padding-bottom:0}.pv1-m{padding-top:.25rem;padding-bottom:.25rem}.pv2-m{padding-top:.5rem;padding-bottom:.5rem}.pv3-m{padding-top:1rem;padding-bottom:1rem}.pv4-m{padding-top:2rem;padding-bottom:2rem}.pv5-m{padding-top:4rem;padding-bottom:4rem}.pv6-m{padding-top:8rem;padding-bottom:8rem}.pv7-m{padding-top:16rem;padding-bottom:16rem}.ph0-m{padding-left:0;padding-right:0}.ph1-m{padding-left:.25rem;padding-right:.25rem}.ph2-m{padding-left:.5rem;padding-right:.5rem}.ph3-m{padding-left:1rem;padding-right:1rem}.ph4-m{padding-left:2rem;padding-right:2rem}.ph5-m{padding-left:4rem;padding-right:4rem}.ph6-m{padding-left:8rem;padding-right:8rem}.ph7-m{padding-left:16rem;padding-right:16rem}.ma0-m{margin:0}.ma1-m{margin:.25rem}.ma2-m{margin:.5rem}.ma3-m{margin:1rem}.ma4-m{margin:2rem}.ma5-m{margin:4rem}.ma6-m{margin:8rem}.ma7-m{margin:16rem}.ml0-m{margin-left:0}.ml1-m{margin-left:.25rem}.ml2-m{margin-left:.5rem}.ml3-m{margin-left:1rem}.ml4-m{margin-left:2rem}.ml5-m{margin-left:4rem}.ml6-m{margin-left:8rem}.ml7-m{margin-left:16rem}.mr0-m{margin-right:0}.mr1-m{margin-right:.25rem}.mr2-m{margin-right:.5rem}.mr3-m{margin-right:1rem}.mr4-m{margin-right:2rem}.mr5-m{margin-right:4rem}.mr6-m{margin-right:8rem}.mr7-m{margin-right:16rem}.mb0-m{margin-bottom:0}.mb1-m{margin-bottom:.25rem}.mb2-m{margin-bottom:.5rem}.mb3-m{margin-bottom:1rem}.mb4-m{margin-bottom:2rem}.mb5-m{margin-bottom:4rem}.mb6-m{margin-bottom:8rem}.mb7-m{margin-bottom:16rem}.mt0-m{margin-top:0}.mt1-m{margin-top:.25rem}.mt2-m{margin-top:.5rem}.mt3-m{margin-top:1rem}.mt4-m{margin-top:2rem}.mt5-m{margin-top:4rem}.mt6-m{margin-top:8rem}.mt7-m{margin-top:16rem}.mv0-m{margin-top:0;margin-bottom:0}.mv1-m{margin-top:.25rem;margin-bottom:.25rem}.mv2-m{margin-top:.5rem;margin-bottom:.5rem}.mv3-m{margin-top:1rem;margin-bottom:1rem}.mv4-m{margin-top:2rem;margin-bottom:2rem}.mv5-m{margin-top:4rem;margin-bottom:4rem}.mv6-m{margin-top:8rem;margin-bottom:8rem}.mv7-m{margin-top:16rem;margin-bottom:16rem}.mh0-m{margin-left:0;margin-right:0}.mh1-m{margin-left:.25rem;margin-right:.25rem}.mh2-m{margin-left:.5rem;margin-right:.5rem}.mh3-m{margin-left:1rem;margin-right:1rem}.mh4-m{margin-left:2rem;margin-right:2rem}.mh5-m{margin-left:4rem;margin-right:4rem}.mh6-m{margin-left:8rem;margin-right:8rem}.mh7-m{margin-left:16rem;margin-right:16rem}.na1-m{margin:-.25rem}.na2-m{margin:-.5rem}.na3-m{margin:-1rem}.na4-m{margin:-2rem}.na5-m{margin:-4rem}.na6-m{margin:-8rem}.na7-m{margin:-16rem}.nl1-m{margin-left:-.25rem}.nl2-m{margin-left:-.5rem}.nl3-m{margin-left:-1rem}.nl4-m{margin-left:-2rem}.nl5-m{margin-left:-4rem}.nl6-m{margin-left:-8rem}.nl7-m{margin-left:-16rem}.nr1-m{margin-right:-.25rem}.nr2-m{margin-right:-.5rem}.nr3-m{margin-right:-1rem}.nr4-m{margin-right:-2rem}.nr5-m{margin-right:-4rem}.nr6-m{margin-right:-8rem}.nr7-m{margin-right:-16rem}.nb1-m{margin-bottom:-.25rem}.nb2-m{margin-bottom:-.5rem}.nb3-m{margin-bottom:-1rem}.nb4-m{margin-bottom:-2rem}.nb5-m{margin-bottom:-4rem}.nb6-m{margin-bottom:-8rem}.nb7-m{margin-bottom:-16rem}.nt1-m{margin-top:-.25rem}.nt2-m{margin-top:-.5rem}.nt3-m{margin-top:-1rem}.nt4-m{margin-top:-2rem}.nt5-m{margin-top:-4rem}.nt6-m{margin-top:-8rem}.nt7-m{margin-top:-16rem}.strike-m{text-decoration:line-through}.underline-m{text-decoration:underline}.no-underline-m{text-decoration:none}.tl-m{text-align:left}.tr-m{text-align:right}.tc-m{text-align:center}.tj-m{text-align:justify}.ttc-m{text-transform:capitalize}.ttl-m{text-transform:lowercase}.ttu-m{text-transform:uppercase}.ttn-m{text-transform:none}.f-6-m,.f-headline-m{font-size:6rem}.f-5-m,.f-subheadline-m{font-size:5rem}.f1-m{font-size:3rem}.f2-m{font-size:2.25rem}.f3-m{font-size:1.5rem}.f4-m{font-size:1.25rem}.f5-m{font-size:1rem}.f6-m{font-size:.875rem}.f7-m{font-size:.75rem}.measure-m{max-width:30em}.measure-wide-m{max-width:34em}.measure-narrow-m{max-width:20em}.indent-m{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-m{font-variant:small-caps}.truncate-m{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.center-m{margin-left:auto}.center-m,.mr-auto-m{margin-right:auto}.ml-auto-m{margin-left:auto}.clip-m{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal-m{white-space:normal}.nowrap-m{white-space:nowrap}.pre-m{white-space:pre}.v-base-m{vertical-align:baseline}.v-mid-m{vertical-align:middle}.v-top-m{vertical-align:top}.v-btm-m{vertical-align:bottom}}@media screen and (min-width:60em){.aspect-ratio-l{height:0;position:relative}.aspect-ratio--16x9-l{padding-bottom:56.25%}.aspect-ratio--9x16-l{padding-bottom:177.77%}.aspect-ratio--4x3-l{padding-bottom:75%}.aspect-ratio--3x4-l{padding-bottom:133.33%}.aspect-ratio--6x4-l{padding-bottom:66.6%}.aspect-ratio--4x6-l{padding-bottom:150%}.aspect-ratio--8x5-l{padding-bottom:62.5%}.aspect-ratio--5x8-l{padding-bottom:160%}.aspect-ratio--7x5-l{padding-bottom:71.42%}.aspect-ratio--5x7-l{padding-bottom:140%}.aspect-ratio--1x1-l{padding-bottom:100%}.aspect-ratio--object-l{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}.cover-l{background-size:cover!important}.contain-l{background-size:contain!important}.bg-center-l{background-position:50%}.bg-center-l,.bg-top-l{background-repeat:no-repeat}.bg-top-l{background-position:top}.bg-right-l{background-position:100%}.bg-bottom-l,.bg-right-l{background-repeat:no-repeat}.bg-bottom-l{background-position:bottom}.bg-left-l{background-repeat:no-repeat;background-position:0}.outline-l{outline:1px solid}.outline-transparent-l{outline:1px solid transparent}.outline-0-l{outline:0}.ba-l{border-style:solid;border-width:1px}.bt-l{border-top-style:solid;border-top-width:1px}.br-l{border-right-style:solid;border-right-width:1px}.bb-l{border-bottom-style:solid;border-bottom-width:1px}.bl-l{border-left-style:solid;border-left-width:1px}.bn-l{border-style:none;border-width:0}.br0-l{border-radius:0}.br1-l{border-radius:.125rem}.br2-l{border-radius:.25rem}.br3-l{border-radius:.5rem}.br4-l{border-radius:1rem}.br-100-l{border-radius:100%}.br-pill-l{border-radius:9999px}.br--bottom-l{border-top-left-radius:0;border-top-right-radius:0}.br--top-l{border-bottom-right-radius:0}.br--right-l,.br--top-l{border-bottom-left-radius:0}.br--right-l{border-top-left-radius:0}.br--left-l{border-top-right-radius:0;border-bottom-right-radius:0}.b--dotted-l{border-style:dotted}.b--dashed-l{border-style:dashed}.b--solid-l{border-style:solid}.b--none-l{border-style:none}.bw0-l{border-width:0}.bw1-l{border-width:.125rem}.bw2-l{border-width:.25rem}.bw3-l{border-width:.5rem}.bw4-l{border-width:1rem}.bw5-l{border-width:2rem}.bt-0-l{border-top-width:0}.br-0-l{border-right-width:0}.bb-0-l{border-bottom-width:0}.bl-0-l{border-left-width:0}.shadow-1-l{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-l{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-l{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-l{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-l{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}.top-0-l{top:0}.left-0-l{left:0}.right-0-l{right:0}.bottom-0-l{bottom:0}.top-1-l{top:1rem}.left-1-l{left:1rem}.right-1-l{right:1rem}.bottom-1-l{bottom:1rem}.top-2-l{top:2rem}.left-2-l{left:2rem}.right-2-l{right:2rem}.bottom-2-l{bottom:2rem}.top--1-l{top:-1rem}.right--1-l{right:-1rem}.bottom--1-l{bottom:-1rem}.left--1-l{left:-1rem}.top--2-l{top:-2rem}.right--2-l{right:-2rem}.bottom--2-l{bottom:-2rem}.left--2-l{left:-2rem}.absolute--fill-l{top:0;right:0;bottom:0;left:0}.cl-l{clear:left}.cr-l{clear:right}.cb-l{clear:both}.cn-l{clear:none}.dn-l{display:none}.di-l{display:inline}.db-l{display:block}.dib-l{display:inline-block}.dit-l{display:inline-table}.dt-l{display:table}.dtc-l{display:table-cell}.dt-row-l{display:table-row}.dt-row-group-l{display:table-row-group}.dt-column-l{display:table-column}.dt-column-group-l{display:table-column-group}.dt--fixed-l{table-layout:fixed;width:100%}.flex-l{display:flex}.inline-flex-l{display:inline-flex}.flex-auto-l{flex:1 1 auto;min-width:0;min-height:0}.flex-none-l{flex:none}.flex-column-l{flex-direction:column}.flex-row-l{flex-direction:row}.flex-wrap-l{flex-wrap:wrap}.flex-nowrap-l{flex-wrap:nowrap}.flex-wrap-reverse-l{flex-wrap:wrap-reverse}.flex-column-reverse-l{flex-direction:column-reverse}.flex-row-reverse-l{flex-direction:row-reverse}.items-start-l{align-items:flex-start}.items-end-l{align-items:flex-end}.items-center-l{align-items:center}.items-baseline-l{align-items:baseline}.items-stretch-l{align-items:stretch}.self-start-l{align-self:flex-start}.self-end-l{align-self:flex-end}.self-center-l{align-self:center}.self-baseline-l{align-self:baseline}.self-stretch-l{align-self:stretch}.justify-start-l{justify-content:flex-start}.justify-end-l{justify-content:flex-end}.justify-center-l{justify-content:center}.justify-between-l{justify-content:space-between}.justify-around-l{justify-content:space-around}.content-start-l{align-content:flex-start}.content-end-l{align-content:flex-end}.content-center-l{align-content:center}.content-between-l{align-content:space-between}.content-around-l{align-content:space-around}.content-stretch-l{align-content:stretch}.order-0-l{order:0}.order-1-l{order:1}.order-2-l{order:2}.order-3-l{order:3}.order-4-l{order:4}.order-5-l{order:5}.order-6-l{order:6}.order-7-l{order:7}.order-8-l{order:8}.order-last-l{order:99999}.flex-grow-0-l{flex-grow:0}.flex-grow-1-l{flex-grow:1}.flex-shrink-0-l{flex-shrink:0}.flex-shrink-1-l{flex-shrink:1}.fl-l{float:left}.fl-l,.fr-l{_display:inline}.fr-l{float:right}.fn-l{float:none}.i-l{font-style:italic}.fs-normal-l{font-style:normal}.normal-l{font-weight:400}.b-l{font-weight:700}.fw1-l{font-weight:100}.fw2-l{font-weight:200}.fw3-l{font-weight:300}.fw4-l{font-weight:400}.fw5-l{font-weight:500}.fw6-l{font-weight:600}.fw7-l{font-weight:700}.fw8-l{font-weight:800}.fw9-l{font-weight:900}.h1-l{height:1rem}.h2-l{height:2rem}.h3-l{height:4rem}.h4-l{height:8rem}.h5-l{height:16rem}.h-25-l{height:25%}.h-50-l{height:50%}.h-75-l{height:75%}.h-100-l{height:100%}.min-h-100-l{min-height:100%}.vh-25-l{height:25vh}.vh-50-l{height:50vh}.vh-75-l{height:75vh}.vh-100-l{height:100vh}.min-vh-100-l{min-height:100vh}.h-auto-l{height:auto}.h-inherit-l{height:inherit}.tracked-l{letter-spacing:.1em}.tracked-tight-l{letter-spacing:-.05em}.tracked-mega-l{letter-spacing:.25em}.lh-solid-l{line-height:1}.lh-title-l{line-height:1.25}.lh-copy-l{line-height:1.5}.mw-100-l{max-width:100%}.mw1-l{max-width:1rem}.mw2-l{max-width:2rem}.mw3-l{max-width:4rem}.mw4-l{max-width:8rem}.mw5-l{max-width:16rem}.mw6-l{max-width:32rem}.mw7-l{max-width:48rem}.mw8-l{max-width:64rem}.mw9-l{max-width:96rem}.mw-none-l{max-width:none}.w1-l{width:1rem}.w2-l{width:2rem}.w3-l{width:4rem}.w4-l{width:8rem}.w5-l{width:16rem}.w-10-l{width:10%}.w-20-l{width:20%}.w-25-l{width:25%}.w-30-l{width:30%}.w-33-l{width:33%}.w-34-l{width:34%}.w-40-l{width:40%}.w-50-l{width:50%}.w-60-l{width:60%}.w-70-l{width:70%}.w-75-l{width:75%}.w-80-l{width:80%}.w-90-l{width:90%}.w-100-l{width:100%}.w-third-l{width:33.33333%}.w-two-thirds-l{width:66.66667%}.w-auto-l{width:auto}.overflow-visible-l{overflow:visible}.overflow-hidden-l{overflow:hidden}.overflow-scroll-l{overflow:scroll}.overflow-auto-l{overflow:auto}.overflow-x-visible-l{overflow-x:visible}.overflow-x-hidden-l{overflow-x:hidden}.overflow-x-scroll-l{overflow-x:scroll}.overflow-x-auto-l{overflow-x:auto}.overflow-y-visible-l{overflow-y:visible}.overflow-y-hidden-l{overflow-y:hidden}.overflow-y-scroll-l{overflow-y:scroll}.overflow-y-auto-l{overflow-y:auto}.static-l{position:static}.relative-l{position:relative}.absolute-l{position:absolute}.fixed-l{position:fixed}.rotate-45-l{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.rotate-90-l{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.rotate-135-l{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.rotate-180-l{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.rotate-225-l{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.rotate-270-l{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.rotate-315-l{-webkit-transform:rotate(315deg);transform:rotate(315deg)}.pa0-l{padding:0}.pa1-l{padding:.25rem}.pa2-l{padding:.5rem}.pa3-l{padding:1rem}.pa4-l{padding:2rem}.pa5-l{padding:4rem}.pa6-l{padding:8rem}.pa7-l{padding:16rem}.pl0-l{padding-left:0}.pl1-l{padding-left:.25rem}.pl2-l{padding-left:.5rem}.pl3-l{padding-left:1rem}.pl4-l{padding-left:2rem}.pl5-l{padding-left:4rem}.pl6-l{padding-left:8rem}.pl7-l{padding-left:16rem}.pr0-l{padding-right:0}.pr1-l{padding-right:.25rem}.pr2-l{padding-right:.5rem}.pr3-l{padding-right:1rem}.pr4-l{padding-right:2rem}.pr5-l{padding-right:4rem}.pr6-l{padding-right:8rem}.pr7-l{padding-right:16rem}.pb0-l{padding-bottom:0}.pb1-l{padding-bottom:.25rem}.pb2-l{padding-bottom:.5rem}.pb3-l{padding-bottom:1rem}.pb4-l{padding-bottom:2rem}.pb5-l{padding-bottom:4rem}.pb6-l{padding-bottom:8rem}.pb7-l{padding-bottom:16rem}.pt0-l{padding-top:0}.pt1-l{padding-top:.25rem}.pt2-l{padding-top:.5rem}.pt3-l{padding-top:1rem}.pt4-l{padding-top:2rem}.pt5-l{padding-top:4rem}.pt6-l{padding-top:8rem}.pt7-l{padding-top:16rem}.pv0-l{padding-top:0;padding-bottom:0}.pv1-l{padding-top:.25rem;padding-bottom:.25rem}.pv2-l{padding-top:.5rem;padding-bottom:.5rem}.pv3-l{padding-top:1rem;padding-bottom:1rem}.pv4-l{padding-top:2rem;padding-bottom:2rem}.pv5-l{padding-top:4rem;padding-bottom:4rem}.pv6-l{padding-top:8rem;padding-bottom:8rem}.pv7-l{padding-top:16rem;padding-bottom:16rem}.ph0-l{padding-left:0;padding-right:0}.ph1-l{padding-left:.25rem;padding-right:.25rem}.ph2-l{padding-left:.5rem;padding-right:.5rem}.ph3-l{padding-left:1rem;padding-right:1rem}.ph4-l{padding-left:2rem;padding-right:2rem}.ph5-l{padding-left:4rem;padding-right:4rem}.ph6-l{padding-left:8rem;padding-right:8rem}.ph7-l{padding-left:16rem;padding-right:16rem}.ma0-l{margin:0}.ma1-l{margin:.25rem}.ma2-l{margin:.5rem}.ma3-l{margin:1rem}.ma4-l{margin:2rem}.ma5-l{margin:4rem}.ma6-l{margin:8rem}.ma7-l{margin:16rem}.ml0-l{margin-left:0}.ml1-l{margin-left:.25rem}.ml2-l{margin-left:.5rem}.ml3-l{margin-left:1rem}.ml4-l{margin-left:2rem}.ml5-l{margin-left:4rem}.ml6-l{margin-left:8rem}.ml7-l{margin-left:16rem}.mr0-l{margin-right:0}.mr1-l{margin-right:.25rem}.mr2-l{margin-right:.5rem}.mr3-l{margin-right:1rem}.mr4-l{margin-right:2rem}.mr5-l{margin-right:4rem}.mr6-l{margin-right:8rem}.mr7-l{margin-right:16rem}.mb0-l{margin-bottom:0}.mb1-l{margin-bottom:.25rem}.mb2-l{margin-bottom:.5rem}.mb3-l{margin-bottom:1rem}.mb4-l{margin-bottom:2rem}.mb5-l{margin-bottom:4rem}.mb6-l{margin-bottom:8rem}.mb7-l{margin-bottom:16rem}.mt0-l{margin-top:0}.mt1-l{margin-top:.25rem}.mt2-l{margin-top:.5rem}.mt3-l{margin-top:1rem}.mt4-l{margin-top:2rem}.mt5-l{margin-top:4rem}.mt6-l{margin-top:8rem}.mt7-l{margin-top:16rem}.mv0-l{margin-top:0;margin-bottom:0}.mv1-l{margin-top:.25rem;margin-bottom:.25rem}.mv2-l{margin-top:.5rem;margin-bottom:.5rem}.mv3-l{margin-top:1rem;margin-bottom:1rem}.mv4-l{margin-top:2rem;margin-bottom:2rem}.mv5-l{margin-top:4rem;margin-bottom:4rem}.mv6-l{margin-top:8rem;margin-bottom:8rem}.mv7-l{margin-top:16rem;margin-bottom:16rem}.mh0-l{margin-left:0;margin-right:0}.mh1-l{margin-left:.25rem;margin-right:.25rem}.mh2-l{margin-left:.5rem;margin-right:.5rem}.mh3-l{margin-left:1rem;margin-right:1rem}.mh4-l{margin-left:2rem;margin-right:2rem}.mh5-l{margin-left:4rem;margin-right:4rem}.mh6-l{margin-left:8rem;margin-right:8rem}.mh7-l{margin-left:16rem;margin-right:16rem}.na1-l{margin:-.25rem}.na2-l{margin:-.5rem}.na3-l{margin:-1rem}.na4-l{margin:-2rem}.na5-l{margin:-4rem}.na6-l{margin:-8rem}.na7-l{margin:-16rem}.nl1-l{margin-left:-.25rem}.nl2-l{margin-left:-.5rem}.nl3-l{margin-left:-1rem}.nl4-l{margin-left:-2rem}.nl5-l{margin-left:-4rem}.nl6-l{margin-left:-8rem}.nl7-l{margin-left:-16rem}.nr1-l{margin-right:-.25rem}.nr2-l{margin-right:-.5rem}.nr3-l{margin-right:-1rem}.nr4-l{margin-right:-2rem}.nr5-l{margin-right:-4rem}.nr6-l{margin-right:-8rem}.nr7-l{margin-right:-16rem}.nb1-l{margin-bottom:-.25rem}.nb2-l{margin-bottom:-.5rem}.nb3-l{margin-bottom:-1rem}.nb4-l{margin-bottom:-2rem}.nb5-l{margin-bottom:-4rem}.nb6-l{margin-bottom:-8rem}.nb7-l{margin-bottom:-16rem}.nt1-l{margin-top:-.25rem}.nt2-l{margin-top:-.5rem}.nt3-l{margin-top:-1rem}.nt4-l{margin-top:-2rem}.nt5-l{margin-top:-4rem}.nt6-l{margin-top:-8rem}.nt7-l{margin-top:-16rem}.strike-l{text-decoration:line-through}.underline-l{text-decoration:underline}.no-underline-l{text-decoration:none}.tl-l{text-align:left}.tr-l{text-align:right}.tc-l{text-align:center}.tj-l{text-align:justify}.ttc-l{text-transform:capitalize}.ttl-l{text-transform:lowercase}.ttu-l{text-transform:uppercase}.ttn-l{text-transform:none}.f-6-l,.f-headline-l{font-size:6rem}.f-5-l,.f-subheadline-l{font-size:5rem}.f1-l{font-size:3rem}.f2-l{font-size:2.25rem}.f3-l{font-size:1.5rem}.f4-l{font-size:1.25rem}.f5-l{font-size:1rem}.f6-l{font-size:.875rem}.f7-l{font-size:.75rem}.measure-l{max-width:30em}.measure-wide-l{max-width:34em}.measure-narrow-l{max-width:20em}.indent-l{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-l{font-variant:small-caps}.truncate-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.center-l{margin-left:auto}.center-l,.mr-auto-l{margin-right:auto}.ml-auto-l{margin-left:auto}.clip-l{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ws-normal-l{white-space:normal}.nowrap-l{white-space:nowrap}.pre-l{white-space:pre}.v-base-l{vertical-align:baseline}.v-mid-l{vertical-align:middle}.v-top-l{vertical-align:top}.v-btm-l{vertical-align:bottom}} diff --git a/themes/cycle/exampleSite/.hugo_build.lock b/themes/cycle/exampleSite/.hugo_build.lock new file mode 100644 index 0000000..e69de29 diff --git a/themes/cycle/exampleSite/content/archive/_index.md b/themes/cycle/exampleSite/content/archive/_index.md new file mode 100644 index 0000000..10db07b --- /dev/null +++ b/themes/cycle/exampleSite/content/archive/_index.md @@ -0,0 +1,3 @@ +--- +title: "Archive" +--- diff --git a/themes/cycle/exampleSite/content/page/support.md b/themes/cycle/exampleSite/content/page/support.md new file mode 100644 index 0000000..b13c124 --- /dev/null +++ b/themes/cycle/exampleSite/content/page/support.md @@ -0,0 +1,18 @@ +--- +title: "Support" +permalink: "/support" +excerpt: "Ways to support me and the blog via affiliate links." +type: "page" +--- +# Support + +I use the following services just about every day and they all offer discounts or other incentives for folks to recommend the service to other people. Signing up for one of these services using the links below helps support me and this blog. Thanks! + +## Fastmail +I've been a [Fastmail](https://www.fastmail.com/?STKI=14274077) user for years now and I don't have a single complaint about the service or company. Highly recommended if all you care about is IMAP service that "just works." + +## Hover +Years ago I switched from GoDaddy to [Hover](https://hover.com/U84GCox3) and haven't looked back. They're a great, no-frills DNS service. + +## Backblaze +I've been using [Backblaze](https://secure.backblaze.com/r/01c40o) for years and absolutely love the service and company. Not only is their product top-notch but the data they publish about [hard drive reliability](https://www.backblaze.com/b2/hard-drive-test-data.html) is incredibly useful. diff --git a/themes/cycle/exampleSite/content/page/uses.md b/themes/cycle/exampleSite/content/page/uses.md new file mode 100644 index 0000000..14b65c4 --- /dev/null +++ b/themes/cycle/exampleSite/content/page/uses.md @@ -0,0 +1,37 @@ +--- +title: "Uses" +permalink: "/uses" +excerpt: "A evolving list of hardware and software that I use." +type: "page" +--- +# Uses + +*Author's note: I 100% stole this format from the incredible [usesthis][uses] site. Check it out.* + +**What hardware do you use?** + +At work I use a [desktop workstation](/writing/new-workstation) running [NixOS](https://nixos.org/) and an Intel 12600k. I game via a Windows 11 VM and a Nvidia 3060 passed through to that VM. + +I love typing on my [Anne Pro](https://www.amazon.com/Anne-PRO-Mechanical-Keyboard-Programmable/dp/B07J4HH6YZ) [GMMK Pro](https://www.pcgamingrace.com/products/glorious-gmmk-pro-75-barebone-black) mechanical keyboard with Gazzew U4 Boba switches for a quieter feel. + +My phone is an iPhone 14. It's fine. + +**And what software?** + +I'm a [big][dotfiles] user of [Emacs][emacs]. I use [mu4e](https://www.djcbsoftware.nl/code/mu/mu4e.html) for email, [org-mode](https://orgmode.org/) for tasks and notes, [Ivy](https://github.com/abo-abo/swiper) for auto-complete, [magit](https://magit.vc/) for git, [ivy-feedwrangler](/writing/introducing-ivy-feedwrangler) for RSS. I've switched to VSCode since the support for all the various LSPs and debug tools is just better at the moment. + +Linux apps I use on my work laptop are: [Signal](https://www.signal.org/), [Tilix](https://gnunn1.github.io/tilix-web/) or [Alacritty](https://github.com/jwilm/alacritty) for terminals, [rofi](https://github.com/davatorium/rofi) for launching, and [i3wm](https://github.com/i3/i3) as my window manager. + +Mac specific apps I use: [Alfred](https://www.alfredapp.com/), [MenuMeters](https://github.com/yujitach/MenuMeters), [1Password](https://1password.com/), [Moom](https://manytricks.com/moom/), [Turbo Boost Switcher Pro](http://tbswitcher.rugarciap.com/), and [Hammerspoon](https://github.com/Hammerspoon/hammerspoon). + +My browser of choice is Firefox. + +I enjoy writing code in [Javascript/Node](https://nodejs.org/en/), [Golang](https://go.dev/), [Ruby](https://www.ruby-lang.org/en/), [Common Lisp](https://common-lisp.net/), and recently [Rust](https://www.rust-lang.org/). + +**Any online services?** + +As far as online services go I use [Netlify](https://www.netlify.com) (at the moment) to host this site, [Hover](https://hover.com/U84GCox3) for domains, [Fastmail](https://www.fastmail.com/?STKI=14274077) for email, [yarr](https://github.com/nkanaev/yarr) manages my RSS feeds, and I use [Backblaze](https://secure.backblaze.com/r/01c40o) for online backup. + +[uses]: https://usesthis.com/ +[dotfiles]: https://github.com/asimpson/dotfiles/tree/master/emacs +[emacs]: https://www.gnu.org/software/emacs/ diff --git a/themes/cycle/exampleSite/content/post/0-14.md b/themes/cycle/exampleSite/content/post/0-14.md new file mode 100644 index 0000000..d3e5d8f --- /dev/null +++ b/themes/cycle/exampleSite/content/post/0-14.md @@ -0,0 +1,42 @@ +--- +title: "0.14" +date: 2019-07-30T10:31:07-0400 +lastmod: 2019-07-30T10:31:07-0400 +slug: 0-14 +excerpt: "I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn't worth it." +--- + +I type this on a [Thinkpad t480s](https://www.lenovo.com/us/en/laptops/thinkpad/thinkpad-t-series/ThinkPad-T480/p/22TP2TT4800) that I recently switched to from a *lifetime* of using Apple machines (literally grew up on Apple computers, shoutout to the Macintosh Classic!). I switched because it was time for a new machine and I didn't want to be using a faulty keyboard for the next 5 years. Here are my caveats before I continue: + +- If I wasn't buying a laptop I would get an iMac or iMac Pro and all would be well. Apple desktop computers are in a great place right now. +- This machine is for my work as a web developer and technical director at Sparkbox. The range of applications I need are largely all cross-platform: 1Password, Dropbox, Slack, Google Calendar, code editor, browser, terminal, email. I miss but don't *need*: iMessage, Photos, Safari, Tweetbot, Sequel Pro etc. +- I haven't completely lost my mind, I'm not running Windows 10. I am using [System76's quite nice Pop_OS linux distro](https://system76.com/pop). +- I got this Thinkpad before the latest (4th?) revision of the Macbook keyboards. I would still make this decision today given the unknown quality of these "fixed" keyboards. + +Some of the niceties that come with the switch: + +- User upgradeable RAM. The t480s has 1 open SO-DIMM slot and 8GB soldered to the motherboard. This feels like a nice compromise. Of course I threw in a 16GB stick to have 24GB total. +- User upgradeable SSD. I can easily swap the stock SSD. A Samsung 970 Pro 512GB SSD that is faster than what Apple ships in the current Macbook Pro is $150 from Amazon. +- Ports. The t480s has 2 USB-A ports and 2 USB-C ports. It also has a full size HDMI, SD card slot, and full-size Ethernet. +- Of course, a best-in-class keyboard. + +Here's what stinks about it: + +- No macOS +- Inferior trackpad + +The stark difference between the current Macbook Pros and this Thinkpad remind me of [John Gruber's apt comparison](https://www.macworld.com/article/1156153/macofthefuturegruber.html) between iOS and macOS when the iPad was new on the scene (emphasis mine): + +> When I say that iOS has no baggage, that’s not because there is no baggage. **It’s because the Mac is there to carry it**. […] Mac OS X has an essential role in an iOS world: serving as the platform for complex, resource-intensive tasks. +> +> The funny thing is, the best slogan to describe the Mac’s role is the same one it started with 25 years ago: +> +> The computer for the rest of us. + +Apple should apply this to hardware as well, let the iPad be *the* ultrathin device with limited ports. Don't force that set of compromises on professional *laptop* users. Like I said above, Apple's desktops are fantastic. Heck the Mac mini RAM is *almost* user serviceable. The t480s is not a thin machine compared to a 13" Macbook Pro: it's 0.73" thick according to Lenovo's official specs and weighs in at 2.9lbs. The Macbook Pro for comparison is 0.59" thick and weighs in at 3.02lbs. Is 0.14" difference in thinness worth access to the ports, user upgrade-ability, and the longevity of the keyboard? I certainly don't think so and I'm disappointed Apple continues to demonstrate they care about that 0.14" more than any other single feature. + +I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn't worth it. + +**Update** + +Quite a bit of discussion happened over at [lobste.rs](https://lobste.rs/s/j4lmry/apple_let_ipad_be_ultrathin_device_with). It's easy to get hung up on *which* ports should be included but [I think looking at Apple's desktops](https://www.apple.com/imac-pro/specs/) is instructive: USB-A, SD Card, and USB-C/TB3 are all included (HDMI is nice in my opinion but I can see the argument for dropping it). None of those ports would cause the device to become unbearably thick and would add significant value and convenience. diff --git a/themes/cycle/exampleSite/content/post/8-line-firewall.md b/themes/cycle/exampleSite/content/post/8-line-firewall.md new file mode 100644 index 0000000..6b77589 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/8-line-firewall.md @@ -0,0 +1,24 @@ +--- +title: "A firewall in 8 lines" +date: 2021-03-31T11:18:24-04:00 +lastmod: 2021-03-31T11:18:24-04:00 +slug: 8-line-firewall +excerpt: "You only need about 8 lines in iptables to have a great home firewall." +--- + +Since 2017 my home router has been a [plain x86 box](https://ark.intel.com/content/www/us/en/ark/products/95597/intel-celeron-processor-j3355-2m-cache-up-to-2-5-ghz.html) running Alpine Linux. I never really think about it anymore. Recently, I was helping a relative set up their own Linux-based router and took the time to appreciate how little config is needed to setup a serviceable home router firewall using `iptables`. You can see my base rule-sets (port forwarding omitted) below: + +``` +-P INPUT DROP +-P FORWARD DROP +-P OUTPUT ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -i eth1 -j ACCEPT +-A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -i eth1 -o eth0 -j ACCEPT +-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +``` + +The benefit of running a x86 box with Alpine (or any version of Linux) is that the box will receive a steady stream of security updates and upgraded kernels as Alpine Linux releases new versions. This is a much better situation to be in than relying on OS and security updates from a vendor like TPLink or Linksys. + +If you have ideas for how to improve the config I listed above or want to chat more about home network stuff, send an email to my [public-inbox](https://lists.sr.ht/~asimpson/public-inbox). diff --git a/themes/cycle/exampleSite/content/post/ATR2100.md b/themes/cycle/exampleSite/content/post/ATR2100.md new file mode 100644 index 0000000..c6beb26 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/ATR2100.md @@ -0,0 +1,24 @@ +--- +title: "ATR2100" +date: 2020-01-29T12:55:45-05:00 +lastmod: 2020-01-29T12:55:45-05:00 +slug: ATR2100 +excerpt: "I recently purchased the ATR2100 microphone and absolutely love it." +--- + +I recently purchased [the ATR2100 mic](https://amzn.to/2RYeOAm) to use for work calls and maybe some podcasting in the future. I stumbled upon the ATR2100 via Marco Arment who has a [great roundup of good podcasting mics](https://marco.org/podcasting-microphones) that I highly recommend if you want to explore mics. I ended up picking up an Amazon bundle that included a Knox boom arm, Knox pop filter, and the ATR2100 for around $90. I don't see it on the site anymore but you could cobble together the same bundle pretty easily. + +## Requirements +These were my requirements for upgrading from the built-in mic on my laptop/webcam: + +### Sound good with little effort +Obvious but important. I didn't want to have to fiddle with things to achieve better sound. I also didn't want to invest in a DAC or other ancillary equipment. + +### Reduce background noise +My office at home is in the basement right below my 3 year-old daughter's room. Kids make noises from time to time and I wanted a mic that would not pick those up. + +### Be under $100 +I didn't have the budget to go get a premium mic. + +## Verdict +I've used the mic for some gaming and Zoom calls and in both cases I've gotten several comments that my voice sounds "radio quality" and "really clear". I have zero complaints with the mic and I can't recommend it enough. I will note that this type of mic requires you to be about 2-6 inches away for optimal volume and quality. This is the cost of not picking up those background noises I mentioned above in my requirements. Windows 10, Linux (Pop_OS), and macOS all recognized the mic without any drivers or needing any configuration. If you're looking to upgrade your audio on a budget look no further than the ATR2100. diff --git a/themes/cycle/exampleSite/content/post/a-few-bash-tips.md b/themes/cycle/exampleSite/content/post/a-few-bash-tips.md new file mode 100644 index 0000000..94060c1 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/a-few-bash-tips.md @@ -0,0 +1,155 @@ +--- +title: "A few Bash Tips" +date: 2012-11-20T03:00:43-05:00 +lastmod: 2017-02-24T09:36:16-05:00 +slug: a-few-bash-tips +excerpt: "A rundown of some of my most used bash and terminal commands and functions. +" +--- + +Here are a few custom little functions and aliases that I use everyday, these are all pretty straightforward, you can tweak any of these to fit your specific workflow. + +![The Bash Brothers](/images/bash-bros.gif) + +### MAMP Virtual Hosts + +It's a pain to set up virtual hosts, which is why I wrote a bash script to automate that horrible process. Here is the script, I'll explain how it works below (or check out the [Gist](https://gist.github.com/3989062)): + +``` +#!/bin/bash +RED="\033[0;31m" +YELLOW="\033[33m" +REDBG="\033[0;41m" +WHITE="\033[1;37m" +NC="\033[0m"

+ +
mkdir -p /Applications/MAMP/Library/vhosts;
+mkdir -p /Applications/MAMP/Library/vhosts/domains;
+
+if [ "$1" = "create" ] || [ "$1" = "add" ]; then
+# Ask for document root
+echo -e "${RED}Enter the document root (relative to 'htdocs'):${NC}";
+read documentRoot;
+
+# Ask for domain name
+echo -e "${RED}Enter local domain: (eg. local.com):${NC}";
+read domain;
+
+# Ask for port number
+echo -e "${RED}Enter MAMP Port Nubmer:${NC}";
+read port;
+
+# Add vhost
+touch /Applications/MAMP/Library/vhosts/domains/$domain;
+
+echo "
+DocumentRoot "/Applications/MAMP/htdocs/$documentRoot"
+ServerName $domain
+
+    Options All
+    AllowOverride All
+    Order allow,deny
+    Allow from all
+
+" >> /Applications/MAMP/Library/vhosts/domains/$domain;
+
+echo "127.0.0.1 $domain" >> /etc/hosts;
+
+# Restart MAMP
+/Applications/MAMP/bin/apache2/bin/apachectl restart;
+
+echo -e "Finished. ${REDBG}${WHITE}$domain:$port${NC} has been copied to your clipboard.";
+echo "$domain:$port" | pbcopy;
+fi
+
+if [ "$1" = "remove" ] || [ "$1" = "delete" ]; then
+echo -e "${RED}Here are the current custom local domains:${NC}"
+for file in /Applications/MAMP/Library/vhosts/domains/*
+do
+  if [ -f "$file" ];then
+    echo -e "${YELLOW}${file##/*/}${NC}"
+  fi
+done
+echo -e "${RED}Enter the site name you wish to remove:${NC}"
+read siteName;
+
+sed -i.bak "/$siteName/d" /etc/hosts;
+rm /Applications/MAMP/Library/vhosts/domains/$siteName;
+
+echo -e "${YELLOW}$siteName removed."
+fi
+```
+
+The script is set up to work with each web project being stored in a directory under htdocs in the MAMP folder. If you want to use a different folder structure, simply change the paths in the script to reflect your particular workflow.
+
+The script asks for three pieces of info, the domain you want, the directory name, and the MAMP port number. The script creates a new directory called 'vhosts' and a sub directory called 'vhosts/domains'. Each file in 'domains' is a single domain, which makes this all easier to manage. The script then modifies your etc/hosts file with the new domain information. Finally, the script restarts MAMP apache and copies the new domain address to your clipboard.
+
+The last piece to this puzzle is the function that fires this script off.
+
+```
+function vhost {
+  sudo ~/.dotfiles/osx/mamp_vh.sh $1
+}
+```
+
+Just specify the path to the script and you are set.
+
+### Jump to project directory
+
+Another pain point is jumping to a specific project directory quickly, and without a lot of path typing. I wrote a function that lists all the folders in my htdocs directory and lets me select the one I want to go to.
+
+```
+function ht {
+  local BLUE="\033[0;34m"
+  local RED="\033[0;31m"
+  local WHITE="\033[0;37m"
+  local NC="\033[0m"
+  echo -e "${BLUE}Projects:${WHITE}"
+    for file in /Applications/MAMP/htdocs/*
+    do
+      if [ -d "$file" ];then
+        echo ${file##/*/}
+      fi
+    done
+  echo -e "${RED}Which Project?${NC}"
+  read dir;
+  cd /Applications/MAMP/htdocs/$dir
+}
+```
+
+Again, simply change the paths in the script to adapt this to your workflow.
+
+### Colored History Grep
+
+One little alias that I snagged from the numerous dotfile repos on Github is the 'h' alias which simply shortcuts the 'history' command. I love this little command, but I found myself typing out `h | grep keyword` to get a list of commands specific to a keyword. I shortened this up and added color highlighting:
+
+```
+function hg {
+  history | grep --color=auto $1
+}
+```
+
+Simply pass the function the term you are looking for. Remember you can execute previous functions by typing `!999` (999 being the number of the command).
+
+### Keep tweaking and hacking
+
+Hopefully these little utilities were useful in someway, feel free to comment or offer advice by reaching out on [twitter](http://twitter.com/a_simpson) or [adn](http://alpha.app.net/a_simpson).
+
+### Update
+
+I forgot to mention that I have two documents, one called "functions" and the other "aliases", which I source at the top of my .bash\_profile like this (You can see all my dotfiles over on [Github](https://github.com/asimpson/dotfiles)):
+
+```
+. /.dotfiles/bash/functions
+. /.dotfiles/bash/aliases
+```
+
+Sourcing these files makes the functions and aliases inside them available on the command line. To use any of the functions or aliases in this post you have to source them to your bash, then you can simply type the alias or function name plus any arguments:
+
+```
+vhost create
+hg term
+ht
+```
+
+Thanks to [Jack McDade](https://twitter.com/jackmcdade/status/270926210798854145) for the advice to include some examples.
diff --git a/themes/cycle/exampleSite/content/post/a-few-posix-shell-tips.md b/themes/cycle/exampleSite/content/post/a-few-posix-shell-tips.md
new file mode 100644
index 0000000..a96d621
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-few-posix-shell-tips.md
@@ -0,0 +1,76 @@
+---
+title: "A few POSIX shell tips"
+date: 2021-07-19T14:53:16-04:00
+lastmod: 2021-07-19T14:53:16-04:00
+slug: a-few-posix-shell-tips
+excerpt: "I wrote down a few of my most used POSIX shell commands and features."
+---
+
+I was recently working on the [release build script](https://github.com/sparkbox/sb/commit/f9d2a0bc5339c4777e73432d9a8208b092a2e9ac) for [`sb`](https://github.com/sparkbox/sb) and decided I should document a few things I find myself looking up just about every time. One of the advantages of the POSIX shell (not bash, zsh, but Bourne shell, usually `/bin/sh` on most unix-y systems) is that it has [a specification](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html) however I'm usually frustrated trying to find the information I need.
+
+
+
+I prefer the POSIX shell because it's _the default_ on most unix-y system. If I have to be sure if the shell is installed on the target system (like `bash` or `zsh`) I'd rather just use a higher-level scripting language like node or ruby where the same requirement exists.
+
+## Arrays
+
+Psych! There aren't any arrays. Bash has arrays but POSIX does not. If I need an array structure I can use a space-separated string (or another delimiter if you've set [`$IFS`](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03)) as the data structure, e.g. `PLATFORMS="arm64-darwin amd64-linux amd64-darwin"`. Now I can loop over the variable using a for loop:
+
+```sh
+PLATFORMS="arm64-darwin amd64-linux amd64-darwin"
+
+for PLATFORM in ${PLATFORMS}; do
+  # GOOS=FOO GOARCH=BAR go build ...
+done
+```
+
+Or I can take the lack of arrays as a signal I should stop writing a shell script and reach for a language that has the concept of arrays to solve my problem.
+
+## Conditional "flags"
+
+I often forget the various flags one can use in a conditional (aka test/if) statement. Here's the [documentation](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html) and here are a few of my favorites:
+
+- `-n` tests if the string is non-zero, e.g.
+
+```sh
+if [ -n "${UPLOAD_URL}" ]; then
+    upload_file "${PLATFORM}"
+fi
+```
+
+- `-z` the opposite of `-n`.
+- `-f` tests if the pathname resolves to a file.
+
+## Functions and args
+
+- Functions must be declared before they are invoked.
+- Functions look like:
+
+```sh
+someFunc() {
+  echo "a func!"
+}
+```
+- There is no syntax for functions accepting args instead they are mapped to `$n`. `$@` is all the args.
+
+```sh
+upload_file() {
+    NAME=$1
+
+    zip "${NAME}.zip" "${NAME}"
+    curl -H "Accept: application/vnd.github.v3+json" \
+         -H "Authorization: Bearer ${GITHUB_TOKEN}" \
+         -H "Content-Type: application/zip" \
+         --data-binary "@${NAME}.zip" \
+         "${UPLOAD_URL}?name=${NAME}.zip"
+}
+
+upload_file "${PLATFORM}"
+```
+
+## Use shellcheck
+This is just preference but I really love using [`shellcheck`](https://www.shellcheck.net/) to avoid any footguns and enforce a consistent style with my shell scripts. I typically invoke it like this: `shellcheck -o all script-name.sh`.
diff --git a/themes/cycle/exampleSite/content/post/a-fluid-userscript-that-adds-read-it-later-to-twitter.md b/themes/cycle/exampleSite/content/post/a-fluid-userscript-that-adds-read-it-later-to-twitter.md
new file mode 100644
index 0000000..e44c50c
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-fluid-userscript-that-adds-read-it-later-to-twitter.md
@@ -0,0 +1,14 @@
+---
+title: "A Fluid Userscript that adds Read it Later to Twitter"
+date: 2013-03-24T03:00:43-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: a-fluid-userscript-that-adds-read-it-later-to-twitter
+excerpt: "A simple Fluid userscript that adds a Read it Later button for Instapaper to any tweet containing a link
+"
+---
+
+I use and love [Craig Mod's](http://craigmod.com/) [Twitter for Minimalists](http://craigmod.com/satellite/twitter_for_minimalists/). It is a great way to experience the Twitter web client without some of the cruft. However, the biggest thing I miss from third party apps like Tweetbot is the ability to send interesting links directly to my Instapaper account with one click.
+
+Since Twitter for Minimalists runs inside a [Fluid](http://fluidapp.com/) instance I can set custom Userstyles (like Twitter for Minimalists) and Userscripts. I decided to write a Userscript that would parse through every tweet and determine if it had a link and - if it did - append a Send to Instapaper button to the bottom of the tweet. I was able to create the button using [Instapaper's iFrame Button API](http://www.instapaper.com/publishers). You can find the the finished code for the Read it Later Userscript [here](https://github.com/asimpson/send-to-instapaper-fluid).
+
+Hope you find it useful\!
diff --git a/themes/cycle/exampleSite/content/post/a-hackintosh.md b/themes/cycle/exampleSite/content/post/a-hackintosh.md
new file mode 100644
index 0000000..6b2cff4
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-hackintosh.md
@@ -0,0 +1,57 @@
+---
+title: "A Hackintosh"
+date: 2017-09-14T10:11:55-04:00
+lastmod: 2017-09-14T10:11:55-04:00
+slug: a-hackintosh
+excerpt: "I built a PC in May to replace my Xbox One (yay no more Live fees!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh."
+---
+
+## Taking the Hackintosh plunge
+
+I built a PC (here's the [partslist](https://pcpartpicker.com/list/GvNtRG)) in May to replace my Xbox One (yay no more Live fees\!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh. The process of getting a Hackintosh up and running wasn't really that much more difficult than setting up Arch Linux. In fact I'd say you could and probably should follow most of the [Arch Linux ideals](https://wiki.archlinux.org/index.php/System_maintenance) about knowing what and why you're updating as you maintain a Hackintosh.
+
+Here's a few tips and things I learned along the way. I'd also recommend reading through the tips in [this reddit post](https://www.reddit.com/r/hackintosh/comments/4jgdny/tips_and_tricks_youve_learnt_living_the/d36pk9f/).
+
+## Happy Path (Use Clover)
+
+The ideal setup is to use [Clover](https://clover-wiki.zetam.org/Home) to add [ktext](http://hackintosher.com/blog/kext-files-macos/) and modify the `config.plist` in the `/EFI` partition. This leaves your actual macos install untouched. Avoid Unibeast and Multibeast, they try do too much and mask complexity. The truly "do-it-yourself" approach is outlined [here](https://eladnava.com/install-os-x-10-11-el-capitan-on-hackintosh-vanilla/). I ended up following a guide and using (and then modifying) their pre-made `/EFI` partition. Speaking of…
+
+## Find a guide
+
+I combined and followed these two guides:
+
+  - 
+  - 
+
+## Keep it simple
+
+Solve one thing at a time. Google error messages.
+
+## Use compatible parts
+
+  - I'd recommend an Intel KabyLake CPU since it's the latest and greatest and it means you'll need a 200 series motherboard which is recommended anyway. AMD CPUs are not really supported.
+  - While my build uses the Pentium G4560 I wouldn't recommend it as a great Hackintosh CPU. It works, but things would be smoother with an i5 or i7.
+  - AMD GPUs (if you can find one at a decent price, damn you [Etherium](https://www.ethereum.org)) have great native support now in 10.12.6, e.g. Metal Support\!
+  - Grab a WiFi/Bluetooth card from [osxwifi.com](http://www.osxwifi.com), genuine Apple parts which means things just work (I'm content with no Bluetooth and Ethernet for now)
+
+## One OS per drive
+
+Don't try to partition a drive and install macos and Windows on it. Keep all operating systems on their own boot drives and then boot into them using Clover.
+
+## Disable hibernation if you're on a Pentium
+
+You'll need to set two power management switches:
+
+`sudo pmset -a hibernatemode 0`
+
+`sudo pmset -a standby 0`
+
+> To disable hibernation images completely, ensure hibernatemode standby and autopoweroff are all set to 0. \~ pmset man page
+
+I didn't run into issues with `autopoweroff`.
+
+## Disable automatic updates.
+
+You can still update through the App Store but it's advised to wait and see if any ktexts or plist changes are needed before updating
+
+That's it. Hopefully this post helps clarify the process to create a Hackintosh of your own.
diff --git a/themes/cycle/exampleSite/content/post/a-little-hydrofoil.md b/themes/cycle/exampleSite/content/post/a-little-hydrofoil.md
new file mode 100644
index 0000000..74af315
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-little-hydrofoil.md
@@ -0,0 +1,18 @@
+---
+title: "A Little Hydrofoil"
+date: 2012-07-23T03:00:44-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: a-little-hydrofoil
+excerpt: "Robin Sloan's description of a programmer.
+"
+---
+
+While taking a short break today, I flipped over to [Robin Sloan's interview on the Setup](http://robin.sloan.usesthis.com/). Now Mr. Sloan almost broke the Internet a few days ago with his [book review in Javascript](http://www.robinsloan.com/summer-reading/and-programming/). In his interview for the Setup he described how he sees himself as a programmer,
+
+> I imagine professional programmers as jumbo jets, capable of cruising smoothly and swiftly at altitude for hours, no internet needed; by contrast, I'm just a little hydrofoil kinda bumping along, held shakily aloft by the ground effect of online documentation, code snippets and tutorial blog posts.
+
+I totally identify with his analogy, and would wager most "jumbo jets" feel the same way. I think this ties into why I agree so strongly with [Alex Sexton's tweet](https://twitter.com/SlexAxton/status/177127432749461504) from earlier this year (hat-tip to [Motherfuton](https://twitter.com/motherfuton/status/177173995840479233) for the RT),
+
+> I think being skilled at debugging is probably more important than being skilled at coding.
+
+Programming is problem-solving, hence my constant dips into [Stackoverflow](http://stackoverflow.com/) and Google. To extend Mr. Sloan's analogy a bit more, even Jumbo Jets need maintenance and fuel.
diff --git a/themes/cycle/exampleSite/content/post/a-new-adventure.md b/themes/cycle/exampleSite/content/post/a-new-adventure.md
new file mode 100644
index 0000000..8b972c6
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-new-adventure.md
@@ -0,0 +1,12 @@
+---
+title: "A New Adventure"
+date: 2012-09-03T03:00:45-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: a-new-adventure
+excerpt: "Today I started working at Sparkbox as  Front-End Dev.
+"
+---
+
+Today I started my new job working as a Front-End Developer at [Sparkbox](http://seesparkbox.com/)\! I am thrilled at the opportunity to work with these guys and can't wait for the adventures and challenges ahead.
+
+Onward and upward.
diff --git a/themes/cycle/exampleSite/content/post/a-new-website-for-2020.md b/themes/cycle/exampleSite/content/post/a-new-website-for-2020.md
new file mode 100644
index 0000000..ad13217
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-new-website-for-2020.md
@@ -0,0 +1,16 @@
+---
+title: "A new website for 2020"
+date: 2020-07-16T13:52:56-04:00
+lastmod: 2020-07-16T13:52:56-04:00
+slug: a-new-website-for-2020
+excerpt: ""
+link: "https://fasterthanli.me/articles/a-new-website-for-2020"
+---
+
+> According to my `Cargo.lock` file, my website currently depends on 364 crates. So it's really about standing on the shoulder of a carefully-curated set of giants.
+
+> 364 may seem like a lot (and in a way, it is), but please reserve your judgement until after you've heard about everything it does.
+
+I /love/ posts like this. Amos goes in deep on the decisions he made while re-writing his website from scratch. It's a truly awesome post.
+
+I'm seriously tempted to copy his `SQLite` full-text search implementation for this blog, but that's a decision for another time.
diff --git a/themes/cycle/exampleSite/content/post/a-public-inbox.md b/themes/cycle/exampleSite/content/post/a-public-inbox.md
new file mode 100644
index 0000000..6da9cbf
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-public-inbox.md
@@ -0,0 +1,20 @@
+---
+title: "A public inbox"
+date: 2020-08-17T23:14:25-04:00
+lastmod: 2020-08-17T23:14:25-04:00
+slug: a-public-inbox
+excerpt: "I'm going to give the idea of a public inbox as a place to have discussions about things on this website and elsewhere a shot."
+---
+
+I've tried a few blog commenting systems in my day but have never really been happy with any of them. Part of the problem with comment systems is that a discussion forum is not a blog.
+
+Recently I've noticed a few other folks ([Drew](https://drewdevault.com/), [Ethan](https://ethanmarcotte.com/wrote/replyin/), [Tom](https://macwright.com/2020/08/01/recently.html), and [Jonnie](https://destroytoday.com/blog/reply-link-in-rss-feed-posts)) around the internet turning to email as the solution to have conversations about the things on their respective websites. I liked how Drew's solution not only leveraged email but mailing lists! The benefits are pretty obvious to me:
+
+- Folks are comfortable composing messages in their email client of choice
+- A mailing list is public
+- A mailing list is searchable
+- A mailing list facilities conversation.
+
+So I'm gonna give it a spin. [Here is my public inbox](https://lists.sr.ht/~asimpson/public-inbox).
+
+Of course I'll always accept direct email at [adam@adamsimpson.net](mailto:adam@adamsimpson.net).
diff --git a/themes/cycle/exampleSite/content/post/a-style-guide-guide.md b/themes/cycle/exampleSite/content/post/a-style-guide-guide.md
new file mode 100644
index 0000000..457027c
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/a-style-guide-guide.md
@@ -0,0 +1,16 @@
+---
+title: "A Style Guide, Guide"
+date: 2012-07-19T03:00:45-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: a-style-guide-guide
+excerpt: "Elyse Holladay reveals her style guide guide.
+"
+---
+
+Thanks to [@behoff](http://twitter.com/behoff) for [tweeting](http://twitter.com/behoff/status/226298234467930112) out [Elyse Holladay's blog post](http://www.elyseholladay.com/2012/07/16/style-guide-guide.html) about a guide for style guides.
+
+The [post](http://www.elyseholladay.com/2012/07/16/style-guide-guide.html) is a fantastic read, and is chock full of good information. I then clicked over to see what else Ms. Holladay had written and found her [Hello World?](http://www.elyseholladay.com/2012/07/10/hello-world.html) post. It really resonated with my own reasons for starting this blog, especially this bit:
+
+> I realized two things have stopped me: the feeling of inadequacy that leads to the fear of not starting, and the need to get it perfect first.
+
+I struggle with the same mindset. I've found the best way to get over it, is to just ship. So, congrats Ms. Holladay on shipping, and congrats on the blog, it's awesome.
diff --git a/themes/cycle/exampleSite/content/post/adam-versus-dropbox-and-oauth.md b/themes/cycle/exampleSite/content/post/adam-versus-dropbox-and-oauth.md
new file mode 100644
index 0000000..db3dee0
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/adam-versus-dropbox-and-oauth.md
@@ -0,0 +1,51 @@
+---
+title: "Adam versus Dropbox and oAuth"
+date: 2012-06-25T03:00:46-04:00
+lastmod: 2015-03-24T13:08:44-04:00
+slug: adam-versus-dropbox-and-oauth
+excerpt: "Adam versus Dropbox and oAuth. Frustration post incoming regarding curl, php, and oAuth.
+"
+---
+
+Frustration post incoming. If you'd like to skip my ranting, [watch this breakdancing bear](http://maxgif.com/8p). Otherwise, let's keep going.
+
+Update: I've posted an [update below](#update).
+
+### Stuck
+
+I've never developed anything using [Dropbox's API](https://www.dropbox.com/developers/reference/api) or [oAuth](http://oauth.net/) before. I'm assuming I'm making a horrible, noobish mistake somewhere in here. There is no official PHP SDK for Dropbox API. There are a couple libraries floating around, but they looked like overkill for the simple app idea I'm working on.
+
+My problem is that when I try to [request a token](https://www.dropbox.com/developers/reference/api#request-token) from Dropbox via PHP and cURL I get an 'Error 4xx'. I've looked at the oAuth specs for the proper parameters to send in the header of the request, and right now my request looks like:
+
+``` 
+
+[request_header] => POST /1/oauth/request_token HTTP/1.1
+Host: api.dropbox.com
+Accept: /
+Authorization: OAuth oauth_consumer_key="CONSUMERKEY", oauth_nonce="1340748835", oauth_signature_method="PLAINTEXT", oauth_timestamp="1340748835", oauth_version="1.0", oauth_signature="CONSUMERSECRET%26"
+Content-Length: -1
+Content-Type: application/x-www-form-urlencoded
+Expect: 100-continue
+```
+
+And this doesn't yield a token, just 'Error 4xx'.
+
+Yet, when I paste in the full request in the address bar of Chrome:
+
+`   https://api.dropbox.com/1/oauth/request_token?oauth_consumer_key=CONSUMERKEY&oauth_nonce=1340743892&oauth_signature_method=PLAINTEXT&oauth_timestamp=1340743892&oauth_version=1.0&oauth_signature=CONSUMERSECRET%26 `
+
+I get my token back no problem. So I'm assuming something is wrong with the format of my cURL request.
+
+The reason I'm using PLAINTEXT as the method is because of [this post](http://forums.dropbox.com/topic.php?id=49346&replies=9#post-373358) in the Dropbox forums. And, like I said, just entering in the request directly works fine.
+
+### Help
+
+Any ideas? Let me know on Twitter [@a\_simpson](http://www.twitter.com/a_simpson). I'll be sure to update this post once I get this problem sorted. So far, the lack of documentation for all this has been frustrating.
+
+### Update
+
+Well I've sorted it out after sleeping on it, and breaking it all down again.
+
+Turns out the cURL options array I was passing was incorrect. I was declaring CURLOPT\_POST =\> true after several other POST-reliant options such as CURLINFO\_HEADER\_OUT and CURLOPT\_POSTFIELDS. This mix-up was causing the request to error out. In retropect I should have realized that right away, oh well. Once I got the order straightened out, the request went through.
+
+However, in my Googling to solve my problem I came across an [awesome post from Wez Furlong](http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl/) detailing how to do HTTP requests in PHP without using cURL or any other library. I'll let you read it, but all I'll say is I switched to the solution he outlines, and I love it.
diff --git a/themes/cycle/exampleSite/content/post/adn-cross-poster.md b/themes/cycle/exampleSite/content/post/adn-cross-poster.md
new file mode 100644
index 0000000..e4b30fb
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/adn-cross-poster.md
@@ -0,0 +1,46 @@
+---
+title: "ADN Cross-poster"
+date: 2013-08-15T03:00:47-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: adn-cross-poster
+excerpt: "How to set up your own App.net to Twitter cross-posting app.
+"
+---
+
+Recently I released a [App.net to Twitter cross-posting app](https://github.com/asimpson/adn-crossposter) that runs via a single [Heroku](https://www.heroku.com/) worker dyno ([which means it's free, gracias Heroku](https://devcenter.heroku.com/articles/usage-and-billing#750-free-dyno-hours-per-app)).
+
+### IFTTT Issues
+
+For awhile I had been using [IFTTT](http://www.adamsimpson.net/ifttt) to crosspost any posts I made on App.net to Twitter, however there were two things I wasn't totally thrilled with.
+
+First, IFTTT automatically converts any links in your App.net post to [bit.ly links](https://bitly.com/), which stinks as I want the links in my intended format and style. The other thing IFTTT did poorly was how it handled posts that were longer than 140 characters. Since App.net posts can be up to 256 characters, sometimes a post will be too long for Twitter, IFTTT would simply chop your post at the 140 character point and be done.
+
+### Features
+
+[ADN-Crossposter](https://github.com/asimpson/adn-crossposter) specifically addresses these two complaints.
+
+First, it leaves links alone. The app simply pushes your post text to Twitter.
+
+Second, the app checks the character count of the App.net post and if it's longer than 140 character it trims the post and adds a link to the App.net post, e.g. a read more link.
+
+### Get the app
+
+[Clone the app](https://github.com/asimpson/adn-crossposter). Add your ADN username to the `config.rb` file. You can also choose how to handle @replies as well.
+
+### Twitter Setup
+
+Since this is something that deals with Twitter there are a few steps involved in getting it up and running with their API. You will need to set up your own app within the [Twitter dev panel](https://dev.twitter.com/). Your Twitter app needs to have *read and write* access to your Twitter account for this to work. Once you have the app created you will need to copy the four OAuth keys into the `config.rb` file.
+
+*You may need to regenerate your keys after changing your app from "Read" to "Read and Write".*
+
+### Heroku Setup
+
+Create a [Heroku app](https://www.heroku.com/) via the Heroku dashboard. Go back to your local git repo and add this Heroku app as a git remote.
+
+### Launch
+
+Run `git push HEROKU_REMOTE master` after committing all the necessary changes to the config.rb file. Heroku will detect what type of app it is automatically. Now set your process or worker dyno to 1 via the Heroku dashboard or the command line, `heroku ps:scale clock=1`
+
+### Wrap Up
+
+That's it. Whew. If for some reason the app isn't working, run `heroku logs` from the command line to see what the error was. If you still have issues, [create an issue on Github](https://github.com/asimpson/adn-crossposter) with any log message you can.
diff --git a/themes/cycle/exampleSite/content/post/ajax-and-rails.md b/themes/cycle/exampleSite/content/post/ajax-and-rails.md
new file mode 100644
index 0000000..cb63fd7
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/ajax-and-rails.md
@@ -0,0 +1,31 @@
+---
+title: "Ajax and Rails"
+date: 2019-01-28T11:25:49-05:00
+lastmod: 2019-01-28T11:25:49-05:00
+slug: ajax-and-rails
+excerpt: "This is just a short post to save a few links and document that \"Server Javascript Responses\" in Rails are still useful in 2018/19."
+---
+
+This is just a short post to save a few links and document that "Server Javascript Responses" in Rails are still useful in 2018/19.
+
+## Lifecycle of SJR
+
+The basic idea behind Server Javascript Responses (SJR) is diagrammed below:
+
+![img](https://adamsimpson.net/images/sjr.png)
+
+SJR works like this:
+
+1.  A User submits a form that has the Rails attribute `remote=true` on the form tag which makes the form submission happen via AJAX. See the [Rails guide](https://guides.rubyonrails.org/working_with_javascript_in_rails.html) for more information.
+
+2.  The server receives the data payload and processes a response.
+
+3.  The Response from the server is a blob of JS *not JSON* that usually comes from a matching `name.js.erb` template.
+
+4.  The User's browser receives the JS blog and evals the JS to update the page.
+
+## Links
+
+1.  [DHH's original post](https://signalvnoise.com/posts/3697-server-generated-javascript-responses)
+2.  [Medium post](https://m.patrikonrails.com/do-you-really-need-that-fancy-javascript-framework-e6f2531f8a38) about eschewing fancy front-end frameworks for SJR
+3.  [Ajax calls the Rails way](https://m.patrikonrails.com/how-to-make-ajax-calls-the-rails-way-20174715d176)
diff --git a/themes/cycle/exampleSite/content/post/alfred-and-web-development.md b/themes/cycle/exampleSite/content/post/alfred-and-web-development.md
new file mode 100644
index 0000000..48afe44
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/alfred-and-web-development.md
@@ -0,0 +1,21 @@
+---
+title: "Alfred and Web Development"
+date: 2012-10-11T03:00:48-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: alfred-and-web-development
+excerpt: "A quick tip on using Alfred in Web Development
+"
+---
+
+Fellow web developer and all around awesome guy [Adam Clark](https://twitter.com/avclark), put together [two](http://thegentlymad.com/2012/09/30/simplify-your-dev-workflow-with-alfred/) [fantastic](http://thegentlymad.com/2012/10/04/easy-wordpress-database-management-with-alfred/) screencasts on his blog which demonstrate the power of [Alfred](http://www.alfredapp.com/) and how to enhance common front-end workflows. Inspired by his post, I thought I would start sharing some tips on how I use Alfred throughout the day.
+
+I use Alfred 57.4 times a day. It's awesome, so awesome that it has replaced Spotlight on my Mac. I have two custom searches that relate directly to front-end development, a [Mozilla Developer Documentation](https://developer.mozilla.org/en-US/) custom search, and a [Can I use](http://caniuse.com/) custom search. These shortcuts allow me to:
+
+1.  Invoke Alfred
+2.  Type "cani" or "mdn" followed by a space.
+3.  Type my query, i.e. "background-size"
+4.  Hit Enter and see the resulting documentation or caniuse page for the query.
+
+Here are the actual URLs as I set them up in Alfred: `https://developer.mozilla.org/en-US/search?q={query}` `http://caniuse.com/#search={query}`
+
+This is a simple thing to setup, and it probably only saves a few seconds, but it feels friction-less which is the whole point of using Alfred.
diff --git a/themes/cycle/exampleSite/content/post/amp-html-terrible-html.md b/themes/cycle/exampleSite/content/post/amp-html-terrible-html.md
new file mode 100644
index 0000000..39af548
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/amp-html-terrible-html.md
@@ -0,0 +1,21 @@
+---
+title: "AMP HTML, Terrible HTML"
+date: 2015-10-08T08:49:01-04:00
+lastmod: 2015-10-08T09:56:38-04:00
+slug: amp-html-terrible-html
+excerpt: "Is the answer developing a subset of HTML/JS/CSS?"
+---
+
+[Seriously](https://github.com/ampproject/amphtml/issues/481), how could this possibly go wrong?\!
+
+[AMP HTML](https://www.ampproject.org/how-it-works/) is another middle finger to publishers and ad companies everywhere, and in the process it throws the baby out with the bath water. Essentially Google is saying to publishers and ad companies, "You can't responsibly handle the power the web gives you. So here's something far more limited. Enjoy."
+
+I agree with the first part, but is the answer developing a subset of HTML/JS/CSS?
+
+![](https://imgs.xkcd.com/comics/standards.png)
+
+## Update
+
+This post explores my misgivings in more detail:
+
+
diff --git a/themes/cycle/exampleSite/content/post/andy-budd-on-time.md b/themes/cycle/exampleSite/content/post/andy-budd-on-time.md
new file mode 100644
index 0000000..6e7acef
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/andy-budd-on-time.md
@@ -0,0 +1,12 @@
+---
+title: "Andy Budd on Time"
+date: 2013-01-10T03:00:48-05:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: andy-budd-on-time
+excerpt: "Great quote by Andy Budd on the value of time
+"
+---
+
+Fantastic [Pastry Box post](http://the-pastry-box-project.net/clearleft/2013-january-7/) from Andy Budd, I'll quote the final thought here, but it's worth it to read the [entire thing](http://the-pastry-box-project.net/clearleft/2013-january-7/)
+
+> The best designers and developers rarely have more talent. They simply have more time.
diff --git a/themes/cycle/exampleSite/content/post/app_store_moment_of_clarity.md b/themes/cycle/exampleSite/content/post/app_store_moment_of_clarity.md
new file mode 100644
index 0000000..84c47ee
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/app_store_moment_of_clarity.md
@@ -0,0 +1,24 @@
+---
+title: "A Moment of Clarity Regarding the Raison d’Etre for the App Store"
+date: 2020-07-13T14:10:09-04:00
+lastmod: 2020-07-13T14:10:09-04:00
+slug: app_store_moment_of_clarity
+excerpt: ""
+link: "https://daringfireball.net/2020/07/app_store_moment_of_clarity"
+---
+
+> I’d like to see all the vim, vigor, and vigilance Apple applies to making sure no app on the App Store is making a dime without Apple getting three cents applied instead to making sure there aren’t any scams or ripoffs, and that popular apps support good-citizen-of-the-platform features within a reasonable amount of time after those features are introduced in the OS. I don’t know exactly how long “reasonable” is, but five fucking years for split-screen support ain’t it.
+
+I've been thinking the same thing ever since the Hey app rejection right before WWDC. The App Store is supposed to be a place to get software that has been vetted by Apple but there seems to be a growing disconnect between what users imagine that vetting is and what Apple is doing.
+
+I want to believe this tweet by Ben Evans is the goal of the App Store:
+
+
+
+If we can trust the apps that come out of the App Store:
+
+- why is the US considering banning TikTok because of its rampant data collection?
+- why do we need a new notification in iOS 14 when apps query the clipboard?
+- why do we need a microphone/camera indicator at the system level?
+
+Maybe I was naive and alone in my assumption that Apple would root this stuff out during the review process. If they're not rooting this out then what is the point of the review process at all?
diff --git a/themes/cycle/exampleSite/content/post/apple-on-batteries-and-performance.md b/themes/cycle/exampleSite/content/post/apple-on-batteries-and-performance.md
new file mode 100644
index 0000000..75f18d6
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/apple-on-batteries-and-performance.md
@@ -0,0 +1,17 @@
+---
+title: "Apple on batteries and performance"
+date: 2017-12-28T18:11:14-05:00
+lastmod: 2017-12-28T18:11:14-05:00
+slug: apple-on-batteries-and-performance
+excerpt: "Apple released a statement on the battery and performance issues."
+---
+
+Apple [released a statement](https://www.apple.com/iphone-battery-and-performance/) on the battery and performance issues.
+
+> Apple is reducing the price of an out-of-warranty iPhone battery replacement by $50 — from $79 to $29 — for anyone with an iPhone 6 or later whose battery needs to be replaced, starting in late January and available worldwide through December 2018. Details will be provided soon on apple.com.
+
+This is the penalty for not being clear with users. How and why did Apple make this so opaque? It continues to baffle me.
+
+> Early in 2018, we will issue an iOS software update with new features that give users more visibility into the health of their iPhone’s battery, so they can see for themselves if its condition is affecting performance
+
+This is what should have been in iOS when the processor management feature was released.
diff --git a/themes/cycle/exampleSite/content/post/automating-socks-proxy.md b/themes/cycle/exampleSite/content/post/automating-socks-proxy.md
new file mode 100644
index 0000000..90c74d9
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/automating-socks-proxy.md
@@ -0,0 +1,28 @@
+---
+title: "Automating SOCKS proxy"
+date: 2015-08-08T13:11:13-04:00
+lastmod: 2017-02-24T09:41:13-05:00
+slug: automating-socks-proxy
+excerpt: "I've used a SOCKS proxy while on public WiFi ever since reading Paul Stamatiou's article years ago. I only recently took the time to automate the process."
+---
+
+I've used a SOCKS proxy while on public WiFi ever since reading [Paul Stamatiou's article](http://paulstamatiou.com/how-to-surf-securely-with-ssh-tunnel) years ago. I recently took the time to automate the setup process.
+
+Paul's article provides a good overview of what the heck a SOCKS proxy is and why it's beneficial, so I won't focus on any of that here. Just know that setting up a SOCKS proxy on a Mac is a multi-step process. This process led me to create [two bash functions](https://github.com/asimpson/dotfiles/blob/master/bash/functions#L10-L17); one to start it and another to shut it down.
+
+    function tunnel_off {
+      PID="$(ps aux | grep $1 | grep -v grep | awk '{print $2}')";
+      kill ${PID} && networksetup -setsocksfirewallproxystate Wi-Fi off;
+    }
+    
+    function tunnel {
+      ssh -D 8080 -f -q -N $1 && networksetup -setsocksfirewallproxystate Wi-Fi on
+    }
+
+I do need to pass the ssh server name (configured in `~/.ssh/config`) I want to use, e.g. `tunnel vpn`.
+
+The only setup is to manually configure which port I want to use for the SOCKS proxy, I set that in System Preferences under Network: ![](/images/socks-proxy-config.jpg)
+
+The best part is the `networksetup -setsocksfirewallproxystate` [command](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/networksetup.8.html). This command makes the whole thing go by toggling the proxy on and off.
+
+For extra credit, I use the fantastic [TextBar](http://www.richsomerfield.com/apps/) utility to monitor if the ssh connection is active and [display the lightning emoji](https://github.com/asimpson/dotfiles/blob/master/tmux/tunnel-status.sh) in my menu bar if it is. I now know when the proxy is running or not by glancing up at the menubar.
diff --git a/themes/cycle/exampleSite/content/post/balancing-devotion.md b/themes/cycle/exampleSite/content/post/balancing-devotion.md
new file mode 100644
index 0000000..07c1b86
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/balancing-devotion.md
@@ -0,0 +1,34 @@
+---
+title: "Balancing Devotion"
+date: 2012-07-17T03:00:50-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: balancing-devotion
+excerpt: "Is it possible to create an extraordinary product and have a healthy life outside of that proudct?
+"
+---
+
+After watching [Indie Game: The Movie](http://buy.indiegamethemovie.com/) I couldn't help but think of the Robert Louis Stevenson quote that [Shawn Blanc used](http://shawnblanc.net/2012/07/on-time-management/) a few weeks ago:
+
+> Perpetual devotion to what a man calls his business, is only to be sustained by perpetual neglect of many other things.
+
+In the movie, the game designers and developers pour their lives into creating these games. At one point in the movie, the creator of [Fez](http://polytroncorporation.com/61-2) said he would literally kill himself if he were unable to finish and release it. Thankfully, he released Fez in 2012 to wide acclaim. Despite his success, his quote still bothers me. Suicide over a game?\! I don't get it.
+
+[Matthew Smith](http://squaredeye.com/) of [Zaarly](http://www.zaarly.com/), recently wrote for the [Pastry Box Project](http://the-pastry-box-project.net/matthew-smith/2012-july-2/):
+
+> Turn off your phone when you get home. Off. Don't just put it on the counter. Turn it off for a few hours at least each day. Why? So that you’re not always available to others. Be available to yourself. Be available to your family. Then at 8am when you turn your phone back on, you can be fully available and totally present.
+
+Matthew is talking about disconnecting from the interewbs in order to recharge, and be a better son/father/daughter/wife/mother/roommate/friend/neighbor/whatever. I struggle with disconnecting, while I don't have the same intensity as suicide over a game, it's the same kind of devotion, and I know how easily it creeps in.
+
+This all makes me wonder if it is possible to create something truly extraordinary without causing everything else to wither? In one of the most recent entries on [The Pastry Box](http://the-pastry-box-project.net/molly-holzschlag/2012-july-17/), Molly Holzschlag tries to answer this question.
+
+> Here’s some advice from the heart: There is nothing wrong with giving your life to an ideal. I have done it, and the rewards are rich— friends from all over the world, respect from my peers, to have traveled much of the earth and been made welcome upon it—that is the miraculous part of giving your work your all, it comes back. Just don’t let what happened to me happen to you—the work, the ideal takes over too young and for too long, and you could easily end up childless or without family, with little or no life structure or real measure of how to reconcile this elusive balance.
+
+She acknowledges that to achieve something extraordinary you have to devote yourself to it. Her solution is to not devote yourself for so long that you are left with nothing. That's the trick.
+
+I think there has to be a better way than planning to "wake up" before your 30s are gone. As I was writing this post yesterday, [Jack McDade posted a short note](http://jackmcdade.com/asides/learning-to-switch-off) that was exactly what I was trying to say. He wrote:
+
+> So how do you "switch off"? It's not hard when you have perspective. You just switch off. Boy does it feel great.
+
+Hes got it. There isn't a secret way to achieve both a great product and a healthy life outside of it. I believe it's possible to do both, *not* keeping them in balance is just much easier. Keeping that balance is a constant struggle, it's a fight, it's learning how to say "no" at the right times, it's turning your phone off when you get home. Hell, merely going home at 5 or 6 helps the balance.
+
+To keep it all in balance, you just have to do it.
diff --git a/themes/cycle/exampleSite/content/post/bash-function-ip-address-to-clipboard.md b/themes/cycle/exampleSite/content/post/bash-function-ip-address-to-clipboard.md
new file mode 100644
index 0000000..af03ed2
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/bash-function-ip-address-to-clipboard.md
@@ -0,0 +1,18 @@
+---
+title: "Bash Function - IP Address to Clipboard"
+date: 2012-12-05T03:00:51-05:00
+lastmod: 2015-03-24T13:11:31-04:00
+slug: bash-function-ip-address-to-clipboard
+excerpt: "A quick post explaining a command line function to copy your IP address to your clipboard
+"
+---
+
+I have to admit, I am addicted to customizing my [bash](http://en.wikipedia.org/wiki/Bash_\(Unix_shell\)) experience. Yesterday, I came up with a little, one-off function that smooths over a point of friction in my workflow – working with my internal IP address.
+
+During any project, I am often testing in virtual machines. On my development machine I have my [host file hacked](http://adamsimpson.net/writing/a-few-bash-tips) to manage all the dev URLs. The friction point is constantly having to look up my IP address to test in VMs, or on other devices. This bash function simply parses out my IP address from the results of 'ifconfig' and copies that IP address to my clipboard. Now, instead of jumping into the Network pane to see my IP, or reading through ifconfig myself, I can simply type "ip", and jump back to my VM and paste in the address. The function also displays the IP address on the command line ready for easy typing into a mobile device.
+
+    function ip {
+      IP=$(ifconfig | grep 'inet 1' | cut -c 6- | awk 'NR==2 {print $1}')
+      echo $IP
+      echo $IP | pbcopy
+    }
diff --git a/themes/cycle/exampleSite/content/post/be-a-good-video-call-citizen.md b/themes/cycle/exampleSite/content/post/be-a-good-video-call-citizen.md
new file mode 100644
index 0000000..f6ff610
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/be-a-good-video-call-citizen.md
@@ -0,0 +1,27 @@
+---
+title: "Be a good video call citizen"
+date: 2017-03-17T09:58:29-04:00
+lastmod: 2017-03-17T11:18:27-04:00
+slug: be-a-good-video-call-citizen
+excerpt: "I've been in my fair share of video calls and I thought I'd share a few tricks that help limit my contributions to the chaos."
+---
+
+Ah the [video call](https://www.youtube.com/watch?v=DYu_bGbZiiQ). Usually fraught with 5 minutes of "Can you hear me now?", distorted faces, or [your two children](https://twitter.com/JOE_co_uk/status/840165524038377472) in the background. I've been in my fair share of video calls and I thought I'd share a few tricks that help limit my contributions to the chaos.
+
+## Be a few minutes early.
+
+If you're there early you can get any hiccups (technical or otherwise) out of the way before the meeting actually starts. No fancy technical trick here.
+
+## Keep your workspace neat
+
+Again, not a technical solution but a practical one. Limit the distractions you may present by having a tidy workspace. Pay special attention to what's behind you before you get on a call. Everyone's been laughing at [poor Professor Kelly](https://medium.com/@benthompson/breaking-down-the-father-on-bbc-being-interrupted-by-his-children-9840cdc8857b#.akw0oxqef) recently but notice that he clearly spent some time before the call trying to make his background look good.
+
+## Use a [cough button](https://en.wiktionary.org/wiki/cough_button) (aka push-to-talk)
+
+I love the [Shush app](http://mizage.com/shush/). It works at the system level to mute or unmute your microphone and binds that action to a hotkey. Shush is fantastic because you don't need to remember where each video service stashes its mute button. The ability to quickly toggle mute is a super power that goes a long way towards minimizing any distractions you may create while on the call.
+
+There you have it, my top three tips for video calls. Do you have any other tips? Let me know about them on [twitter](https://twitter.com/a_simpson) and I'll list them below.
+
+## Replies
+
+
diff --git a/themes/cycle/exampleSite/content/post/before-circles-2017.md b/themes/cycle/exampleSite/content/post/before-circles-2017.md
new file mode 100644
index 0000000..c8eda13
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/before-circles-2017.md
@@ -0,0 +1,37 @@
+---
+title: "Before Circles 2017"
+date: 2017-09-06T11:52:29-04:00
+lastmod: 2017-09-06T11:52:29-04:00
+slug: before-circles-2017
+excerpt: "I thought I'd list out a few of the talks I'm looking forward to and what I hope to come away with."
+---
+
+I'm currently sitting on an airplane headed to Grapevine, Texas for [Circles Conf](http://circlesconference.com). Circles Conf is a design conference that I've kept an eye on for the last couple years. I specifically chose this conference because it wasn't a development conference. As a frontend developer, I think it's important to be well-rounded in all aspects of the frontend and that includes design. I feel like the last couple years I've invested deeply in Javascript and all the incredible ways frontend code is changing. However, I think it's time to work out a different set of muscles. So, I'm headed to a design conference as a frontend developer and I don't see a single talk about "Slack bots with Node" (or something about "Serverless and React") on the schedule and I'm super pumped.
+
+## Expectations
+
+I thought I'd list out a few of the talks I'm looking forward to and what I hope to come away with. I think the entire lineup looks great but there are a few TBA slots with no title so I have no idea what to think about those. I'm hoping to review this post after the conference and use it as a kind of guide to digest everything that happened.
+
+### Panels
+
+I have no idea what to expect from the scheduled Panels. There is one each day maybe this will be some solid Q/A or good round-table discussion?
+
+### Dan Rubin
+
+I'm excited to hear [Dan Rubin](https://instagram.com/danrubin). I've followed Dan on Twitter and Instagram for some time but I've never heard him speak.
+
+### Ash Huang
+
+I've never heard of [Ash](http://ashsmash.com/) until I saw the speaker line-up, but she's seems like a prolific writer and deep thinker. Her talk is called "Design was supposed to be The Answer" and I can't wait to hear it. I also think there is a talk called "Javascript was supposed to be The Answer" just waiting to be written.
+
+### Jay Argaet
+
+I'm a fan of [Hillsong's music](https://hillsong.com/united/) along with their branding and art direction. I'm curious to hear what [Jay](http://hillsong.com/contributor/jay-argaet/) has to say about "Unlocking Creativity".
+
+### Annette Neu
+
+The topic for [Annette's](http://handsome.is/) talk resonates with me. I often feel unsure how to begin on a problem that has lots of uncertainty surrounding it. I'm confident this will apply to *all* creative disciplines (e.g. development as well as design).
+
+## Here we go
+
+So there you have it. My scant expectations on what I'm looking forward to at Circles Conf. If you're attending Circles don't hesitate to say hi (or hit me up on [twitter](https://twitter.com/a_simpson)) and get a swanky [Sparkbox](https://seesparkbox.com) business card\!
diff --git a/themes/cycle/exampleSite/content/post/benedict-evans-in-on-fire.md b/themes/cycle/exampleSite/content/post/benedict-evans-in-on-fire.md
new file mode 100644
index 0000000..b5f997e
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/benedict-evans-in-on-fire.md
@@ -0,0 +1,27 @@
+---
+title: "Benedict Evans is on fire"
+date: 2015-05-18T11:51:04-04:00
+lastmod: 2015-05-25T00:54:17-04:00
+slug: benedict-evans-in-on-fire
+excerpt: "Benedict Evan's last three pieces are right on the money regarding mobile, and the web versus native apps."
+---
+
+I've been behind my [pinboard](https://pinboard.in/u:asimpson/) unread queue for a few days and consequently have been missing the truth pouring out of [Benedict Evans](http://www.twitter.com/benedictevans).
+
+His last *three* pieces are right on the money regarding mobile, and the web versus native apps.
+
+Starting with [Mobile First](http://ben-evans.com/benedictevans/2015/5/14/mobile-first), he says:
+
+> \[...\]the smartphone itself is an internet platform in a way that a PC was not. On a PC the web browser was the internet platform, but on a smartphone it's the entire device and the browser is turned from 'the internet' to one icon, just a phone calls turned from the purpose of the device to just one icon.
+
+Then in [Apps versus the web](http://ben-evans.com/benedictevans/2015/5/14/apps-versus-the-web) he finishes the piece by saying:
+
+> In either of these cases - whether you have an app and a website or just a website, you should presume that your customers will engage with you only on mobile.
+
+And finally his last piece [The future is mobile and apps, except that it isn't](http://ben-evans.com/benedictevans/2015/5/17/the-future-is-mobile-and-apps-except-that-it-isnt) he writes:
+
+> So the mobile experience needs to be complete. That might, paradoxically, mean that your total experience might need to be edited, to fit, but it's dangerous to pick a subset of your offer and put just that on mobile - it might be your only touch point. Conversely, **one could argue** that in some cases it's the desktop experience that should be a subset of the mobile one.
+
+## Complete
+
+The mobile experience needs to be complete, and that experience can be just a website, or just an app, or both. Regardless it needs to be complete. Complete is the operative word that binds these thoughts together. [As we saw last week](http://adamsimpson.net/writing/web-performance-and-facebooks-instant-articles), complete includes performance, especially performance on mobile.
diff --git a/themes/cycle/exampleSite/content/post/better-scripting-with-gh.md b/themes/cycle/exampleSite/content/post/better-scripting-with-gh.md
new file mode 100644
index 0000000..eaa9a8e
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/better-scripting-with-gh.md
@@ -0,0 +1,66 @@
+---
+title: "Better scripting with gh"
+date: 2023-07-22T11:33:16-0400
+lastmod: 2023-07-22T11:49:30-0400
+slug: better-scripting-with-gh
+excerpt: "I've become a big fan of the gh CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts."
+---
+
+I've become a big fan of the [gh](https://cli.github.com/) CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. Instead of using `curl` with a Github token and the Github API, I can simply use `gh`. What's even better is that in more advanced situations where there isn't a valid subcommand for what I want to script, I can use the [`gh api`](https://cli.github.com/manual/gh_api) escape hatch to do `curl`-style HTTP requests to the API without messing with authentication or even pagination. Here are two recent scripts I wrote that highlight the power and convenience of `gh`.
+
+## PR Kudos
+
+I created this script to help me give better kudos to folks in our retro meeting. When I provide a Github team name as an argument, it displays all PRs from members of that team. What I really like is that it only shows PRs from the last two weeks, which gives me a nice overview of recent activity.
+
+```bash
+#!/bin/bash
+
+start=$(date -d "2 weeks ago" +%Y-%m-%d)
+end=$(date +%Y-%m-%d)
+
+details=$(gh api /orgs/grafana/teams/$1 | jq -r '"\(.id),\(.organization.id)"')
+teamId=$(echo ${details} | cut -d , -f 1)
+orgId=$(echo ${details} | cut -d , -f 2)
+
+gh api "organizations/${orgId}/team/${teamId}/members" | \
+  jq -r '.[] | .login' | \
+  xargs -I % gh search prs --author=% --created="${start}..${end}" \
+  --json="state,repository,url,title,updatedAt,author" --template '{{range .}}{{tablerow (.author.login | autocolor "green") (hyperlink .url .title) (.repository.name | autocolor "blue") (.state | autocolor "red") (timeago .updatedAt)}}{{end}}
+{{tablerender}}'
+```
+
+## Notification OCD
+
+The second script focuses on managing notifications related to pull requests and issues. I usually find that about one-third of my notifications are for merged PRs, PRs created by bots, or closed Issues. I don't care about these types of events. With this script, I can mark those notifications as done, which reduces clutter in my GitHub notifications and helps me see important updates. As I mentioned above, one cool feature of the `api` subcommand is that it allows me to consume all possible pages of a response using the `--paginate` flag, eliminating the need for a loop + token field dance!
+
+```bash
+#!/bin/bash
+declare -A typeLookup
+typeLookup["PullRequest"]="pull"
+typeLookup["Issue"]="issues"
+
+resp=$(gh api /notifications --paginate | jq -r '.[] | select(.subject.type == "PullRequest" or .subject.type == "Issue") | "\(.repository.full_name),\(.subject.url),\(.id),\(.subject.type)"')
+
+for x in $resp; do
+  name=$(echo "${x}" | cut -d ',' -f 1)
+  id=$(echo "${x}" | cut -d ',' -f 3)
+  number=$(basename $(echo "${x}" | cut -d ',' -f 2))
+  ofType=$(echo "${x}" | cut -d ',' -f 4)
+  urlType=$(echo ${typeLookup["${ofType}"]})
+  isBot="false"
+
+  if [ "${ofType}" == "PullRequest" ]; then
+    isMerged=$(gh pr view --repo "${name}" "${number}" --json closed | jq -r .closed)
+    isBot=$(gh pr view --repo "${name}" "${number}" --json author | jq -r .author.is_bot)
+  fi
+
+  if [ "${ofType}" == "Issue" ]; then
+    isMerged=$(gh issue view --repo "${name}" "${number}" --json closed | jq -r .closed)
+  fi
+
+  if [ "${isMerged}" == "true" ] || [ "${isBot}" == "true" ]; then
+    echo "marking https://github.com/${name}/${urlType}/${number} as done..."
+    gh api -X PATCH "/notifications/threads/${id}"
+  fi
+done
+```
diff --git a/themes/cycle/exampleSite/content/post/blog-rewrite.md b/themes/cycle/exampleSite/content/post/blog-rewrite.md
new file mode 100644
index 0000000..f716923
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/blog-rewrite.md
@@ -0,0 +1,80 @@
+---
+title: "Blog rewrite"
+date: 2018-11-20T23:01:04-05:00
+lastmod: 2018-11-20T23:02:21-05:00
+slug: blog-rewrite
+excerpt: "I haven't posted here recently. That's largely because I did the classic \"Time to rewrite the blog, I'll post when it's done\" thing. Well it's not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I'm trying to rectify that now with some scant and scattered sentences."
+---
+
+I haven't posted here recently. That's largely because I did the classic "Time to rewrite the blog, I'll post when it's done" thing. Well it's not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I'm trying to rectify that now with some scant and scattered sentences.
+
+## Current setup
+
+The blog is currently built using a custom Node app that lives inside a few [AWS lambda functions](https://aws.amazon.com/lambda/).
+
+To begin with I created my own auth system (insert eyeroll emoji I know) which works like this:
+
+![Image depicting the AWS Lambda system that provides authentication for my blog.](/images/lambda-auth.png)
+
+Once the user is authenticated they can create posts which looks like this:
+
+![Image depicting the various stages of the AWS Lambda system that creates posts.](/images/lambda-blog.png)
+
+### Benefits
+
+The benefits of my current setup are:
+
+1.  Entirely static.
+2.  No server to maintain.
+3.  Provides ability to post from my phone using the /admin interface in the browser.
+
+### Drawbacks
+
+The things pushing me to consider a re-write, are:
+
+1.  Local development is *hard*. The site generation is very tightly coupled to Lambda. There is no local server option for /admin.
+2.  Because of its disorganized nature it's getting harder to maintain and add features (high microservices :wave:).
+3.  Fully reliant on AWS stack (Lambda, DynamoDB, Cognito, S3, CloudFront, Certificates, Route53).
+
+## Where do I want to go?
+
+I'm thinking of moving towards what I call "The Jekyll model": an engine to build the site. I could then combine that engine with the following functionality to fill in the gaps:
+
+1.  Mobile publishing via SFTP of markdown files to a VPS/home server.
+2.  [Use a file system watcher](https://en.wikipedia.org/wiki/Inotify) to trigger new builds when a new post is uploaded/changed.
+3.  Built site is uploaded to Netlify, S3, or Github pages. Keep it static.
+
+Going this route addresses all the Drawbacks but introduces a server to maintain. I'm OK with that change if I can iterate on design changes quicker than I can now, did I mention how painful that is currently? The one aspect of this I don't have solved completely is post metadata (remember currently I'm using SQLite as my DB). I'm not a huge fan of the front-matter + markdown file approach because I'd rather have my data in a more standard data structure, e.g. a JSON file per post or something. If I go with a JSON file per post then I need to create something to generate that file upon post creation or modification. The other option is to keep using SQLite I guess.
+
+![Image outlining how a potential new system would work for the blog.](/images/new-process.png)
+
+### The Engine
+
+The above *should* work. I just need something that consumes markdown and can match my existing URL scheme. I've ping-ponged back and forth between the following options:
+
+  - Common Lisp
+    
+    I initially thought I would build out the engine myself in Common Lisp (to get more experience in CL). Part of the draw of Common Lisp was that I could create an executable and send that to the server and not have to install a bunch of dependencies just to get it to run. However the lack of a markdown library that supports [code-fencing](https://help.github.com/articles/creating-and-highlighting-code-blocks/) (which I use extensively) has killed the idea (and my spirit).
+
+  - Jekyll/Hugo/Gatsby
+    
+    I toyed with just using Jekyll/Hugo but I would have to convert *every* post to MD + front matter. That sounded like a pain. I've also thought about using GatsbyJS but that introduces a ton of new tech that my site doesn't need.
+
+  - Node
+    
+    I don't really want to do Node again because:
+    
+    1.  I've done a *lot* of Node recently
+    2.  Requires installing dependencies and language runtime on server.
+
+  - Emacs
+    
+    This one is the craziest idea I've had. Use an [Emacs docker container](https://github.com/Silex/docker-emacs) + org-mode + [some command line magic](https://stackoverflow.com/a/48121525/2344737) to have Emacs with org-mode be responsible for publishing the HTML for my site.
+
+  - Rust
+    
+    I'm currently considering upping my fledgling Rust game and writing my engine in Rust. I can then create a binary and ship that to a server. And yes, before anyone asks I already checked and there are several solid looking markdown crates (libraries).
+
+## Now what?
+
+I have no idea where this leaves me. This post has been a thinking/documentation exercise for me more than a post. I think I'll keep exploring the Rust option and see where that leads me.
diff --git a/themes/cycle/exampleSite/content/post/blogs-data-and-social-networks.md b/themes/cycle/exampleSite/content/post/blogs-data-and-social-networks.md
new file mode 100644
index 0000000..7c6b6cb
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/blogs-data-and-social-networks.md
@@ -0,0 +1,30 @@
+---
+title: "Blogs, data, and social networks"
+date: 2012-08-19T03:00:51-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: blogs-data-and-social-networks
+excerpt: "I bring together a few different voices to illustrate the argument for blogs, open data, and open social networks.
+"
+---
+
+[Anil Dash](http://dashes.com/anil/about.html) wrote a [piece last week](http://dashes.com/anil/2012/08/stop-publishing-web-pages.html) advocating for a transition from "page-centric" publishing platforms to "stream-centric". He points to services such as Twitter, Facebook, and even Tumblr as examples for why stream-based publishing platforms are the future. His observation that the only reason the "old page model" is still around is because of advertising is spot-on and well said.
+
+However, Dash misses on one big point in his post, he writes:
+
+> So: Start publishing streams. Start moving your content management system towards a future where it outputs content to simple APIs, which are consumed by stream-based apps that are either HTML5 in the browser and/or native clients on mobile devices.
+
+These APIs already exist, we call them RSS. We don't need a ton of VC money, and developers and designers to solve this problem; it's already solved. What we need are those designers and developers to start creating tools that work on top of the existing RSS/Atom layer.
+
+After reading Dash's article, I stumbled across [Scott Hanselman's](http://www.hanselman.com/blog/AboutMe.aspx) [post on blogging](http://www.hanselman.com/blog/YourWordsAreWasted.aspx). He starts off with a bang, and I'll just post it here,
+
+> You are not blogging enough. You are pouring your words into increasingly closed and often walled gardens. You are giving control - and sometimes ownership - of your content to social media companies that will SURELY fail. These companies are profoundly overvalued, don't care about permalinks, don't make your content portable, and have terms of service that are so complex and obtuse that there are entire websites dedicate to explaining them.
+
+Interesting uh? This blog right here is mine; I own the content, the URL, the design, everything. I have structured it so that each item has a permanent link for people to save, retweet, share, whatever. I don't have to worry about this great service I use being bought by someone else and killed off as a "talent acquisition". I still use Twitter of course, and I have an app.net account, but the "important" pieces of data, flow from this blog to those streams.
+
+Scott ends his post by asking a simple question:
+
+> You want control? Buy a domain and blog there.
+
+He's right. Start blogging, and start re-thinking how that blog looks and functions. Mr. Dash is right too, streams are the better way to go, the beauty of it is that blogs can easily be streams. I know I have a couple ideas that I want to experiment with right here in the coming months.
+
+So get to it, start a blog. Make something, stop whining, and enjoy the incredible era we live in.
diff --git a/themes/cycle/exampleSite/content/post/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels.md b/themes/cycle/exampleSite/content/post/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels.md
new file mode 100644
index 0000000..b4c5c14
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels.md
@@ -0,0 +1,14 @@
+---
+title: "Britain goes coal free as renewables edge out fossil fuels"
+date: 2020-06-30T13:09:40-04:00
+lastmod: 2020-06-30T13:09:40-04:00
+slug: britain-goes-coal-free-as-renewables-edge-out-fossil-fuels
+excerpt: ""
+link: "https://www.bbc.com/news/science-environment-52973089"
+---
+
+> Britain is about to pass a significant landmark - at midnight on Wednesday it will have gone two full months without burning coal to generate power.
+
+> A decade ago about 40% of the country's electricity came from coal; coronavirus is part of the story, but far from all.
+
+This is fascinating. The UK has been aggressively investing in renewable energy sources for years and it appears all that investment is starting to catch up with demand.
diff --git a/themes/cycle/exampleSite/content/post/broadcast-channel.md b/themes/cycle/exampleSite/content/post/broadcast-channel.md
new file mode 100644
index 0000000..380417f
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/broadcast-channel.md
@@ -0,0 +1,10 @@
+---
+title: "Broadcast channel"
+date: 2014-04-08T03:00:52-04:00
+lastmod: 2015-03-21T19:45:36-04:00
+slug: broadcast-channel
+excerpt: "Along with the move to Siteleaf I've also set up an App.net Broadcast channel.
+"
+---
+
+Along with the [move to Siteleaf](/writing/moved-to-siteleaf/) I've also set up an [App.net Broadcast channel](http://app.net/c/207j). The Broadcast channel fires off a push notification to your iOS or Android device whenever I publish a new post. You can also subscribe via e-mail if you wish.
diff --git a/themes/cycle/exampleSite/content/post/casperjs-node-and-the-raspberry-pi.md b/themes/cycle/exampleSite/content/post/casperjs-node-and-the-raspberry-pi.md
new file mode 100644
index 0000000..15ca028
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/casperjs-node-and-the-raspberry-pi.md
@@ -0,0 +1,35 @@
+---
+title: "CasperJs, Node, and the Raspberry Pi"
+date: 2015-10-10T19:16:59-04:00
+lastmod: 2015-10-20T10:06:01-04:00
+slug: casperjs-node-and-the-raspberry-pi
+excerpt: "I've been working on getting my Raspberry Pi to be a dedicated screen-scraping machine with CasperJS and Node.
+
+This post is intended to be a log for myself and hopefully a helpful resource for others."
+---
+
+So I've been working on a pet project today, getting my Raspberry Pi to be a dedicated screen-scraping machine.
+
+I'm still in the middle of getting things working, so I'll be updating this post as I figure more stuff out. This post is intended to be a log for myself and hopefully a helpful resource for others.
+
+## Boot Image
+
+I'm using the [Raspbian Jessie image](https://www.raspberrypi.org/downloads/raspbian/) provided by Raspberry Pi. To create and backup my SD card images I'm using the excellent [ApplePi Baker](http://www.tweaking4all.com/hardware/raspberry-pi/macosx-apple-pi-baker/) app. It provides a GUI wrapper around some gnarly command line tools to flash images to the Raspberry Pi SD card.
+
+## Installing Node
+
+[This post](http://blog.wia.io/installing-node-js-v4-0-0-on-a-raspberry-pi/) by [Conall Laverty](https://twitter.com/ConallLaverty) shows exactly how to get node and npm up and running on a Pi. I tried using the `apt-get` manager like I do with a VPS and the Pi wasn't liking it.
+
+## Installing CasperJS and Phantom
+
+Another [helpful post](https://quaintproject.wordpress.com/2015/04/26/how-to-install-casperjs-on-the-raspberry-pi/) by [Alexander Bilz](http://alexbilz.com) shows how to get casperjs and a specialized version of phantomjs working on the Pi.
+
+I've run into issues with the 1.9.8 version of phantom compared to the 2.0 version on my laptop. Finding a compiled binary of 2.0 has proven to be quite difficult. So I'm on hold for now until I can get a 2.0 version running.
+
+## Troubleshooting
+
+Since I'm using my Pi headless, I'm configuring everything over ssh. Sometimes this just doesn't work well. I've found VNC to be a nice solution in those cases. [This post](http://gettingstartedwithraspberrypi.tumblr.com/post/24142374137/setting-up-a-vnc-server) has simple instructions for getting a VNC server up and running on your Pi. I use [Chicken VNC](http://sourceforge.net/projects/chicken/) as the client on my Mac to connect to the Pi's server.
+
+## Speed
+
+The Pi is slow. *Really* slow. I've found adding some `casper.wait`s to my code have helped iron out some random errors.
diff --git a/themes/cycle/exampleSite/content/post/command-line-notification.md b/themes/cycle/exampleSite/content/post/command-line-notification.md
new file mode 100644
index 0000000..2cd7eb7
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/command-line-notification.md
@@ -0,0 +1,13 @@
+---
+title: "Command line notification"
+date: 2016-01-16T15:40:26-05:00
+lastmod: 2016-01-16T15:40:26-05:00
+slug: command-line-notification
+excerpt: "This week I wrote a bash function that curls the SendGrid API and sends a Boxcar notification."
+---
+
+This week I wrote a [bash function](https://github.com/asimpson/dotfiles/blob/master/bash/functions#L10) that `curls` the [SendGrid API](https://sendgrid.com/pricing) and sends a [Boxcar](https://boxcar.io) notification. This is useful to chain to the end of long-running commands, e.g. [transcoding a video](https://github.com/donmelton/video_transcoding). When the command finishes I get a push notification on my phone.
+
+If you're unfamiliar with the various ways to chain commands together in bash, [here's a cheatsheet](http://askubuntu.com/a/539293). One thing I didn't know is that you can *combine* the various operators like `long-running command || alert "failure!" && alert "success!"`.
+
+Happy scripting.
diff --git a/themes/cycle/exampleSite/content/post/compose-key-and-i3.md b/themes/cycle/exampleSite/content/post/compose-key-and-i3.md
new file mode 100644
index 0000000..fe626d9
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/compose-key-and-i3.md
@@ -0,0 +1,35 @@
+---
+title: "Compose key and i3"
+date: 2020-09-18T11:28:19-0400
+lastmod: 2020-09-18T11:28:19-0400
+slug: compose-key-and-i3
+excerpt: "Here's how to bind the compose key to caps lock in i3wm."
+---
+
+The [compose key](https://en.wikipedia.org/wiki/Compose_key) on Linux and other systems enables you to enter symbols like ™ that don't have a dedicated key on most keyboards. GNOME makes this [easy to do via Gnome Tweaks](https://help.gnome.org/users/gnome-help/stable/tips-specialchars.html.en). However, using a window manager like i3 means there's no dedicated GUI for changing the hotkey for compose.
+
+[This stackexchange answer](https://unix.stackexchange.com/a/195160/41593) sent me down the right path of adding the following config to `~/.Xmodmap` to bind Caps lock to compose:
+
+```ini
+.keysym 66 = Mode_switch
+clear Lock
+```
+
+You can then enable the key map by running:
+
+```shell
+xmodmap ~/.Xmodmap
+```
+
+However, that config didn't work because `Mode_switch` wasn't the right name for the compose key (at least under Ubuntu/PopOS 20 for me). The [Arch Wiki states](https://wiki.archlinux.org/index.php/Xorg/Keyboard_configuration#Configuring_compose_key) that the name for the compose key is actually `Multi_key`. With this new name I was able to get Caps lock to act as the compose key by updating the config in `~/.Xmodmap` to:
+
+```ini
+keycode 66 = Multi_key
+clear Lock
+```
+
+The final step is to set that mapping every time i3 runs by putting this inside your [i3 config file like so](https://github.com/asimpson/dotfiles/commit/c86e4216e09e940c2cf7126581e8e69b95fe1511):
+
+```shell
+exec --no-startup-id "xmodmap ~/.Xmodmap"
+```
diff --git a/themes/cycle/exampleSite/content/post/confessions-marcus-hutchins-hacker-who-saved-the-internet.md b/themes/cycle/exampleSite/content/post/confessions-marcus-hutchins-hacker-who-saved-the-internet.md
new file mode 100644
index 0000000..2e9b8fe
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/confessions-marcus-hutchins-hacker-who-saved-the-internet.md
@@ -0,0 +1,14 @@
+---
+title: "The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet"
+date: 2020-05-18T10:20:08-04:00
+lastmod: 2020-05-18T10:20:08-04:00
+slug: confessions-marcus-hutchins-hacker-who-saved-the-internet
+excerpt: ""
+link: "https://www.wired.com/story/confessions-marcus-hutchins-hacker-who-saved-the-internet/"
+---
+
+> Janet Hutchins had the day off from her job as a nurse at a local hospital. She had been in town catching up with friends and had just gotten home and started making dinner. So she had only the slightest sense of the crisis that her colleagues had been dealing with across the NHS. That's when her son came upstairs and told her, a little uncertainly, that he seemed to have stopped the worst malware attack the world had ever seen.
+
+> “Well done, sweetheart,” Janet Hutchins said. Then she went back to chopping onions.
+
+It's hard to pick my favorite section from this article about Marcus Hutchins — the hacker who stopped the WannaCry malware attack.
diff --git a/themes/cycle/exampleSite/content/post/convince-the-boss.md b/themes/cycle/exampleSite/content/post/convince-the-boss.md
new file mode 100644
index 0000000..26cfb4c
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/convince-the-boss.md
@@ -0,0 +1,18 @@
+---
+title: "Convince the Boss"
+date: 2012-08-02T03:00:53-04:00
+lastmod: 2015-03-24T13:12:39-04:00
+slug: convince-the-boss
+excerpt: "Jeremy Keith on convincing bosses to adopt new web standards.
+"
+---
+
+Speaking of [cultivation and passion](http://adamsimpson.net/writing/create-passion), Jeremy Keith wrote up a [great post](http://adactio.com/journal/5634/) on how to convince one's boss or client to adopt new web standards or methods.
+
+> I do sometimes wonder whether we use the big bad client or the big bad boss as a crutch. “Oh, I’d love to try out this technique, but the client/boss would never go for it. Something something IE6.” Maybe we’re not giving them enough credit. Given the right argument, they might just listen to reason.
+
+Go *work* on getting the right arguments for your specific client or boss, go *cultivate* a metric-ton of data to overwhelm whoever is holding back progress. No one is going to reach out and whack your boss or client with a "Web Standards Genius" stick for you, do the whacking yourself (figuratively, I do not endorse or condone violence against one's superiors, peers, or underlings). If after all that effort you're still not getting anywhere, then follow Mr. Keith's other piece of advice:
+
+> Another tactic that I’ve used in the past is to simply not ask for permission, but go ahead and use the new technologies and techniques anyway.
+
+Go do.
diff --git a/themes/cycle/exampleSite/content/post/create-passion.md b/themes/cycle/exampleSite/content/post/create-passion.md
new file mode 100644
index 0000000..478fb02
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/create-passion.md
@@ -0,0 +1,14 @@
+---
+title: "Create Passion"
+date: 2012-08-02T03:00:53-04:00
+lastmod: 2015-03-24T13:12:21-04:00
+slug: create-passion
+excerpt: "Tiffani Jones Brown talks about passion in volume 3 of The Manual
+"
+---
+
+I'm slowly working my way through the latest edition of [The Manual Vol. \#3](http://alwaysreadthemanual.com). I just finished [Tiffani Jones Brown's](http://tiffanijonesbrown.com) excellent essay on Practicing Passion. This quote really stuck with me,
+
+> Instead of asking "what will make me feel passion?" we should ask, "how can I make passion happen?" The answer is to cultivate a way of living and working that makes passion more likely.
+
+I love this, it doesn't leave room for me to have any excuses. Cultivation takes effort, perseverance, hard work, and purpose. Time to [get to work](http://adamsimpson.net/writing/someone-is-working-harder-than-you), the passion will show up if I do.
diff --git a/themes/cycle/exampleSite/content/post/css-reusability.md b/themes/cycle/exampleSite/content/post/css-reusability.md
new file mode 100644
index 0000000..44ce464
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/css-reusability.md
@@ -0,0 +1,20 @@
+---
+title: "CSS Reusability"
+date: 2012-07-23T03:00:54-04:00
+lastmod: 2015-03-21T19:45:37-04:00
+slug: css-reusability
+excerpt: "How much CSS am I reusing?
+"
+---
+
+Chris Coyier posted [a great question](http://css-tricks.com/a-discussion-about-css-reusability/) over at [CSS-Tricks](http://css-tricks.com).
+
+> You've probably coded up something like that, right? How many times? A lot? Did you do it from scratch each time?
+
+I'll be honest, aside from the usual normalise.css I don't re-use much CSS. Unlike PHP or JS, where I re-use a lot of code.
+
+Chris continues on in the [comment thread](http://css-tricks.com/a-discussion-about-css-reusability/#comment-182699),
+
+> If a developer needs a login function for a website, do they write it from scratch? I bet very rarely. They use an existing project (e.g. a CMS like WordPress) or a modular component to a framework (e.g. a Rails gem). What makes back-end so code much more reusable?
+
+Chris has a great point. I know the obvious answer is that CSS deals with layout and design, which is wildly different from project to project. Yet, I think he's on to something, I need to be more efficient with the code I write. I can be more efficient by starting to think about CSS in a more modular way, what little re-usable objects or chunks can I carry from project to project?
diff --git a/themes/cycle/exampleSite/content/post/cycle-v030-released.md b/themes/cycle/exampleSite/content/post/cycle-v030-released.md
new file mode 100644
index 0000000..aff3748
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/cycle-v030-released.md
@@ -0,0 +1,13 @@
+---
+title: "cycle v0.3.0 released"
+date: 2020-09-11T12:04:16-0400
+lastmod: 2020-09-11T12:04:16-0400
+slug: cycle-v030-released
+excerpt: "Cycle version v0.3.0 is now available which features syntax highlighting via Chroma."
+---
+
+I just released [v0.3.0 of `cycle`](https://github.com/asimpson/cycle/releases/tag/v0.3.0).
+
+This version uses [Chroma](https://github.com/alecthomas/chroma/) for syntax highlighting instead of [Pygments](https://pygments.org/). I never got Pygments running correctly in [Netlify's build](https://docs.netlify.com/configure-builds/get-started/) environment. Chroma requires no dependencies since it's distributed as a static binary and it's also faster due to being written in [golang](https://golang.org/).
+
+This version also refactors the `main` function to accept an optional working directory arg. This allows me to build a site via the CL REPL. It also shortens the feedback loop to try out new features.
diff --git a/themes/cycle/exampleSite/content/post/dead-cells-might-be-a-perfect-game.md b/themes/cycle/exampleSite/content/post/dead-cells-might-be-a-perfect-game.md
new file mode 100644
index 0000000..00abbf0
--- /dev/null
+++ b/themes/cycle/exampleSite/content/post/dead-cells-might-be-a-perfect-game.md
@@ -0,0 +1,29 @@
+---
+title: "Dead Cells might be a perfect game"
+date: 2019-09-20T10:23:59-04:00
+lastmod: 2019-09-20T10:23:59-04:00
+slug: dead-cells-might-be-a-perfect-game
+excerpt: "Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it)."
+---
+
+Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it). It only took a few minutes before I felt like a total badass running around squashing baddies. However, that feeling is tempered by the fact that this game is quite fiendishly difficult.
+
+It's available on Steam for Mac, Linux, and Windows. It's also available on most consoles, including the Switch, and recently iOS.
+
+I was so impressed with this game I went hunting around for information on the creators of the game, Motion Twin. I found this documentary on Youtube about the studio and the game which is quite good:
+
+
+
+
+ +
+ +There's also this video which highlights some of the smart ways the developers made the game feel better to players: + +
+ +
+ +If you're looking for a new game or something different I highly recommend checking out Dead Cells. diff --git a/themes/cycle/exampleSite/content/post/declining-expectations.md b/themes/cycle/exampleSite/content/post/declining-expectations.md new file mode 100644 index 0000000..19620b5 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/declining-expectations.md @@ -0,0 +1,14 @@ +--- +title: "Declining Expectations" +date: 2012-07-22T03:00:55-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: declining-expectations +excerpt: "Matthew Butterick's talk on declining expectations. +" +--- + +[Matthew Butterick's talk at TYPO Berlin](http://unitscale.com/mb/reversing-the-tide/) is a fantastic read. + +> And that’s really what I mean tonight by declining expectations. This idea of what happens when we defer to technology, instead of standing on its shoulders. What happens when we choose convenience over quality. Eventually, we’re going to forget what quality was like. + +Chilling and inspiring. diff --git a/themes/cycle/exampleSite/content/post/diceware.md b/themes/cycle/exampleSite/content/post/diceware.md new file mode 100644 index 0000000..6026f5b --- /dev/null +++ b/themes/cycle/exampleSite/content/post/diceware.md @@ -0,0 +1,21 @@ +--- +title: "Diceware" +date: 2017-04-19T21:47:54-04:00 +lastmod: 2017-04-19T21:47:54-04:00 +slug: diceware +excerpt: "Glenn Fleishman recently linked to a method for generating passphrases called Diceware. Being a fan of dice (d20 for life) I thought this was super cool and worth sharing." +--- + +Glenn Fleishman ([@GlennF](https://twitter.com/GlennF)) recently linked to a method for generating *passphrases* called [Diceware](https://en.m.wikipedia.org/wiki/Diceware). + +> [@craigmod](https://twitter.com/craigmod) Switch to diceware-style ones, if you haven’t. It’s so goddamn much easier, even with 2x the characters of a random one. +> +> — Glenn Fleishman (@GlennF) [March 24, 2017](https://twitter.com/GlennF/status/845101244368601088) + +Being a fan of dice (d20 for life) I thought this was super cool and worth sharing. + +The basic premise is (to quote [Wikipedia](https://en.m.wikipedia.org/wiki/Diceware)): + +> Diceware is a method for creating passphrases, passwords, and other cryptographic variables using ordinary dice as a hardware random number generator. For each word in the passphrase, five rolls of the dice are required. The numbers from 1 to 6 that come up in the rolls are assembled as a five-digit number, e.g. 43146. That number is then used to look up a word in a word list. In the English list 43146 corresponds to munch. By generating several words in sequence, a lengthy passphrase can be constructed. + +I dig this, it's an analog solution to a digital problem. The incredible folks at the [EFF](https://www.eff.org/) have a [couple wordlists](https://www.eff.org/deeplinks/2016/07/new-wordlists-random-passphrases) to get you started. Happy rolling\! 🎲 diff --git a/themes/cycle/exampleSite/content/post/eight-years.md b/themes/cycle/exampleSite/content/post/eight-years.md new file mode 100644 index 0000000..375c278 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/eight-years.md @@ -0,0 +1,17 @@ +--- +title: "Eight years" +date: 2020-09-04T09:25:36-04:00 +lastmod: 2020-09-04T09:25:36-04:00 +slug: eight-years +excerpt: "Eight years ago I started working at Sparkbox. Thank you Sparkbox team for giving me an opportunity to work with ya'll and for making me a better developer and person." +--- + +Eight years ago I started working at Sparkbox. Here are some of things that have happened since I started: + +- The Cubs won a World Series. +- Facebook released a small Javascript library called React. +- The iPhone 5 was unveiled the week _after_ I started. + +Time flies when you're having fun. + +Thank you Sparkbox team for giving me an opportunity to work with ya'll and for making me a better developer and person. Let's keep it rolling! diff --git a/themes/cycle/exampleSite/content/post/emacs-lite.md b/themes/cycle/exampleSite/content/post/emacs-lite.md new file mode 100644 index 0000000..c80d6e4 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/emacs-lite.md @@ -0,0 +1,19 @@ +--- +title: "Emacs lite" +date: 2018-04-19T10:42:41-04:00 +lastmod: 2018-04-19T10:42:41-04:00 +slug: emacs-lite +excerpt: "A small, friendly starting point for Emacs." +--- + +I really dig Emacs. I think it's a one-of-kind computing experience. However, it's defaults are pretty rough and some of my favorites aspects of Emacs are third party packages. + +I wondered if I could cram the "awesome Emacs" experience into 200 lines of configuration or less. [Turns out I could](https://github.com/asimpson/dotfiles/blob/master/emacs/emacs-lite.org). I only included what I consider (as someone who writes JS most days) "essential". I didn't re-bind any keys except for `M-x` and that has the same function with an [upgraded interface](https://adamsimpson.net/writing/helm-to-ivy). I didn't include `evil-mode` (Vim emulation) either, introducing Emacs *and* Vim keybinds to someone is a suicide mission. + +To use this config copy and paste the config snippet [into one of three config file locations](https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html) (sooooo Emacs): + +> Emacs looks for your init file using the filenames \~/.emacs, \~/.emacs.el, or \~/.emacs.d/init.el + +Then boot up Emacs (I'm assuming you [already have it installed](https://www.gnu.org/software/emacs/)), there will be a bit of waiting the first time as packages are installed for you. + +If you run into issues, hit me up via email, [github issue](https://github.com/asimpson/dotfiles/issues), [twitter](https://twitter.com/a_simpson), [micro.blog](https://micro.blog/simpson) etc. There's also a [reddit thread](https://www.reddit.com/r/emacs/comments/8cpkc3/emacs_lite_just_the_essentials_config_in_200_lines/) with some helpful discussion from the awesome `/r/emacs` community. diff --git a/themes/cycle/exampleSite/content/post/emacs-tips.md b/themes/cycle/exampleSite/content/post/emacs-tips.md new file mode 100644 index 0000000..f8298ad --- /dev/null +++ b/themes/cycle/exampleSite/content/post/emacs-tips.md @@ -0,0 +1,34 @@ +--- +title: "Emacs tips" +date: 2017-03-27T11:53:53-04:00 +lastmod: 2017-11-17T23:41:43-05:00 +slug: emacs-tips +excerpt: "A evolving collection of emacs tips aimed at someone starting out with emacs and evil-mode." +--- + +[`evil-mode`](https://github.com/emacs-evil/evil) (vim for [emacs](https://www.gnu.org/software/emacs/)) is good but not perfect. There will be occasions where you will get dropped into regular 'ole emacs mode for some feature or plugin. The trick is to not panic remember a few basic movement keys that will get through in 90% of cases. + +1. `C-n` and `C-p` (`C` stands for the ctrl key) go down and up by line respectively. +2. `M-f` (`M` stands for the alt key) and `M-b` will go forwards and backwards by word respectively. +3. `C-g` is the universal emacs key for "STOP WHATEVER YOU'RE DOING". + +There are a few other random things to keep in mind that will make life easier. + +1. `M-x` (remember, `M` stands for the alt key) allows you to execute just about any function, e.g. `kill-buffer`. +2. `F1 f` will bring up documentation for any loaded function. +3. `F1 v` will bring up documentation for any variable. +4. `F1 k` will allow you to type a keybind and see what it's bound to. + +## Scripting tips + +A few helpful built-in functions to know to start making your own functions. + +1. `nth` is a [built-in](https://www.gnu.org/software/emacs/manual/html_node/elisp/List-Elements.html#List-Elements) which lets you pull a specific item from a list by it's index like so: `(nth 1 '("red", "blue"))`. Returns `"blue"`. + +2. `split-string` is another [built-in](https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Strings.html#Creating-Strings) that splits a string given a separator and returns the results in a list. `(split-string "foo-bar" "-")`. Returns `("foo" "bar")` + +3. `concat` also a [built-in](https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Strings.html#Creating-Strings), combines strings. `(concat "hello" "world")`. Returns `"helloworld"`. + +4. `null` also a built-in. Return t if OBJECT is nil, and return nil otherwise. `(null OBJECT)`. + +I'll add to this post as I think of things that helped me out when I first started using emacs. You can also check out my [emacs config in my dotfiles](https://github.com/asimpson/dotfiles/tree/master/emacs) if you want to see how I have everything setup. diff --git a/themes/cycle/exampleSite/content/post/end-of-an-era.md b/themes/cycle/exampleSite/content/post/end-of-an-era.md new file mode 100644 index 0000000..201c57f --- /dev/null +++ b/themes/cycle/exampleSite/content/post/end-of-an-era.md @@ -0,0 +1,15 @@ +--- +title: "End of an era" +date: 2023-06-15T14:13:50-04:00 +lastmod: 2023-06-15T14:13:50-04:00 +slug: end-of-an-era +excerpt: "Today I removed two of my most-used apps on my phone, Apollo and Tweetbot. It feels like the end of an era." +--- + +Today I removed two of my most-used apps on my phone, [Apollo](https://apolloapp.io/) and [Tweetbot](https://tapbots.com/tweetbot/). It feels like the end of an era. + +Twitter and Reddit were both social websites that are/were terrible without a lot of cultivation and effort, but over the years I had shaped my experience on those services to be pretty good thanks in large part to Apollo and Tweetbot being such powerful tools. + +Ironically the only social web thing I still use (outside of Instagram) is [RSS](https://feedbin.com/). I will probably spin up a Mastodon instance here eventually but for now I've subscribed to folks via Mastodon's RSS support and it's good enough for now. + +I guess I just wanted to give a shout out to the devs of Apollo and Tweetbot: thank you for making such great apps, I will miss them. diff --git a/themes/cycle/exampleSite/content/post/evening-edition.md b/themes/cycle/exampleSite/content/post/evening-edition.md new file mode 100644 index 0000000..bc84173 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/evening-edition.md @@ -0,0 +1,12 @@ +--- +title: "Evening Edition" +date: 2012-07-18T03:00:55-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: evening-edition +excerpt: "The Evening Edition is a great little resource +" +--- + +Those clever chaps over at [Mule Design](http://muledesign.com/) have released [The Evening Edition](http://evening-edition.com/) and I'm sure most of you have seen it. + +It's a little bit of a [slow web](http://blog.jackcheng.com/post/25160553986/the-slow-web) idea, and I just love the execution. diff --git a/themes/cycle/exampleSite/content/post/facetime-killer.md b/themes/cycle/exampleSite/content/post/facetime-killer.md new file mode 100644 index 0000000..f8cd05e --- /dev/null +++ b/themes/cycle/exampleSite/content/post/facetime-killer.md @@ -0,0 +1,24 @@ +--- +title: "Facetime Killer" +date: 2017-04-03T09:44:57-04:00 +lastmod: 2017-04-03T09:44:57-04:00 +slug: facetime-killer +excerpt: "I made an app, VDCAssistant-Killer, to restart the process that manages the Facetime camera on your Mac." +--- + +TLDR: I made an app, [VDCAssistant-Killer](https://github.com/asimpson/VDCAssistant-killer/releases), to restart the process that manages the Facetime camera on your Mac. + +Anyone who uses a Cinema Display with their Macbook has undoubtedly noticed that occasionally the Cinema Display Facetime camera will not be available for use in Hangouts/Zoom/Facetime call. The only fix was to restart the machine which usually made me late (and is a terrible solution in 2017). + +Since [I'm on video calls quite a bit](https://adamsimpson.net/writing/be-a-good-video-call-citizen) this quickly started to drive me batty. I jumped into a google deep dive and found out the culprit was the process that manages the Facetime cameras on a Mac, VDCAssistant. + + + +This command worked fine for anyone comfortable with the command line, but what about folks who would rather have a GUI to do this? So I made [VDCAssistant-Killer](https://github.com/asimpson/VDCAssistant-killer/releases) a menubar app that executes the exact shell command to restart the VDCAssistant process for you. You shouldn't have to restart the computer or even the video call program, the assistant should automatically restart and make all connected cameras available to you immediately. + +A few other notes: + + - The app is all Swift. + - It's incredibly easy to piece together a basic app with storyboards and some googling. + - The actually shell command piece uses [AppleScript APIs to pop up the password dialog](https://github.com/asimpson/VDCAssistant-killer/blob/master/FaceTime%20Killer/Killer.swift#L13). + - Emoji make great [stand-in icons](https://github.com/asimpson/VDCAssistant-killer/blob/master/FaceTime%20Killer/MenuController.swift#L26) diff --git a/themes/cycle/exampleSite/content/post/family-first.md b/themes/cycle/exampleSite/content/post/family-first.md new file mode 100644 index 0000000..8c484dd --- /dev/null +++ b/themes/cycle/exampleSite/content/post/family-first.md @@ -0,0 +1,14 @@ +--- +title: "Family First" +date: 2012-10-21T03:00:56-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: family-first +excerpt: "Chris Bowler weighs in with some fantastic advice for those who have families. +" +--- + +[Chris Bowler](http://chrisbowler.com/) jots down some fantastic advice in his [latest post](http://chrisbowler.com/journal/overcoming-project-guilt) (emphasis mine). + +> But my purpose here is to simply encourage those with families. **Please do not spend your time endlessly comparing your accomplishments or progress** with those who have no family. Your setting yourself up for guilt at best, and resenting your family at worst. + +I do not have any kids yet but I think this advice applies to everyone, especially those working on the web. I've been slowly learning that I cannot continue to compare myself to other people in my industry - it's counterproductive. diff --git a/themes/cycle/exampleSite/content/post/farewell-heroku.md b/themes/cycle/exampleSite/content/post/farewell-heroku.md new file mode 100644 index 0000000..1f7a57f --- /dev/null +++ b/themes/cycle/exampleSite/content/post/farewell-heroku.md @@ -0,0 +1,52 @@ +--- +title: "Farewell Heroku" +date: 2015-10-06T13:17:08-04:00 +lastmod: 2015-10-06T14:00:52-04:00 +slug: farewell-heroku +excerpt: "I've migrated my apps off Heroku and won't be using the service for personal apps going forward." +--- + +I've migrated my apps off [Heroku](https://www.heroku.com/) and won't be using the service for personal apps going forward. Why? Let me back up a bit and explain what was so great about Heroku. + +## Haiku? Ha-who? + +Heroku is a "hosting as a service" company. They try to take away the pain of deploying and managing web applications. They actually do this quite well, it's a great service. The "secret sauce" that made Heroku so good was it's free pricing tier. The free tier essentially allowed a single web or a single "worker" process to run 24/7. There was enough processing power to run apps or processes for a small number of users, perfect for apps like my [six plus checker](/writing/iphone-checker-with-capybara-and-twilio) or [youtuberss app](http://ytrss.co). + + + +If apps grew popular enough they would hit processing limits and I could go in and scale the app up to meet demand. Scaling an app also meant that I was no longer in the free tier and would begin paying Heroku for the additional resources. It really was an ideal setup (from my perspective as a developer). + +## Sadness + +Sadly, Heroku [announced a few months ago](https://blog.heroku.com/archives/2015/5/7/new-dyno-types-public-beta) a pretty big shift in their pricing. The free tier would no longer run 24/7 as a single process: + +> Every app using free dynos can include not just a free web, but also one free worker, and free usage of heroku run and Heroku Scheduler. Free dynos can run up to *eighteen hours a day, but have to “sleep” for at least the remaining six*. That’s eighteen hours each of serving traffic, running a background worker, and scheduled processes + +I totally get they are trying to offer *more* of their platform in "demo mode" but I think it's the wrong move. To be clear, I'm not griping about a free lunch going away. I'm griping because the new pricing: + +1. Is harder to understand and manage. Seriously, I'm supposed to monitor my app in 18 hour increments? +2. Doesn't incentivize developers to try out new apps that could potentially become paying applications. + +Re: \#2, The very impressive [emojitracker](http://emojitracker.com) [was built on Heroku's platform](https://medium.com/@mroth/how-i-built-emojitracker-179cfd8238ac). Matthew Rothenberg, the project's developer, recounts how Heroku let him easily scale to meet demand: + +> I did this manually. That first evening I needed a break from intense computer usage all day, so I actually spent the evening in a bar across the street from my apartment with some friends, having a drink while passively monitoring these charts on some iPhones sitting on the table. Whenever it looked like something was spiking, I used the Nezumi Heroku client to scale up instances from my phone directly. I didn’t even have to put down my drink\! + +This is awesome. It illustrates the ideal scenario: no money up front to try something out and a natural path to scaling it up if it takes off. Simple, it was. + +## Where to now? + +I tweeted yesterday: + + + +I've now finished moving my node apps over to [Chunkhost](https://chunkhost.com/r/46012). With Chunkhost I get 1GB of RAM for under $5/month by paying yearly and via bitcoin (I use [Coinbase](https://www.coinbase.com/join/526d7fc9d296a258e800005c) to purchase and manage Bitcoins). In comparison, Digital Ocean offers 512MB of RAM for $5/month. With the extra overhead from Chunkhost, I can easily host multiple apps on the same box. Plus, I've found that the two node apps I have running are both only using \~50MB of RAM\! + +## Sysadmin + +Yes, with Chunkhost I have to play as sysadmin and keep the VPS running. However I'm in total agreement with this [quote from Marco Arment](http://www.marco.org/2014/03/27/web-hosting-for-app-developers): + +> Modern Linux server administration is much easier than you think. If you can write a halfway decent app, you can manage a Linux VPS in your sleep. + +He's exactly right, managing a VPS isn't beyond the abilities of anyone who can write an app and put it on Heroku. I've found [Ansible](http://www.ansible.com/get-started) + [Bitbucket private repos](http://bitbucket.org) + [PM2](http://pm2.keymetrics.io) a great deployment and management combo; one that I'll write more about later. It took some effort to set up, but now I can launch new apps in minutes. + +Heroku's new pricing has forced me to branch out and figure out how to host, manage, and deploy my apps. Perhaps the pricing change wasn't *all* bad after all. diff --git a/themes/cycle/exampleSite/content/post/ffmpeg-convert-multiple-files-using-xargs.md b/themes/cycle/exampleSite/content/post/ffmpeg-convert-multiple-files-using-xargs.md new file mode 100644 index 0000000..50c55d1 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/ffmpeg-convert-multiple-files-using-xargs.md @@ -0,0 +1,14 @@ +--- +title: "FFMPEG: Convert multiple files using xargs" +date: 2020-06-04T14:43:26-04:00 +lastmod: 2020-06-04T14:43:26-04:00 +slug: ffmpeg-convert-multiple-files-using-xargs +excerpt: "" +link: "https://webcache.googleusercontent.com/search?q=cache:53fkpNAjK8UJ:https://www.joshcurry.co.uk/posts/ffmpeg-convert-multiple-files-using-xargs+&cd=1&hl=en&ct=clnk&gl=us" +--- + +I stumbled [upon this post](https://www.joshcurry.co.uk/posts/ffmpeg-convert-multiple-files-using-xargs/) ([Google cache link](https://webcache.googleusercontent.com/search?q=cache:53fkpNAjK8UJ:https://www.joshcurry.co.uk/posts/ffmpeg-convert-multiple-files-using-xargs+&cd=1&hl=en&ct=clnk&gl=us)) when I was trying to process multiple files via `xargs`. + +> `ls *.webm | xargs -I % ffmpeg -i % %.m4a` + +> The key part of this one-liner is xargs `-i %`. This means that each line of STDIN passed to xargs is put into a variable and can be referenced as `%`. Hence, the following text which specifies `ffmpeg -i x.webm x.m4a` to make it convert. diff --git a/themes/cycle/exampleSite/content/post/five-years.md b/themes/cycle/exampleSite/content/post/five-years.md new file mode 100644 index 0000000..09838a1 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/five-years.md @@ -0,0 +1,13 @@ +--- +title: "Five years" +date: 2017-09-05T23:00:18-04:00 +lastmod: 2017-09-05T23:00:18-04:00 +slug: five-years +excerpt: "Five years is a long time, especially working on the internet, and I've loved every stinking minute of it." +--- + +# Five years + +Today is my five year anniversary at [Sparkbox](https://seesparkbox.com)\! Five years is a long time, especially working on the internet, and I've loved every stinking minute of it. + +To my fellow Sparkboxers: thank you for making Sparkbox such an incredible place to work. Here's to the next five\! diff --git a/themes/cycle/exampleSite/content/post/flatkill.md b/themes/cycle/exampleSite/content/post/flatkill.md new file mode 100644 index 0000000..b50212c --- /dev/null +++ b/themes/cycle/exampleSite/content/post/flatkill.md @@ -0,0 +1,14 @@ +--- +title: "flatkill" +date: 2020-06-15T13:03:27-04:00 +lastmod: 2020-06-15T13:03:27-04:00 +slug: flatkill +excerpt: "" +link: "http://flatkill.org/" +--- + +> And it's not only about these security problems. Running KDE apps in fakepak? Forget about desktop integration (not even font size). Need to input Chinese/Japanese/Korean characters? Forget about that too - fcitx has been [broken since flatpak 1.0](https://github.com/flatpak/flatpak/issues/2031), never fixed since. + +> The way we package and distribute desktop applications on Linux surely needs to be rethinked, sadly flatpak is introducing more problems than it is solving. + +[Flatpak](https://flatpak.org/) is an emerging alternative way to install applications on Linux that is apparently rife with security and usability issues. This is a bummer because there's lots of room in this space for improvement. The lack of multi-lingual input is especially egregious. diff --git a/themes/cycle/exampleSite/content/post/format-json-in-emacs.md b/themes/cycle/exampleSite/content/post/format-json-in-emacs.md new file mode 100644 index 0000000..3fb147e --- /dev/null +++ b/themes/cycle/exampleSite/content/post/format-json-in-emacs.md @@ -0,0 +1,21 @@ +--- +title: "Format JSON in emacs" +date: 2017-05-23T14:11:28-04:00 +lastmod: 2017-05-23T14:11:28-04:00 +slug: format-json-in-emacs +excerpt: "I wrote an elisp function to yank JSON off my clipboard, prettify it." +--- + +I wrote an elisp function to yank JSON off my clipboard, prettify it, and then return it to my clipboard ready to be pasted wherever. + +``` elisp +(defun simpson-pretty-json() + "ideal for getting pretty JSON from JSON that is copied from a XHR request" + (interactive) + (with-temp-buffer + (clipboard-yank) + (json-pretty-print-buffer) + (kill-new (buffer-string)) + ) +) +``` \ No newline at end of file diff --git a/themes/cycle/exampleSite/content/post/four-ways-to-approach-hacktoberfest-2020.md b/themes/cycle/exampleSite/content/post/four-ways-to-approach-hacktoberfest-2020.md new file mode 100644 index 0000000..6c3682f --- /dev/null +++ b/themes/cycle/exampleSite/content/post/four-ways-to-approach-hacktoberfest-2020.md @@ -0,0 +1,28 @@ +--- +title: "Four ways to approach Hacktoberfest 2020" +date: 2020-10-01T10:26:38-0400 +lastmod: 2020-10-01T11:41:44-0400 +slug: four-ways-to-approach-hacktoberfest-2020 +excerpt: "I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor." +--- + +Hacktoberfest 2020 is here! I can't believe 2020 is winding down, good riddance! + +I've been talking about Hacktoberfest with my co-worker [Bryan](https://www.bryanbraun.com/) and I thought of four different approaches to Hacktoberfest this year that I wanted to share. + + + + +## Dependency scrub +This is probably common everywhere but the Javascript/web communities are filled with npm packages. It's packages all the way down. I think it would be interesting to approach this month looking for ways to remove third-party code from projects you love and use frequently. + +## Polygot Achievement +Try to submit four pull requests in four different languages. As [Drew DeVault writes](https://drewdevault.com/2018/03/17/Hack-everything-without-fear.html): Hack everything without fear! + +## Unknown lands +Similar to the previous one it could be fun to submit PRs against a project you've never been in before that's in a language you don't know. This could be anything from diving into Wordpress core, to working on some C for some Linux utilities, or even submitting PRs to open source Mac/iOS applications. + +## Bug doctor +Go into a project and find the oldest issues and try to resolve them via PR. This is inspired by [Richard Schneeman's video](https://schneems.com/2020/09/22/triage-with-me-11-issues-2-prs-in-15-hours/) and post where he runs through 11 issues and 2 PRs in a hour and a half. + +How are you approaching Hacktoberfest this year? My public inbox is open, let me know! diff --git a/themes/cycle/exampleSite/content/post/getting-started-with-rofi.md b/themes/cycle/exampleSite/content/post/getting-started-with-rofi.md new file mode 100644 index 0000000..6542483 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/getting-started-with-rofi.md @@ -0,0 +1,72 @@ +--- +title: "Getting started with Rofi" +date: 2020-05-28T13:35:15-04:00 +lastmod: 2020-05-28T13:35:15-04:00 +slug: getting-started-with-rofi +excerpt: "I've been using Rofi for about a year but didn't really understand how to write my own scripts for it until recently. In this post I explain what dmenu is and Rofi's implementation of it and also show how to change audio inputs on Linux via pactl." +--- + +[Rofi is a Linux app](https://github.com/davatorium/rofi) that is a: + +> [..] window switcher, application launcher and dmenu replacement + +I've been using Rofi for about a year but didn't really understand how to write my own scripts for it until recently. + +## dmenu? Huh? +A key to my lack of apprecaition for Rofi's feature set was that I didn't understand why it billed itself as a "dmenu replacement". What the heck is [`dmenu`](https://tools.suckless.org/dmenu/)? + +> dmenu is a fast and lightweight dynamic menu for X. **It reads arbitrary text from stdin, and creates a menu with one item for each line. The user can then select an item, through the arrow keys or typing a part of the name, and the line is printed to stdout**. (emphasis mine) + +Essentially `dmenu` lets you create and present your own menu and then act once a menu item is selected by the user. One of my favorite applications of all time is [Alfred](https://www.alfredapp.com/workflows/), the infinitely customizable launcher utility for macOS. The best part about Alfred was [Workflows](https://www.alfredapp.com/workflows/) which (like dmenu) allow you to create custom menus and actions as part of the main launcher interface. How do we create a menu though? + +## STDIN STDOUT +`dmenu` will display whatever comes in on `STDIN` as the menu, e.g. `echo "foo\nbar" | dmenu"` (if you have a Linux install available install `dmenu` and give that command a try). Each new line in `STDIN` becomes a new line in the `dmenu` menu. The previous command creates a menu with two options: `foo` and `bar`. Once the user hits enter on a menu item the value of the selected item gets sent to `STDOUT`. That's it. `dmenu` reads in from `STDIN` and prints out selections to `STDOUT`. `dmenu` is super handy to add to workflows and scripts to give them a bit of UI. You can squeeze `dmenu` anywhere you need feedback from the user, e.g.: `echo "Hello $(echo 'World\nPeople' | dmenu)"`. This prints a hello world message after the users chooses "World" or "People" from `dmenu`. + +## Rofi + dmenu +Rofi adds `dmenu` capability _plus_ lots of other things like selecting open windows, running ssh commands etc. To enable `dmenu` mode in Rofi pass it as an option `-dmenu`. Let's port our previous example code snippet to Rofi: `echo "foo\nbar" | rofi -dmenu`. Easy enough! With the `dmenu` option Rofi becomes just as useful as Alfred and makes me think Alfred should gain a command line option to pop open Alfred from within scripts like dmenu or Rofi. + +## My first script +The motivation to write this post came a couple weeks ago when I wrote my first real Rofi script. I use [Pop_OS!](https://pop.system76.com/) as my Linux distribution of choice for work and the defaults are _really good_. However when I want to change my audio output (headphones or external speakers) I've grown annoyed by having to manually mouse up to the menubar and select the desired output. I set out to write a Rofi script to handle changing the audio output. On Linux you can control everything related to the audio system via the `pactl` utility. The pieces of data I needed for my script were: + +- A list of all available outputs to generate my Rofi menu +- A way to change to the selected output + +`pactl list sinks` displays all active "sinks" or available outputs ("Sinks" is the Linux audio system term for outputs). We can customize this a bit further wih `pactl list short sinks` which will cram relevant sink information into one line each instead of multiple lines per sink. This makes parsing the output much easier. + +Now that I had a list of available speakers/headphones on the system I needed to change to that output. This turned out to be a two step process because of how the audio system works: + +1. `pactl move-sink-input INPUT SINK` moves anything currently playing to the specified speaker/headphone. +2. `pactl set-default-sink SINK` sets the specified speaker/headphones as the default output going forward, e.g. launching a video call or playing a video. + +To accomplish #1 I needed to get the currently playing input which can be done via: `pactl list sink-inputs`. Again we can specify `short` to get the relevant information on a single line: `pactl list short sink-inputs`. + +The finished script looks like this: + +```shell +#!/bin/bash + +source="$(pactl list short sinks | cut -f 2 | rofi -dpi 1 -dmenu -p "Change audio:")"; +inputs="$(pactl list sink-inputs short | cut -f 1)"; + +for input in $inputs; do + pactl move-sink-input "$input" "$source"; +done + +pactl set-default-sink "$source"; +``` + +Upon invoking the script, Rofi presents me with a menu that contains all the available outputs. Once I select one the audio changes instantly. + +
+ +
Video showing the change-audio script running via Rofi.
+
+ +## Conclusion +I find Rofi so useful that I have a system-wide hotkey that invokes Rofi as a general launcher like this: `rofi -combi-modi run,window,drun -show combi -modi combi -dpi 1`. The flags I'm using are documented under "Combi settings" in the Rofi manpage. + +Rofi transforms otherwise vanilla shell scripts into poweful transient workflows that allow me to control aspects of my machine without leaving whatever I'm currently working on. It's become an essential part of my toolbox. diff --git a/themes/cycle/exampleSite/content/post/gists-snippets-and-sublime-text-2.md b/themes/cycle/exampleSite/content/post/gists-snippets-and-sublime-text-2.md new file mode 100644 index 0000000..33ed154 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/gists-snippets-and-sublime-text-2.md @@ -0,0 +1,16 @@ +--- +title: "Gists, Snippets, and Sublime Text 2" +date: 2012-08-06T03:00:57-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: gists-snippets-and-sublime-text-2 +excerpt: "How I now use Gists instead of snippets in Sublime Text 2. +" +--- + +I've been using [Sublime Text 2](http://www.sublimetext.com/2) for a little under a year I guess, but I've only recently started customizing the hell out of it largely thanks to the [Fetch](https://github.com/weslly/Nettuts-Fetch) plugin. Today I had the thought of setting up Fetch to download and insert the raw code of a [Github Gist](https://gist.github.com/). + +Gists are great for a couple reasons. One is that they are version controlled, it's easy to track any changes right from the gist. Another great thing is that Gists are independent of Sublime, and more importantly my local computer, this makes them easier to share and backup. The only drawback from normal snippets I can see is that I can't set up tab triggers, and hot keys. + +So today I created [three](https://gist.github.com/3285891) [Worpress](https://gist.github.com/3289411) [specific](https://gist.github.com/3289584) gists, and set up Fetch in Sublime Text 2 to pull them down. These are pretty basic snippets, but they are ones that I use a lot and don't want to think about. + +I just started messing around with this stuff today, so I'd love any comments regarding snippets or how you set up any kind of automation in Sublime Text 2. Reply to [@a\_simpson](http://twitter.com/a_simpson/) with your comments. diff --git a/themes/cycle/exampleSite/content/post/git-commit-template.md b/themes/cycle/exampleSite/content/post/git-commit-template.md new file mode 100644 index 0000000..6337ce8 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/git-commit-template.md @@ -0,0 +1,22 @@ +--- +title: "Git Commit Template" +date: 2013-08-22T03:00:58-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: git-commit-template +excerpt: "Set up a Git commit message template +" +--- + +[TL;DR how do I do this?](#add_your_own_template) + +At work we've been moving toward [standardized Git commit messages](https://github.com/sparkbox/how_to/tree/master/style/git). By following the pattern, it's very easy to see what type of code is in a specific commit. + +We use [Sprint.ly](https://sprint.ly/) and [Github](https://github.com/). Both of these services can perform actions based on what is in a commit message. [Github can close or reference an issue](https://github.com/blog/831-issues-2-0-the-next-generation) if I type `closes #144` at the end of my commit. [Sprint.ly can pull a commit message into a specific ticket](http://help.sprint.ly/knowledgebase/articles/108139-available-scm-vcs-commands) in much the same way. + +The problem with all this, is remembering to actually do it in the heat of the moment, when I'm buried in code and trying to push stuff out the door. That's why I put together a [Git commit message template](http://git-scm.com/book/ch7-1.html). All [my template](https://github.com/asimpson/dotfiles/blob/master/git/gitmessage.txt) does is list the various flags and an example of how to reference a Sprint.ly ticket, but it shows this in my editor every time I commit. It's been incredibly useful. + +### Add your own template + +1. Create a file to hold your template, e.g. `git-commit-template.txt`. Put in whatever you want to remember, just be sure to keep everything commented out (via \#) or it will be in the actual message. +2. Run `git config --global commit.template /path/to/git-commit-template.txt` or edit `~/.gitconfig` and add `template = /path/to/.gitmessage.txt` under the `[commit]` block. +3. Done. diff --git a/themes/cycle/exampleSite/content/post/git-worktree.md b/themes/cycle/exampleSite/content/post/git-worktree.md new file mode 100644 index 0000000..f0d398a --- /dev/null +++ b/themes/cycle/exampleSite/content/post/git-worktree.md @@ -0,0 +1,23 @@ +--- +title: "Git worktree" +date: 2017-12-11T00:00:17-05:00 +lastmod: 2017-12-11T00:00:17-05:00 +slug: git-worktree +excerpt: "What the heck is git-worktree?" +--- + +I was happily (I had just started obviously) browsing Twitter today when I saw this tweet from the esteemed [Wilfred Hughes](http://www.wilfred.me.uk): + + + +Huh? What is `git-worktree`? A quick Google landed me on [the documentation](https://git-scm.com/docs/git-worktree) for `git-worktree`. The ;TLDR of `git-worktree` is that it breaks time and space and lets a user check out multiple branches *at the same time*. No more stash-checkout-stash-pop dance between branches and fixes\! The [example](https://git-scm.com/docs/git-worktree#_examples) in the documentation is really really good (except for the boss part, that's usually played by my short-attention span). + +## Magit + +After reading the documentation, my next thought was "Does [magit](https://magit.vc) support this?" Yep, [since last year](https://github.com/magit/magit/blob/94980fed2b87a2194c325702d1b70a58ca5738b7/lisp/magit-worktree.el)\! Let me take this moment to rave like a maniac, magit is amazing and everyone should be using it as their primary git client (irregardless of Emacs usage for text-editing). As the [documentation explains](https://emacsair.me/2016/05/19/magit-2.7/), to get worktree information in the standard magit status buffer the `magit-status-sections-hook` needs to be updated like so: + +`(add-hook 'magit-status-sections-hook 'magit-insert-worktrees)`. + +The actions for creating or checking out a worktree are (hiding) in the branches (`b`) popup. I don't know why I've never noticed them until now\! + +`git-worktree` is another example of `git` not standing still. It's exceptional (even under-appreciated) software that continues to improve and that's something that doesn't get enough praise and attention. diff --git a/themes/cycle/exampleSite/content/post/goat-counter.md b/themes/cycle/exampleSite/content/post/goat-counter.md new file mode 100644 index 0000000..fd9aea2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/goat-counter.md @@ -0,0 +1,12 @@ +--- +title: "GoatCounter web analytics" +date: 2020-07-01T15:49:45-04:00 +lastmod: 2020-07-01T15:49:45-04:00 +slug: goat-counter +excerpt: "" +link: "https://www.goatcounter.com/" +--- + +> What seems to be lacking is a “middle ground” that offers useful statistics to answer business questions, without becoming a specialized marketing tool requiring in-depth training to use effectively. Furthermore, some tools have privacy issues (especially Google Analytics). I saw there was space for a new service and ended up putting my original idea in the freezer and writing GoatCounter. + +I agree 100% with this assessment and I'm excited about Goatcounter. I setup a free instance of Goatcounter for this site as a way to kick the tires on it. So far, I'm enjoying that it's privacy respecting and doesn't drag down page performance. diff --git a/themes/cycle/exampleSite/content/post/goodbye-sparkbox.md b/themes/cycle/exampleSite/content/post/goodbye-sparkbox.md new file mode 100644 index 0000000..48b2abd --- /dev/null +++ b/themes/cycle/exampleSite/content/post/goodbye-sparkbox.md @@ -0,0 +1,17 @@ +--- +title: "👋 Sparkbox" +date: 2022-04-01T18:20:31 +lastmod: 2022-04-01T18:20:31 +slug: goodbye-sparkbox +excerpt: "I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox." +--- + +I can’t believe I’m writing this but after 9 and a half years today is my last day at [Sparkbox](https://sparkbox.com). + +Now, I know it can be problematic to think about work like your (extended) family but when you work at the same place through your twenties and early thirties, have 3 different apartments, buy a house, and have two kids it’s impossible not to view that place differently. I can confidently say Sparkbox changed my life. The team there will always have a special place in my heart. + +_deep breath_ + +So where to? Well, I’m super stoked to be joining [Grafana](https://grafana.com) as a Senior Software Engineer on their Cloud Data team! I’m looking forward to writing more Go, solving new problems, and learning from the stellar folks there. + +Here we go… diff --git a/themes/cycle/exampleSite/content/post/google-fi-and-data-only-plans.md b/themes/cycle/exampleSite/content/post/google-fi-and-data-only-plans.md new file mode 100644 index 0000000..b8d6927 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/google-fi-and-data-only-plans.md @@ -0,0 +1,23 @@ +--- +title: "Google Fi and data only plans" +date: 2015-04-30T21:17:07-04:00 +lastmod: 2015-04-30T22:05:58-04:00 +slug: google-fi-and-data-only-plans +excerpt: "Why doesn't Google just offer data? There already is already a fantastic data-only plan in America, and it's on T-Mobile." +--- + +Last week, Google began selling wireless cellular service via a new program, [Google Fi](https://fi.google.com/about/), which utilizes Sprint *and* T-Mobile for coverage. Fi's pricing model is refreshingly straight-forward (following the example of T-Mobile and [Ting](https://ting.com)); every plan is $20 with data billed at $10/Gb on top of that. [@benthompson](http://twitter.com/benthompson) and [@jamesallworth](http://twitter.com/jamesallworth) discussed the various aspects of Fi on a [recent episode](http://exponent.fm/episode-043-project-fi-and-facebooks-feed/) of their podcast, [Exponent](http://exponent.fm). At one point, [James](http://twitter.com/jamesallworth) asked (I'm paraphrasing here) why the base of the Fi plan includes voice/sms. Why doesn't Google just offer data? James went on to say that he always thought if anyone were to offer a data-only plan, it would be Google. What he didn't know was this: there is already a fantastic data-only plan in America, and it's on T-Mobile. + +### Data only-ish + +On [T-Mobile's prepaid site](http://prepaid-phones.t-mobile.com/prepaid-plans), the company heavily advertises its main pre-paid price tiers: $40, $50, and $60. However, a quick scroll down the page will reveal two additional plans. The first one is talk and text only, with no data included. The second is the best kept secret in wireless. This second plan is **$30/month** for 100 minutes, unlimited SMS, and 5GB of LTE data (throttled after 5GB). 100 minutes is nothing, so this plan is essentially just data. There's no catch - the LTE isn't throttled at all, and the plan includes free international texting from the US. It even qualifies for [Music Freedom](https://www.t-mobile.com/offer/free-music-streaming.html), which doesn't count music streaming against your 5GB LTE allowance. You can add hotspot tethering for $15/month, and this can be added and removed as you need it. + +### What are minutes for? + +My wife and I have been on this plan for almost a year now. It's perfect. We use [FaceTime Audio](https://support.apple.com/en-us/HT204380) if we need to call each other or anyone else that has an iOS device. We use [the Vonage mobile app](http://www.vonage.com/personal/vonage-mobile-app) (any VOIP service would work) when we need to make a normal call and don't want to use our 100 minutes. Both Vonage and FaceTime Audio use data, not voice minutes, exactly the scenario James outlined on Exponent. + +### Caveats + +The only downside to this plan I have found is that T-Mobile's coverage is still behind AT\&T's and Verizon's, though it's much closer now than it has ever been. [2015](http://www.fiercewireless.com/story/t-mobiles-legere-vows-go-toe-toe-verizons-network-overtake-sprint-2015/2014-12-30) has seen T-Mobile continue to build out its LTE reach, and it's impressive. Living in Columbus, OH, one of the first cities to get Wideband LTE, I see speedtest results as high as 70mbps down. + +If Google Fi isn't as radical as you'd like, I would recommend giving this T-Mobile plan a try. It’s $30 (plus the cost of a SIM card) to give it a shot. The one "catch" is that it's only for phones (or SIMs) activated in Walmart or online, but it’s easy enough to [order a SIM card](http://www.t-mobile.com/bring-your-own-phone.html) and give it a try. diff --git a/themes/cycle/exampleSite/content/post/grow-it-dont-build-it.md b/themes/cycle/exampleSite/content/post/grow-it-dont-build-it.md new file mode 100644 index 0000000..3d06e31 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/grow-it-dont-build-it.md @@ -0,0 +1,14 @@ +--- +title: "Grow it, don't build it" +date: 2012-07-18T03:00:58-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: grow-it-dont-build-it +excerpt: "Growing software versus building it +" +--- + +[John Graham-Cumming wrote up a fantastic list](http://blog.jgc.org/2012/07/some-things-ive-learnt-about.html) of things he's learned about programming. There all great. Yet, I really resonated with \#6. So. True. + +> It's easier to grow software than build it \[…\] When you create a massive architecture from the start you (a) get it wrong and (b) have created a Byzantine maze that you'll find hard to change. If, on the other hand, you work from small pieces that communicate with each other, refactoring will be easier when you realize you got it wrong from the start. + +Hat-tip to [Jonathan Christopher](http://mondaybynoon.com/20120719/some-things-ive-learnt-about-programming/) for the article link. diff --git a/themes/cycle/exampleSite/content/post/guidelines-for-data.md b/themes/cycle/exampleSite/content/post/guidelines-for-data.md new file mode 100644 index 0000000..24022fd --- /dev/null +++ b/themes/cycle/exampleSite/content/post/guidelines-for-data.md @@ -0,0 +1,20 @@ +--- +title: "Guidelines for Data" +date: 2012-07-26T03:00:59-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: guidelines-for-data +excerpt: "The guidelines for data and how it pertains to Wordpress +" +--- + +The wonderful [Contents Magazine](http://contentsmagazine.com/) released a special report entitled [Data Protection](http://contentsmagazine.com/data/). In that report they outlined three principles for Data Protection. All three principles are fantastic, but number two really stood out to me. + +> No upload without download. Build in export capabilities from day one. + +That seems pretty straightforward, but I started thinking of this in the context of the sites I build for clients. Our platform of choice at my company is [Wordpress](http://www.wordpress.org) which has a capable Import/Export tool available. + +Is this enough? Do my clients know about it? Is the XML it exports good enough that clients can migrate platforms in a couple years? A quick bit of searching uncovered the [Export to Text](http://wordpress.org/extend/plugins/export-to-text/) plugin, which allows Wordpress users to export their data as plain txt files. This certainly seems better than XML, but again will my clients know how to use it if they want to leave? Should Wordpress have more robust export options built in? + +I don't have any answers right now, but I think it's important that I do. + +Do you have a solid solution for this type of situation? Let me know [@a\_simpson](http://www.twitter.com/a_simpson). diff --git a/themes/cycle/exampleSite/content/post/hacking-on-grafana-with-web-assembly.md b/themes/cycle/exampleSite/content/post/hacking-on-grafana-with-web-assembly.md new file mode 100644 index 0000000..7a59f12 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/hacking-on-grafana-with-web-assembly.md @@ -0,0 +1,146 @@ +--- +title: "Hacking on Grafana with Web Assembly" +date: 2022-08-19T15:10:19-0400 +lastmod: 2022-08-19T15:10:19-0400 +slug: hacking-on-grafana-with-web-assembly +excerpt: "Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM." +--- + + +[Grafana](https://grafana.com/) had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. + +The original inspiration for this idea came from [Simon Willison’s work with Datasette Lite](https://simonwillison.net/2022/May/4/datasette-lite/). However, compiling Grafana as a WASM binary proved [difficult](https://github.com/golang/go/issues/32548) with existing [build constraints](https://pkg.go.dev/go/build#hdr-Build_Constraints). After spending some time trying to get that to work I changed course a bit and instead focused on compiling a basic `go` HTTP server as a WASM module. The new goal being to have a proof of concept that bundled the HTTP server as a WASM binary and intercepted any clicked links on the page and finally passed those links to be resolved by the `go` server in WASM. + +I used a [Web Worker](https://developer.mozilla.org/en-US/docs/WebAssembly/Concepts) to interact with the WASM binary. This frees up the main thread of the browser. To put the WASM binary into the worker I loaded the binary and sent a message that contained the binary as a [`WebAssembly.Module`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module). + +The Web Worker can then call any `go` functions that have been exposed via [`FuncOf`](https://pkg.go.dev/syscall/js#FuncOf). Once the `go` function returns data, the worker posts that response back to the main thread via another message. + +```js +let module; +importScripts("wasm_exec.js") +go = new Go(); + +self.onmessage = async (e) => { + if (e.data.type === "module") { + module = e.data.module; + return; + } + + if (module) { + console.log('Message received: ', e.data.path); + const instance = await WebAssembly.instantiate(module, go.importObject); + go.run(instance); + postMessage(parsePath(e.data.path)); // parsePath is exposed via FuncOf + } +} +``` + +Sidenote: I wish `go` could use the same pragma syntax `tinygo` uses to expose functions instead of the verbose `FuncOf`. There's [an issue](https://github.com/golang/go/issues/25612) but it has been open since 2018. + +Obviously, there is no `localhost` to listen on in a WASM environment. To get around that I created a bare bones [`ResponseWriter`](https://pkg.go.dev/net/http#ResponseWriter) and used that with the [`Request`](https://pkg.go.dev/net/http#Request) to run the Handler’s [`ServeHTTP`](https://pkg.go.dev/net/http#HandlerFunc.ServeHTTP) function which consults the routes that are defined and runs the matching handler code. This allowed me to use a build constraint (`setup.go` and `setup_js.go`) and keep my HTTP server functioning normally when run from a terminal but then also worked when run in a WASM context. Here's what those two files look like: + +`setup` + +```go +//go:build !js +// +build !js + +package main + +import ( + "fmt" + "net/http" +) + +func setup() { + s := NewServer() + err := http.ListenAndServe(":9001", s.mux) + if err != nil { + fmt.Println("error: ", err) + } +} +``` + +`setup_js` + +```go +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "syscall/js" +) + +type ResponseWriter struct { + Body *bytes.Buffer +} + +func (r ResponseWriter) Header() http.Header { + return make(http.Header) +} + +func (r ResponseWriter) Write(buf []byte) (int, error) { + if r.Body != nil { + r.Body.Write(buf) + } + return len(buf), nil +} + +func (r ResponseWriter) WriteHeader(statusCode int) {} + +func createWriter() ResponseWriter { + return ResponseWriter{ + Body: new(bytes.Buffer), + } +} + +func parsePath(this js.Value, args []js.Value) interface{} { + fmt.Println("args: ", args) + server := NewServer() + path := args[0].String() + req, err := http.NewRequest(http.MethodGet, path, nil) + + if err != nil { + fmt.Println("request error: ", err) + } + + h, p := server.mux.Handler(req) + + fmt.Println("pattern: ", p) + + w := createWriter() + + h.ServeHTTP(w, req) + + b, err := ioutil.ReadAll(w.Body) + + if err != nil { + fmt.Println("ioutil error: ", err) + } + + return string(b) +} + +func setup() { + js.Global().Set("parsePath", js.FuncOf(parsePath)) +} +``` + +## Conclusions + +The PoC worked! It's pretty slick to see a HTTP server running in WASM return back the correct data when a link is clicked. However, in my opinion, WASM continues to be a "solution in search of a problem". Yes it's incredibly cool technology but so are the JS engines in Chrome, Firefox, and Safari. The sheer amount of money and engineering time being spent on making JS fast is a race no other technology can win at the moment. + +That said, Go seems to have done decent work at providing the necessary pieces to make compiling to WASM not awful. + +Honestly, the thing that surprised and impressed me the most was working with Web Workers. They are seriously useful and seem to "just work". + +## Links that helped me out along the way + +- [Simon Willison’s post about Datasette Lite](https://simonwillison.net/2022/May/4/datasette-lite/) +- [Philippe Charrière's post](https://blog.suborbital.dev/foundations-wasm-in-golang-is-fantastic) +- [Roman Romadin's post](https://itnext.io/webassemply-with-golang-by-scratch-e05ec5230558) diff --git a/themes/cycle/exampleSite/content/post/hello-micro-blog.md b/themes/cycle/exampleSite/content/post/hello-micro-blog.md new file mode 100644 index 0000000..34a1820 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/hello-micro-blog.md @@ -0,0 +1,25 @@ +--- +title: "Hello micro.blog" +date: 2018-02-01T16:45:31-05:00 +lastmod: 2018-02-01T16:45:31-05:00 +slug: hello-micro-blog +excerpt: "Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting." +--- + +👋 [micro.blog](https://micro.blog/) + +I've started posting my normal blog feed *and* a new micro feed to . My motivation for integrating with [micro.blog](https://micro.blog/) is that it feels like the right approach for the "open web". + +It did take me awhile to understand the core concepts of micro.blog. The description on the iOS App Store is illuminating: + +![Instead of trying to be a full social network, Micro.blog is a thin layer that glues the open web together, making it more useful. Micro.blog adds discovery and conversations on top of previously unconnected blog posts.](https://adamsimpson.net/images/micro-blog-description.jpg) + +Brent Simmons (of [inessential.com](http://inessential.com/)) had a [good post today](http://inessential.com/2018/02/01/why_micro_blog_is_not_another_app_net) summarizing what makes micro.blog different from app.net or other social networks: + +> And so everyone who follows me on Micro.blog sees my blog posts, and I see theirs. Simple. +> +> And anyone who wants to could just read my blog in an RSS reader instead. All good, all open. + +Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting. + +So hop on board\! Follow me over at [micro.blog/simpson](https://micro.blog/simpson) or subscribe directly to my new [micro feed](https://adamsimpson.net/micro/feed.json). diff --git a/themes/cycle/exampleSite/content/post/hello-world.md b/themes/cycle/exampleSite/content/post/hello-world.md new file mode 100644 index 0000000..19e9d17 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/hello-world.md @@ -0,0 +1,66 @@ +--- +title: "Hello World" +date: 2012-06-24T03:01:00-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: hello-world +excerpt: "I'm proud, nervous, and a little surprised that adamsimpson.net is finally live! +" +--- + +I'm proud, nervous, and a little surprised that adamsimpson.net is finally live\! It has been a long time in the making, and I'm relieved to have it up. Now the fun begins. + +### A Little About Me + +To sum me up, I'll bust out the 'ol bullet points. + + - I work for a [small web shop](http://www.fewloosescrews.com), based in Pennsylvania (though I live in Ohio) and do anything from front-end development and design to "social media" and copy-writing. + - I am twenty-five years old and married to the greatest gal there is. + - I graduated from [college](http://www.cedarville.edu) with a degree in English Lit (the web is made of words, so this works, right? right?). + - I love: the interwebs, design, development, David Foster Wallace, C.S. Lewis, Don DeLillo, and Jimmy Eat World. + - I dislike: most vegetables, Windows (not the ones in buildings), Jane Austen, bad drivers, and when the blinds in our apartment are open at night, it just skeeves me out. + +### About This Site + +Still here uh? Brave. Very brave. You have leveled up +1 in patience. + +Anyway, my vision for this site is a place where I can share the things I'm learning as I do my job, so lots of nerdy posts about front-end development stuff, design stuff, and writing stuff. I'll probably also throw in observations on the latest tech gadgetry. I may also do more general posts regarding general creative work or whatever else strikes my fancy. + +### Technical Bits + +This site is powered by [Jekyll](http://jekyllrb.com/), a static-site generator. Jekyll is fantastic for a number of reasons, but I love it because I give it text files, and it gives me my site. + +I've modified my Jekyll install a bit. I added [Steven Romej's permalink changes](https://github.com/azsromej/jekyll/commit/4b039b2804bc34382add7462f4e0f47c255e2151) to stop Jekyll from creating 'post-name-as-a-folder-\>index.html' to 'post-name-as-a-file.html'. I also adopted the pagination changes from [Dane Harrigan's fork](https://github.com/daneharrigan/jekyll). + +Jekyll is running on top of a [Linode 512](http://www.linode.com/?r=a4bf52b7804eb5bb3add85d3caeeee5f1d84cf67) running Unbuntu and [Nginx](http://nginx.com/). I added one line to my Nginx conf file to support better permalinks thanks to [this great post](http://www.allampersandall.com/2012/06/nginx-rewrite-remove-html). I just used the one line, `try_files $uri.html $uri/ 404.html;`. + +My posting process is simple and straightforward, all I need is Dropbox and a text editor. Usually this means I am using [iA Writer](http://www.iawriter.com/), which happily melds the two requirements (and works on my iPhone, iPad, or Mac). I simply write a post and save it in my posts folder in Dropbox. Dropbox takes care of syncing it to the Linode which has Dropbox and a shared copy of my site folder. When a new post is synced up, Jekyll builds my site with the new data and it's done, the post is live. + +Now I owe [Ted Kulp](http://tedkulp.com/2011/05/22/automating-jekyll-builds/) and [Tyler Hall](http://clickontyler.com/blog/2011/11/publishing-your-blog-with-dropbox-and-jekyll/) a beer for their posts that got me going with this Dropbox to Jekyll setup. I followed Mr. Kulp's idea and had [incron](http://inotify.aiken.cz/?section=incron&page=doc&lang=en) fire a little bash script when a new post came in from Dropbox. + +The other obvious benefit to having my site in Dropbox is that my site is automatically backed up. + +### Hardware + +And now, the infamous, what-do-I-use-at-my-desk section. + +Well, I currently use a 15" MacBook Pro circa 2009. I connect it to an old 20" Dell LCD at my desk, and also use a Apple Wireless Keyboard, and Magic Mouse. + +I also have an iPhone 4, iPad 2, and a Kindle. + +Overall, I'm happy with my current setup, though I do plan on picking up an SSD + 8GB of RAM in the near future. + +### Software + +As I already mentioned, I use [iA Writer](http://www.iawriter.com/) to write this site, and also for any writing needs for work. I also use [Simplenote](http://simplenoteapp.com/) & [NValt](http://brettterpstra.com/project/nvalt/) for quick thoughts and to-do lists on the go. + +I use Fireworks and Photoshop for any design related work. I use a combination of [Transmit](http://panic.com/transmit/) and [Sublime Text 2](http://www.sublimetext.com/2) for my FTPing and coding needs. Terminal is usually open for Git, or server tomfoolery. + +Finally, for my browsers I use Safari & [Chrome Canary](https://tools.google.com/dlpage/chromesxs) for browsing and development respectively. + +### The End + +I hope this wall of text isn't too intimidating and that you learned a little bit about me and what makes this site tick. Just a word of warning, the look and feel of this site may change from time to time. I love to tinker, so consider it a constant work in progress. Thanks for reading. + +Stick around and enjoy the ride with me\! + +\-Adam diff --git a/themes/cycle/exampleSite/content/post/helm-to-ivy.md b/themes/cycle/exampleSite/content/post/helm-to-ivy.md new file mode 100644 index 0000000..9b36488 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/helm-to-ivy.md @@ -0,0 +1,24 @@ +--- +title: "From helm to ivy" +date: 2017-08-14T23:10:07-04:00 +lastmod: 2017-08-15T11:28:18-04:00 +slug: helm-to-ivy +excerpt: "A log of my experience switching from helm to ivy; two completion plugins for emacs." +--- + +I started playing around with [Ivy](https://github.com/abo-abo/swiper) earlier today. I was motivated in part by reading through the author's blog, [oremacs](http://oremacs.com). I also love his swiper plugin and figured I had to give Ivy a try. + +## Background + +For the record I discovered [Helm](https://github.com/emacs-helm) about 20 minutes into my initial foray into emacs. I ❤ Helm. I support the project on [Patreon](https://www.patreon.com/emacshelm). It's great. I'm all about mastering my tools though and to do that I need to at least try other tools. Enter my attempt to switch to Ivy. + +## Progress + +This post isn't meant to be a finished product. I'm going to try and circle back occasionally as I use Ivy for the next couple days. A few notes on my experience so far: + + - I somehow had an old version of Ivy installed and when I went to install counsel I was getting weird errors. Deleting Ivy from my `elpa` directory manually cleared things up. + - Wow, by default, Ivy feels much more sparse than Helm. The first thing I had to do was figure out the "buffers list" implementation and change my `C-=` binding from helm to ivy. It's definitely more spartan, but I don't *think* its a negative necessarily just a change. + - Ivy is just a completion package, by itself it doesn't do a ton. That's why it comes with `counsel` and `swiper` these are the primary interfaces to the good stuff, e.g. `counsel-ag` searches your project with [Silver Searcher](https://github.com/ggreer/the_silver_searcher). + - Previews are incredible\! Thanks to [this comment](https://www.reddit.com/r/emacs/comments/51lqn9/helm_or_ivy/d7d4420/) on reddit. With the `C-M-n` and `C-M-p` commands you cycle through any matches and you see the entire file in the buffer. Imagine searching for a keyword in a project and then getting to see all the glorious context as you pick through the matches without having to open every single file\! + - ~~Not sure how to completely prevent a package from loading. I don't want `helm` to load while I play with Ivy. The `:disabled:` keyword in use-package doesn't really prevent it from being loaded, it just prevents the `use-package` form from being executed. I ended up relying on `git` and removed the lines from my .emacs and I `rm -rf` the helm package directories.~~ I looked at this again after sleeping on it. I defined two variables `simpson-evil` and `simpson-helm` and I check those values in my config to set up configurations depending on which packages is available. Easy enough. + - I had a epiphany about how `use-package` works. `use-package` will auto load any package that has a `:bind`, `:mode`, `:command`, or `:init` keyword. If all you have is `:config` that package won't load itself. However adding `:defer 1` will load that package once emacs is idle for a second and then fire off the `:config` body. So far so good. `:disabled` comes into play even if you have a `:after` keyword because if you have `:after` combined with any of the "auto load" keywords above the package will try to do stuff. diff --git a/themes/cycle/exampleSite/content/post/heroku-and-ssh-keys.md b/themes/cycle/exampleSite/content/post/heroku-and-ssh-keys.md new file mode 100644 index 0000000..5177a10 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/heroku-and-ssh-keys.md @@ -0,0 +1,10 @@ +--- +title: "Heroku and SSH Keys" +date: 2012-09-21T03:01:00-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: heroku-and-ssh-keys +excerpt: "Quick solution to fixing Heroku SSH key errors using ssh config. +" +--- + +[Heroku](http://www.heroku.com/) rocks. I've been using it to host this blog (for free, mind you) for the last couple months. However, I've run into a problem where Heroku refuses to authorize a `git push heroku` by declaring `Permission denied (publickey)`. After messing around deleting, creating, and re-adding SSH keys, I found these [two](http://zylstra.wordpress.com/2008/08/29/overcome-herokus-permission-denied-publickey-problem/) [posts](http://eveningsamurai.wordpress.com/2011/07/13/herokus-permission-deniedpublickey-problem/) that solved the problem for me. Apparently Heroku fails if you point it to any kind of custom SSH key. Simply add Heroku to your SSH config file and specify the key to use, problem solved. diff --git a/themes/cycle/exampleSite/content/post/hiking-the-pacific-crest-trail-in-three-minutes.md b/themes/cycle/exampleSite/content/post/hiking-the-pacific-crest-trail-in-three-minutes.md new file mode 100644 index 0000000..9ec4369 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/hiking-the-pacific-crest-trail-in-three-minutes.md @@ -0,0 +1,10 @@ +--- +title: "Hiking the Pacific Crest Trail in Three Minutes" +date: 2020-05-07T10:27:56-04:00 +lastmod: 2020-05-07T10:27:56-04:00 +slug: hiking-the-pacific-crest-trail-in-three-minutes +excerpt: "The Pacific Crest Trail runs 2650 miles from the border of Mexico to the border of Canada through California, Oregon, and Washington. Hiking the whole thing usually takes months, but this video by Mac of Halfway Anywhere compresses the entire experience down to just three minutes presented in 1-second snippets." +link: "https://kottke.org/20/05/hiking-the-pacific-crest-trail-in-three-minutes" +--- + +> [The Pacific Crest Trail](https://www.pcta.org/discover-the-trail/) runs 2650 miles from the border of Mexico to the border of Canada through California, Oregon, and Washington. Hiking the whole thing usually takes months, but this video by Mac of [Halfway Anywhere](https://www.halfwayanywhere.com/) compresses the entire experience down to just three minutes presented in 1-second snippets. diff --git a/themes/cycle/exampleSite/content/post/hosting-assets-via-github-pages.md b/themes/cycle/exampleSite/content/post/hosting-assets-via-github-pages.md new file mode 100644 index 0000000..71e4e64 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/hosting-assets-via-github-pages.md @@ -0,0 +1,31 @@ +--- +title: "Hosting assets via Github Pages" +date: 2018-05-11T15:41:35-04:00 +lastmod: 2018-05-11T15:41:35-04:00 +slug: hosting-assets-via-github-pages +excerpt: "Screenshots in README.mds are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult." +--- + +Screenshots in `README.md`s are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult. There are a couple options: + +## The Problem + +1. Upload the image to a image hosting service and then reference the direct URL in the `README.md`. +2. Check the image into the repo and reference its `raw` URL in the `README.md`. + +Both of these have their downsides. The first option means that your image is tied to the uptime of the image hosting service. If the service is down your image is now 404. Option two means you have the image mixed in with your source files which stinks from an organizational perspective. + +## The Solution + +The solution is fairly obvious but took me awhile to realize it: use [Github pages](https://pages.github.com) by pushing assets to the `gh-pages` branch. + +Hosting assets via Github pages means I don't have to worry about the image hosting service uptime since Github is hosting both the `README.md` and the asset now. I also don't have to worry about those assets cluttering my source directories because Github pages uses a specific branch `gh-pages` and those assets only show up when that branch is checked out. + +Here's a quick walk-through of how to push an image to Github pages (assuming there isn't a `gh-pages` branch yet). + +1. Create a `gh-pages` branch off of `master` (usually). +2. Add the image to the repo via `git add /path/to/image`. +3. Stage, commit, and push the branch to Github. +4. Go to Github and head to your project settings to grab the Github pages URL. Append the asset name to the end of it and check if you can view the image in your browser. +5. Go back to the command line and checkout `master`. +6. Add the image to the `README.md` and check it in. diff --git a/themes/cycle/exampleSite/content/post/how-are-you-living.md b/themes/cycle/exampleSite/content/post/how-are-you-living.md new file mode 100644 index 0000000..1e08816 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/how-are-you-living.md @@ -0,0 +1,12 @@ +--- +title: "How are you living" +date: 2012-09-06T03:01:01-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: how-are-you-living +excerpt: "Shawn Blanc poses some tough questions about life and purpose +" +--- + +One of my favorite writers, [Shawn Blanc](http://shawnblanc.net/) recently published a short piece entitled, [Most People](http://shawnblanc.net/2012/09/most-people/). I highly encourage everyone to head over and read the entire essay. However, because I love the ending so much, I had to share it here as it is truly fantastic: + +> Here’s a metric that can help you determine if you’re on track for reaching your goals: are you spending your time, money, and attention differently than most people? diff --git a/themes/cycle/exampleSite/content/post/how-do-we-make-the-web-better.md b/themes/cycle/exampleSite/content/post/how-do-we-make-the-web-better.md new file mode 100644 index 0000000..71ebb28 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/how-do-we-make-the-web-better.md @@ -0,0 +1,53 @@ +--- +title: "How do we make the Web better" +date: 2016-01-29T11:12:52-05:00 +lastmod: 2016-01-29T11:12:52-05:00 +slug: how-do-we-make-the-web-better +excerpt: "My post for the Shift for January. I tackle the question within the question: how do we (internet workers) have more meaningful conversations in order to make the web better?" +--- + +[The introductory post for The Shift](http://seesparkbox.com/foundry/introducing_the_shift) started with this statement about Twitter (emphasis mine): + +> Twitter has become a dumping ground for ill-thought-out opinions. Removing the barriers to publishing seems like a great way to encourage people to be a part of discussions they might not otherwise. Unfortunately, for all its possibilities, *the platform can actually discourage well-thought-out conversation*. + +Ben is completely right, but I find the complaint framed around having a conversation especially apt. I've been reading *[Reclaiming Conversation: The Power of Talk in a Digital Age](http://amzn.to/1P1OATn)* by Sherry Turkle and she makes the same assertion regarding social media and how it warps our understanding of the very nature of conversation. She writes that: + +> As we ramp up the volume and velocity of our online connections, we want immediate answers. In order to get them, we ask simpler questions; we dumb down our communications, even on the most important matters. + +This is profound and terrifying. We've traded deeper conversations for shallow ones, as a culture we are preferring quantity over quality. + +## We've got to go deeper + +So, how do we make the Web better? Simple, go deeper and have more meaningful conversations. Done. We can all go home, thanks for reading everyone. + +Not so fast. The question within the question is how do we (internet workers) have more meaningful conversations in order to make the Web better? I don't have the answer, but I have a few ideas: + +1. Pick better places or platforms for these conversations. Twitter, Reddit, and Hacker News seem to have proven they are not the correct venue. + +2. Come with truckloads of empathy. + +3. Disconnect + +## Platforms + +I don't want to get all hippie-dippie, but writing on a blog ([with comments disabled](https://adactio.com/journal/1195)) seems like a promising alternative to social media. This is why I think the Shift is such a great idea. Blogs require work to write and work to read. That work or friction is closer to the work of an actual conversation. It's easier to blast out a snarky tweet, or rip someone apart in a comment thread. So let's start writing on blogs more and reacting to half-thoughts on Twitter less. + +## Empathy + +People always talk about empathy. It comes up everywhere, but in practice empathy is not very sexy. The dictionary definition of empathy from [Merriam-Webster](http://www.merriam-webster.com/dictionary/empathy) is: + +> the action of understanding, being aware of, being sensitive to, and vicariously experiencing the feelings, thoughts, and experience of another of either the past or present without having the feelings, thoughts, and experience fully communicated in an objectively explicit manner; also : the capacity for this + +Empathy is making the mental effort to think from another perspective. Empathy is having patience as someone struggles through formulating a thought. Empathy is time. We need this so badly in our conversations around the Web. We can't even begin to make the Web better if we're not going to take the time to consider other opinions or ideas. + +## Disconnect + +Turkle highlights another side of conversation that is fading, solitude. She writes that: + +> of the rewards of solitude is an increased capacity for self-reflection—the conversations we have with ourselves in the hope of greater insight about who we are and want to be. Professionally, what is our vocation? Personally, what gives us purpose and meaning? Can we forgive our transgressions and those of others? In self-reflection, we come to understand ourselves better and we nurture our capacity for relationship. + +To make the Web better we may need to step back and disconnect to better understand the world and how the Web fits in it. Instead of listening to podcast after podcast in our commutes, what if we spent 20 minutes just thinking in silence? Could we even bear it? We won't have those ideas to make the Web better without this "lonely thinking". + +## The future + +The Shift is a great opportunity to start formulating some of these ideas. I'm excited to see the writings and thoughts that emerge from this experiment. At its core the Web is conversations and relationships. To make it better we need to have better conversations which will enrich our relationships which will ultimately improve the Web. diff --git a/themes/cycle/exampleSite/content/post/how-to-use-siji-font-on-polybar.md b/themes/cycle/exampleSite/content/post/how-to-use-siji-font-on-polybar.md new file mode 100644 index 0000000..a9f5010 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/how-to-use-siji-font-on-polybar.md @@ -0,0 +1,14 @@ +--- +title: "How to use Siji font on polybar" +date: 2020-11-06T11:18:47-05:00 +lastmod: 2020-11-06T11:18:47-05:00 +slug: how-to-use-siji-font-on-polybar +excerpt: "" +link: "https://www.reddit.com/r/Polybar/comments/ht0jnr/guide_how_to_use_the_siji_font_on_polybar/" +--- + +Nice guide on Reddit about how to use the [Siji font](https://github.com/stark/siji) with polybar. + +> [..] install the siji font, and then run `"view.sh"` in the terminal. If you get an error, try to launch the `install.sh` again. You'll get a list of all the glyphs available, select the one you want [..] to use and then look where it says "Character 0x00e002" or something like that. + +Of note is that you'll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do. diff --git a/themes/cycle/exampleSite/content/post/huffduffer.md b/themes/cycle/exampleSite/content/post/huffduffer.md new file mode 100644 index 0000000..c9b2936 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/huffduffer.md @@ -0,0 +1,14 @@ +--- +title: "Huffduffer" +date: 2013-07-06T03:01:02-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: huffduffer +excerpt: "Use Huffduffer to listen to individual podcast episodes. +" +--- + +I [have quite the commute to Sparkbox](https://maps.google.com/maps?saddr=Columbus,+OH&daddr=Dayton,+OH&hl=en&ll=39.87075,-83.596344&spn=0.60499,1.277161&sll=39.982951,-82.990829&sspn=0.603995,1.277161&geocode=FVjCYQId9okN-ylx3pC5wYk4iDEztbHP-GYy5A%3BFWSsXgIdiVb7-ikDFN2u1YBAiDHkTA7ykuNApg&mra=ls&t=m&z=10), as such I listen to a lot of podcasts (usually via [Instacast](http://vemedio.com/products/instacast3) on my iPhone). + +My one pain point with this setup was when someone would recommend a specific episode of a podcast I didn't subscribe to. In order for me to listen to that episode, I would have to either download the MP3 and send it over to my phone via iTunes, stream it via Safari on my phone, or subscribe to the whole podcast in Instacast. None of those options are very convenient. + +Enter [Huffduffer](http://huffduffer.com/). *Huffduffer is simple genius*, I don't know why I didn't use it sooner\! Once you sign up for a Huffduffer account, you get your own Huffduffer feed URL. Subscribe to that feed and you're done. Now, when someone recommends a podcast episode, simply visit the episode page and click your Huffduffer bookmarklet to "huffduff" the episode. Your podcast app will receive the new episode via your Huffduffer feed subscription, sweet eh? diff --git a/themes/cycle/exampleSite/content/post/i-moved-to-hover.md b/themes/cycle/exampleSite/content/post/i-moved-to-hover.md new file mode 100644 index 0000000..b97ebb1 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/i-moved-to-hover.md @@ -0,0 +1,14 @@ +--- +title: "I moved to Hover" +date: 2012-09-09T03:01:02-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: i-moved-to-hover +excerpt: "I switched from GoDaddy to Hover. +" +--- + +In case you didn't hear, [Anonymous broke GoDaddy today](http://techcrunch.com/2012/09/10/godaddy-outage-takes-down-millions-of-sites/). I figured now would be as good a time as any to explain why I moved away from GoDaddy a few weeks ago. + +I chose [Hover](https://www.hover.com/) to be my GoDaddy replacement. I've never hosted anything through GoDaddy (I'm not a crazy person), but I did manage all my domain names through them. [Hover](https://www.hover.com/) and GoDaddy could not be more different, GoDaddy's interface is comedically awful, Hover's interface is relatively simple and light - two words you never, ever hear about GoDaddy's administrative panels. I figure that 90% of using a DNS service is spent in front of their admin interface, it counts to have a good one. + +I would highly recommend switching from GoDaddy to [Hover](https://www.hover.com/), or [Namecheap](http://www.namecheap.com/), or [DNS Simple](https://dnsimple.com/), the point is to switch *away from* GoDaddy not really where you switch to. So take the leap, and stop feeling sad inside when you hear another joke about GoDaddy. diff --git a/themes/cycle/exampleSite/content/post/ifttt.md b/themes/cycle/exampleSite/content/post/ifttt.md new file mode 100644 index 0000000..c477476 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/ifttt.md @@ -0,0 +1,34 @@ +--- +title: "IFTTT" +date: 2013-07-21T03:01:03-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: ifttt +excerpt: "Ways I use IFTTT. App.net to Twitter, App.net from Day One, and Camera Roll to FLickr. +" +--- + +I love [IFTTT](https://ifttt.com/). IFTTT is one of those awesome services that I desperately wished had a business plan. + +Here are a few of my favorite [IFTTT recipes](https://ifttt.com/wtf). + +### App.net to Twitter + +A few weeks ago I made the decision to give [ADN](https://alpha.app.net/a_simpson/) another try, largely because ADN offers a RSS feed of my posts, something Twitter thought was too complicated. So I decided to funnel my *original* posts through ADN and then post them to Twitter. IFTTT facilities all of this with ease. + +[Get the App.net to Twitter recipe](https://ifttt.com/recipes/53771) + +### Post to App.net from Day One + +I love [Day One](http://dayoneapp.com/), however it doesn't support posting to ADN. I set up an IFTTT recipe that works off an email from Day One and posts it ADN. This recipe also gets bonus points for working in conjunction with the above ADN To Twitter Recipe. + +[Get the post to ADN via Email recipe](https://ifttt.com/recipes/106909) + +### Camera Roll to Flickr + +This recipe is only possible through the new, delightful [IFTTT iOS app](https://ifttt.com/mobile). Whenever a new photo is taken, IFTTT uploads the photo to my [Flickr](http://www.flickr.com/) account. This recipe serves the second purpose of offloading my Camera Roll backups from iCloud to Flickr. + +[Get the Camera Roll to Flickr recipe](https://ifttt.com/recipes/106908) + +### Feature Request + +I do wish IFTTT had one additional feature, Feed actions. I would love to have a personal feed, ala [Huffduffer](http://www.adamsimpson.net/huffduffer), into which IFTTT would dump any data from the various IFTTT triggers. A Feed action would technically allow basic looping when combined with the Feed trigger, which would be super useful and interesting. diff --git a/themes/cycle/exampleSite/content/post/indexing-my-blogs-links.md b/themes/cycle/exampleSite/content/post/indexing-my-blogs-links.md new file mode 100644 index 0000000..ae75ecd --- /dev/null +++ b/themes/cycle/exampleSite/content/post/indexing-my-blogs-links.md @@ -0,0 +1,10 @@ +--- +title: "Indexing My Blog’s Links" +date: 2020-09-25T15:49:21-04:00 +lastmod: 2020-09-25T15:49:21-04:00 +slug: indexing-my-blogs-links +excerpt: "" +link: "https://blog.jim-nielsen.com/2020/indexing-my-blogs-links/" +--- + +Owning your content means you can do interesting things with that data. [Jim Nielsen](https://blog.jim-nielsen.com/) did just that by tweaking his static site generator to see all the outbound links he's ever posted. diff --git a/themes/cycle/exampleSite/content/post/introducing-cycle.md b/themes/cycle/exampleSite/content/post/introducing-cycle.md new file mode 100644 index 0000000..0313ce3 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/introducing-cycle.md @@ -0,0 +1,117 @@ +--- +title: "Introducing Cycle" +date: 2019-04-05T23:05:17-0400 +lastmod: 2019-04-05T23:05:17-0400 +slug: introducing-cycle +excerpt: "Cycle is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today." +--- + +[Cycle](https://github.com/asimpson/cycle) is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today. + + +## Language choice + +I wrote in my [previous post announcing](/writing/blog-rewrite) my re-write that I was considering Rust or Common Lisp because those languages allowed me to build a stand alone binary of my site builder. I got some feedback on Twitter that Common Lisp would actually be a good choice: + + + +I ended up going with Common Lisp and I really enjoyed the experience. Common Lisp has the best REPL I've ever used in any language. It's wonderful to use. Having a good REPL is a key component of not only creating new features but also fixing bugs. Once I had chosen the language it was time to figure out how I wanted my program to consume and build my site. + + +## Mimic Jekyll…to a point + +I spent some time understanding how [Jekyll](https://jekyllrb.com/) works to figure out which parts I wanted to emulate and which parts I wanted to leave behind or solve differently. + + +### JSON > YAML + +Jekyll relies heavily on YAML for data files and inside every post. The decision to include it in every post has always bugged me about Jekyll so I wondered what a static site generator would look like if it used JSON instead of YAML. In my implementation every post is represented as a Markdown file and data for that post is represented as a separate JSON file. The directory structure looks like this: + + ./ + ├── README.md + ├── posts + │   ├── a-few-bash-tips.json + │   ├── a-few-bash-tips.md + +While this increases the amount of files needed to build the site, I find keeping the Markdown files as "vanilla" as possible worth the trade-off. + + +### The Good Parts + +I copied Jekyll's directory and file structure pretty closely. The site is built from these source files into a directory called `site` that holds the entire site. Here's a breakdown of the required directories and files: + +- `public`: anything in `public` is copied over verbatim to `site`. This is the place to put assets like images, third-party JS etc. +- `posts`: contains posts that are processed through templates and dropped into `site`. Cycle processes all the posts into a data structure that is then available globally inside Cycle for any other part of the build process to use. +- `templates`: hold the various templates for pages and posts as well as templates for RSS and Sitemap. +- `pages`: holds files that are either `.mustache` files or `.md` files. If a page file is a `.md` file then it gets processed with a generic `templates/page.mustache` template. The only supported `.mustache` file at the moment is the `archive.mustache` file which is passed the entire post data object to generate paginated archive pages. +- `site.css` is a file in the root of the project. Any CSS in this file is inlined into the `` of the built site. + + +## Easy to add new features and fix bugs + +Another aspect I was hoping to solve with this re-write was to make it easier to add new features and fix bugs as they come up. Common Lisp's previously mentioned REPL helps in this area. [Slime is an Emacs extension](https://github.com/slime/slime) that integrates Common Lisp's REPL into Emacs along other functionality like debugger support. Having the ability to set breakpoints and execute portions of my program at will right inside my editor helps identify bugs. The expressiveness of Lisp also helps in ramping up on code that I wrote months ago. I've been using Cycle for a few months now and I've enjoyed that I don't feel overwhelmed when I have to look back at the code. + + +## Building binaries in Travis + +One last thing about Common Lisp and it's stand-alone binaries. I got [Travis CI](https://travis-ci.com/) hooked up and [building macOS and Linux versions of cycle](https://github.com/asimpson/cycle/blob/master/.travis.yml) without too much struggle. Now whenever I tag a new release Travis builds the binaries and attaches them to the [Release in Github](https://github.com/asimpson/cycle/releases/tag/v0.2.1). Automating this build and release work has made the actual hosting and building of the site pretty painless. + + +## Netlify + +I switched from AWS S3 to Netlify not because S3 was inadequate in anyway but more because I wanted an excuse to play with Netlify's features. I ended up writing a [`Makefile`](https://github.com/asimpson/blog/blob/master/Makefile) that Netlify can execute to download the latest version of Cycle and then build the site. Netlify is configured to run `make cycle && make` when a new post is pushed to the repo. + + +## Some Common Lisp helper functions + +Over the course of getting a working version of Cycle out the door I wrote a few helper functions that remove some friction in some common tasks. + + +### String concat + +The `concatenate` function in Common Lisp is a general purpose function that works over strings as well as lists and other data types. It's typically used like this: `(concatenate 'string "hello" "world")`. Notice that `concatenate` requires that the type of the values to be specified. I didn't like this so I wrote this: + +```common-lisp +(defun concat (&rest strings) + "Wrapper around the more cumbersome concatenate form." + (let (result) + (dolist (x strings) + (setf result (concatenate 'string result x))) + result)) +``` + +`concat` takes any number of strings and uses the `dolist` macro to call `concatenate` on them. It's used like this: `(concat "hello" "world")`. Much better in my opinion. + + +### Write to file + +Cycle writes a lot of files. That's pretty much it's main jam. I realized I was writing the same boilerplate to write files all over the place so I wrote a wrapper function: + +```common-lisp +(defun write-file (contents file) + "Write CONTENTS to FILE." + (with-open-file (stream file + :direction :output + :if-exists :supersede) + (write-sequence contents stream))) +``` + +Now I can write a file like this: `(write-file "Hello world" "./hello-world")`. + + +### String splitting + +The last helper function I want to show is my wrapper around the [`UIOP:split-string`](https://common-lisp.net/project/asdf/uiop.html) function. Much like the `concat` function this mainly avoids extra typing: + +```common-lisp +(defun split-string (string sep) + "Wrapper around uiop:split-string to avoid keyword typing." + (uiop:split-string string :separator sep)) +``` + +Now I can split a string like this: `(split-string "Hello World" " ")`. Much easier. + + +## Never done + +While I may be using Cycle to publish this very site it's not done and I don't think it ever will be. That's the beauty of software and specifically software written for an audience of me. I will always have new ideas and things I want to fix and Common Lisp provides some fairly unique and fun ways to keep iterating. diff --git a/themes/cycle/exampleSite/content/post/introducing-ivy-feedwrangler.md b/themes/cycle/exampleSite/content/post/introducing-ivy-feedwrangler.md new file mode 100644 index 0000000..695cbec --- /dev/null +++ b/themes/cycle/exampleSite/content/post/introducing-ivy-feedwrangler.md @@ -0,0 +1,32 @@ +--- +title: "Introducing ivy-feedwrangler" +date: 2017-11-16T11:06:20-05:00 +lastmod: 2017-11-16T11:06:20-05:00 +slug: introducing-ivy-feedwrangler +excerpt: "In exploring what Ivy was capable of I had the idea to write a small package that used Ivy as the interface for my RSS service of choice, Feedwrangler." +--- + +It's not secret that I've become quite the Emacs fan over the past couple years. One of my favorite things about Emacs is the [Ivy package](https://github.com/abo-abo/swiper) (and counsel and swiper of course). In exploring what Ivy was capable of I had the idea [to write a small package](https://github.com/asimpson/ivy-feedwrangler) that used Ivy as the interface for my RSS service of choice, [Feedwrangler](http://feedwrangler.net). You can check out the repository [here](https://github.com/asimpson/ivy-feedwrangler) and [install the package via melpa](https://melpa.org/#/ivy-feedwrangler). + +## What is Ivy? + +Ivy is, according to it's [Github repo](https://github.com/abo-abo/swiper), a "a generic completion mechanism for Emacs." Quite simply Ivy is an interface for quickly working with lists of data whether that be: + + - fuzzy-finding commands + - searching for files in a project + - [interacting](https://github.com/ecraven/ivy-pass) with the [pass unix password manager](https://www.passwordstore.org) + - [browsing lobste.rs](https://github.com/julienXX/ivy-lobsters) + - or [searching youtube](https://github.com/squiter/ivy-youtube) + +## Ivy-feedwrangler + +Ivy makes manipulating and filtering lists super quick and easy. In fact, I'd say it's *the* quickest way to work with this kind of data. Working with my RSS feed is now lightning fast. Here are a few features of ivy-feedwrangler: + + - Mark individual posts as read or mark all as read + - View text posts inside a buffer in Emacs, this supports [inline images](https://asimpson.github.io/ivy-feedwrangler/images/post-view.png)\! + - Quickly filter through unread items since Ivy can handle regex out of the box + - Uses [authinfo](https://www.emacswiki.org/emacs/GnusAuthinfo) to handle authentication which uses GPG to encrypt credentials. + +The other big perk to using ivy-feedwrangler is that, unlike [elfeed](https://github.com/skeeto/elfeed) (*the* package for RSS in Emacs), it interacts directly with the [Feedwrangler API](https://feedwrangler.net/developers)\! That means I can read things in Emacs and that state is synced correctly to my phone and vice-versa. + +So, if you have a Feedwrangler account, give ivy-feedwrangler a try and let me know what you think\! diff --git a/themes/cycle/exampleSite/content/post/ip-address-alfred-extension.md b/themes/cycle/exampleSite/content/post/ip-address-alfred-extension.md new file mode 100644 index 0000000..eab3c00 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/ip-address-alfred-extension.md @@ -0,0 +1,14 @@ +--- +title: "IP Address Alfred Extension" +date: 2012-12-07T03:01:04-05:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: ip-address-alfred-extension +excerpt: "I enhance the previous IP bash function as an Alfred Extension +" +--- + +I have to admit, I am addicted to customizing my [bash](http://en.wikipedia.org/wiki/Bash_\(Unix_shell\)) experience. Yesterday, I came up with a little, one-off function that smooths over a point of friction in my workflow – working with my internal IP address. + +During any project, I am often testing in virtual machines. On my development machine I have my [host file hacked](http://www.adamsimpson.net/a-few-bash-tips) to manage all the dev URLs. The friction point is constantly having to look up my IP address to test in VMs, or on other devices. This bash function simply parses out my IP address from the results of 'ifconfig' and copies that IP address to my clipboard. Now, instead of jumping into the Network pane to see my IP, or reading through ifconfig myself, I can simply type "ip", and jump back to my VM and paste in the address. The function also displays the IP address on the command line ready for easy typing into a mobile device. + +` function ip { IP=$(ifconfig | grep 'inet 1' | cut -c 6- | awk 'NR==2 {print $1}') echo $IP echo $IP | pbcopy } ` diff --git a/themes/cycle/exampleSite/content/post/iphone-checker-with-capybara-and-twilio.md b/themes/cycle/exampleSite/content/post/iphone-checker-with-capybara-and-twilio.md new file mode 100644 index 0000000..b37c1d2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/iphone-checker-with-capybara-and-twilio.md @@ -0,0 +1,26 @@ +--- +title: "iPhone checker with Capybara and Twilio" +date: 2014-10-30T03:01:05-04:00 +lastmod: 2015-04-03T11:53:41-04:00 +slug: iphone-checker-with-capybara-and-twilio +excerpt: "I set up a small Heroku app that uses Capybara to check Apple's website for availability and sends a text to my phone via Twilio. +" +--- + +I got my gigantic iPhone 6+ last weekend, and not via the online Apple Store where my order had been sitting for a couple weeks and wasn't going to ship until Nov. 5th. Instead I got a friendly text message the minute the phone was available at my local Apple Store. With a few great tools it was incredibly easy to set this system up. + +TL;DR: I set up a small Heroku app that uses [Capybara](https://github.com/jnicklas/capybara) to check Apple's website for availability and sends a text to my phone using the [Twilio service](https://www.twilio.com). + +The entire process was pretty simple once I figured out a few Heroku oddities. The app hinges on the fact that Apple provides a "Check Availability" link during the ordering process. This link pops open a modal that take your zip code and checks nearby Apple stores for your product. + +All I had to tell Capybara to do was visit the URL, click the check availability button, and enter my zip code. After that I loop through the store list and check the status message. If the phone is available I send myself a text with the store name, phone model, and link. + +The toughest part of this project was figuring out how to tell Heroku where the [Phantomjs](http://phantomjs.org) executable was located. Capybara uses Phantomjs behind the scenes and without it the whole thing wouldn't work. I initially tried to use [the Phantomjs build pack](https://github.com/stomita/heroku-buildpack-phantomjs) but a weird thing with Heroku is that declaring a build pack seemingly removes the path for the Ruby executable. I then discovered the awesome [multi build pack](https://github.com/ddollar/heroku-buildpack-multi) tool. Once I created my `.buildpack` document I just had to tell Heroku to load the Phantomjs build pack *and* the Ruby build pack like this: + +``` +https://github.com/stomita/heroku-buildpack-phantomjs.git https://github.com/heroku/heroku-buildpack-ruby +``` + +The last piece of the app uses [clockwork](https://github.com/tomykaira/clockwork) to kick off the scrape every 10 minutes. Clockwork is incredibly easy to setup and use. Specify the command in the `Procfile` and Heroku will understand exactly what to do. + +The [code for the project can be found over at Github](https://github.com/asimpson/phone-checker). Reach out on [Twitter](https://twitter.com/a_simpson) or file an issue if you have any questions. diff --git a/themes/cycle/exampleSite/content/post/is-webp-really-better-than-jpeg.md b/themes/cycle/exampleSite/content/post/is-webp-really-better-than-jpeg.md new file mode 100644 index 0000000..e57f233 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/is-webp-really-better-than-jpeg.md @@ -0,0 +1,14 @@ +--- +title: "Is WebP really better than JPEG?" +date: 2020-06-30T13:13:04-04:00 +lastmod: 2020-06-30T13:13:04-04:00 +slug: is-webp-really-better-than-jpeg +excerpt: "" +link: "https://siipo.la/blog/is-webp-really-better-than-jpeg" +--- + +> If you have used tools like Google’s PageSpeed Insights, you probably have run into a suggestion to use “next-gen image formats”, namely Google’s [WebP image format](https://developers.google.com/speed/webp). Google [claims that](https://developers.google.com/speed/webp/docs/webp_study) their WebP format is 25 – 34% smaller than JPEG at equivalent quality. + +> In any case, when converting images to WebP, check that they are actually smaller than the JPEG equivalent. There’s no need to serve larger images to your users than needed. + +Great analysis of the WebP image format and a good reminder to not blindly follow what various auditing tools are reporting. Test and verify in addition to implementing the various suggested improvements. diff --git a/themes/cycle/exampleSite/content/post/ivy-pinboard-popular.md b/themes/cycle/exampleSite/content/post/ivy-pinboard-popular.md new file mode 100644 index 0000000..c63893c --- /dev/null +++ b/themes/cycle/exampleSite/content/post/ivy-pinboard-popular.md @@ -0,0 +1,40 @@ +--- +title: "Pinboard popular page in Emacs" +date: 2018-04-26T23:12:34-04:00 +lastmod: 2018-04-26T23:16:14-04:00 +slug: ivy-pinboard-popular +excerpt: "A quick look at how I made an Ivy extension that displays the links from the pinboard.in popular page" +--- + +Ok, this one is still piping hot in my `*scratch*` buffer so remember that before you criticize the rough edges. I've long wanted to quickly filter through the [popular links page](https://pinboard.in/popular) on [pinboard.in](https://pinboard.in) without jumping over to a browser. Ideally this page would have an RSS feed or API end point but alas it has neither. I love [pulling things into Emacs](https://github.com/asimpson/ivy-feedwrangler) (yay for text-based interfaces\!); so I set out to pull these links into Emacs and display them via [Ivy](https://github.com/abo-abo/swiper). + +Feel free to skip ahead and [checkout the repo](https://github.com/asimpson/ivy-pinboard-popular) if you're so inclined. + +## Steps + +I `curl`ed the page down and pasted the HTML into a buffer in Emacs so I could start pulling things apart. My first attempt was to use the excellent [`elquery` library](https://github.com/AdamNiederer/elquery) but that was choking on the DOM structure and I never could quite pin down where (sorry Adam, I need to post an issue about that\!). My next attempt was to use a more "manual" scripting approach. Since Emacs possesses so many ways to manipulate buffer text I was sure there could be a programmatic way to do this (without doing a bunch of regexing which I'm terrible at and even more so in Emacs). The basic series of steps boiled down to this: + + - Use the new-to-me `keep-lines` function to trim everything out of the buffer *except* the popular links. I used the classname of the links (`bookmark_title`) to identify them. + - Use `loop-for-each-line` to well loop over each line. Inside this loop I would need to pull out the `href` and the title of each anchor link. + - I used `re-search-forward` to move from target to target to figure out the point boundaries for my href and my link text. + +I ended up breaking this functionality out into it's own function since I used it more than once and it was cumbersome to type it all out. + +``` elisp + (defun re-capture-between(re-start re-end) + "Return the string between two regexes." + (let (start end) + (setq start (re-search-forward re-start)) + (setq end (re-search-forward re-end)) + (buffer-substring-no-properties start end))) +``` + + - The final step was dumping the `href` and the link text into a plist and `push` that into a larger collection I could pass onto `ivy-read` to generate my interface. + +## Coding string + +One gotcha I ran into is that my titles would occasionally contain odd character sequences like `\302`. Turns out those are punctuation and various text symbols. The solution is to run the title through `decode-coding-string` for `'utf-8` to generate the proper characters. + +## ❤ Emacs + +Emacs is so powerful for this type of text manipulation because you can interactively work each step of a program out in an actual buffer and then put those steps together into a function. Each potential solution I thought of was quickly trialed via `M:` and frequent looks at documentation. Hopefully this has been a helpful look into how I approach solving problems in Emacs. Thanks for reading\! diff --git a/themes/cycle/exampleSite/content/post/js2coffee-alfred-workflow.md b/themes/cycle/exampleSite/content/post/js2coffee-alfred-workflow.md new file mode 100644 index 0000000..62fe0de --- /dev/null +++ b/themes/cycle/exampleSite/content/post/js2coffee-alfred-workflow.md @@ -0,0 +1,14 @@ +--- +title: "JS2Coffee Alfred Workflow" +date: 2013-07-08T03:01:06-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: js2coffee-alfred-workflow +excerpt: "An Alfred workflow that converts Javascript to Coffeescript +" +--- + +Update: + +I changed the download link to point to the repo release page to ease future updates. + +[Updated Download link](https://github.com/asimpson/js2coffee-alfred-workflow/releases) diff --git a/themes/cycle/exampleSite/content/post/just-start-over.md b/themes/cycle/exampleSite/content/post/just-start-over.md new file mode 100644 index 0000000..ac85673 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/just-start-over.md @@ -0,0 +1,16 @@ +--- +title: "Just Start Over" +date: 2012-07-19T03:01:06-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: just-start-over +excerpt: "Sebastiaan De With describes his design process for doubleTwist's Alarm Clock +" +--- + +I love when designers write about their experience and process in designing a product. + +Recently, [Sebastiaan De With wrote a post](http://dewith.com/2012/an-android-design-process/) about his experience designing the [doubleTwist Alarm Clock](http://doubletwist.com/alarmclock/), an Android Clock app made by [doubleTwist](http://www.doubletwist.com/). I found myself nodding my head at this paragraph in his write up: + +> During the process, I threw away a ton of designs and simply started over. I also touched on this being an important part of the design process in [the interview I gave on design.org](http://design.org/blog/interview-doubletwist-alarm-ui-designer-sebastiaan-de): when you feel like what you’re working on really needs a little bit extra, you have to realize that — even though you spent so much time on them — your designs are just pixels, and you can probably simply do better. Throw it out. Kill your baby. Start over. It’s made this app what it is today. + +Starting over is a skill, and it's something I need to get better at. diff --git a/themes/cycle/exampleSite/content/post/keeping-up.md b/themes/cycle/exampleSite/content/post/keeping-up.md new file mode 100644 index 0000000..752a2f5 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/keeping-up.md @@ -0,0 +1,26 @@ +--- +title: "Keeping up" +date: 2014-04-08T03:01:07-04:00 +lastmod: 2015-03-21T19:45:36-04:00 +slug: keeping-up +excerpt: "Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week +" +--- + +Thanks to [this tweet by Adam Clark](https://twitter.com/avclark/status/453220061831237632) and [this post by Brian Rinadli](http://flippinawesome.org/2014/03/31/paralyzed-by-choice-in-front-end-development/) I've been thinking about how I keep up with changes in the web development world. + +Brian writes in his article that + +> One of the biggest difficulties front-end developers face can be deciding what is worth paying attention to and what isn’t. If you follow social media, Hacker News, EchoJS or even a handful of blogs, it can be hard to decipher the tools or frameworks that are deserving of investigation versus those that maybe just aren’t there yet. + +I agree; there's good signal in those streams. However, it's incresingly difficult to parse the good stuff from the link bait. Brian shares a great list of email newsletters that aim to help cull the noise into manageable chunks of information. I subscribe to [Web Design Weekly](http://web-design-weekly.com/) and [Web Development Reading List](http://tinyletter.com/wdrl). I probably only click on 3-4 links in each one, but this approach has worked really well for me for quite some time. + +Adam expressed another angle to this issue: + + + +Personally, I gave up trying to read my entire feed a while ago; it isn't feasible. I also try to be selective about how many folks I follow. The harsh reality is that eventually you won't be able to keep up. I recommend [News.Me](http://www.news.me/) which emails you the top couple links that were shared in your twitter feed the previous day. + +I also highly recommend [Pinboard's popular page](https://pinboard.in/popular/). While not specifically related to web development, I always find a good link or two perusing it every few days. + +These tools allow me to relax. Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week. diff --git a/themes/cycle/exampleSite/content/post/kyle-steed-on-rest.md b/themes/cycle/exampleSite/content/post/kyle-steed-on-rest.md new file mode 100644 index 0000000..6601a01 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/kyle-steed-on-rest.md @@ -0,0 +1,14 @@ +--- +title: "Kyle Steed on rest" +date: 2012-08-03T03:01:08-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: kyle-steed-on-rest +excerpt: "Fantastic article by Kyle Steed on work, rest, and life +" +--- + +Inspiring article by [Mr. Kyle Steed](http://kylesteed.com), do yourself a favor and take a few minutes and [read it](http://blog.kylesteed.com/2012/08/keeping-up-with-myself/). + +> Resting isn’t being lazy. Resting is the promise we receive by faith to believe what the Father has spoken and trusting Him to provide all the while continuing to live and work and love. + +I found this quote especially important given my recent string of posts on working hard. Life is all about balance, which is hard. diff --git a/themes/cycle/exampleSite/content/post/lambda-talk.md b/themes/cycle/exampleSite/content/post/lambda-talk.md new file mode 100644 index 0000000..718f260 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/lambda-talk.md @@ -0,0 +1,11 @@ +--- +title: "Lambda Talk" +date: 2017-02-23T13:04:21-05:00 +lastmod: 2017-02-23T13:04:21-05:00 +slug: lambda-talk +excerpt: "Last week I gave a talk at GemCityJS about going serverless with AWS Lambda." +--- + +Last week I gave a talk at [GemCityJS](http://gemcityjs.com) about going serverless with AWS Lambda. + +I posted the slides to . I plan to write more in-depth about Lambda in the future, so stay tuned. diff --git a/themes/cycle/exampleSite/content/post/learning-to-think-in-react.md b/themes/cycle/exampleSite/content/post/learning-to-think-in-react.md new file mode 100644 index 0000000..1469364 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/learning-to-think-in-react.md @@ -0,0 +1,61 @@ +--- +title: "Learning to think in React" +date: 2015-06-08T07:51:12-04:00 +lastmod: 2015-06-24T11:42:13-04:00 +slug: learning-to-think-in-react +excerpt: "I outline how I built my blog using React and the WordPress API. This post covers isomorphic app structure and data flow in React with React-Router." +--- + +Some of you may have noticed that this blog has been going through some renovations. I’ve spent the last couple months moving off [Siteleaf](http://siteleaf.com/) and towards a hosted WordPress install. My ultimate goal is to use Wordpress strictly for managing content and to attach a separate front-end written in React.js. While not completely finished, I’m at the point where all pieces are functional enough that I feel comfortable to begin sharing what I’ve learned through the process. + +## React + +At the moment, React is definitely the cool kid on the Javascript framework block, which history tells us is a perilous and passing position. Regardless, I’ve been intrigued by its philosophy and decisions for a while. Love Facebook or hate them, you can’t deny they have a [fantastic engineering team](https://code.facebook.com/) solving some of the hardest problems on the web. My interest in React stems from the fact that that, instead of setting out to solve all the problems of building a web app, it aims to solve just one: the complexity of building user-interfaces. Facebook explains how React makes building UIs easier in [a perfect introductory post](https://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html) (which I’ve gone back to many times) that walks through building up a frontend from scratch. Because React is focused on the user interface, it isn’t a very large API to learn. This focus encourages you to use any other tooling, frameworks, or libraries for other aspects of your app. + +## Isomorphic + +React’s other big draw for me is that it easily enables an isomorphic structure for your web application, which simply means that the same code can render HTML pages on the server and render HTML in the browser. React accomplishes this via two render methods: `render` and `renderToString`. `render` is the default method that inserts the React HTML into a DOM node, and `renderToString` does what it says on the tin by passing the HTML out as a string. + +The biggest challenge has been learning to think "isomorphically." Thankfully, there are several fantastic articles that walk through how to structure and reason about an isomorphic app. [Nicolas Hery has a fantastic overview](http://nicolashery.com/exploring-isomorphic-javascript/) of what an isomorphic app structure can and *should* look like; I still have this one open in my browser, as I refer to it constantly. I was inspired by [James Long’s excellent post](http://jlongster.com/Presenting-The-Most-Over-Engineered-Blog-Ever) on moving his blog to React. Additionally, [Charlie Marsh’s post](http://www.crmarsh.com/react-ssr/) helped me get off the ground when it comes to writing an isomorphic app with React. + +## Data flow + +Having an isomorphic app means data flow in the app is going to change, and I definitely bent my brain trying to figure out a reasonable approach. The [aforementioned Hery article](http://nicolashery.com/exploring-isomorphic-javascript/) does a great job of outlining one possible solution. Facebook of course has its Flux architecture as the "preferred" approach, but I opted for a simpler approach more akin to [James](http://jlongster.com/Presenting-The-Most-Over-Engineered-Blog-Ever)’ flow. Essentially, I defined a [static function](https://facebook.github.io/react/docs/component-specs.html#statics) called `fetchData` anywhere I needed to request data. I then called this function on the router level. + +## React-router + +Speaking of the router, I’m using the awesome and delightful [React-router](https://github.com/rackt/react-router). React-router is a fantastic example of how to maintain an open-source project. [This post announcing changes to its API](https://github.com/rackt/react-router/wiki/Announcements#whats-the-deal-with-the-new-api) reveal the depth of thinking and intentionality of React-router’s authors. I’ve poured over the docs and issues in the course of this project and have been impressed with it constantly. + +I’m using React-router to handle routes on the server and the client (yay, isomorphic\!) with React’s `render` and `renderToString` methods. This means that I have a `server-routes.js` file and a `client-routes.js` file, which are the only two files that *aren’t* shared between the client and the server. I’m using a vanilla Express server to kickoff the server portion of the blog. React-router simply plugs in as middleware to handle serving up the application. On the client, I have React-router using the History APIs to navigate, which greatly increases the perceived performance of the site. + +## Promises + +This was my first experience working with Promises in Javascript. I don’t know how I could have done this project without them - I’d probably still be untangling all the callbacks. Luckily, the brilliant minds behind [CujoJS](http://cujojs.com/) have not only a [great promises library](https://github.com/cujojs/when), but also a [rest library that returns promises](https://github.com/cujojs/rest). Moreover, both libraries work in the browser and on the server. The pattern I followed for my data fetching looks like this: + + var promises = state.routes.filter(function (route) { + return route.handler.fetchData; + }).reduce(function (promises, route) { + promises[route.name] = route.handler.fetchData(state.params); + return promises; + }, {}); + + resolveHash(promises).then(function (data) { + React.render(, container); + }); + +Sidenote: For a fantastic primer on `.map`, `.reduce`, and `.filter`, check out [Elijah Manor’s post](http://www.elijahmanor.com/reducing-filter-and-map-down-to-reduce/). + +These functions go in [react-router’s run callback](https://github.com/rackt/react-router/blob/master/docs/api/run.md). The `state.routes` object contains the matching route components, so you can filter over them and get all the necessary `fetchData` functions. We massage this object of functions into a key:value structure to use with the `resolveHash` method that ships with [whenjs](https://github.com/cujojs/when). `resolveHash` will call all the `fetchData` methods, and once all data has been fetched it calls back to React to render with the new data. This is all possible because, thanks to [rest](https://github.com/cujojs/rest), every `fetchData` method returns a promise. Here is an example of what a `fetchData` function looks like: + + fetchData: function(pageNumber) { + var fetchPosts = rest(url).then(function(response) { + var postInfo = { + }; + return postInfo; + }); + return fetchPosts; + } + +## Going Forward + +I think that covers the React portion for now. I've pulled the React portion out of my private repo and [published it on Github](https://github.com/asimpson/react-blog), feel free to browse around. I hope to outline other interesting pieces of the blog, including the WordPress side of things, soon. Feel free to ping me on [twitter](http://twitter.com/a_simpson) with any questions. diff --git a/themes/cycle/exampleSite/content/post/lessons-learned-from-integrating-openai-into-a-grafana-data-source.md b/themes/cycle/exampleSite/content/post/lessons-learned-from-integrating-openai-into-a-grafana-data-source.md new file mode 100644 index 0000000..483f992 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/lessons-learned-from-integrating-openai-into-a-grafana-data-source.md @@ -0,0 +1,10 @@ +--- +title: "Lessons learned from integrating OpenAI into a Grafana data source" +date: 2023-07-25T15:10:24-04:00 +lastmod: 2023-07-25T15:10:24-04:00 +slug: lessons-learned-from-integrating-openai-into-a-grafana-data-source +excerpt: "I wrote over on the Grafana blog about a few lessons or observations we learned while integrating OpenAI into the ADX data source. It's my first post on the Grafana blog and I'm pretty excited, so check it out!" +--- + +I wrote over on the [Grafana blog](https://grafana.com/blog/) about a few [lessons or observations we learned while integrating OpenAI into the ADX data source](https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/). It's my first post on the Grafana blog and I'm pretty excited, so check it out! + diff --git a/themes/cycle/exampleSite/content/post/lyza-gardner-on-laying-down-our-burdens.md b/themes/cycle/exampleSite/content/post/lyza-gardner-on-laying-down-our-burdens.md new file mode 100644 index 0000000..0187947 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/lyza-gardner-on-laying-down-our-burdens.md @@ -0,0 +1,12 @@ +--- +title: "Lyza Gardner on Laying Down our Burdens" +date: 2012-10-21T03:01:09-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: lyza-gardner-on-laying-down-our-burdens +excerpt: "Another great article from Lyza Gardner. +" +--- + +> Part of being successful on the pan-device web is relinquishing control of things we never had control of in the first place. Some of this you have probably heard. Web design processes are being re-imagined with an emphasis on adaptation and a rejection of pixel-perfect mockups. Content is increasingly given a position of centrality, and design flows around it. + +Just go read [the whole thing](http://blog.cloudfour.com/laying-down-our-burdens-steps-towards-simplifying-the-mobile-web/). diff --git a/themes/cycle/exampleSite/content/post/macos-catalina-slow-by-design.md b/themes/cycle/exampleSite/content/post/macos-catalina-slow-by-design.md new file mode 100644 index 0000000..51c3b54 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/macos-catalina-slow-by-design.md @@ -0,0 +1,20 @@ +--- +title: "macOS 10.15: Slow by Design" +date: 2020-05-28T21:22:03-04:00 +lastmod: 2020-05-28T21:22:03-04:00 +slug: macos-catalina-slow-by-design +excerpt: "" +link: "https://sigpipe.macromates.com/2020/macos-catalina-slow-by-design/" +--- + +A few days ago [Allan Odgaard](https://sigpipe.macromates.com/) wrote up the reasons for the frequent slowdowns he's experiencing in macOS Catalina and it's shocking: + +> Apple has introduced notarization, setting aside the inconvenience this brings to us developers, it also results in a degraded user experience, as the first time a user runs a new executable, Apple delays execution while waiting for a reply from their server. This check for me takes close to a second. + +> This is not just for files downloaded from the internet, nor is it only when you launch them via Finder, this is everything. So even if you write a one line shell script and run it in a terminal, you will get a delay! + +> I am writing this post to call attention to what I consider a serious design problem with Apple’s most recent OS where it appears that low-level system API such as `exec` and `getxattr` now do synchronous network activity before returning to the caller. + +[Marco Arment](https://marco.org/) hit the nail on the head with [his tweet summary of the post](https://twitter.com/marcoarment/status/1263855479668834304): + +> The macOS security team needs to ask themselves hard questions about their implementation choices when very smart people are disabling huge parts of their OS security layer just to get reasonable performance from common tasks. diff --git a/themes/cycle/exampleSite/content/post/maybe-you-shouldits-not-youmove-on.md b/themes/cycle/exampleSite/content/post/maybe-you-shouldits-not-youmove-on.md new file mode 100644 index 0000000..6cbdd1c --- /dev/null +++ b/themes/cycle/exampleSite/content/post/maybe-you-shouldits-not-youmove-on.md @@ -0,0 +1,19 @@ +--- +title: "Maybe you should…it's not you…move on." +date: 2012-08-16T03:01:09-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: maybe-you-shouldits-not-youmove-on +excerpt: "A collection of reactions to how Twitter muddled there recent API announcement. +" +--- + +Twitter's recent API changes and announcements seem to be purposefully obtuse. I don't know why they can't just make an announcement telling third-party, client developers to "kick rocks" and turn off the API? It would be easier, their brand probably wouldn't suffer as much. Maybe they think that any publicity is good publicity? Or maybe Twitter has been incompetent from the start (the fail whale was fun right?), and we forget how they really didn't contribute any meaningful features or innovations to their own platform, users did. + +Don't get me wrong, [I'm not ganging up on Twitter (wouldn't want to hurt a companies feelings right?)](http://dashes.com/anil/2012/08/what-twitters-api-announcement-could-have-said.html) or anything. I'm not upset with Twitter for changing how their platform works, it is their platform after all. I'm just amazed at the lack of *clear*, direct communication. + +So, here is a list of other writers who have attempted to unravel what Twitter's recent announcements actually mean. Enjoy. + + - Marco Arment wrote a [great breakdown](http://www.marco.org/2012/08/16/twitter-api-changes). + - Ben Brooks piggybacked off Marco's post with [his own](http://brooksreview.net/2012/08/twitter-bullshit/). + - Matthew Panzarino also did a solid job in [his post](http://thenextweb.com/twitter/2012/08/17/twitter-4/). + - And finally, Gruber had some [fantastic verbiage to express his frustration](http://daringfireball.net/linked/2012/08/16/twitter-drop-dead). diff --git a/themes/cycle/exampleSite/content/post/medium-isnt-permanent.md b/themes/cycle/exampleSite/content/post/medium-isnt-permanent.md new file mode 100644 index 0000000..92bd765 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/medium-isnt-permanent.md @@ -0,0 +1,15 @@ +--- +title: "Medium isn't a permanent fixture on the Internet" +date: 2018-05-21T11:49:15-04:00 +lastmod: 2018-05-21T11:49:15-04:00 +slug: medium-isnt-permanent +excerpt: "If you're writing on the Internet and you aren't hosting (owning) your content you're work will disappear; it's just a matter of time." +--- + +Owen Williams just realized [Medium isn't a permanent fixture on the Internet](http://click.mlsend3.com/link/c/YT04OTYxNDcyODIxNTg2ODgwNjEmYz16MHI1JmU9NTQxNjU3ODAmYj0xNzcxOTA5NTgmZD1tMGIxZzV2.Ih4lJDXWFC2yKp4Olw8dx-J27KB9xaWDs5hLKy6GX04): + +> It's not difficult to imagine an acquisition on the horizon (by who, one would wonder) or some other sort of exit. It doesn't feel like Medium has a strategy, living on borrowed time and money; what happens if this beautiful, simple central store of content just disappears? + +No offense to Owen but this has been Medium's problem from day one. If you're writing on the Internet and you aren't hosting (owning) your content you're work *will* disappear; it's just a matter of time. + +Owning your content is why [micro.blog](https://micro.blog) is so interesting to me. Owning your content is why RSS is never going away. Owning your content is why things like Wordpress, Moveable Type, and the [JAM stack](https://jamstack.org) are much better choices than yet another online service. diff --git a/themes/cycle/exampleSite/content/post/messi-is-re-writing-the-record-book.md b/themes/cycle/exampleSite/content/post/messi-is-re-writing-the-record-book.md new file mode 100644 index 0000000..e37b5d2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/messi-is-re-writing-the-record-book.md @@ -0,0 +1,13 @@ +--- +title: "Messi is re-writing the record book" +date: 2017-12-02T15:53:22-05:00 +lastmod: 2017-12-02T15:53:22-05:00 +slug: messi-is-re-writing-the-record-book +excerpt: "In a fantastic video the YouTube channel MagicalMessi documents all the various records that Messi has broken during his illustrious career." +--- + +In a [fantastic video](https://www.youtube.com/watch?v=lyJkGP4p01s) the YouTube channel [MagicalMessi](https://www.youtube.com/channel/UCsObGXVUdSh-bHT7CdVXrrw) documents all the various records that Messi has broken during his illustrious career. It's a fantastic video. Messi is one of a kind and we'll never see someone like him again. + +
+ +
diff --git a/themes/cycle/exampleSite/content/post/microblogging.md b/themes/cycle/exampleSite/content/post/microblogging.md new file mode 100644 index 0000000..c0d45b5 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/microblogging.md @@ -0,0 +1,18 @@ +--- +title: "Microblogging" +date: 2015-06-25T10:14:44-04:00 +lastmod: 2015-06-25T13:02:57-04:00 +slug: microblogging +excerpt: "My microblogging setup with Twilio, Twitter, SMS, and WordPress." +--- + +[Manton Reece](http://www.manton.org) recently shared [his microblogging setup](http://www.manton.org/2015/06/microblogging-with-wordpress.html) with WordPress. I have a similar system that was inspired by [Jeremy Keith's example](https://adactio.com/journal/6826). Like Manton, I had to figure out the quickest way to create a new post. I eventually settled on SMS-to-post thanks ([once again](http://adamsimpson.net/writing/iphone-checker-with-capybara-and-twilio)) to [Twilio](http://twilio.com). SMS-to-post lets me text my Twilio number which sends the text to WordPress where it becomes a new "note". Publishing that "note" to Twitter is just a matter of hooking into the WordPress `publish_post` action and sending the post to Twitter via its API. + +Here are a few other implementation notes: + + - I created a custom post type in WordPress called "Notes". + - The [post status API](http://codex.wordpress.org/Post_Status_Transitions) makes this entire process smooth. + - SMS-to-post has a few gotchas, the biggest one is that [SMS with emoji are limited to 70 characters](https://www.twilio.com/help/faq/sms/why-are-my-messages-with-unicode-being-split). + - I don't have an RSS feed for my Notes...yet + - I save the tweet ID of every post that gets posted to Twitter. I use that ID to pull in the favorite and retweet counts and display them next to each "note" in the WordPress dashboard. + - Twilio needs an endpoint to POST incoming texts to WordPress. Creating custom endpoints is trivial thanks to [this great guide](http://coderrr.com/create-an-api-endpoint-in-wordpress/). I also recommend [the rewrite rules inspector plugin](https://wordpress.org/plugins/rewrite-rules-inspector/) for working with rewrite rules. diff --git a/themes/cycle/exampleSite/content/post/migrate-an-existing-build-process-to-npm-scripts.md b/themes/cycle/exampleSite/content/post/migrate-an-existing-build-process-to-npm-scripts.md new file mode 100644 index 0000000..7076802 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/migrate-an-existing-build-process-to-npm-scripts.md @@ -0,0 +1,111 @@ +--- +title: "Migrate an existing build process to npm scripts" +date: 2015-10-18T11:44:35-04:00 +lastmod: 2017-05-23T14:05:10-04:00 +slug: migrate-an-existing-build-process-to-npm-scripts +excerpt: "Not all projects need Grunt or Gulp, npm is a great build tool by itself. I recently replaced a Grunt task (with multiple plugins) with a npm script task." +--- + +Last week I gave a short introduction to using npm as a build tool at [GemCity JS](http://gemcityjs.com). + + + +## Rewrite? + +There were a few questions about how to start using npm as a build tool on an existing project. The short answer is: start abstracting tasks behind [npm scripts](https://docs.npmjs.com/misc/scripts). This weekend I migrated this blog to [my new favorite host](https://chunkhost.com/r/46012) and ended up replacing a [grunt](http://gruntjs.com) task with a npm task. Here's how it went down. + +## Pick a task + +I was using two plugins, [grunt-usemin](https://github.com/yeoman/grunt-usemin) and [grunt-rev](https://github.com/cbas/grunt-rev), to "fingerprint" or rev my asset files. It *barely* worked (only some files were properly rev'd and inserted) and it was awkward. Usemin requires specific HTML comments so that it knows what files to replace. I finally decided to write my own rev task. + +## The old + +For reference here is my old Grunt config: + +``` coffeescript + rev: + files: + src: ["public/js/browser.js", "public/css/base.css"] + + usemin: + html: 'server/app.hbs' + options: + assetsDirs: 'public/' + + useminPrepare: + html: ['server/app-tmp.hbs']` +``` + +These tasks were run in this order during deployment: `rev, useminPrepare, usemin`. + +## The plan + +I stared off by jotting down the flow and transformations required for revving my assets. I came up with this list: + +1. Compile assets (sass, babel) +2. Rev them (this is just magic right?) +3. Overwrite non-rev'd paths in `app.hbs`. + +That list was terribly shortsighted. Here's how it actually turned out: + +1. Compile assets +2. Generate rev filename for each asset +3. Write new asset file with rev'd filename for each asset. +4. Create (force if necessary) `app.hbs` from `app-tmp.hbs` (-tmp for template) +5. Read `app.hbs` as a string. +6. Replace non-rev'd paths with rev'd paths in `app.hbs` using `String.replace()`. + +Seem like this might be more code and trouble than it's worth? Not at all. + +## The new task + +Since we're going to replace a grunt task with a npm script task, lets use ES6 goodness. I [installed `babel`](https://babeljs.io) which lets me execute scripts [using `babel-node` instead of `node`](https://babeljs.io/docs/usage/cli/#babel-node). I then created a new directory called `tasks/` and named my new task file, `tasks/rev.js`. I also installed the super awesome [rev-file](https://www.npmjs.com/package/rev-file) package to handle the reving. + +The code turns out to be fairly succicent: + +``` javascript +import rev from "rev-file"; +import path from "path"; +import fs from "fs-extra"; + +const projectPath= path.dirname(__dirname); +const tmp = `${projectPath}/server/app-tmp.hbs`; +const app = `${projectPath}/server/app.hbs`; + +fs.copySync(tmp, app, {'clobber': true}); + +const assets = [ + `${projectPath}/public/css/base.css`, + `${projectPath}/public/js/browser.js` +]; + +assets.forEach((f) => { + const revPath = rev.sync(f); + fs.copySync(f, revPath); + const appString = fs.readFileSync(app, 'utf8'); + fs.writeFileSync(app, appString.replace( path.basename(f), path.basename(revPath) )); +}); +``` + +## Wrap it up + +Now I have a task. How do I integrate this into my existing Grunt process? [npm scripts](https://docs.npmjs.com/misc/scripts) to the rescue. I created a new script entry in my `package.json` like this: + +``` language-javascript + +"scripts": { + "start": "node ./bin/www", + "rev": "babel-node tasks/rev.js" +} +``` + +npm scripts can be called directly using `npm run`, `npm run rev` in this case. The final step is to modify my `Gruntfile` to run the rev command using the handy [grunt shell plugin](https://github.com/sindresorhus/grunt-shell): + +``` language-coffeescript + + shell: + rev: + command: "npm run rev" +``` + +And that's all I had to do. Now I can continue to replace pieces of my build system with npm scripts without having to do a big re-write. Using npm as a build tool also illustrates the simplicity of some of these tasks. It's much easier to maintain a 20 line task than to keep multiple plugins up to date. diff --git a/themes/cycle/exampleSite/content/post/moved-to-siteleaf.md b/themes/cycle/exampleSite/content/post/moved-to-siteleaf.md new file mode 100644 index 0000000..8327ae8 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/moved-to-siteleaf.md @@ -0,0 +1,15 @@ +--- +title: "Moved to Siteleaf" +date: 2014-03-31T03:01:10-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: moved-to-siteleaf +excerpt: "I moved to Siteleaf from Jekyll +" +--- + +I've moved this blog from Jekyll on Heroku to [Siteleaf](http://www.siteleaf.com/) on S3. I did this for a couple reasons: + +1. Siteleaf gives me more control without having to be on my computer. The ability to post from my phone is the secret sauce in my opinion. +2. Siteleaf is just an API. I was able to easily convert my Jekyll posts to Siteleaf with a [simple Ruby script](https://gist.github.com/asimpson/9255595). I can just as easily switch to another platform in the future. + +I'm excited by the move, I also took the opportunity to freshen the design up around here too. Hopefully you'll see more posts, more regularly. diff --git a/themes/cycle/exampleSite/content/post/moving-away-from-google.md b/themes/cycle/exampleSite/content/post/moving-away-from-google.md new file mode 100644 index 0000000..16fe2fa --- /dev/null +++ b/themes/cycle/exampleSite/content/post/moving-away-from-google.md @@ -0,0 +1,15 @@ +--- +title: "Moving away from Google" +date: 2015-06-01T09:07:54-04:00 +lastmod: 2015-06-01T09:07:54-04:00 +slug: moving-away-from-google +excerpt: "I recently started using DuckDuckGo and Fastmail. So I thought I'd share a few thoughts on both services." +--- + +[Marco](http://www.marco.org/2015/05/29/why-not-google) and [Gruber](http://daringfireball.net/linked/2015/05/30/why-not-google) shared last week that they both use [DuckDuckGo](http://duckduckgo.com) and [Fastmail](http://www.fastmail.com/?STKI=14274077)(referral link) instead of Google search and Gmail. Since I just started using both services, here are a few of my thoughts on them. + +I previously had Google Apps set up for my domain email (adam@adamsimpson.net). By far the best thing I can say about Fastmail is that I haven't noticed anything different since switching. Fastmail's spam protection, speed, and reliability all seem on par with Google's and I appreciate the superior incentives of Fastmail when it comes to privacy. + +It's the same story with DuckDuckGo, I haven't noticed a drop-off in the quality of the search results. One of my favorite features is the ability to send search queries as `POST` requests instead of `GET` requests. I love this because it prevents my history from getting polluted with DuckDuckGo pages that have terms in the URL; a little thing for sure, but one I appreciate. + +I was skeptical about how happy I would be with things outside of Google's ecosystem, but I've been pleasantly surprised. Fastmail and DuckDuckGo offer a great alternative to Google's apps. diff --git a/themes/cycle/exampleSite/content/post/moving-tweetbot-beta-to-a-new-mac.md b/themes/cycle/exampleSite/content/post/moving-tweetbot-beta-to-a-new-mac.md new file mode 100644 index 0000000..1ffc7b1 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/moving-tweetbot-beta-to-a-new-mac.md @@ -0,0 +1,14 @@ +--- +title: "Moving Tweetbot Beta to a new Mac" +date: 2012-09-21T03:01:11-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: moving-tweetbot-beta-to-a-new-mac +excerpt: "How to migrate Tweetbot Beta to a new Mac. +" +--- + +Tweetbot for Mac entered Beta a few weeks ago, and also cut off new users from trying out the Beta to comply with new [API changes from Twitter](/maybe-you-should-its-not-you-move-on). + +I love Tweetbot, and the Mac client is no exception. However I ran into a snag when I tried to set up the Tweetbot Beta on my new MacBook Air. The app kept redirecting me to the [Tweetbot Beta blog post](tapbots.com/blog/news/tweetbot-for-mac-beta-sort-of). Now to be fair, I think if I had used the Migration Assistant built into OS X I wouldn't have run into this issue. However I had already decided to "start fresh" on this new machine and only bring things over from my old MacBook Pro when needed. After spending a couple minutes Googling around for a solution, I gave up and reverted to my trusty, stand-by [Twitterific](http://iconfactory.com/software/twitterrific). + +After a couple days of this I got the bug again to see if I could get Tweetbot Beta up and running on my new machine. New comments on the Tweetbot Beta blog post revealed the solution. Check out these [two](http://tapbots.com/blog/news/tweetbot-for-mac-beta-sort-of#comment-3609) [answers](http://tapbots.com/blog/news/tweetbot-for-mac-beta-sort-of#comment-3605), Tweetbot Beta is now happily running on my new MacBook Air. To move Tweetbot Beta to a new machine copy the **Tweetbot Keychain item, Application Support folder, and Container folder** to your new Mac and you should be good to go. diff --git a/themes/cycle/exampleSite/content/post/my-first-bookmarklet.md b/themes/cycle/exampleSite/content/post/my-first-bookmarklet.md new file mode 100644 index 0000000..650612c --- /dev/null +++ b/themes/cycle/exampleSite/content/post/my-first-bookmarklet.md @@ -0,0 +1,23 @@ +--- +title: "My First Bookmarklet" +date: 2012-07-12T03:01:12-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: my-first-bookmarklet +excerpt: "My first bookmarklet, an ESPN Insider paywall" +--- + +### Update + +ESPN has wisely fixed this workaround as of 08/10. I'll leave the rest of the post up for posterity though. + +### Original Post + +It all started when I was doing my daily sports news catch-up, and clicked on a link that lead me to an [ESPN Insider article](http://www.espn.com/insider), only without the Insider paywall. I clicked on another Insider article and hit the paywall. I wondered if the Insider paywall simply checked the URL scheme, and didn't have any session or cookie security. + +I compared the two links and noticed some minor differences, I decided to match the paywalled link to the structure of the non-paywalled link and it worked\! Now, I'm assuming ESPN knows this is one way around their Insider paywall, most paywalls seem to have holes (see NYT, WSJ, etc.). + +Anyway, like any good geek, I went ahead and made my first ever bookmarklet to automate the URL matching. The code is below. + +` javascript:(function(){ var pathArray = window.location.href; var newValue = pathArray.split('&action='); var firstUrl = newValue[0]+newValue[1]+newValue[1]; var secondUrl = firstUrl.split('login&'); var finalUrl = firstUrl+'login%26'+secondUrl[2]; function readInsider() { windowObjectReference = window.open(finalUrl, "_blank"); } readInsider(); })(); ` + +You may have to hit the bookmarklet more than once for it to work. Despite the hacky nature of the code and skittish performance, the success of my quick little project has me thinking of how I can BOOKMARKLET ALL THE THINGS\! diff --git a/themes/cycle/exampleSite/content/post/new-workstation.md b/themes/cycle/exampleSite/content/post/new-workstation.md new file mode 100644 index 0000000..695fbdb --- /dev/null +++ b/themes/cycle/exampleSite/content/post/new-workstation.md @@ -0,0 +1,83 @@ +--- +title: "New workstation" +date: 2022-05-02T18:14:25 +lastmod: 2022-05-02T18:14:25 +slug: new-workstation +excerpt: "I detail my new workstation build featuring the Intel i5-12600k." +--- + +[New job](/writing/goodbye-sparkbox) means time for a new workstation. + +## Some history +The first computer I ever purchased was the [12" Powerbook G4](https://everymac.com/systems/apple/powerbook_g4/specs/powerbook_g4_1.5_12.html). Since that Powerbook I've always had laptops as my main machines (desktop gaming PC not withstanding). Remote working the last few years has made me realize that the portability of a laptop is largely wasted since I only travel a handful of times a year and yet I live with the downsides of a laptop the rest of the time. So, last year I started thinking about a desktop machine for my primary workstation. A desktop is appealing for a handful of reasons: + + +- More powerful CPUs +- More expansion capabilities +- More durable + +## The options +The [Mac Studio](https://www.apple.com/mac-studio/) was recently released to much fanfare and was really intriguing to me. However, when I started considering it I only had about a week to 10 days before my start date at [Grafana](https://grafana.com) and I couldn't wait the quoted 4-6 weeks delivery time for a Mac Studio with 32GB of RAM. + +I was also pretty unwilling to leave my comfy [NixOS](https://nixos.org) install + [i3](https://i3wm.org/). [Michael Stapelberg's latest post](https://michael.stapelberg.ch/posts/2022-01-15-high-end-linux-pc/) about his new workstation proved timely and convinced me to give the new Intel Alder Lake CPUs a shot. + +Apple's M1 family of chips deliver incredible performance per watt but I wasn't as concered about the power usage given this was a desktop machine not a laptop. I was however focused on at least matching the M1 chips in single-threaded performance since a good chunk of my development work (Node, build tools, etc) are still single-threaded. I ended up with the Intel i5-12600k and I really couldn't be happier. Here's the full parts list: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PartPrice
i5-12600k$278
Sliger Cerberus case$285
140mm Noctua NF-A14 PWM$21
Noctua NH-C14S$85
Sabrent 1TB Rocket NVMe$130
Corsair SF600$130
ASUS ROG Strix Z690-G$350
G.SKILL Trident Z5 Series 32GB DDR5$330
+ + +## XMP issues +I ran into the same memory XMP issues that Michael mentions in his post so I disabled the XMP profile and the system passed the "[Coding Horror burn in tests](https://blog.codinghorror.com/is-your-computer-stable/)" with flying colors. + +## Cooling +I mounted the 140mm fan to the bottom of the case as intake and the CPU cooler is of course positioned as intake as well. Hot air rises out the top of the case quite well. During the prime95 torture test the CPU never got over 78°C and I couldn't ever hear either fan. I run both fans in the "silent profile" in the BIOS and I use [Noctua's adapters](https://noctua.at/en/na-src7) to lower the voltage even more. Now the only fan I could hear during max load was the PSU fan which doesn't spin at all under low to medium loads but under high load it kicks on. Day to day it's hardly on so the system is dead quiet most of the time. + +## Case +I absolutely love the Cerberus case. It's Mini-ATX but still super compact and fits on my desk quite well. All the panels are solid metal and the way all the panels pop off is really really nice. I opted for the handle mount on the top and the internal PSU moutning. + +## Linux +NixOS [installed just fine](https://github.com/asimpson/dotfiles/blob/master/nixos/fin/configuration.nix). I'm runing the 5.17 kernel because Alder Lake needs a newer kernel for it's graphics and CPU scheduler (coming soon?). I have WiFi and Bluetooh disabled in the BIOS since everything is hard-wired to the machine. + +## Verdict +This build has proven quite comfortable over the few weeks I've used it. I love that I have 2 free RAM slots if I ever feel the need for more RAM. I also love that I have 3 remaining Nvme slots on the motherboard for additional solid state storage in the future. diff --git a/themes/cycle/exampleSite/content/post/nginx-www-rewrite.md b/themes/cycle/exampleSite/content/post/nginx-www-rewrite.md new file mode 100644 index 0000000..9891ed6 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/nginx-www-rewrite.md @@ -0,0 +1,26 @@ +--- +title: "Nginx www rewrite" +date: 2012-07-12T03:01:13-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: nginx-www-rewrite +excerpt: "How to rewrite www to non-www in Nginx +" +--- + +[Quick tip](http://aleksandarsavic.com/nginx-redirect-wwwexamplecom-requests-to-examplecom-or-vice-versa/) for rewriting www.example.com to example.com or vice versa in [Nginx](http://nginx.com/). + +My conf file originally looked like: + +` server { server_name www.example.com example.com; } ` + +I had to create another server block, and move all the conf information to the new block. In my case I was rewriting www to non-www. + +` server { server_name www.example.com; //rewrite here; } server { server_name http://example.com; //all the server stuff goes in this block; } ` + +### Update + +Instead of mucking around with rewriting, I should have just used return, like so: + +` server { server_name www.example.com; return 301 http://example.org$request_uri; } ` + +The lesson is, always check out [the official docs](http://nginx.org/en/docs/http/converting_rewrite_rules.html) before Google. diff --git a/themes/cycle/exampleSite/content/post/nixpkgs-is-a-treasure.md b/themes/cycle/exampleSite/content/post/nixpkgs-is-a-treasure.md new file mode 100644 index 0000000..36eda81 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/nixpkgs-is-a-treasure.md @@ -0,0 +1,42 @@ +--- +title: "nixpkgs is a treasure" +date: 2024-05-10T14:07:43-04:00 +lastmod: 2024-05-10T14:07:43-04:00 +slug: nixpkgs-is-a-treasure +excerpt: "Nix and NixOS continue to be the best way to manage and build software that I've found." +--- + +Nix and NixOS continue to be the best way to manage and build software that I've found. Every project has a `shell.nix` file in the root where I can define the specific software needed to work on that project along with any necessary environment variables or `$PATH` modifications. I ran into an issue this week though where I needed an "old" version of Go (`1.20`) but the version had already been [removed from `nixpkgs`](https://github.com/NixOS/nixpkgs/tree/2e31c3a7e9825ec1ef087b5db2b801e1a9fb6f3b/pkgs/development/compilers/go). How can I pull in an "unlisted" version into my `shell.nix`? + +It's actually pretty straightforward, utilize [`fetchTarball`](https://nixos.org/manual/nix/stable/language/builtins.html?highlight=fetchtarball#builtins-fetchTarball) to pull in `nixpkgs` based on a commit where the version was present sometime in the past. You can mix that `import` in with regular/"current" packages with no issue like so: + +```nix +{ pkgs ? import {} }: + +let oldGo = import (builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/33c51330782cb486764eb598d5907b43dc87b4c2.tar.gz"; + sha256 = "sha256:0nflmpfp3pk704vhlvlgh5vgwl8qciqi18mcpl32k79qjziwmih8"; + }) {}; +in + +pkgs.mkShell { + buildInputs = [ + oldGo.go_1_20 + pkgs.gopls + pkgs.nodejs_18 + ]; + + hardeningDisable = [ "fortify" ]; + + shellHook = '' + mkdir -p .go .npm + export GOPATH=$PWD/.go + export NODE_PATH=$PWD/.npm + export NPM_CONFIG_PREFIX=$NODE_PATH + export PATH=$PWD/.yarn/sdks/typescript/bin:$PWD/.go/bin:$PATH:$NODE_PATH/bin + ''; +} +``` + +Notice I can reference the "`nixpkgs`" tarball/snapshot, `oldGo`, and pull in the version of Go I need?! `nixpkgs` is such a treasure trove of software, it's absolutely incredible! + diff --git a/themes/cycle/exampleSite/content/post/nothing-speaks-like-a-demo.md b/themes/cycle/exampleSite/content/post/nothing-speaks-like-a-demo.md new file mode 100644 index 0000000..4f732c2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/nothing-speaks-like-a-demo.md @@ -0,0 +1,14 @@ +--- +title: "Nothing speaks like a demo" +date: 2020-07-19T23:46:14-04:00 +lastmod: 2020-07-19T23:46:14-04:00 +slug: nothing-speaks-like-a-demo +excerpt: "" +link: "https://www.bryanbraun.com/2020/07/18/nothing-speaks-like-a-demo/" +--- + +Great post from my friend and co-worker Bryan Braun on the value of demoing. + +> It didn’t matter that his demos weren’t fully built, or available for anyone to use. We simply needed to see it, in order to understand. + +I find this is true for any kind of project: hobby or professional. Feedback — that elusive crucial ingredient to a good product — tends to arrive when someone else can see/hear/touch/examine what you're working on. diff --git a/themes/cycle/exampleSite/content/post/on-diminishing-modes-in-emacs.md b/themes/cycle/exampleSite/content/post/on-diminishing-modes-in-emacs.md new file mode 100644 index 0000000..c167dc2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/on-diminishing-modes-in-emacs.md @@ -0,0 +1,45 @@ +--- +title: "On diminishing modes in emacs" +date: 2017-08-17T12:09:25-04:00 +lastmod: 2017-08-17T12:09:25-04:00 +slug: on-diminishing-modes-in-emacs +excerpt: "An explanation of how to change or diminish major and minor modes in emacs" +--- + +"Diminishing modes" in Emacs is a popular topic. It took me a while to understand the basic (and simple) rules around how to customize the display of the various mode names. + +## What are modes + +Modes in Emacs come in two flavors, major and minor modes. The [Emacs manual](https://www.gnu.org/software/emacs/manual/html_node/emacs/Modes.html#Modes) explains modes like this: + +> Emacs contains many editing modes that alter its basic behavior in useful ways. + +Major modes: + +> \[...\] provide specialized facilities for working on a particular file type \[...\] Major modes are mutually exclusive; each buffer has one and only one major mode at any time. + +Minor modes are: + +> \[...\] optional features which you can turn on or off, not necessarily specific to a type of file or buffer. \[...\] Minor modes are independent of one another, and of the selected major mode. + +## Customize the mode line + +Modes are great, yet they [fill up the mode line](https://www.emacswiki.org/emacs/ModeLine). I only really want to know about a handful of minor modes and the major mode. On top of that I don't like how some modes name themselves (e.g. all caps, too long, etc.). Changing the display or completely hiding a mode is different for major and minor modes. + +### Changing minor mode names + +Minor mode names are stored in a list variable called `minor-mode-alist`. You can customize that directly or use the fantastic package [diminish](https://github.com/myrjola/diminish.el) as a wrapper around that functionality, like so: + +`(diminish 'flyspell "spell")` + +### Changing major mode names + +Major mode names are not stored in a simple list variable. Yet, fear not\! In reading the source of the diminish package, I stumbled [across this comment](https://github.com/myrjola/diminish.el/blob/master/diminish.el#L98): + +> To diminish a major mode, (setq mode-name "whatever") in the mode hook. + +The variable `mode-name` couldn't be correct could it? Yes, yes it is. Here's an example of changing the mode name for the default `elisp-mode`: + +`(add-hook 'emacs-lisp-mode-hook (λ () (setq mode-name "λ")))` + +Now you have all the tools at your disposal to change every mode's name in your mode line. diff --git a/themes/cycle/exampleSite/content/post/on-equifax.md b/themes/cycle/exampleSite/content/post/on-equifax.md new file mode 100644 index 0000000..0ccccf0 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/on-equifax.md @@ -0,0 +1,11 @@ +--- +title: "On Equifax" +date: 2017-09-08T16:31:42-04:00 +lastmod: 2017-09-08T16:31:42-04:00 +slug: on-equifax +excerpt: "I don't do many link posts but Ian Bogost sums up my feelings perfectly about the Equifax breach." +--- + +> In the end, the truth of the Equifax breach—who was affected, and how, and what the company will do to help, and what the terms of such assistance entail—might not be the most important lesson from this incident. More than anything, it suggests that a corner has been turned in corporate consumer data responsibility. Like severe weather, breaches have become so frequent and severe that they can begin receding from prominence. No matter their grievous effects, Equifax’s response suggests that fatalism might replace responsibility, planning, and foresight. This is just what happens now. + +I don't do many link posts but Ian Bogost [sums up my feelings perfectly](https://www.theatlantic.com/technology/archive/2017/09/the-equifax-breach-marks-the-end-of-shame-over-data-security/539202/) about the Equifax breach. diff --git a/themes/cycle/exampleSite/content/post/on-george-floyd.md b/themes/cycle/exampleSite/content/post/on-george-floyd.md new file mode 100644 index 0000000..fba6742 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/on-george-floyd.md @@ -0,0 +1,34 @@ +--- +title: "On George Floyd" +date: 2020-06-30T11:01:58-04:00 +lastmod: 2020-06-30T11:01:58-04:00 +slug: on-george-floyd +excerpt: "I haven't written anything here about George Floyd's murder. I still don't have a cogent response but here's what I've been mulling over." +--- + +I haven't written anything here about George Floyd's murder. I still don't have a cogent response but here's what I've been mulling over: + +- America has a problem when year after year the very institution put in place to serve folks in our communities ends up killing and harassing them and even goes out of its way to target Black people in those communities. +- Like everything in America today the response to Floyd's murder has become politicized. We all need to make the effort to move past our collective politics and biases and grapple with what changes need to be made both personally and collectively. + +I've collected three links that have stuck with me over the last handful of weeks. + +Unsurprisingly [Dave Chappelle's 8:46 special](https://www.youtube.com/watch?v=3tR6mKcBbT4) on George Floyd is insightful, gripping, and poignant. + +
+ +
+ +Around the [5:40 mark](https://youtu.be/3tR6mKcBbT4?t=340) he breaks down _the problem_: + +> What are you signifying — that you can kneel on a man’s neck for eight minutes and 46 seconds and feel like you wouldn’t get the wrath of God? That’s what is happening right now. It’s not for a single cop. It’s for all of it. Fucking all of it. + +Elsewhere, McSweeney's, in typical fashion, [cast the issue in a new light](https://www.mcsweeneys.net/articles/just-because-theyve-turned-against-humanity-doesnt-mean-we-should-defund-the-terminator-program): + +> This initiative, also known as Skynet, was created by Cyberdyne Systems for the Department of Defense as a way to keep Americans safe. Critics have said that spending half of our country’s GDP on developing an army of state-of-the-art cyborgs with advanced weapons systems and an AI specifically trained to neutralize threats was a bad idea. And while the recent killings might seem to confirm that, we feel that, despite a few stumbles here and there, this program has still been an overwhelming success. + +Finally, Chris Rock has [this great segment](https://www.youtube.com/watch?v=1h5sRgW6sQY) about "bad apples". + +
+ +
diff --git a/themes/cycle/exampleSite/content/post/on-webpack.md b/themes/cycle/exampleSite/content/post/on-webpack.md new file mode 100644 index 0000000..7e7eacb --- /dev/null +++ b/themes/cycle/exampleSite/content/post/on-webpack.md @@ -0,0 +1,9 @@ +--- +title: "On Webpack" +date: 2015-12-07T14:05:04-05:00 +lastmod: 2015-12-07T14:05:04-05:00 +slug: on-webpack +excerpt: "I wrote a love letter to Webpack over on the Foundry." +--- + +I wrote a love letter to Webpack over on [the Foundry](http://seesparkbox.com/foundry/write_better_frontend_modules_with_webpack). diff --git a/themes/cycle/exampleSite/content/post/openring.md b/themes/cycle/exampleSite/content/post/openring.md new file mode 100644 index 0000000..65688d1 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/openring.md @@ -0,0 +1,31 @@ +--- +title: "Openring" +date: 2020-08-21T16:09:44-04:00 +lastmod: 2020-08-21T16:09:44-04:00 +slug: openring +excerpt: "I've added Drew DeVault's openring project to the blog." +--- + +I've added Drew DeVault's [openring project](https://git.sr.ht/~sircmpwn/openring) to the blog. `openring` is a nice utility (written in Golang) that parses RSS feeds and generates an HTML template file to include on your website. I love things that utilize RSS feeds and things that make indie sites better and `openring` does both! Thanks to Drew for the tool. + +It was pretty easy to integrate into my build system. I added a new `Makefile` task that looks like this: + +```make +openring.mustache: + ./bin/openring \ + -s https://drewdevault.com/feed.xml \ + -s https://fasterthanli.me/index.xml \ + -s https://endler.dev/rss.xml \ + -s https://inessential.com/xml/rss.xml \ + -s https://www.bryanbraun.com/rss.xml \ + < openring.html \ + > ./templates/partials/openring.mustache +``` + +I then added this new task as a dependency on my build/generate step and I was done. + +You can view my [template file here](https://github.com/asimpson/blog/blob/master/openring.html). + +I also added the `openring` binary directly to the repo. It's not pretty but it beats compiling the binary every time my site deploys (Note: I do pull down a new [`cycle`](https://github.com/asimpson/cycle) binary every time the site deploys but I can control that flow whereas I can't control where `openring` builds.) + +For now I'm only displaying my `openring` on the home page of the blog but if folks think it would be useful on other pages (like this post page) shoot me a message in my public inbox (link below). diff --git a/themes/cycle/exampleSite/content/post/oscar.md b/themes/cycle/exampleSite/content/post/oscar.md new file mode 100644 index 0000000..31d4b9f --- /dev/null +++ b/themes/cycle/exampleSite/content/post/oscar.md @@ -0,0 +1,14 @@ +--- +title: "Introducing oscar" +date: 2020-04-29T16:21:17-04:00 +lastmod: 2020-04-29T16:21:17-04:00 +slug: oscar +excerpt: "I've been working on oscar which is a small command-line utility written in Rust that polls the pbskids.org API for new episodes of any PBS show." +--- + +I've been working on a small command-line utility written in [Rust](https://www.rust-lang.org/ "Link to rust-lang website") called [`oscar`](https://github.com/asimpson/oscar). `oscar` polls the pbskids.org API for new episodes of any PBS show. If it finds an episode it hasn't seen before it downloads the episode to the specified directory. + +I run `oscar` via the `cron` scheduler on my home server and over the past few months it's been largely invisible and maintenance-free. Whenever new episodes show up, `oscar` downloads them and my 3 year-old can stream it on any of the devices in the house via [Plex](https://www.plex.tv/) or [Infuse](https://firecore.com/infuse). + + +To get started I recommend pulling down the [latest release from Github](https://github.com/asimpson/oscar/releases "Link to Github release for oscar") (if it's not broken) or building locally via `cargo build --release`. To view the available shows run `oscar list`. Once you have found a show tell `oscar` to find episodes by invoking it with the `--show-slug` option and the destination directory option like: `oscar --show-slug SHOW_SLUG --output /path/to/video/folder`. diff --git a/themes/cycle/exampleSite/content/post/parsing-memory-usage-in-htoptop.md b/themes/cycle/exampleSite/content/post/parsing-memory-usage-in-htoptop.md new file mode 100644 index 0000000..e8f9187 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/parsing-memory-usage-in-htoptop.md @@ -0,0 +1,13 @@ +--- +title: "Parsing memory usage in htop/top" +date: 2015-10-04T09:06:46-04:00 +lastmod: 2015-10-04T09:07:37-04:00 +slug: parsing-memory-usage-in-htoptop +excerpt: "I've been trying to figure out how much memory a node app is using on my VPS, and I've found output from top or htop to be overwhelming." +--- + +I've been trying to figure out how much memory a node app is using on my VPS, and output from `top` or `htop` is fairly overwhelming. In searching around I found [Mugurel Sumanariu's post](http://mugurel.sumanariu.ro/linux/the-difference-among-virt-res-and-shr-in-top-output/) clearly explaining each column related to memory usage. + +The column I should be paying attention to is `RES`, which + +> \[..\] stands for the resident size, which is an accurate representation of how much actual physical memory a process is consuming. (This also corresponds directly to the %MEM column.) diff --git a/themes/cycle/exampleSite/content/post/plaintext-and-markdown-a-primer.md b/themes/cycle/exampleSite/content/post/plaintext-and-markdown-a-primer.md new file mode 100644 index 0000000..d0e7f5a --- /dev/null +++ b/themes/cycle/exampleSite/content/post/plaintext-and-markdown-a-primer.md @@ -0,0 +1,44 @@ +--- +title: "Plaintext and Markdown - A Primer" +date: 2012-08-08T03:01:13-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: plaintext-and-markdown-a-primer +excerpt: "A quick introduction to the beauty of plaintext and the Markdown syntax +" +--- + +My little sister is headed for her freshmen year of college, and so of course she asked me the classic question, "Should I get Word or Pages for my Mac?". I told her to get Pages and call it good, but inside I wanted to tell her go get a copy of [Byword](http://bywordapp.com), [iA Writer](http://www.iawriter.com/), [Write Room](http://www.hogbaysoftware.com/products/writeroom/), or any of the other fabulous text editors on the Mac and iOS. I didn't say any of these things, but I did decide to write it all down. + +### Plaintext + +Plaintext is all the little .txt files TextEdit saves (but only if you're in Plaintext mode, naturally). A Plaintext file is the most basic kind of text document. The format is literally just text, there is no formatting aside from basic paragraphs and indents, and no compatibility requirements. None. Read it again. No. Compatibility. Requirements. Last year [David Sparks](http://macsparky.com) wrote up a [fantastic article for Macworld](http://www.macworld.com/article/1161549/forget_fancy_formatting_why_plain_text_is_best.html) explaining the benefits of Plaintext, he wrote (emphasis mine): + +> Although modern word processing programs can do some amazing things—adding charts, tables, and images, applying sophisticated formatting—there’s one thing they can’t do: **Guarantee that the words I write today will be readable ten years from now**. +> +> That’s just one of the reasons I prefer to work in plain text: **It’s timeless**. My grandchildren will be able to read a text file I create today, long after anybody can remember what the heck a .docx file is. + +Plaintext will last (at least much longer than .doc will), you can count on it. If you need to apply some arcane formatting for a research paper, fire up a copy of Pages or Word and copy and paste your text in. Keep the plaintext file around though, let the actual text live on in those .txt files. + +### Markdown + +The jelly to Plaintext's peanut butter is [Markdown](http://daringfireball.net/projects/markdown/) by [John Gruber](http://daringfireball.net). Markdown extends Plaintext by adding basic formatting such as headings, unordered and order lists, block quotes, and italics and bolding. Markdown allows you to add inline images, external and internal hyperlinks, and even tables, without compromising the integrity of your Plaintext documents. + +Every post on this blog is written in Markdown. The blog engine, Jekyll, interprets the Markdown and spits out the appropriate HTML. If I ever wanted to switch to another blog engine, I have a bunch of simple plaintext files that are very portable. + +If you want to see Markdown in action, or want to practice with the syntax, head over to [Markdownr](http://markdownr.com) by the indefatigable [Mr. Sam Soffes](http://samsoff.es). Markdownr lets you input Markdown on the left side and instantly see the formatted text on the right side. Check it out. + +If you want the Markdownr experience on your desktop, check out [Brett Terpstra's](http://brettterpstra.com) app [Marked](http://markedapp.com). + +### A Few Bullet Points + +Other benefits of Plaintext and Markdown are: + + - Easy for modern Operating Systems to index and search + - Simple to backup + - Simple to move + - Easy to edit on any device + - Format agnostic. + +Plaintext and Markdown make a great pair, they are unrestricted by compatibility, specific software, or corporate governance. I've moved all my text-related work to plaintext and Markdown and it has added a lightness to working with text that is just perfect. + +Give Markdown + Plaintext a shot, there is literally no barrier to entry. Hopefully you will realize that getting out of heavy word processors like Word or Pages frees up your text, mind, and words. diff --git a/themes/cycle/exampleSite/content/post/polybar-fonts-and-ubuntu.md b/themes/cycle/exampleSite/content/post/polybar-fonts-and-ubuntu.md new file mode 100644 index 0000000..a2418ce --- /dev/null +++ b/themes/cycle/exampleSite/content/post/polybar-fonts-and-ubuntu.md @@ -0,0 +1,20 @@ +--- +title: "On Polybar bitmap fonts and Ubuntu" +date: 2020-11-06T10:15:09-05:00 +lastmod: 2020-11-06T10:15:09-05:00 +slug: polybar-fonts-and-ubuntu +excerpt: "Enable bitmap fonts on Ubuntu for an optimal polybar experience." +--- + +I use [polybar](https://polybar.github.io/) as my status bar in i3 and it's been going great for months now. However, I was recently grepping through the `syslog` trying to figure out why a browser crash happened and the log was filled with polybar spam that looked like this: `polybar|warn: Dropping unmatched character`. So I started picking at solving the warning. + +Turns out there's a [Github issue](https://github.com/polybar/polybar/issues/392#issuecomment-310778138) that contains the solution which is to enable bitmap fonts which I'll paste here for posterity: + +``` shell +# "Un-disable" bitmap fonts +sudo rm /etc/fonts/conf.d/70-no-bitmaps.conf +# Clear the font cache +sudo fc-cache -f -v +``` + +Apparently Ubuntu disables bitmap fonts by default but polybar uses bitmap fonts for icon rendering. I also needed to install the [sijj icon font family](https://github.com/stark/siji) which was painless. diff --git a/themes/cycle/exampleSite/content/post/pretty-git-log.md b/themes/cycle/exampleSite/content/post/pretty-git-log.md new file mode 100644 index 0000000..73d5281 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/pretty-git-log.md @@ -0,0 +1,16 @@ +--- +title: "Pretty Git log" +date: 2012-07-18T03:01:14-04:00 +lastmod: 2017-02-24T13:36:58-05:00 +slug: pretty-git-log +excerpt: "Handy tip for pretty git logs. +" +--- + +![pretty git log via David DeSandro](/images/pretty-git.png) + +Yesterday, [David DeSandro posted](http://dropshado.ws/post/27506212928/pretty-git-log) a handy little command-line alias to make git logs a bit "prettier". + +`alias glog="git log --format='%Cgreen%h%Creset%C(cyan)%an%Creset - %s' --graph"` + +Hat-Tip to [Mr. TJ Holowaychuk](http://tjholowaychuk.com/post/26904939933/git-extras-introduction-screencast) for the original idea. diff --git a/themes/cycle/exampleSite/content/post/psychicpaper.md b/themes/cycle/exampleSite/content/post/psychicpaper.md new file mode 100644 index 0000000..30a9632 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/psychicpaper.md @@ -0,0 +1,25 @@ +--- +title: "Psychic Paper" +date: 2020-05-18T10:27:38-04:00 +lastmod: 2020-05-18T10:27:38-04:00 +slug: psychicpaper +excerpt: "" +link: "https://siguza.github.io/psychicpaper/" +--- + +> RIP my very first 0day and absolute best sandbox escape ever: + +``` +application-identifier +... + +platform-application + +com .apple.private.security.no-container + +task_for_pid-allow + + +``` + +[Tweet](https://twitter.com/s1guza/status/1255641164885131268) that demonstrates a recent zero-day (now patched) in iOS. This serves as your annual reminder that parsing xml-like things is a fraught activity. diff --git a/themes/cycle/exampleSite/content/post/rands-on-email.md b/themes/cycle/exampleSite/content/post/rands-on-email.md new file mode 100644 index 0000000..189bcbb --- /dev/null +++ b/themes/cycle/exampleSite/content/post/rands-on-email.md @@ -0,0 +1,14 @@ +--- +title: "Rands on Email" +date: 2012-10-21T03:01:15-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: rands-on-email +excerpt: "A fantastic post from Michael Lopp. +" +--- + +Michael Lopp delivers a great piece on dealing with Email. I especially loved this quote: + +> Email is imprecise. It is easy to misinterpret. Email is a digital force of nature. It’s not going anywhere, but email, while convenient and sometimes efficient, is dehumanizing. + +Do yourself a favor and [read the whole thing](http://www.randsinrepose.com/archives/2012/10/14/the_elegant_email.html). diff --git a/themes/cycle/exampleSite/content/post/recently-16.md b/themes/cycle/exampleSite/content/post/recently-16.md new file mode 100644 index 0000000..3a8bfc4 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/recently-16.md @@ -0,0 +1,46 @@ +--- +title: "Recently" +date: 2021-04-23T11:37:19-04:00 +lastmod: 2021-04-23T11:37:19-04:00 +slug: recently-16 +excerpt: "A random assortment of links and miscellaneous updates on things." +--- + +I'm stealing the title format of this post from [Tom MacWright's](https://macwright.com/) Recently posts. + +Here's a random assortment of links and miscellaneous updates on things. + +## autofs +[autofs](https://help.ubuntu.com/community/Autofs) is a cool utility that watches a specific directory path and when a program tries to read or write to that path it mounts a filesystem at that location. I'm using this to auto mount my NAS via SMB for [mpd](https://www.musicpd.org). With autofs in place I can run mpd locally (in a ["satellite setup"](https://www.musicpd.org/doc/html/user.html#satellite-setup)) and have its `music_directory` point to a path managed by autofs. + +One thing that was helpful getting the configuration right was testing autofs by running `automount -f -v` directly which puts it in the foreground and gives verbose output. + +The two files I configured were `auto.master.d/foo.autofs` and `auto.foo`. + +- **foo.autofs** contains one line: `/- /etc/auto.foo` +- **auto.foo** contains one line as well: `/foo -fstype=cifs,rw,credentials=/home/me/.foo-creds ://NAS.IP/foo` + +## mailpreview updates +[mailpreview-cli](https://git.sr.ht/~asimpson/mailpreview-cli) is a little program I use multiple times a day to quickly see my unread email without moving from what I'm currently working on and without touching my mouse. I recently noticed it wasn't grabbing the body of a specific type of email. In the process of fixing that I also added proper unit tests for every format I currently parse through. Yay faster feedback loops! + +## ffmpeg +I've been a fan of OBS for awhile now. I was recently doing a quick screen recording of my browser window and the browser window wasn't full-screen so there were black bars around the edges of the recording. I didn't love that but it's time to touch the "ffmpeg exists and is awesome" sign again. + +[This superuser post](https://superuser.com/a/810524) has the answer which consists of two steps: + +1. Get the crop parameters of the video from ffmpeg. ffmpeg will detect the black borders and report back the actual content coordinates. +`ffmpeg.exe -i '.\some-video.mkv' -vf cropdetect -f null -` +2. Re-encode and crop using the crop parameters to trim the borders. +`ffmpeg.exe -i '.\some-video.mkv' -vf crop=624:704:332:10 -c:a copy output.mp4` +3. Enjoy your pristine video. + +## Links I've enjoyed + +- [Docker without docker](https://fly.io/blog/docker-without-docker/) +Really anything on the fly.io blog is _gold_. +- [David Crawshaw: SQLite and Go](https://www.youtube.com/watch?v=RqubKSF3wig)(Talk) +- [DNSFS](https://blog.benjojo.co.uk/post/dns-filesystem-true-cloud-storage-dnsfs) +- [Writing Small CLI Programs in Common Lisp](https://stevelosh.com/blog/2021/03/small-common-lisp-cli-programs/) +- [My Dream of the Great Unbundling](https://www.wired.com/story/my-dream-of-the-great-unbundling/) + +Fin diff --git a/themes/cycle/exampleSite/content/post/recently-44.md b/themes/cycle/exampleSite/content/post/recently-44.md new file mode 100644 index 0000000..a83ca7c --- /dev/null +++ b/themes/cycle/exampleSite/content/post/recently-44.md @@ -0,0 +1,24 @@ +--- +title: "Recently" +date: 2020-10-27T23:30:46-0400 +lastmod: 2020-10-27T23:30:46-0400 +slug: recently-44 +excerpt: "I've written a few small tools over the last couple months and I figured it's time I post about them." +--- + +I've published a few new projects in the last couple of months and I'm behind on announcing them, so I bundled them up together into this post. I'm stealing the title format of this post from [Tom MacWright's](https://macwright.com/) Recently posts. + +One thing to note is that the source code for all these projects is stored on [sourcehut](https://sourcehut.org/). Sourcehut (or sr.ht) bills itself as "the hacker's forge". I highly recommend checking it out. It's also where I host [my public inbox](https://lists.sr.ht/~asimpson/public-inbox). + +## hover-dns +Now that I have fiber internet at the house I've been hosting one-off services and apps on my own hardware at the house. This is great, however my residential connection is a typical dynamic IP not a static one. Instead of using a service like [DynamicDNS](https://account.dyn.com/) I decided to write some Rust (shocker) and leverage the "unofficial" Hover API. The result is: [hover-dns](https://git.sr.ht/~asimpson/hover-dns). + +I have `hover-dns` running in a crontab for a few different domains to keep my domains pointed to the correct IP for my house. While I'm a little uncomfortable with how similar `npm` and `cargo` can feel, the [`trust-dns`](https://docs.rs/trust-dns-resolver) package is _excellent_. I was able to quickly read the source code to understand how to setup a `Resolver` for [opendns](https://www.opendns.com/). Also impressive is that `hover-dns ip` beats out `dig` in returning your public IP. I didn't expect that! + +## podcastfilter +Speaking of hosting things at home, [podcastfilter.com](https://podcastfilter.com) is one of those things. [podcast-filter is a small Go project](https://git.sr.ht/~asimpson/podcast-filter) that allows you to filter a podcast feed by each episode's description and return a feed of just those episodes that match. + +## mailpreview +The recent project I use the most day-to-day is [mailpreview-cli](https://git.sr.ht/~asimpson/mailpreview-cli). `mailpreview-cli` is very straight-forward, it accepts a Mail message and returns either the plain text version or the html version of that message. The reason I don't just pull the Mail message directly is because a Mail message can contain several versions of the message in different encodings (start here if you're curious: [RFC-822](https://tools.ietf.org/html/rfc822)). Instead of writing my own parser I grabbed the excellent [mailparse crate](https://docs.rs/mailparse/) and wrapped the behavior I wanted around it. On it's own `mailpreview-cli` isn't super fancy but I trigger it from `rofi` via a [shell script](https://github.com/asimpson/dotfiles/blob/master/linux/mail-preview) which allows me to browse (and then view) all my unread emails right from `rofi`. Shameless plug: I wrote a short post about [getting started with `rofi`](https://adamsimpson.net/writing/getting-started-with-rofi) if you're unfamiliar. `mailpreview-cli` could be used with [Alfred](https://www.alfredapp.com/) if you're on a Mac to accomplish the same thing as I'm doing with a shell script and `rofi`. + +Fin diff --git a/themes/cycle/exampleSite/content/post/rename-utility.md b/themes/cycle/exampleSite/content/post/rename-utility.md new file mode 100644 index 0000000..146ac86 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/rename-utility.md @@ -0,0 +1,14 @@ +--- +title: "Rename utility" +date: 2013-02-13T03:01:15-05:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: rename-utility +excerpt: "A short primer on the rename command line utility. +" +--- + +I often find myself needing to rename batches of files. I find myself doing this when I have a set of images that are named `image-2x.png`, and I duplicate them for 1x assests. I tried [Automator](http://support.apple.com/kb/HT2488) to see if I could whip up a quick service that would remove the '-2x' from my 1x assests. I couldn't figure it out in 5 minutes, so I gave up (par for the course with these types of things). I then googled around a bit and turned up several tutorials using awk, sed, or some other custom function. None of that sounded very fun or easy; I then stumbled upon `rename`. + +Rename is a standard Unix utility that simply renames files given a pattern to search for and something (or nothing) to replace the pattern with. It supports standard things like globbing, and even supports testing your query to see the results\! A basic command looks like this: `rename 's/2x copy//g' *.jpg` Simple and perfect. In this case rename is going to strip out '2x copy' from any files that have that pattern and replace it with nothing, hence the double slashes at the end. That's all there is to it. Hopefully this helps someone else who just wants to rename a batch of files. + +To get rename on a Mac, just brew it, `brew install rename`. diff --git a/themes/cycle/exampleSite/content/post/rotten-tomatoes-and-launch-center.md b/themes/cycle/exampleSite/content/post/rotten-tomatoes-and-launch-center.md new file mode 100644 index 0000000..5ba8a14 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/rotten-tomatoes-and-launch-center.md @@ -0,0 +1,20 @@ +--- +title: "Rotten Tomatoes and Launch Center" +date: 2012-08-13T03:01:16-04:00 +lastmod: 2017-02-24T09:38:13-05:00 +slug: rotten-tomatoes-and-launch-center +excerpt: "Hack together a faster Rotten Tomatoes experience on the iPhone +" +--- + +I appreciate [Rotten Tomatoes](http://rottentomatoes.com), I don't always agree with the ratings, but I like how they can add to an argument or conversation about a movie. + +I hate the Rotten Tomatoes experience on an iPhone. It starts with this horrible app pop-up: ![Rotten Tomatoes Nag](/images/rotten-tomatoes-nag.png) + +Then it nags you to add the site to your homescreen, my home screen is meticulously planned out and I don't have the room for non-apps, so Rotten Tomatoes can go kick rocks. + +A month or so ago I decided to do something about these things that bug me about Rotten Tomatoes. I spent an hour or two poking around the [API](http://developer.rottentomatoes.com) and cobbled together [Diet Rotten Tomatoes](https://github.com/asimpson/Diet-Rotten-Tomatoes). It's a quick, lightweight way to get a movie's ratings, a full-size movie poster (click the thumbnail), and a link to the movie on Rotten Tomatoes. + +I also added a way to search using [Alfred](http://www.alfredapp.com) or [Launch Center Pro](http://appcubby.com/launch-center/). Simple append your search term to the URL like `#die hard` and it'll fire off a search as the page loads. + +Hopefully you find it useful. diff --git a/themes/cycle/exampleSite/content/post/rust-module-system.md b/themes/cycle/exampleSite/content/post/rust-module-system.md new file mode 100644 index 0000000..595836e --- /dev/null +++ b/themes/cycle/exampleSite/content/post/rust-module-system.md @@ -0,0 +1,14 @@ +--- +title: "Clear explanation of Rust’s module system" +date: 2020-07-19T23:52:26-04:00 +lastmod: 2020-07-19T23:52:26-04:00 +slug: rust-module-system +excerpt: "" +link: "http://www.sheshbabu.com/posts/rust-module-system/" +--- + +This is a _great_ explanation of Rust's module system. I wish I had this clear of a picture when I was using modules for the first time in creating [`oscar`](https://github.com/asimpson/oscar). + +The big takeaway and deviation from `npm` is this: + +> We need to explicitly build the module tree in Rust, there’s no implicit mapping to file system. diff --git a/themes/cycle/exampleSite/content/post/rust-strings-and-str.md b/themes/cycle/exampleSite/content/post/rust-strings-and-str.md new file mode 100644 index 0000000..877eac3 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/rust-strings-and-str.md @@ -0,0 +1,133 @@ +--- +title: "Understanding Rust Strings and str inside structs." +date: 2020-01-08T10:26:02-05:00 +lastmod: 2020-07-03T23:20:47-04:00 +slug: rust-strings-and-str +excerpt: "Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here's a short breakdown of a compiler error message around Strings and ownership that stumped me for a bit." +--- + +Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here's a short breakdown of a compiler error message that stumped me for a bit. + + +# Background + +First, some background about Rust. Rust is a strongly-typed language, which means variables and return values from functions usually require a type annotation that looks like this: + +```rust +let favorite_number: u32 = 12; +``` + +The type annotation on the variable `favorite_number` is `u32`. This should look familiar to anyone who has used a strongly typed language before. + +A struct in Rust is a way for the user to define any data type. Here's an example: + +```rust +struct Config { + name: String, + id: u32 +} +``` + +Here is how we would approximate this in Javascript: + +```js +const config = { + name: "Adam", + id: 4 +} +``` + +Notice how, in Javascript, we use an Object named `config` to hold some config for our application. In Rust, we create a `struct` called `Config` and define the various fields we need. Rust is strongly typed, so even the fields in the `Config` struct are type-annotated. Let's move to where I got tripped up. + + +# Stumped + +I created a `Vector` (a mutable Array data structure) that contained a couple of instances of a struct. It looked something like this: + +```rust +struct Example { + id: String +} + +fn main() { + let example: Vec = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}]; + println!("{:?}", example); +} +``` + +So far, so good. However, I now wanted to `map` over the collection and create a new collection that just contained the `id`. Here's what I tried and what failed: + +```rust +struct Example { + id: String +} + +fn main() { + let example: Vec = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}]; + let map_fail: Vec = example.iter().map(|item| item.id).collect(); + println!("{:?}", map_fail); +} +``` + +[Rust playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=50f404dd47af19b0f4373fea1f7a3719) + + +# Understanding the problem + +What's happening here? Well, the compiler message is instructive: + +```shell + error[E0507]: cannot move out of `item.id` which is behind a shared reference + --> src/main.rs:10:59 + | + 10 | let map_fail: Vec = example.iter().map(|item| item.id).collect(); + | ^^^^^^^ move occurs because `item.id` has type `std::string::String`, which does not implement the `Copy` trait + + error: aborting due to previous error + + For more information about this error, try `rustc --explain E0507`. +``` + +In Rust there is no [Garbage collection](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)) (automatic memory management). Instead, Rust requires you, the programmer, to indicate to the Rust compiler [what variables have ownership over the value they represent](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html). If that ownership moves in an invalid way, Rust will throw a compile error to prevent a memory error at runtime. The benefit in not having Garbage Collection is two-fold: + +1. Faster code without a GC process. +2. Whole classes of bugs are impossible due to Rust's ownership rules. + +In our error case, mapping over our vector moves the data stored at `id` to a new `Vector`. This shift to a new `Vector` means Rust can no longer guarantee the safety of that portion of memory. Let's look at the documentation around this error code from the compiler. + +The [explainer page for this error](https://doc.rust-lang.org/stable/error-index.html#E0507) gives us three options: + +> 1. Try to avoid moving the variable. +> 2. Somehow reclaim the ownership. +> 3. Implement the Copy trait on the type. + +\#3 sounded like too much for this specific case. #2 also seemed like the wrong approach because I didn't want to change the ownership, I just wanted a copy or reference to it. #1 was the right answer, but how do I avoid moving the variable? + + +# The Solution + +This is where it's important to understand the two basic types for strings in Rust, `String` and `str`. The [doc page for `String`](https://doc.rust-lang.org/std/string/struct.String.html) states (I added the underlines for emphasis): + +> The String type is the most common string type that has ownership over the contents of the string. It has a close relationship with its borrowed counterpart, the primitive str. + +Aha, so we're dealing with a `String` here, and it sounds like we need a `str`. A quick glance at the `String` doc page again [reveals just the function we need: `as_str`](https://doc.rust-lang.org/std/string/struct.String.html#method.as_str). `as_str` gives us a reference [called a `slice`](https://doc.rust-lang.org/book/ch04-03-slices.html#string-slices) to the value of a `String`. Armed with this new knowledge, here's the solution to this compiler error: + +```rust +struct Example { + id: String +} + +fn main() { + let example: Vec = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}]; + println!("{:?}", example); + + let map_str: Vec<&str> = example.iter().map(|item| item.id.as_str()).collect(); + println!("{:?}", map_str); +} +``` + +[Rust playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fa5624ee76fbecafbe282de6190b079c) + +# Fin + +Rust has proven challenging to learn, but I think the journey and difficulty is worth it. Ownership, the type-system, and the excellent performance continue to impress me. I hope this post encourages folks to give Rust a try! I'm happy to answer any questions via the comments or [twitter](https://twitter.com/a_simpson) or wherever else. diff --git a/themes/cycle/exampleSite/content/post/s3-security-policy.md b/themes/cycle/exampleSite/content/post/s3-security-policy.md new file mode 100644 index 0000000..66bbbab --- /dev/null +++ b/themes/cycle/exampleSite/content/post/s3-security-policy.md @@ -0,0 +1,18 @@ +--- +title: "S3 Security Policy" +date: 2014-04-26T03:01:17-04:00 +lastmod: 2015-03-21T19:45:36-04:00 +slug: s3-security-policy +excerpt: "A basic AWS S3 bucket policy that restricts access to a single bucket, and allows access via the AWS cli. +" +--- + +I love S3, I use it with [Arq](http://www.haystacksoftware.com/arq/), I use it to host this site, backup configs on VPSs, and to transfer random files that are too big for e-mail. + +As my S3 usage has grown I've started creating seperate AMI users for each task, e.g. a siteleaf user for this blog. It wasn't until tonight that I took the time to craft a better security policy for some of these users. + +I struggled finding good policy examples until I stumbled across [this one](http://blogs.aws.amazon.com/security/post/Tx1P2T3LFXXCNB5/Writing-IAM-policies-Grant-access-to-user-specific-folders-in-an-Amazon-S3-bucke) over on the [AWS Security blog](http://blogs.aws.amazon.com/security/). I highly recommend reading it all the way through. + +[Here's the basic policy I came up with](https://gist.github.com/asimpson/11335531). This policy restricts access to a single bucket, and allows access via the AWS cli. + +Note: I had to move the policy to a [gist](https://gist.github.com/asimpson/11335531) as [prismjs](http://prismjs.com) was having a hard time with it. diff --git a/themes/cycle/exampleSite/content/post/seamless-branch-deploys-with-kubernetes.md b/themes/cycle/exampleSite/content/post/seamless-branch-deploys-with-kubernetes.md new file mode 100644 index 0000000..6b06c5c --- /dev/null +++ b/themes/cycle/exampleSite/content/post/seamless-branch-deploys-with-kubernetes.md @@ -0,0 +1,12 @@ +--- +title: "Seamless branch deploys with Kubernetes" +date: 2020-04-27T10:10:46-04:00 +lastmod: 2020-04-27T10:10:46-04:00 +slug: seamless-branch-deploys-with-kubernetes +excerpt: "" +link: "https://m.signalvnoise.com/seamless-branch-deploys-with-kubernetes/" +--- + +A trait of good software is the ability to quickly see and verify changes: + +> The result is what’s in-use today for HEY: a system that (almost) immediately deploys any branch to a branch-specific endpoint that you can access right away to test your changes without having to use the claims system or talk to anyone else (along with an independent job processing fleet and Redis instance to support the environment). diff --git a/themes/cycle/exampleSite/content/post/search-imessage-sql.md b/themes/cycle/exampleSite/content/post/search-imessage-sql.md new file mode 100644 index 0000000..ee6b226 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/search-imessage-sql.md @@ -0,0 +1,14 @@ +--- +title: "Using SQL to Look Through All of Your iMessage Text Messages" +date: 2020-05-28T21:25:06-04:00 +lastmod: 2020-05-28T21:25:06-04:00 +slug: search-imessage-sql +excerpt: "" +link: "https://spin.atomicobject.com/2020/05/22/search-imessage-sql/" +--- + +> If you use iMessage on your Mac, you can access the SQLite database where all of your messages are stored. With a little setup, you can use SQL’s raw power to look through your old messages. + +[via Simon Willison](https://simonwillison.net/2020/May/22/using-sql-look-through-all-your-imessage-text-messages/) + +In this post Dan Kelch walks through how to access the SQLite database that backs iMessage on a Mac. He also shares a few helpful SQL snippets to demonstrate how powerful using SQL on your text messages can be. diff --git a/themes/cycle/exampleSite/content/post/second-guessing-the-modern-web.md b/themes/cycle/exampleSite/content/post/second-guessing-the-modern-web.md new file mode 100644 index 0000000..fad1c28 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/second-guessing-the-modern-web.md @@ -0,0 +1,12 @@ +--- +title: "Second-guessing the modern web" +date: 2020-05-13T11:34:19-04:00 +lastmod: 2020-05-13T11:34:19-04:00 +slug: second-guessing-the-modern-web +excerpt: "" +link: "https://macwright.org/2020/05/10/spa-fatigue.html" +--- + +> The low performance parts don’t need to be React. Listing pages, static pages, blogs - these things are increasingly built in React, but the benefits they accrue are extremely narrow. A lot of the optimizations that are cropping up in these corners, things like bundle splitting, server-side rendering, and prerendering, are triangulating, essentially, what we had before the rise of React. + +This isn't really about React but more about the over-engineering of large swaths of page-types and sites that used to "just work". I _love_ React and it's been a giant leap forward for creating complex UIs on the web, that doesn't mean it's right for every situation. diff --git a/themes/cycle/exampleSite/content/post/setting-a-default-browser-in-i3.md b/themes/cycle/exampleSite/content/post/setting-a-default-browser-in-i3.md new file mode 100644 index 0000000..8db71e6 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/setting-a-default-browser-in-i3.md @@ -0,0 +1,42 @@ +--- +title: "Setting a default browser in i3" +date: 2020-09-11T00:01:05-0400 +lastmod: 2020-09-11T00:01:05-0400 +slug: setting-a-default-browser-in-i3 +excerpt: "Using a desktop manager like GNOME makes setting default applications easy. However when using a tiling window manager like i3 setting a default application is opaque to the newbie such as myself." +--- + +## The problem +I've been using the excellent [qutebrowser](https://qutebrowser.org/) for a few weeks now and I really enjoy it's minimal approach to web browsing. I still reach for Firefox or Chrome for web development purposes but `qutebrowser` shines as a daily driver. An issue I ran into is I didn't know how to set `qutebrowser` as my default web browser when using [i3wm](https://i3wm.org/) (or any tiling window manager really). + +## The Solution +Here's the solution if you don't care about the process of figuring it out: + +``` +xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop +``` + +## The Yak +Thankfully there's an [issue on the qutebrowser repo](https://github.com/qutebrowser/qutebrowser/issues/22) where folks discussed this very thing. Let's pull the solution apart to gain some understanding of the systems at play here. + +The first part of the solution in the issue thread is: + +``` +ls /usr/share/applications/ | grep qutebrowser +``` + +which lists all the files in `/usr/share/applications` and then greps that list for entries that contain the word `qutebrowser`. [The Arch Wiki entry on "Desktop entries"](https://wiki.archlinux.org/index.php/Desktop_entries) explains what the files inside `/usr/share/applications` are and why that directory is important. + +> Desktop entries for applications, or .desktop files, are generally a combination of meta information resources and a shortcut of an application. These files usually reside in /usr/share/applications/ or /usr/local/share/applications/ for applications installed system-wide, or ~/.local/share/applications/ for user-specific applications. + +So by looking for `qutebrowser` in `/usr/share/applications` we're looking for its `.desktop` file which is important for the next step. + +Looking at the next part of the solution involves running a program called `xdg-settings`. What is that? The man page declares that `xdg-settings` is used to "get various settings from the desktop environment". OK, so it's a tool to get (and apparently set?) desktop environment settings. This seems like the right thing. Let's keep reading the man page. + +Further on in the man page we find an example on how to set Chrome as the default web browser: `xdg-settings set default-web-browser google-chrome.desktop`. Notice the `.desktop` file at the end of the command? XDG uses that file name to figure out which app to use for certain file and link types like `text/html` or `x-scheme-handler/http`. Back to our specific case, we need the full name of the desktop file to pass to `xdg-settings` which is `org.qutebrowser.qutebrowser.desktop`. With this information we can change the default browser to `qutebrowser` by running: + +``` +xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop +``` + +This tells the desktop environment to launch whatever process is defined in that `.desktop` file for "browser things". diff --git a/themes/cycle/exampleSite/content/post/simple-account-set-up.md b/themes/cycle/exampleSite/content/post/simple-account-set-up.md new file mode 100644 index 0000000..63575b6 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/simple-account-set-up.md @@ -0,0 +1,22 @@ +--- +title: "Simple Account Set-up" +date: 2012-08-01T03:01:18-04:00 +lastmod: 2017-02-24T09:39:40-05:00 +slug: simple-account-set-up +excerpt: "Simple does account set-up right. +" +--- + +I recently received my invite to [Simple](https://www.simple.com/), a new banking service that has taken the design and development communities by storm with the promise of intelligently designed banking apps and interfaces. Now, I'm still waiting for my card to come, so I can't comment on the service itself. But, during the account set-up process, I was struck by how "right" it all felt, I took some screenshots as I went through to share. + +Once you fill in your personal info and are approved for an account, you are taken to a page to set up a username and pass*phrase*. Yes, you read that correctly, not a password, a pass*phrase*. Simple claims a passphrase is easier to remember and improves the security of the account. + +Once your passphrase and username are set up, Simple moves you to the next stage of the process, as pictured below: ![download the simple app](/images/simple-1.png) + +I elected to have a SMS sent to my iPhone to download the Simple app, sure enough in a few seconds there it was. I left the browser window open and proceeded to install the app which had me pick a 4 digit PIN as part of its setup. + +Once I selected my PIN, the app presented the various user agreements and banking terms with a signature box to sign with my finger. After signing the box and poking around the app a bit more, I looked up at my computer screen and saw that the Simple page had changed to this: ![signature complete](/images/simple-2.png) + +Slick\! The app had sent my signature to the page\! In doing so, Simple infused a little bit of magic into a typically mundane sign-up process. The other key point of this process is that it ensures the focal point of the service, the Simple app, is set up and ready to go on every customer's phone. + +I'm excited to get my Simple card and start using the service, I hope every other bank in the world is paying attention, these little details matter\! diff --git a/themes/cycle/exampleSite/content/post/slanted-elements-with-css3.md b/themes/cycle/exampleSite/content/post/slanted-elements-with-css3.md new file mode 100644 index 0000000..59132c2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/slanted-elements-with-css3.md @@ -0,0 +1,10 @@ +--- +title: "Slanted Elements with CSS3" +date: 2013-04-21T03:01:19-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: slanted-elements-with-css3 +excerpt: "How to use CSS3 transforms to work with slanted elements +" +--- + +I wrote up a post over on the [Foundry](http://seesparkbox.com/foundry/) detailing how to use CSS3 transforms to work with slanted elements. [Check it out](http://seesparkbox.com/foundry/slanted_elements_with_css3)\! diff --git a/themes/cycle/exampleSite/content/post/small-tech.md b/themes/cycle/exampleSite/content/post/small-tech.md new file mode 100644 index 0000000..9c66e62 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/small-tech.md @@ -0,0 +1,18 @@ +--- +title: "Small tech" +date: 2020-09-25T15:53:06-04:00 +lastmod: 2020-09-25T15:53:06-04:00 +slug: small-tech +excerpt: "" +link: "https://scattered-thoughts.net/writing/small-tech/" +--- + +[Jamie Brandon](https://scattered-thoughts.net/) has a nice post about "small tech": tech that isn't backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list. + +- [curl](https://curl.haxx.se/) is open-source and has thousands of contributors but is still primarily designed and managed by [@bagder (Daniel Stenberg)](https://daniel.haxx.se/). If you ever do anything with http for any kind of development mastering `curl` is worth the time investment. + +- [git](https://git-scm.com/) is _the_ premier version control system on the planet. It started out as a side-project to manage Linux kernel development. + +- [Alpine Linux](https://www.alpinelinux.org/) is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images. + +- [sr.ht](https://sr.ht/) does not have the type of scale or impact that the others items on this list have _but_ I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—[Drew DeVault](https://drewdevault.com/)—and is 100% open-source. diff --git a/themes/cycle/exampleSite/content/post/small-things.md b/themes/cycle/exampleSite/content/post/small-things.md new file mode 100644 index 0000000..e5735cc --- /dev/null +++ b/themes/cycle/exampleSite/content/post/small-things.md @@ -0,0 +1,15 @@ +--- +title: "Small things" +date: 2015-08-22T16:42:04-04:00 +lastmod: 2015-08-22T16:43:26-04:00 +slug: small-things +excerpt: "Recently I've come to love MicroJS. I love that I can find tiny, specific libraries that do one thing, and do it well" +--- + +Recently I've come to love [MicroJS](http://microjs.com). I love that I can find tiny, specific libraries that do one thing, and do it well. I think my affection for MicroJS is fueled by my [current fascination](/writing/learning-to-think-in-react), [React](http://reactjs.com). React bills itself as: + +> A Javascript library for building user interfaces. + +I think this focus on building user interfaces pushes me to seek out complimentary tools that focus on solving singular problems. React's narrowly-defined API and reliance on Javascript's primitives leaves lots of space for me to cobble together the stack that best solves the current problem(s). + +As I've thought about this more, I've realized just how powerful a framework's aspirations can be. They trickle in and bend my perspective when I use them. It is a small thing that developers, myself included, often overlook. diff --git a/themes/cycle/exampleSite/content/post/solving-busybox-crond-hanging-on-alpine-linux-boot.md b/themes/cycle/exampleSite/content/post/solving-busybox-crond-hanging-on-alpine-linux-boot.md new file mode 100644 index 0000000..11c6816 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/solving-busybox-crond-hanging-on-alpine-linux-boot.md @@ -0,0 +1,33 @@ +--- +title: "Solving busybox crond hanging on Alpine Linux boot" +date: 2019-05-05T14:13:02-0400 +lastmod: 2019-05-05T14:13:02-0400 +slug: solving-busybox-crond-hanging-on-alpine-linux-boot +excerpt: "How busybox crond hanging at startup sent me down a rabbit hole where I learned about entropy and Linux." +--- + +I recently clean installed [Alpine Linux 3.9.3](https://alpinelinux.org/posts/Alpine-3.9.0-released.html) on my home router (more to come on that in a future post) and ran into a weird bug. Once I successfully installed Alpine and rebooted, the system would start and then hang for over a half hour(!) with the message "Starting busybox crond...". I tried downgrading to 3.8.0 without any luck. I did some quick Googling and didn't find anything about busybox crond hanging. + +Stumped I headed over to the [`#alpine-linux` IRC](https://www.alpinelinux.org/community/) and posted my situation there. A friendly user suggested it might have something to do with "entropy changes" and to switch the daemons in question to use `/dev/urandom`. I didn't feel like switching the daemons was going to be a good long-term solution but I was intrigued by the entropy angle. I looked it up and stumbled upon this reply to a [bug thread](http://lists.alpinelinux.org/alpine-user/0605.html) about "Startup hangs (aports: sshd?)": + +> +> > Hello. +> > +> > After upgrading to [edge] i see a possibly endless hang upon +> > startup, which seems to be caused by PRNG init. +> +> Try add `random.trust_cpu=1` as boot option. +> +> See: +> +> +> and: +> +> +> -nc + +Interesting. Entropy and boot time *are* related. Remember I had installed Alpine on a router: a *headless* PC without any I/O other than two Ethernet NICs and a SSD. Not much there for Linux to generate entropy with, especially since the default was to *not* trust my CPU. + +I searched for entropy on the excellent Alpine wiki and found [this page](https://wiki.alpinelinux.org/wiki/Entropy_and_randomness). This lead me to [Haveged](https://wiki.alpinelinux.org/wiki/Entropy_and_randomness#Haveged). [Haveged](https://issihosts.com/haveged/) is a service that [generates additional entropy](https://opium.io/blog/haveged/). I stared it up, enabled it to run at boot, and I no longer had any hang time at boot! + +I later found [this bug report](https://bugs.alpinelinux.org/issues/9960) that outlined my problem exactly. Turns out I was too focused on the `crond` aspect of my boot problem and not the general delay in booting. Oh well, TIL. diff --git a/themes/cycle/exampleSite/content/post/someone-is-working-harder-than-you.md b/themes/cycle/exampleSite/content/post/someone-is-working-harder-than-you.md new file mode 100644 index 0000000..6f0cc93 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/someone-is-working-harder-than-you.md @@ -0,0 +1,20 @@ +--- +title: "Someone is working harder than you" +date: 2012-07-19T03:01:20-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: someone-is-working-harder-than-you +excerpt: "Hard work and how to be creative +" +--- + +When I was in junior high I attended a basketball camp. The camp moto for the week went something like: "There's always more one can do, always someone working harder than you". + +At the time I thought this meant Michael Jordan was working harder than me (he was\!), but that I was right up there cause I was at camp, duh\! + +[Scott Berkun wrote](http://www.scottberkun.com/blog/2012/how-to-become-creative-the-short-honest-truth/) a few days ago: + +> Few people in history that we call creatives today read books or took courses on creativity. Instead they apprenticed with masters in a craft and worked with them. They did the grunt work until they had the skills needed to do more sophisticated work. They learned how to develop ideas and deliver finished work by working. There is no other way. + +Go work. + +As the youths say, 'nough said. diff --git a/themes/cycle/exampleSite/content/post/sparrow-and-the-app-store.md b/themes/cycle/exampleSite/content/post/sparrow-and-the-app-store.md new file mode 100644 index 0000000..ff0bfff --- /dev/null +++ b/themes/cycle/exampleSite/content/post/sparrow-and-the-app-store.md @@ -0,0 +1,14 @@ +--- +title: "Sparrow and the App Store" +date: 2012-07-23T03:01:20-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: sparrow-and-the-app-store +excerpt: "App Cubby's take on Google's acquisition of Sparrow +" +--- + +[David Barnard writes up](http://appcubby.com/blog/the-sparrow-problem/) his take on why [Sparrow](http://sparrowmailapp.com/) sold out. I found the end of his post fascinating: + +> The age of selling software to users at a fixed, one-time price is coming to an end. It’s just not sustainable at the absurdly low prices users have come to expect. Sure, independent developers may scrap it out one app at a time, and some may even do quite well and be the exception to the rule, but I don’t think Sparrow would have sold-out if the team — and their investors — believed they could build a substantially profitable company on their own. The gold rush is well and truly over. + +We are witnessing so many changes on the web and in the mobile industry. Software pricing and sustainability is just another item on a long list of things that are evolving. diff --git a/themes/cycle/exampleSite/content/post/sqlite-tips.md b/themes/cycle/exampleSite/content/post/sqlite-tips.md new file mode 100644 index 0000000..b21bc7b --- /dev/null +++ b/themes/cycle/exampleSite/content/post/sqlite-tips.md @@ -0,0 +1,25 @@ +--- +title: "SQLite Tips" +date: 2015-12-20T14:52:41-05:00 +lastmod: 2020-09-17T11:53:48-0400 +slug: sqlite-tips +excerpt: "I've been playing around with SQLite recently and I've stumbled across a few things I want to remember, so I'm putting them here." +--- + +I've been playing around with SQLite recently and I've stumbled across a few things I want to remember, so I'm putting them here. + +1. The [SQLite CLI](https://sqlite.org/cli.html) is pretty darn good. Just remember to read in the SQLite DB file first, e.g. `.open /path/to/file`. After that, any SQLite command is valid. Specific CLI commands are prefixed with a period. + +2. Set the the `.mode` to `line` to visually grep the results. + +3. To see the `rowid` include it specifically in `SELECT` statements on the CLI, e.g. `SELECT rowid,* from table`. + +4. Delete an entry by `rowid` like this, `DELETE FROM table WHERE rowid=7;` + +5. When structuring a database, create a unique ID for each row like so: `create table foo (id INTEGER AUTO_INCREMENT PRIMARY KEY UNIQUE NOT NULL, other_column TEXT)`. + +6. View all tables via `.tables`. + +7. View schema for a table via `.schema TABLENAME`. + +That's all I got for now. I'll drop more tips in this post as I come across them. diff --git a/themes/cycle/exampleSite/content/post/story.md b/themes/cycle/exampleSite/content/post/story.md new file mode 100644 index 0000000..093e082 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/story.md @@ -0,0 +1,18 @@ +--- +title: "Story" +date: 2012-07-26T03:01:21-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: story +excerpt: "The importance of story in products, design, and development. +" +--- + +> Before a technologist writes a line of code, or a marketer writes a line of copy, or a designer creates a single wireframe or design, you have to establish the story that your product is going to tell. + +\-[UX Mag](http://uxmag.com/articles/why-we-need-storytellers-at-the-heart-of-product-development) + +Story is essential for many things, beyond just products. Stories are how we as humans define our memories and explain our world. + +A product without a good story - a story that explains where something came from and where it is going - inspires apathy and disinterest. + +Stories not only affect the consumer and the success of the product, they also affect the people working on the product. If you are feeling "disinterested" or "unmotivated" in your work, examine the story behind your work or product. diff --git a/themes/cycle/exampleSite/content/post/the-era-of-the-screenshot.md b/themes/cycle/exampleSite/content/post/the-era-of-the-screenshot.md new file mode 100644 index 0000000..010e1c2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-era-of-the-screenshot.md @@ -0,0 +1,20 @@ +--- +title: "The era of the screenshot" +date: 2017-06-12T22:56:24-04:00 +lastmod: 2017-06-12T22:56:24-04:00 +slug: the-era-of-the-screenshot +excerpt: "We really couldn't have picked a worse data exchange format." +--- + +From [Benedict Evan's weekly newsletter](http://mailchi.mp/ben-evans/benedicts-newsletter-no-450333?e=c97fd3b467) on the new screenshot features in iOS11: + +> Finally, screenshots. It's pretty clear that smartphone screenshots are the new PDF - a universal data exchange format. + +:facepalm: We really couldn't have picked a worse data exchange format. + +\-1000 internets everybody. + + - How do those with vision handicaps parse the data in a screenshot? + - How do machines reliably parse screenshot information? + +\-100 more internets after I've thought about it some more. diff --git a/themes/cycle/exampleSite/content/post/the-future-is-prototyping.md b/themes/cycle/exampleSite/content/post/the-future-is-prototyping.md new file mode 100644 index 0000000..eda6dd6 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-future-is-prototyping.md @@ -0,0 +1,14 @@ +--- +title: "The Future is Prototyping" +date: 2012-07-31T03:01:23-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: the-future-is-prototyping +excerpt: "A fantastic quote from a fantastic article over at Big Spaceship +" +--- + +First off, you need to read this entire post, [Try and Try Again – Why Prototyping Matters](http://www.bigspaceship.com/2012/07/try-and-try-again-why-prototyping-matters/) over at [Big Spaceship](http://www.bigspaceship.com/). It's fantastic, awesome, informative, funny, and best of all correct\! I'll be posting more on my personal experience with this topic eventually, but for now here is my favorite quote from the post, + +> If action speaks louder than words, then prototyping must be doing the death-metal guttural scream right in speculation’s ear. Instead of spending time discussing possibilities, we can spend time actually making something work. The earlier you get to the trying, the better you can inform the design – from font choices and colors to advanced interaction and mental models. + +[Go read](http://www.bigspaceship.com/2012/07/try-and-try-again-why-prototyping-matters/) the whole thing. diff --git a/themes/cycle/exampleSite/content/post/the-manhattan-project-time-lapse.md b/themes/cycle/exampleSite/content/post/the-manhattan-project-time-lapse.md new file mode 100644 index 0000000..2a0cecb --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-manhattan-project-time-lapse.md @@ -0,0 +1,14 @@ +--- +title: "The Manhattan Project Time-Lapse" +date: 2012-06-24T03:01:23-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: the-manhattan-project-time-lapse +excerpt: "An incredible time-lapse of Manhattan +" +--- + +[This](http://vimeo.com/43580167) is just an incredible time-lapse of Manhattan by [Cameron Michael](http://cameron-michael.tumblr.com/). + +Hat-tip to [Khoi Vinh](http://twitter.com/khoi/status/217338217970671616) for the tweet. + +Stunning work. diff --git a/themes/cycle/exampleSite/content/post/the-stream-hasnt-won.md b/themes/cycle/exampleSite/content/post/the-stream-hasnt-won.md new file mode 100644 index 0000000..8519eb5 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-stream-hasnt-won.md @@ -0,0 +1,13 @@ +--- +title: "The Stream hasn't won" +date: 2015-07-17T10:36:58-04:00 +lastmod: 2015-07-17T10:37:33-04:00 +slug: the-stream-hasnt-won +excerpt: "Hossein Derakhshan outlines how the web as he knew it has disappeared and been replaced by \"The Stream\", or social media. His post is beautifully written and I highly recommend reading it." +--- + +[Hossein Derakhshan](https://twitter.com/h0d3r) wrote a [fascinating piece over on Medium](https://medium.com/matter/the-web-we-have-to-save-2eb1fe15a426) that speaks about the web and his relation to it before and after his time in an Iranian prison. He outlines how the web as he knew it has disappeared and been replaced by "The Stream", or social media. His post is beautifully written and I highly recommend reading it. However, I disagree with some of his conclusions: + +> I miss when people took time to be exposed to different opinions, and bothered to read more than a paragraph or 140 characters. I miss the days when I could write something on my own blog, publish on my own domain, without taking an equal time to promote it on numerous social networks; when nobody cared about likes and reshares. + +Nothing in this statement has gone away\! The rise of social networks does not mean "the blog" or "the web" is in decline. "The Stream" hasn't won, I'm not convinced there's even a fight. diff --git a/themes/cycle/exampleSite/content/post/the-thing-about-computers.md b/themes/cycle/exampleSite/content/post/the-thing-about-computers.md new file mode 100644 index 0000000..7e4fd60 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-thing-about-computers.md @@ -0,0 +1,15 @@ +--- +title: "The thing about computers" +date: 2019-09-21T13:40:51-04:00 +lastmod: 2019-09-21T13:40:51-04:00 +slug: the-thing-about-computers +excerpt: "Brent Simmons talks about what made computing so compelling and what we might be losing." +--- + +> Maybe because I lived through this — maybe because I’m a certain age — I believe that that freedom to use my computer exactly how I want to, to make it do any crazy thing I can think of — is _the_ thing about computers. + +[Brent Simmons](https://inessential.com/2019/04/23/freedom) + +I literally cannot agree with this more strongly! It's been open in a tab on my phone since Brent published it and I can't stop thinking about it. + +I think there's a line somewhere where convenience and ease-of-use meets this freedom to do anything computing ideal. I think I will always bend toward the _freedom_ side over convenience when it comes to my personal computers. Conversely, I think I bend towards the _convenience_ side over freedom when it comes to my phone. I'm not sure why that is. diff --git a/themes/cycle/exampleSite/content/post/the-web-and-my-goal.md b/themes/cycle/exampleSite/content/post/the-web-and-my-goal.md new file mode 100644 index 0000000..73bd81f --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-web-and-my-goal.md @@ -0,0 +1,16 @@ +--- +title: "The web, and my goal" +date: 2012-07-12T03:01:24-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: the-web-and-my-goal +excerpt: "Thought from the Pastry Box Project's Bruce Lawson. +" +--- + +[The Pastry Box Project](http://the-pastry-box-project.net/) is a [fantastic collaboration](http://the-pastry-box-project.net/bakers/) that is updated once every day with entries regarding the web, development, best practices, or life. + +Today, [Bruce Lawson wrote](http://the-pastry-box-project.net/bruce-lawson/2012-july-13/): + +> \[...\]So the next time you hit upon a clever technique, blog about it. Or if you write some code that could be useful to someone else, put it on Github. Put something back into the community. + +That is my motivation for starting this blog. I glean so much information from fellow web workers that I thought it was high-time I began giving back. diff --git a/themes/cycle/exampleSite/content/post/the-web-is-not-print.md b/themes/cycle/exampleSite/content/post/the-web-is-not-print.md new file mode 100644 index 0000000..4b37aa6 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-web-is-not-print.md @@ -0,0 +1,14 @@ +--- +title: "The Web is Not Print" +date: 2012-07-22T03:01:25-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: the-web-is-not-print +excerpt: "The infamous Zeldman dishses on the web and print +" +--- + +[Zeldman's notes](http://www.zeldman.com/2012/07/09/mobile-to-the-future-luke-wroblewski/) from [Luke Wroblewski's](http://www.lukew.com/) talk, "Mobile to the Future" at Austin, AEA. + +> Likewise, we still have ingrained print characteristics impacting how we think about web and mobile. (Page/canvas, grid layouts, typography, graphical ads.) As many people will tell you — but not many people practice — the web is not print. + +It's exciting to be working on the web when some of these "print ideas" are starting to give way as the web matures. diff --git a/themes/cycle/exampleSite/content/post/the-wordpress-http-api-is-awesome.md b/themes/cycle/exampleSite/content/post/the-wordpress-http-api-is-awesome.md new file mode 100644 index 0000000..b346d88 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/the-wordpress-http-api-is-awesome.md @@ -0,0 +1,14 @@ +--- +title: "The Wordpress HTTP API is Awesome" +date: 2012-06-28T03:01:25-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: the-wordpress-http-api-is-awesome +excerpt: "The title says it all. I completely forgot about the Wordpress HTTP API until today. +" +--- + +The title says it all. I completely forgot about [the Wordpress HTTP API](http://codex.wordpress.org/HTTP_API) until today, when I was working with HTTP requests in a plugin. I stumbled upon the [wp\_remote\_post](http://codex.wordpress.org/Function_API/wp_remote_post) function and it immediately replaced my custom HTTP function. + +### Hidden Gem + +One of the hidden gems in the [wp\_remote\_post](http://codex.wordpress.org/Function_API/wp_remote_post) function is in the optional arguments you can pass along, specifically the ["blocking" option](http://codex.wordpress.org/HTTP_API#Other_Arguments). This option allows you to block script execution while it waits for the response or allows the script to continue on. So simple\! diff --git a/themes/cycle/exampleSite/content/post/theme-the-chrome-dev-tools.md b/themes/cycle/exampleSite/content/post/theme-the-chrome-dev-tools.md new file mode 100644 index 0000000..21657de --- /dev/null +++ b/themes/cycle/exampleSite/content/post/theme-the-chrome-dev-tools.md @@ -0,0 +1,16 @@ +--- +title: "Theme the Chrome Dev Tools" +date: 2012-10-09T03:01:26-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: theme-the-chrome-dev-tools +excerpt: "A short post on how to theme the Chrome Dev Tools +" +--- + +Let me start by explaining that the Chrome Developer Tools are incredible, and that I consider them essential to doing my job. What I did not know about these awesome tools is that they are essentially a web app; an app that I can tweak, change, and even inspect with itself. + +Last week, I stumbled across [this post](http://darcyclarke.me/design/skin-your-chrome-inspector/) by Mr. Clarke where he explains how to theme the Dev Tools using a single CSS file. This blew my mind and led to a fury of Googling for different themes. I eventually found the exact same theme I use in Sublime, only for the Dev Tools. [The Tomorrow Theme for Chrome by Ben Truyman](https://gist.github.com/1163300) was almost perfect, I made a few slight modifications to it and posted my own gist [here](https://gist.github.com/3841278). + +Some of you may be wondering, "Wait, how did you make modifications? Guesswork?". Nope. Paul Irish [explains in this thread](http://paulirish.com/2011/a-re-introduction-to-the-chrome-developer-tools/#comment-82042) how to inspect the Dev Tools…using the Dev Tools\! With this little hint, you can easily tweak or completely theme the Chrome Dev Tools. + +I hope this post was helpful to someone who was unaware of all this functionality a mere stylesheet away. diff --git a/themes/cycle/exampleSite/content/post/thirty-five.md b/themes/cycle/exampleSite/content/post/thirty-five.md new file mode 100644 index 0000000..2df1aba --- /dev/null +++ b/themes/cycle/exampleSite/content/post/thirty-five.md @@ -0,0 +1,53 @@ +--- +title: "Thirty five" +date: 2022-03-03T10:28:44-0500 +lastmod: 2022-03-03T10:28:44-0500 +slug: thirty-five +excerpt: "It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday." +--- + +Well crap. + +It's been 5 years since I wrote ["Thirty"][thirty]. So now I have to come up with 35 things as I turned 35 yesterday. If anything from Thirty is grossly wrong or really interesting I'll update it at the same number eh? + +Let's go... + +1. I still don't have it figured out, but this isn't such a shock anymore. +2. Building a house is _more_ scary. +3. Minivans are _awesome_. +4. Expecting a third kid is not nearly as scary as expecting the first. +5. COVID sucked. +6. Modern medicine is pretty cool actually. +7. More stuff hurts, still just as healthy. +8. Dishwashers aren't really as scary to repair as they seem (but that doesn't mean you won't lose your mind fixing one). +9. The feeling you get as a parent when your kid gets hurt is impossible to describe. +10. Being knocked out from a crazy car accident is also no fun. +11. Carseats are magic. +12. I've accepted that the music I liked in 2010 is going to be the music I'll like forever. +13. Thanks to the internet there is an endless stream of new music that is at home with music from 2010 or even 2000 (Underoath just released a new album for crying out loud). +14. Open source software is incredible. +15. The thrill from in-progress software working for the first time will never get old for me. +16. Feedback loops are important in every area of life not just software. +17. The year of Linux on the desktop is a moving target. +18. RSS will never die. +19. Mechanical keyboards are a refreshing change and I'm not sure why. +20. The Aeropress is still incredible. +21. Computers were a mistake. +22. Computers are a miracle. +23. The Three-Body Problem trilogy continues to knock around in my brain months after finishing it. +24. Watching your child accomplish something for the first time that they've been working on is a feeling unlike any other. +25. I've realized I learn best by doing, I need to get better at accounting for the bumps along the way. +26. I write things down to remember them later not to look them up later which means most note systems are not worth the trouble for me. +27. Life will be shallow if you only hang out with people like you. +28. Anything is possible on an infinite timescale the trick is figuring out what do with finite time. +29. RIP Rdio. +30. Never pass on an opportunity to twirl your kids around when they're small. They get big fast. +31. Hanlon's razor explains most of social media. +32. If you work at a desk all day you owe it to yourself to remove as much Bluetooth from that setup as possible. +33. None of your peers has it all figured out. Ask them "dumb" questions. +34. Properly evaluating risks when your kids are involved is _hard_. +35. Keep a sweatshirt handy by your bed when your kids are young, getting up at 2am in the winter is _cold_. + +❤️ you Christi + +[thirty]: /writing/thirty diff --git a/themes/cycle/exampleSite/content/post/thirty.md b/themes/cycle/exampleSite/content/post/thirty.md new file mode 100644 index 0000000..588c766 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/thirty.md @@ -0,0 +1,42 @@ +--- +title: "Thirty" +date: 2017-03-02T10:32:47-05:00 +lastmod: 2017-03-02T10:32:47-05:00 +slug: thirty +excerpt: "Today I turn 30. So here is a list of 30 things I've learned in the last year (or so)." +--- + +Today I turn 30. For the last couple birthdays I've wanted to do a "X things I've learned" post like the incomparable [Mr. Noah Stokes](http://esbueno.noahstokes.com/post/155722679971/forty) but I kept forgetting. Not this year\! This past year has been exceptionally full. In my mind, turning 30 has always been a milestone. Turns out (*spoilers\!*) the day is just a that, a marker; all the exciting stuff is ahead and behind. I'm so thankful I get to navigate it all with a great partner in crime/life/adventure, my wife Christi 😍. + +Without further ado, I present to you my list of 30 things I've learned in the past year (or so). + +1. You won't have it figured out by the time you turn 30. +2. Buying a house is scary. +3. Buying a house is amazing. +4. Expecting a kid is scary. +5. Expecting a kid is amazing. +6. Problems in software are usually never software problems. +7. When something hurts sometimes your not dying, it just hurts. +8. You can take your dryer apart and put it back together and it will be ok. +9. Vim is better *inside* emacs. +10. Passing out is no fun. +11. JavaScript is everywhere, get used to it. +12. [We all need a team](/writing/we-all-need-a-team) +13. The command line will never die. +14. Drywall molleys are amazing. +15. You can't keep water out, you can only redirect it. +16. Remembering what is Real™ is vital. +17. Relationships are a \#1 priority. I forget this too often. +18. Nothing beats pen and paper. +19. Physical fitness involves way more sleeping and eating well than pumping iron. +20. There is no better coffee maker than the [Aeropress](http://amzn.to/2lx0bBu). +21. Setting aside time for reading and writing is difficult. +22. I need to spend more time reading and writing. +23. Two opposing things can both be True at the same time. Dealing with that is adulthood. +24. I will always enjoy the Fast and the Furious franchise. +25. LeBron is under-rated. +26. Never give up, even when your down 3-1. +27. No one makes it on their own. +28. I need to read more novels. +29. I still miss Rdio. +30. Read a little C.S. Lewis every morning ([start here](http://amzn.to/2m05LhO)). It's good for you. diff --git a/themes/cycle/exampleSite/content/post/three-easy-tuneups-to-fix-video-calls-while-working-from-home.md b/themes/cycle/exampleSite/content/post/three-easy-tuneups-to-fix-video-calls-while-working-from-home.md new file mode 100644 index 0000000..9b02da2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/three-easy-tuneups-to-fix-video-calls-while-working-from-home.md @@ -0,0 +1,48 @@ +--- +title: "Three easy tuneups to fix video calls while working from home" +date: 2020-03-17T16:59:34-04:00 +lastmod: 2020-03-17T16:59:34-04:00 +slug: three-easy-tuneups-to-fix-video-calls-while-working-from-home +excerpt: "In light of COVID-19 and lots of folks working from home, I've written down the three things I try to tune on my home network to deliver the best possible video call experience." +--- + +Thanks to the COVID-19 virus (aka the coronavirus) lots of folks are experiencing the joys and existential terror of working from home. There's many things to tackle when optimizing a work from home setup like: + +- Proper workspace ergonomics +- Proper lighting for video calls +- [Proper audio](/writing/atr2100) for video/audio calls +- Picking up the dirty laundry/toys/pizza boxes that are visible in the background on video calls + +These are all important but pale in comparison to this one: tuning your network for peak performance in video calls and remote screen sharing. + + +## Three problems + +There is usually some combination of the following three problems going on when [Zoom](https://zoom.us/) pops up the dreaded "Your connection is unstable": + +1. Your internet speed is too slow +2. You're Wifi signal is bad +3. Your router/modem from the ISP is suffering from bufferbloat. + + +### Speed + +The first one is *easy* to fix: speed. Zoom lists their [bandwidth requirements](https://support.zoom.us/hc/en-us/articles/201362023-System-Requirements-for-PC-Mac-and-Linux) and the highest requirement is `3.0 Mbps` (up/down) which is for sending 1080p video. For consumer broadband that is nothing, heck for DSL that's nothing. However, it's the first and easiest thing to check: do you have `3.0 Mbps+`? Head over to [fast.com](https://fast.com) and run a speed test. + +### Wifi + +The second one, wifi signal strength, is more difficult to nail down. I check two things: the connection bit rate and the connection frequency. Bit rate will tell you the speed of the connection; it should be above `3 Mbps` (honestly it should be above `100 Mbps` if you have ac wifi). I also *always* choose to connect to the `5Ghz` band if I can. `2.4Ghz` suffers from interference much more so than `5Ghz` and that interference will result in an unstable connection. An easy check to see if your Wifi is causing the problem, connect directly to the router with an Ethernet cord if you have one. If the problems goes away, it's the wifi if not keep reading. To view connection and bitrate on a Mac: Option + click on the WiFi icon and you'll be able to see the bit rate and connection frequency. On Linux `iwconfig` in the terminal will print the relevant info. + +### Bufferbloat + +A *very* long explanation (and solution) of bufferbloat can be found [here](https://apenwarr.ca/log/?m=201808). The gist of it is that most routers/modems are (mis-)configured out of the box to prioritize speed over everything else. The software will stuff as many packets as it can and then once it's full things start getting laggy. To see if you are suffering from bufferbloat head over to [fast.com](https://fast.com) again and click on the "Show more info" button after the test. You want the difference between "loaded" and "unloaded" to be as small as possible. If you see a difference over 100, e.g. 25 unloaded and 150 loaded, you are probably suffering from bufferbloat. + +![](/images/fast-com-latency.png) + +The solution here is to poke around in your modem/router admin interface and look for something like "QoS" or "Codel" settings. QoS stands for Quality of Service and it typically allows you to either setup device prioritization or better yet implement [`fq_codel`](https://www.bufferbloat.net/projects/codel/wiki/). The beauty of `fq_codel` is that it's pretty transparent to everyone on the network. Kiddos can stream Frozen 2 until their eyes bleed and your Zoom will never stutter. Device prioritization QoS works but other devices on the network feel the squeeze. + +If you're modem/router doesn't have QoS settings then it's time to look into buying some new equipment (or yes flash your existing router with [OpenWRT](https://openwrt.org/) but that's outside the scope of this post). If you already have your own router/wifi, *that is separate from your modem*, then I'd recommend picking up a [Ubiquiti EdgeRouter X](https://www.ui.com/edgemax/edgerouter-x/) and placing that between your modem and your existing router/wifi. The EdgeRouter X has built-in support for [`fq_codel`](https://www.bufferbloat.net/projects/codel/wiki/) as a QoS setting. Adding QoS at any point in the chain between your computer and the public internet will fix bufferbloat as the traffic only needs to be shaped once. + +![](/images/bufferbloat.png) + +Addressing the three primary culprits for unstable connections should dramatically improve your conference call experience. Please reach out if you have questions or I was incorrect about anything. I'll try to respond as quickly as I can. diff --git a/themes/cycle/exampleSite/content/post/three-years.md b/themes/cycle/exampleSite/content/post/three-years.md new file mode 100644 index 0000000..35480f5 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/three-years.md @@ -0,0 +1,11 @@ +--- +title: "Three years" +date: 2015-09-04T12:17:30-04:00 +lastmod: 2015-09-04T12:17:30-04:00 +slug: three-years +excerpt: "The adventure is just getting started." +--- + +[Three years](/writing/a-new-adventure). I'll be honest it snuck up on me. + +Working with these [immensely talented people every day](http://www.seesparkbox.com/team) is such a privilege and has made me a better developer. I'm so proud of this team and what we've done together. I'm stoked for the adventures to come. diff --git a/themes/cycle/exampleSite/content/post/tigers-and-social-networks.md b/themes/cycle/exampleSite/content/post/tigers-and-social-networks.md new file mode 100644 index 0000000..f487300 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/tigers-and-social-networks.md @@ -0,0 +1,18 @@ +--- +title: "Tigers and Social Networks" +date: 2012-08-21T03:01:27-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: tigers-and-social-networks +excerpt: "A response to Charlie Pratt's blog post about the problem of social networks and catering to the crowd +" +--- + +Charlie Pratt [published a post](http://charliepratt.com/the-crowd-is-a-hungry-tiger/) today giving his take on current happenings with both Twitter and Facebook. One company that has a history of ignoring any outside feedback, and one that he leaves out of his post, is Apple. While not a social network (R.I.P. Ping), Apple still sells multiple products to a massive, global consumer base. The difference between Apple and Twitbook is that Apple makes money from their consumers, something Twitter and Facebook are currently trying to put together. + +Mr. Pratt goes on to observe: + +> As we watch Facebook and Twitter peak, one can’t help but notice that they suddenly seem incredibly vulnerable to the whim of the crowd. Crowds are finicky\[...\] + +This only happens when you try to turn your consumer base, your crowd, into the product your selling. + +Tigers don't like being sold, feeling captive, or turned into anything other than tigers. diff --git a/themes/cycle/exampleSite/content/post/track-redirects-with-curl.md b/themes/cycle/exampleSite/content/post/track-redirects-with-curl.md new file mode 100644 index 0000000..3a4de84 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/track-redirects-with-curl.md @@ -0,0 +1,51 @@ +--- +title: "Track redirects with curl" +date: 2019-10-22T13:25:50-04:00 +lastmod: 2019-10-22T13:25:50-04:00 +slug: track-redirects-with-curl +excerpt: "I made a bash alias that takes a URL as an arguement and runs it through curl resuting in the Headers from each redirect, the final URL, and the number of redirects printed to the console." +--- + +I was recently debugging some `.htaccess` redirects and wanted to know two things: + +1. How was my URL changing as it went through the redirects? +2. How many redirects occurred? + +I quickly got fed up with testing in the browser because of 301/302 redirect caching issues. With my limited `curl` knowledge I knew I could dump headers and that would show me the redirect code and the URL but figuring out how many hops occurred was frustrating. + +I searched around and found this [*very* helpful post](https://www.chrislatta.org/articles/web/curl/track-redirects-curl-command-line) by Chris Latta. The `curl` command from the post introduced me to the fact that `curl` has basic templating support! I read through `man curl` and noticed there were other built-in variables besides `url_effective`, like `num_redirects`! This was exactly what I wanted. Below is what I eventually ended up with: + +``` +curl -LSs -D - -o /dev/null -w 'Final URL: %{url_effective} \nNumber of Redirects: %{num_redirects} ' +``` + +I added this to my dotfiles as an alias called `redirects`, here is a sample of what the output looks like: + +``` +❯ redirects "http://adamsimpson.net/uses" +HTTP/1.1 301 Moved Permanently +Cache-Control: public, max-age=0, must-revalidate +Content-Length: 44 +Content-Type: text/plain +Date: Tue, 22 Oct 2019 17:39:10 GMT +Location: https://adamsimpson.net/uses +Age: 0 +Connection: keep-alive +Server: Netlify +X-NF-Request-ID: de179b0f-db8b-401a-97ad-7ce523020763-108626 + +HTTP/2 200 +cache-control: public, max-age=0, must-revalidate +content-type: text/html; charset=UTF-8 +date: Tue, 22 Oct 2019 17:39:10 GMT +etag: "3f4bb560fd31e7328aedc7bc08a9c541-ssl" +strict-transport-security: max-age=31536000 +age: 0 +server: Netlify +x-nf-request-id: de179b0f-db8b-401a-97ad-7ce523020763-108794 + +Final URL: https://adamsimpson.net/uses +Number of Redirects: 1 % +``` + +`curl` might be one of the most important tools I have at my disposal for working with HTTP requests and I feel like I've only begun to scratch the surface of what it can do. diff --git a/themes/cycle/exampleSite/content/post/tweet-stash.md b/themes/cycle/exampleSite/content/post/tweet-stash.md new file mode 100644 index 0000000..2db14de --- /dev/null +++ b/themes/cycle/exampleSite/content/post/tweet-stash.md @@ -0,0 +1,20 @@ +--- +title: "Tweet stash" +date: 2019-12-12T21:54:49-05:00 +lastmod: 2019-12-12t21:54:49-05:00 +slug: tweet-stash +excerpt: "Two tweets that I've had stuck in my tabs for _awhile_ and decided to stash them here." +--- + +Two tweets that I've had stuck in my tabs for _awhile_ and decided to stash them here. + +## Dismal laptops +The first one is a tweet from Dave Nanian, [creator of SuperDuper](https://www.shirt-pocket.com/), which paints a good picture of how bad Apple laptops had gotten from 2016-2019. + + + +## Talk show entrances + +This next tweet is hysterical. It's a clip of Nic Cage being _hyped_ in the 90s when he's introduced to on a talk show in England. The thread is worth reading as you'll also see Chris Farley's Letterman entrance which is even more incredible. + + diff --git a/themes/cycle/exampleSite/content/post/using-the-kindle-to-harness-the-web.md b/themes/cycle/exampleSite/content/post/using-the-kindle-to-harness-the-web.md new file mode 100644 index 0000000..c22234d --- /dev/null +++ b/themes/cycle/exampleSite/content/post/using-the-kindle-to-harness-the-web.md @@ -0,0 +1,18 @@ +--- +title: "Using the Kindle to harness the Web" +date: 2012-08-01T03:01:28-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: using-the-kindle-to-harness-the-web +excerpt: "how I use Readability’s Kindle bookmarklet to harness the web. +" +--- + +Currently, I have the cheapest [Kindle](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000750701&tag=googhydr-20&hvadid=19552942650&hvpos=1t1&hvexid=&hvnetw=g&hvrand=488712776137896327&hvpone=&hvptwo=&hvqmt=e&ref=pd_sl_9h7vyrl94n_e) you can buy and I love it. I love it for reasons entirely different from my iPad. I love this Kindle cause it's super cheap and durable, and I never worry about its battery life or wether it's getting smashed in a bag when I travel. + +I also love this Kindle for reading. I set up my [Instapaper](http://www.instapaper.com/) account to send me a digest of my Unread list every weekend, perfect for traveling, the pool, or even the beach – you know, places the iPad shouldn't and can't go. The Kindle feature in Instapaper got me excited about other possibilities for reading web stuffs on my Kindle. + +The first thing I stumbled upon shortly after setting up my Instapaper to Kindle connection was [Readlists](http://readlists.com). Readlists are brought to you by the same folks behind [Readability](http://www.readability.com). Readlists allows you to cobble together a list of articles from all over the web that they then compile into a Kindle digest. Rad\! + +After I discovered Readlists, I started finding [several](http://addyosmani.com/resources/essentialjsdesignpatterns/book/) [fantastic](http://eloquentjavascript.net/contents.html) guides or books on JavaScript and Javascript best practices. Prominent members of the developer community are releasing these materials for free via Github or personal sites. I wanted to convert these excellent resources into documents on my Kindle. It was then that I discovered another fantastic resource from the Readability folks. + +Readability released a [simple bookmarklet](http://www.readability.com/bookmarklets/) that takes whatever page you're viewing in your browser and sends it to your Kindle. Problem solved\! I now have a couple Kindle "books" that are sourced from the web, how awesome is that? Try it out for yourself and start utilizing the incredible resources out there. diff --git a/themes/cycle/exampleSite/content/post/verse-recall.md b/themes/cycle/exampleSite/content/post/verse-recall.md new file mode 100644 index 0000000..5d5dfd0 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/verse-recall.md @@ -0,0 +1,25 @@ +--- +title: "Verse Recall" +date: 2015-12-23T09:31:02-05:00 +lastmod: 2015-12-23T09:31:02-05:00 +slug: verse-recall +excerpt: "Whew, time to share something with the world I haven't really talked about online at all, my first and only (so far) iOS app." +--- + +Whew, time to share something with the world I haven't really talked about online at all, my first and only (so far) iOS app. I did manage to find this tweet celebrating the launch (thanks to Twitter's advanced search): + + + +Verse Recall was a Christmas gift to my Dad in 2013. He got a TestFlight beta, and it actually shipped in March. I'm pretty proud of it. The app was simple. It let you look up a Bible verse, save it locally to the device and schedule a local notification with the text of the verse. The goal was to help memorize verses. + +When I started I didn't know Obj-C (no Swift at the time), had never used Xcode, and had no real clue where to start. Despite all that I shipped it and I'm proud of the 30-odd copies I sold ($0.99 big money\!). I never would have made it without these awesome tools: + + - [FMDB](https://github.com/ccgus/fmdb) + - [AFNetworking](https://github.com/AFNetworking/AFNetworking) + - [Cocoa Pods](https://cocoapods.org) + +A few days ago I let my Apple Developer account "expire" therefore removing Verse Recall from the App Store. I've gone back and forth the last couple months on wether to renew again. There's more I'd like to do with it, bugs I'd like to fix and features I'd like to add (like maybe port it to React Native?\!), but I never spent the time to do those things for whatever reason. It works fine for now and my Dad still uses it so I'm content. If and when it breaks with an iOS update, I'll either update it and side-load the fix onto my Dad's phone or we'll let it die. + +This morning I moved the current state of the project from my private Bitbucket repo to [Github](https://github.com/asimpson/verse-recall). I wanted to share the entire project history because the commits are hilarious to read (they range from rage to despair and back again), but I foolishly committed API keys and the like that were too difficult to clean out of Git's history. I doubt the code will be that useful to anyone at this point, but I like having it out there so I can point to it as a thing I did. + +So ends Verse Recall, I'm proud of it and I learned a ton making it. In my mind it was a raging success. diff --git a/themes/cycle/exampleSite/content/post/vim-ramblings.md b/themes/cycle/exampleSite/content/post/vim-ramblings.md new file mode 100644 index 0000000..74bb84b --- /dev/null +++ b/themes/cycle/exampleSite/content/post/vim-ramblings.md @@ -0,0 +1,30 @@ +--- +title: "Vim Ramblings" +date: 2014-06-27T03:01:29-04:00 +lastmod: 2015-03-21T19:45:36-04:00 +slug: vim-ramblings +excerpt: "So, in the past 6 months I've switched from Sublime Text to Vim. Here are some good articles and tips on Vim. +" +--- + +So, in the past 6 months [I've switched from Sublime Text to Vim](https://github.com/asimpson/dotfiles/blob/master/.vimrc). + +And just like that I've fulfilled [Harry Robert's](http://twitter.com/csswizardry) tweet: + + + +Whelp. Anyway, onwards and upwards I guess. + +Speaking of Harry, if your looking to get started with Vim, checkout [his awesome guide that he wrote to save me the trouble of writing one myself\!](http://csswizardry.com/2014/06/vim-for-people-who-think-things-like-vim-are-weird-and-hard/) + +Earlier tonight I was perusing the interwebs (shocker right?) and wound up on [Wynn Netherland's](http://wynnnetherland.com) [archives](http://wynnnetherland.com/archives), because he's an awesome dude and wicked smart. I came across a few really good Vim posts that I thought I'd highlight here: + + - [A Good Vimrc](http://dougblack.io/words/a-good-vimrc.html) + - [Vim anti-patterns](http://blog.sanctum.geek.nz/vim-anti-patterns/) + - [Relative line numbers in Vim](http://jeffkreeftmeijer.com/2012/relative-line-numbers-in-vim-for-super-fast-movement/) + +I totally agree with the [anti-patterns](http://blog.sanctum.geek.nz/vim-anti-patterns/) and [vimrc](http://dougblack.io/words/a-good-vimrc.html) posts. I also need to try the [relative numbers approach](http://jeffkreeftmeijer.com/2012/relative-line-numbers-in-vim-for-super-fast-movement/). + +To finish up this hode-podge of links and rambling, my buddy [@seanwashington](http://twitter.com/seanwashington) recently [pointed me](https://twitter.com/seanwashington/status/482247769747255297) to [vimawesome](http://vimawesome.com), and holy crap it's awesome, I highly recommend checking out the awesome plugins on that site. + +Anyway, [back to your regularly scheduled internets](http://media.giphy.com/media/NO3XxB6Ny3eZq/giphy.gif). diff --git a/themes/cycle/exampleSite/content/post/we-all-need-a-team.md b/themes/cycle/exampleSite/content/post/we-all-need-a-team.md new file mode 100644 index 0000000..22289f1 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/we-all-need-a-team.md @@ -0,0 +1,15 @@ +--- +title: "We all need a team" +date: 2016-06-28T13:48:07-04:00 +lastmod: 2016-06-28T13:48:38-04:00 +slug: we-all-need-a-team +excerpt: "We all need a team. On the right team we can go higher and be better than we ever thought we could." +--- + +[Bill Simmons'](https://twitter.com/BillSimmons) latest piece [on Pat Riley](https://theringer.com/pat-riley-gets-what-he-wants-undeniables-bill-simmons-4064cf607e42) is full of great Riley stories. One particular moment where Riley talks to Kevin Garnett really resonated with me (italics mine): + +> It happened to everyone. *You won’t truly know how outstanding you are, Riley promised him, until you’re surrounded by elite teammates who make you better.* He told stories about Magic’s Lakers teams, how special they were, how many battles they fought, how those postseasons bonded them for life. There was a higher level of basketball. It was out there. You wouldn’t understand until you’ve experienced it. And until you’ve lost it, too. + +We all need a team. On the *right* team we can go higher and be better than we ever thought we could. + +To put it another way, we can only go so far alone. diff --git a/themes/cycle/exampleSite/content/post/web-performance-and-facebooks-instant-articles.md b/themes/cycle/exampleSite/content/post/web-performance-and-facebooks-instant-articles.md new file mode 100644 index 0000000..47ead81 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/web-performance-and-facebooks-instant-articles.md @@ -0,0 +1,21 @@ +--- +title: "Web performance and Facebook's Instant Articles" +date: 2015-05-13T19:55:02-04:00 +lastmod: 2015-05-14T10:45:57-04:00 +slug: web-performance-and-facebooks-instant-articles +excerpt: "Crafting a high-performing web experience for mobile is not easy, but it's not so impossibly hard that Facebook's Instant Articles is the only solution." +--- + +John Gruber wrote down his [initial thoughts](http://daringfireball.net/2015/05/facebook_instant_articles) on [Facebook's Instant Articles](http://instantarticles.fb.com/). This portion regarding performance stood out: + +> I’m intrigued by the emphasis on speed. Not only is native mobile code winning for app development, but with things like Instant Articles, native is making the browser-based web look like a relic even just for publishing articles. If I’m right about that, it might pose a problem even for my overwhelmingly-text work at Daring Fireball. Daring Fireball pages load fast, but the pages I link to often don’t. I worry that the inherent slowness of the web and ill-considered trend toward over-produced web design is going to start hurting traffic to DF. + +Maybe I can't see past my web developer bias, but I don't believe this is a death knell for the "open web." I think this *is* a wake-up call; there is no reason that Instant Articles should have such a speed advantage over a webpage. + +Crafting a high-performing web experience for mobile is not easy, but it's not so impossibly hard that Instant Articles is the only solution. With Instant Articles, Facebook is saving publishers from themselves - notice the lack of advertising, over-the-top branding, or massive image slideshows. Instant Articles isn't faster because native beats the web. It's faster because disciplined, curated content wins over content shoved between 1MB of advertisements. + +----- + +**Update:** + + diff --git a/themes/cycle/exampleSite/content/post/web-scraper-cookbook.md b/themes/cycle/exampleSite/content/post/web-scraper-cookbook.md new file mode 100644 index 0000000..d6f4bf2 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/web-scraper-cookbook.md @@ -0,0 +1,11 @@ +--- +title: "Web scraper cookbook" +date: 2016-02-20T21:44:55-05:00 +lastmod: 2016-02-20T21:44:55-05:00 +slug: web-scraper-cookbook +excerpt: "I've been on a web scraping tear lately. So, I thought I'd compile what I've learned and put together a repo as a howto/cookbook/guide thing." +--- + +I've been on a [web scraping tear lately](https://github.com/asimpson/espn-scraper-to-rss). So, I thought I'd compile what I've learned and put together a repo as a howto/cookbook/guide thing. So, here it is: introducing [the Node web scraper cookbook](https://github.com/asimpson/nodejs-web-scraper-cookbook). + +I hope it's useful. It's nice to have this stuff written down just for my own sake. If you find it useful, awful, or confusing feel free to create an issue on the repo and I'll try to update things. diff --git a/themes/cycle/exampleSite/content/post/what-happens-when-you-remove-friction.md b/themes/cycle/exampleSite/content/post/what-happens-when-you-remove-friction.md new file mode 100644 index 0000000..731b365 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/what-happens-when-you-remove-friction.md @@ -0,0 +1,13 @@ +--- +title: "What happens when you remove friction" +date: 2017-03-27T13:33:36-04:00 +lastmod: 2017-03-27T13:33:36-04:00 +slug: what-happens-when-you-remove-friction +excerpt: "When you remove friction from a process or task, all the factors change. This seems obvious, but it's fundamental to understanding the world as it currently is." +--- + +When you remove friction from a process or task, all the factors change. This seems obvious, but it's fundamental to understanding the world as it currently is. Polygon has a [post](http://www.polygon.com/2017/2/21/14683942/pewdiepie-controversy-youtube-drama) up about the rash of "Youtuber burnouts" lately. The conclusion of the article stuck out to me (emphasis mine): + +> YouTube has a *speed and quantity problem, and it affects all aspects of the business*. If you are a content creator, take a little time with controversial stuff. It really is fun to make things, but irreverent, boundary-breaking stuff is high-risk/high-reward. Don’t just spit it out: run things by friends and people not in the business. Test the tone before you go live. Sleep on it. + +Youtube is entertainment without traditional support mechanisms (i.e. friction). It's relentless and there are no structures in place to push back at all. I think this lack of friction is at the root of the majority of problems in tech. Things move quickly and because of that speed safeguards and checks haven't been instantiated yet. Not everything that pushes back is bad, that push-back can be life-saving. diff --git a/themes/cycle/exampleSite/content/post/what-is-medium.md b/themes/cycle/exampleSite/content/post/what-is-medium.md new file mode 100644 index 0000000..797bacf --- /dev/null +++ b/themes/cycle/exampleSite/content/post/what-is-medium.md @@ -0,0 +1,17 @@ +--- +title: "What is Medium?" +date: 2015-08-27T12:56:54-04:00 +lastmod: 2015-08-27T14:37:02-04:00 +slug: what-is-medium +excerpt: "I'm curious to see how Medium continues to evolve." +--- + +Manton Reece [in a post about Medium](http://www.manton.org/2015/08/startup-life-and-medium.html) wondered: + +> Is it a blogging tool? Sort of. Is it a social network? Not exactly. + +I've found Medium incredibly useful for browsing a community's current thoughts and ideas. For instance, I love browsing the [React tag](http://medium.com/tag/react) on Medium. It's filled with various posts about build tools, upcoming libraries, and thought pieces that I would never have found via RSS or Twitter. + + + +Regardless of what Medium intends to be, they at least seem to have stumbled upon something interesting with tags (from my perspective). I'm curious to see how Medium continues to evolve. diff --git a/themes/cycle/exampleSite/content/post/what-its-all-about.md b/themes/cycle/exampleSite/content/post/what-its-all-about.md new file mode 100644 index 0000000..494bb97 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/what-its-all-about.md @@ -0,0 +1,16 @@ +--- +title: "What it's all about" +date: 2012-07-23T03:01:30-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: what-its-all-about +excerpt: "Jonathan Christopher hits the nail on the head +" +--- + +Wordpress Pro, and all around Nice Guy, Jonathan Christopher [posted one of his many asides](http://mondaybynoon.com/20120724/write-less-code/). This little snippet stuck out to me so much, I decided to post what is essentially an aside about an aside. Blogging has no rules right? Cool. + +Jonathan wrote this about writing code, + +> The real joy comes from struggling to figure something out for way longer than you thought it would take and then actually seeing it work. That’s what it’s all about\! + +Spot on. diff --git a/themes/cycle/exampleSite/content/post/what-matters.md b/themes/cycle/exampleSite/content/post/what-matters.md new file mode 100644 index 0000000..b47581e --- /dev/null +++ b/themes/cycle/exampleSite/content/post/what-matters.md @@ -0,0 +1,14 @@ +--- +title: "What Matters" +date: 2013-01-10T03:01:30-05:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: what-matters +excerpt: "A great quote from a post over at 37 signals. +" +--- + +A [post](http://37signals.com/svn/posts/3389-your-lifes-work) from [David Heinemeier Hansson](http://david.heinemeierhansson.com/) over at [37 Signals](http://37signals.com/svn/posts/3389-your-lifes-work) on settling into your work for the long term. This is something I've been thinking about lately, largely because I've found a place at [Sparkbox](http://seesparkbox.com/) that is such a fantastic place to work. + +David provides two solid reasons for why it's worth it to stay put at an organization for both the employee and the employeer. This one stuck out to me the most. + +> \[Focus\] on the residue of knowledge and practices carried over from game to game is far more important than worrying about the output of any one game. diff --git a/themes/cycle/exampleSite/content/post/what-time-is-it-in-london.md b/themes/cycle/exampleSite/content/post/what-time-is-it-in-london.md new file mode 100644 index 0000000..9522665 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/what-time-is-it-in-london.md @@ -0,0 +1,10 @@ +--- +title: "What Time Is It in London?" +date: 2020-05-22T10:44:04-04:00 +lastmod: 2020-05-22T10:44:04-04:00 +slug: what-time-is-it-in-london +excerpt: "" +link: "https://daringfireball.net/linked/2020/05/22/what-time-is-it-in-london" +--- + +> Nilay Patel asked this of Siri on his Apple Watch. After too long of a wait, he got the correct answer — for London Canada. I tried on my iPhone and got the same result. Stupid _and_ slow is heck of a combination. diff --git a/themes/cycle/exampleSite/content/post/whats-best-for-the-readers.md b/themes/cycle/exampleSite/content/post/whats-best-for-the-readers.md new file mode 100644 index 0000000..89b0c1b --- /dev/null +++ b/themes/cycle/exampleSite/content/post/whats-best-for-the-readers.md @@ -0,0 +1,16 @@ +--- +title: "What's best for the readers" +date: 2012-07-24T03:01:31-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: whats-best-for-the-readers +excerpt: "Jonah Peretti's letter to employees and investors of Buzzfeed. +" +--- + +So good, it doesn't need an intro. + +> For the same reason, we don’t show crappy display ads and we make all our revenue from social advertising that users love and share. We never launched one of those “frictionless sharing” apps on Facebook that automatically shares the stories you click because those apps are super annoying. We don’t post deceptive, manipulative headlines that trick people into reading a story. We don’t focus on SEO or gaming search engines or filling our pages with millions of keywords and tags that only a robot will read. We avoid anything that is bad for our readers and can only be justified by short term business interests. Instead, we focus on publishing content our readers love so much they think it is worth sharing. It sounds simple but it’s hard to do and it is the metric that aligns our company with our readers. In the long term is good for readers and good for business. + +This excerpt is from [Chris Dixon's post](http://cdixon.org/2012/07/24/buzzfeeds-strategy/) where he published Jonah Peretti's letter to employees and investors of Buzzfeed. + +You should read all of it. diff --git a/themes/cycle/exampleSite/content/post/when-the-music-stops.md b/themes/cycle/exampleSite/content/post/when-the-music-stops.md new file mode 100644 index 0000000..11492b8 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/when-the-music-stops.md @@ -0,0 +1,14 @@ +--- +title: "When the Music Stops" +date: 2012-08-23T03:01:32-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: when-the-music-stops +excerpt: "Dave Winer has a great post on what happens when a service disappears. +" +--- + +Dave Winer [wrote a great post](http://scripting.com/stories/2012/08/16/privatizingAndSocializing.html) last week; he describes what happens when a piece of web software (i.e. Tumblr, Wordpress, etc) disappears. I decided to link to his post because I think it relates to my own [Plaintext](http://adamsimpson.net/plaintext-and-markdown-a-primer) and [Blogs, Data, and Social Networks](http://adamsimpson.net/blogs-data-and-social-networks) posts. Ultimately we are each responsible for our own data, or as Winer writes: + +> I'm writing this \[…\] to the users to wise up and also to stop being such children. If you feel there's value in your writing, then treat it like it has value. If you depend on strangers to pay your rent, you have to know that isn't going to work, long-term. + +Start owning. diff --git a/themes/cycle/exampleSite/content/post/windows-11-as-kvm-guest.md b/themes/cycle/exampleSite/content/post/windows-11-as-kvm-guest.md new file mode 100644 index 0000000..f6b6414 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/windows-11-as-kvm-guest.md @@ -0,0 +1,60 @@ +--- +title: "Windows 11 as KVM guest" +date: 2022-02-28T13:39:37-0500 +lastmod: 2022-02-28T13:39:37-0500 +slug: windows-11-as-kvm-guest +excerpt: "How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager." +--- + +Windows 11 famously has new, stricter [requirements for installation](https://www.microsoft.com/en-us/windows/windows-11-specifications); a TPM device and Secure Boot. Here's how I satisfied those requirements with Windows 11 as a KVM guest with NixOS as the host. The following is pulled from my [NixOS `configuration.nix`](https://github.com/asimpson/dotfiles/commit/ab08fd88a5617d9199f78726c1f22f32b8fc85d0): + +```nix +libvirtd.qemu = { + package = pkgs.qemu_kvm; + runAsRoot = true; + swtpm.enable = true; + ovmf = { + enable = true; + package = (pkgs.OVMFFull.override { + secureBoot = true; + tpmSupport = true; + }); + }; +}; +``` + +The most important bit is the `pkgs.OVMFFull.override` section where you must specify `tpmSupport` and `secureBoot` as `true`. + +In [virt-manager](https://virt-manager.org/) you'll need to add "new hardware" and select TPM v2.0. Here's the relevant XML from my config: + +```xml + + + +``` + +With the above settings you should be able to go through the Windows 11 installer and get the machine up and running as a KVM guest. + +## Stretch goal: nested virtualization +If you want to use Docker or WSL 2 inside KVM you'll need to enable "nested virtualization" in virt-manager. I couldn't figure this out until I found [this great answer on superuser](https://superuser.com/a/1589286). + +My original CPU config XML looked like this: + +```xml + + + +``` + +The new XML looks like this: + +```xml + + Skylake-Client-noTSX-IBRS + + + + +``` + +With this applied I could install WSL2 _and_ get Docker Desktop for Windows installed and running. diff --git a/themes/cycle/exampleSite/content/post/working-with-wordpress-offset-and-pagination.md b/themes/cycle/exampleSite/content/post/working-with-wordpress-offset-and-pagination.md new file mode 100644 index 0000000..fab02fe --- /dev/null +++ b/themes/cycle/exampleSite/content/post/working-with-wordpress-offset-and-pagination.md @@ -0,0 +1,37 @@ +--- +title: "Working with Wordpress, offset and pagination" +date: 2012-08-10T03:01:32-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: working-with-wordpress-offset-and-pagination +excerpt: "A code snippet to have posts offset and have pagination work. +" +--- + +Yesterday I was working on a project (that will hopefully be released soon) that displays the most recent post differently than the rest of the posts on the page. This project also calls for pagination-like behavior on the second set of posts, while the feature post (most recent post) should be static and have no pagination. + +I initially tried to use the [offset parameter](http://codex.wordpress.org/Class_Reference/WP_Query#Offset_Parameter) for the second post query to remove the most recent post from that loop. This however didn't seem to work with the pagination. + +Turns out Wordpress' offset and pagination features collide, as the [note says](http://codex.wordpress.org/Class_Reference/WP_Query#Offset_Parameter) (always read those little notes\!), + +> **Note:** Setting offset parameter will ignore the paged parameter. + +I think the pagination feature uses offset internally which is why an explicit offset breaks the pagination. + +Anyway, after hunting around a bit to see if anyone had a quick fix for this, I stumbled upon [a post](http://wordpress.org/support/topic/query_posts-offset-and-pagination#post-1245582) which had a quite complex question and an equally complex answer. Yet, it confirmed what I thought I'd have to do. + +I simplified the solution quite a bit for my particular scenario, here is my code (note I am using verbose variable names here to help clarify): + + $number_of_feature_posts = 1; + $number_of_secondary_posts = 3; + $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; + $how_many_secondary_posts_past = ($number_of_secondary_posts * ($paged - 1)); + $off = $number_of_feature_posts + (($paged > 1) ? $how_many_secondary_posts_past : 0); + +I then used a simple *`WP_Query` loop for the first loop, the featured (most recent) post, and then just used the normal `query_posts`* with the additional arguments from the above snippet, for the second loop + +``` + +query_posts( "posts_per_page=$number_of_secondary_posts&offset=$off&showposts=$number_of_secondary_posts" ); +``` + +This basically keeps the offset *dynamic* and *relative* to the page we are on. Hope you find it useful. diff --git a/themes/cycle/exampleSite/content/post/youtube-subscriptions.md b/themes/cycle/exampleSite/content/post/youtube-subscriptions.md new file mode 100644 index 0000000..f93d2c9 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/youtube-subscriptions.md @@ -0,0 +1,14 @@ +--- +title: "youtube-subscriptions" +date: 2020-05-08T11:36:23-04:00 +lastmod: 2020-05-08T11:36:23-04:00 +slug: youtube-subscriptions +excerpt: "a terminal client to browse youtube subscriptions" +link: "https://github.com/yazgoo/youtube-subscriptions" +--- + +I've been using `youtube-subscriptions` for a few months now and I really enjoy it. It's described as a: + +> terminal client to browse youtube subscriptions + +It's great to quickly see any new videos right in the terminal and videos play via [`mpv`](https://mpv.io/) or [`vlc`](https://www.videolan.org/index.html)! diff --git a/themes/cycle/exampleSite/content/post/zach-beane.md b/themes/cycle/exampleSite/content/post/zach-beane.md new file mode 100644 index 0000000..9b0bd69 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/zach-beane.md @@ -0,0 +1,13 @@ +--- +title: "Uses This / Zach Beane" +date: 2020-09-01T16:34:26-04:00 +lastmod: 2020-09-01T16:34:26-04:00 +slug: zach-beane +excerpt: "" +link: "https://usesthis.com/interviews/zach.beane/" +--- + +A great interview with the creator of [Quicklisp](https://www.quicklisp.org/), Zach Beane. I enjoy two things about this interview: + +1. The inclusion of outdoor/farming tools in the list of tools. +2. Zach's conservative approach to languages and software tools. diff --git a/themes/cycle/exampleSite/content/post/zen-garden-part-2.md b/themes/cycle/exampleSite/content/post/zen-garden-part-2.md new file mode 100644 index 0000000..5a25ef7 --- /dev/null +++ b/themes/cycle/exampleSite/content/post/zen-garden-part-2.md @@ -0,0 +1,28 @@ +--- +title: "Zen Garden Part 2?" +date: 2012-07-18T03:01:33-04:00 +lastmod: 2015-03-21T19:45:37-04:00 +slug: zen-garden-part-2 +excerpt: "Is it time for a Return to the CSS Zen Garden? Rick Monro thinks Responsive Web Design needs it. +" +--- + +Remember the glorious days of the [CSS Zen Garden](http://www.csszengarden.com/) before all of this CSS3 @font-face crazyness and @media resizing insanity? + +I do, and probably most web designers and developers do to. [Rick Monro](http://blog.rickmonro.com/community/return-to-the-garden/) definitely does, and he [wrote yesterday](http://blog.rickmonro.com/community/return-to-the-garden/) that we need to create another CSS Garden, this time for Responsive Web Design (RWD). + +Now, I think that's a great idea, the more RWD resources, the better in my opinion. Of course we already have the [RWD Book](http://www.abookapart.com/products/responsive-web-design/), which is a must read for any web designer or developer. And [Trent Walton](http://trentwalton.com/), [Brad Frost](http://bradfrostweb.com/blog/), [Mark Boulton](http://www.markboulton.co.uk/), and [Jordan Moore](http://www.jordanm.co.uk/) are all chronicling their experiences and solutions with Responsive Web Design as they use it in the real world. Hell, [Brad Frost](http://bradfrostweb.com/responsive-web-design-newsletter/) even has an e-mail newsletter dedicated entirely to RWD, so it's not like resources on RWD don't exist. I think Mr. Monro knows this, but he's seeking a resource that mimics the Zen Garden and goes beyond the [Mediaqueri.es](http://mediaqueri.es/) gallery approach. Again, I think this is a great idea. + +Yet, I take issue with how he frames the need for a RWD Garden. His claims make it sound like a "RWD Garden" is needed to finish the argument that RWD is the next advancement in our practice. In my opinion and the opinion of many in our industry, Responsive Web Design is the future, period. We're past the convincing point with RWD, the web is changing. + +I want to note that Responsive Web Design is not only concerned with fluid-width design. RWD incorporates other principles for developing sites, such as sites that are responsive to: mobile-sized screens, low bandwidth situations, and [HD / Retina](http://www.jordanm.co.uk/post/21074721287/web-hd) graphics. The entire package, this package called Responsive Web Design, is what is pushing the web forward. If all we are concerned with is narrow and wide views then Mr. Monro is quite right when he says: + +> Designers and developers are the only people I know who sit and accordion their browser window to see how a site will respond. We’re too in love with technique because we know that somewhere, another designer or developer is going to think it’s cool. And folks, when it gets to the point when we are designing for other designers, that should ring some pretty loud alarm bells + +I think as a community we are still figuring out what this Responsive Web Design thing is, what it looks like, how we design for it, where Photoshop fits (does it?\!), etc. We've had years to figure out how to design with and for CSS, we're only just getting started with RWD. It's an exciting time to be working on the web, yet Mr. Monro thinks there is too much "pressure" to use RWD: + +> The overwhelmingly positive spin accompanying a responsive site launch creates a subtle (but tangible) pressure on conscientious designers to ‘step up’ and deliver RWD on their own projects. Which would be fine, but the inference that RWD is desirable at any cost. + +Of course, I'm not advocating an eyes-closed acceptance of Responsive Web Design for every client project. Tables are still used on the web, mostly in emails now, but there not gone; the same holds true for a site designed without applying RWD. However, "Positive spin" implies that we're all trying to cover up something bad, which isn't true. Any "spin" or "pressure" is simply the same encouragement as when moving from tables to CSS, that this is the right way to go. That "pressure" is what makes this industry so incredible. The web thrives on action, learning, pushing, and experimenting. + +We shouldn't slow down because the web is changing and things are all new and scary again. New and scary does not mean we're going in the wrong direction. We are headed in the right direction, and that is why I fully support the creation of as many additional resources as possible to educate each other, as well as push RWD further. diff --git a/themes/cycle/exampleSite/hugo.toml b/themes/cycle/exampleSite/hugo.toml new file mode 100644 index 0000000..4e17cc4 --- /dev/null +++ b/themes/cycle/exampleSite/hugo.toml @@ -0,0 +1,21 @@ +baseURL = "https://adamsimpson.net/" +languageCode = "en-us" +title = "adamsimpson.net" +theme = "cycle" + +[params] + description = "The design and development log of Adam Simpson." + +[permalinks] + post = "/writing/:slug/" + +[outputs] + home = ["HTML", "RSS"] + section = ["HTML", "RSS"] + +[outputFormats.RSS] + mediatype = "application/rss+xml" + baseName = "rss" + +[services.rss] + limit = 20 diff --git a/themes/cycle/exampleSite/public/archive/index.html b/themes/cycle/exampleSite/public/archive/index.html new file mode 100644 index 0000000..3867421 --- /dev/null +++ b/themes/cycle/exampleSite/public/archive/index.html @@ -0,0 +1,2454 @@ + + + + + + Archive + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
    + +
  • + + nixpkgs is a treasure + +
    May 10, 2024
    +
    + + Nix and NixOS continue to be the best way to manage and build software that I've found. + +
    +
  • + +
  • + + Lessons learned from integrating OpenAI into a Grafana data source + +
    July 25, 2023
    +
    + + I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! + +
    +
  • + +
  • + + Better scripting with gh + +
    July 22, 2023
    +
    + + I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. + +
    +
  • + +
  • + + End of an era + +
    June 15, 2023
    +
    + + Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. + +
    +
  • + +
  • + + Hacking on Grafana with Web Assembly + +
    August 19, 2022
    +
    + + Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. + +
    +
  • + +
  • + + New workstation + +
    May 2, 2022
    +
    + + I detail my new workstation build featuring the Intel i5-12600k. + +
    +
  • + +
  • + + 👋 Sparkbox + +
    April 1, 2022
    +
    + + I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. + +
    +
  • + +
  • + + Thirty five + +
    March 3, 2022
    +
    + + It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. + +
    +
  • + +
  • + + Windows 11 as KVM guest + +
    February 28, 2022
    +
    + + How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. + +
    +
  • + +
  • + + A few POSIX shell tips + +
    July 19, 2021
    +
    + + I wrote down a few of my most used POSIX shell commands and features. + +
    +
  • + +
  • + + Recently + +
    April 23, 2021
    +
    + + A random assortment of links and miscellaneous updates on things. + +
    +
  • + +
  • + + A firewall in 8 lines + +
    March 31, 2021
    +
    + + You only need about 8 lines in iptables to have a great home firewall. + +
    +
  • + +
  • + + How to use Siji font on polybar + +
    November 6, 2020
    +
    + +

    Nice guide on Reddit about how to use the Siji font with polybar.

    +
    +

    [..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

    +
    +

    Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

    + + 🔗 Permalink + +
    +
  • + +
  • + + On Polybar bitmap fonts and Ubuntu + +
    November 6, 2020
    +
    + + Enable bitmap fonts on Ubuntu for an optimal polybar experience. + +
    +
  • + +
  • + + Recently + +
    October 27, 2020
    +
    + + I've written a few small tools over the last couple months and I figured it's time I post about them. + +
    +
  • + +
  • + + Four ways to approach Hacktoberfest 2020 + +
    October 1, 2020
    +
    + + I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. + +
    +
  • + +
  • + + Small tech + +
    September 25, 2020
    +
    + +

    Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

    +
      +
    • +

      curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

      +
    • +
    • +

      git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

      +
    • +
    • +

      Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

      +
    • +
    • +

      sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

      +
    • +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Indexing My Blog’s Links + +
    September 25, 2020
    +
    + +

    Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Compose key and i3 + +
    September 18, 2020
    +
    + + Here's how to bind the compose key to caps lock in i3wm. + +
    +
  • + +
  • + + cycle v0.3.0 released + +
    September 11, 2020
    +
    + + Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. + +
    +
  • + +
  • + + Setting a default browser in i3 + +
    September 11, 2020
    +
    + + Using a desktop manager like GNOME makes setting default applications easy. However when using a tiling window manager like i3 setting a default application is opaque to the newbie such as myself. + +
    +
  • + +
  • + + Eight years + +
    September 4, 2020
    +
    + + Eight years ago I started working at Sparkbox. Thank you Sparkbox team for giving me an opportunity to work with ya'll and for making me a better developer and person. + +
    +
  • + +
  • + + Uses This / Zach Beane + +
    September 1, 2020
    +
    + +

    A great interview with the creator of Quicklisp, Zach Beane. I enjoy two things about this interview:

    +
      +
    1. The inclusion of outdoor/farming tools in the list of tools.
    2. +
    3. Zach’s conservative approach to languages and software tools.
    4. +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Openring + +
    August 21, 2020
    +
    + + I've added Drew DeVault's openring project to the blog. + +
    +
  • + +
  • + + A public inbox + +
    August 17, 2020
    +
    + + I'm going to give the idea of a public inbox as a place to have discussions about things on this website and elsewhere a shot. + +
    +
  • + +
  • + + Clear explanation of Rust’s module system + +
    July 19, 2020
    +
    + +

    This is a great explanation of Rust’s module system. I wish I had this clear of a picture when I was using modules for the first time in creating oscar.

    +

    The big takeaway and deviation from npm is this:

    +
    +

    We need to explicitly build the module tree in Rust, there’s no implicit mapping to file system.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Nothing speaks like a demo + +
    July 19, 2020
    +
    + +

    Great post from my friend and co-worker Bryan Braun on the value of demoing.

    +
    +

    It didn’t matter that his demos weren’t fully built, or available for anyone to use. We simply needed to see it, in order to understand.

    +
    +

    I find this is true for any kind of project: hobby or professional. Feedback — that elusive crucial ingredient to a good product — tends to arrive when someone else can see/hear/touch/examine what you’re working on.

    + + 🔗 Permalink + +
    +
  • + +
  • + + A new website for 2020 + +
    July 16, 2020
    +
    + +
    +

    According to my Cargo.lock file, my website currently depends on 364 crates. So it’s really about standing on the shoulder of a carefully-curated set of giants.

    +
    +
    +

    364 may seem like a lot (and in a way, it is), but please reserve your judgement until after you’ve heard about everything it does.

    +
    +

    I /love/ posts like this. Amos goes in deep on the decisions he made while re-writing his website from scratch. It’s a truly awesome post.

    +

    I’m seriously tempted to copy his SQLite full-text search implementation for this blog, but that’s a decision for another time.

    + + 🔗 Permalink + +
    +
  • + +
  • + + A Moment of Clarity Regarding the Raison d’Etre for the App Store + +
    July 13, 2020
    +
    + +
    +

    I’d like to see all the vim, vigor, and vigilance Apple applies to making sure no app on the App Store is making a dime without Apple getting three cents applied instead to making sure there aren’t any scams or ripoffs, and that popular apps support good-citizen-of-the-platform features within a reasonable amount of time after those features are introduced in the OS. I don’t know exactly how long “reasonable” is, but five fucking years for split-screen support ain’t it.

    +
    +

    I’ve been thinking the same thing ever since the Hey app rejection right before WWDC. The App Store is supposed to be a place to get software that has been vetted by Apple but there seems to be a growing disconnect between what users imagine that vetting is and what Apple is doing.

    +

    I want to believe this tweet by Ben Evans is the goal of the App Store:

    + +

    If we can trust the apps that come out of the App Store:

    +
      +
    • why is the US considering banning TikTok because of its rampant data collection?
    • +
    • why do we need a new notification in iOS 14 when apps query the clipboard?
    • +
    • why do we need a microphone/camera indicator at the system level?
    • +
    +

    Maybe I was naive and alone in my assumption that Apple would root this stuff out during the review process. If they’re not rooting this out then what is the point of the review process at all?

    + + 🔗 Permalink + +
    +
  • + +
  • + + GoatCounter web analytics + +
    July 1, 2020
    +
    + +
    +

    What seems to be lacking is a “middle ground” that offers useful statistics to answer business questions, without becoming a specialized marketing tool requiring in-depth training to use effectively. Furthermore, some tools have privacy issues (especially Google Analytics). I saw there was space for a new service and ended up putting my original idea in the freezer and writing GoatCounter.

    +
    +

    I agree 100% with this assessment and I’m excited about Goatcounter. I setup a free instance of Goatcounter for this site as a way to kick the tires on it. So far, I’m enjoying that it’s privacy respecting and doesn’t drag down page performance.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Is WebP really better than JPEG? + +
    June 30, 2020
    +
    + +
    +

    If you have used tools like Google’s PageSpeed Insights, you probably have run into a suggestion to use “next-gen image formats”, namely Google’s WebP image format. Google claims that their WebP format is 25 – 34% smaller than JPEG at equivalent quality.

    +
    +
    +

    In any case, when converting images to WebP, check that they are actually smaller than the JPEG equivalent. There’s no need to serve larger images to your users than needed.

    +
    +

    Great analysis of the WebP image format and a good reminder to not blindly follow what various auditing tools are reporting. Test and verify in addition to implementing the various suggested improvements.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Britain goes coal free as renewables edge out fossil fuels + +
    June 30, 2020
    +
    + +
    +

    Britain is about to pass a significant landmark - at midnight on Wednesday it will have gone two full months without burning coal to generate power.

    +
    +
    +

    A decade ago about 40% of the country’s electricity came from coal; coronavirus is part of the story, but far from all.

    +
    +

    This is fascinating. The UK has been aggressively investing in renewable energy sources for years and it appears all that investment is starting to catch up with demand.

    + + 🔗 Permalink + +
    +
  • + +
  • + + On George Floyd + +
    June 30, 2020
    +
    + + I haven't written anything here about George Floyd's murder. I still don't have a cogent response but here's what I've been mulling over. + +
    +
  • + +
  • + + flatkill + +
    June 15, 2020
    +
    + +
    +

    And it’s not only about these security problems. Running KDE apps in fakepak? Forget about desktop integration (not even font size). Need to input Chinese/Japanese/Korean characters? Forget about that too - fcitx has been broken since flatpak 1.0, never fixed since.

    +
    +
    +

    The way we package and distribute desktop applications on Linux surely needs to be rethinked, sadly flatpak is introducing more problems than it is solving.

    +
    +

    Flatpak is an emerging alternative way to install applications on Linux that is apparently rife with security and usability issues. This is a bummer because there’s lots of room in this space for improvement. The lack of multi-lingual input is especially egregious.

    + + 🔗 Permalink + +
    +
  • + +
  • + + FFMPEG: Convert multiple files using xargs + +
    June 4, 2020
    +
    + +

    I stumbled upon this post (Google cache link) when I was trying to process multiple files via xargs.

    +
    +

    ls *.webm | xargs -I % ffmpeg -i % %.m4a

    +
    +
    +

    The key part of this one-liner is xargs -i %. This means that each line of STDIN passed to xargs is put into a variable and can be referenced as %. Hence, the following text which specifies ffmpeg -i x.webm x.m4a to make it convert.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Using SQL to Look Through All of Your iMessage Text Messages + +
    May 28, 2020
    +
    + +
    +

    If you use iMessage on your Mac, you can access the SQLite database where all of your messages are stored. With a little setup, you can use SQL’s raw power to look through your old messages.

    +
    +

    via Simon Willison

    +

    In this post Dan Kelch walks through how to access the SQLite database that backs iMessage on a Mac. He also shares a few helpful SQL snippets to demonstrate how powerful using SQL on your text messages can be.

    + + 🔗 Permalink + +
    +
  • + +
  • + + macOS 10.15: Slow by Design + +
    May 28, 2020
    +
    + +

    A few days ago Allan Odgaard wrote up the reasons for the frequent slowdowns he’s experiencing in macOS Catalina and it’s shocking:

    +
    +

    Apple has introduced notarization, setting aside the inconvenience this brings to us developers, it also results in a degraded user experience, as the first time a user runs a new executable, Apple delays execution while waiting for a reply from their server. This check for me takes close to a second.

    +
    +
    +

    This is not just for files downloaded from the internet, nor is it only when you launch them via Finder, this is everything. So even if you write a one line shell script and run it in a terminal, you will get a delay!

    +
    +
    +

    I am writing this post to call attention to what I consider a serious design problem with Apple’s most recent OS where it appears that low-level system API such as exec and getxattr now do synchronous network activity before returning to the caller.

    +
    +

    Marco Arment hit the nail on the head with his tweet summary of the post:

    +
    +

    The macOS security team needs to ask themselves hard questions about their implementation choices when very smart people are disabling huge parts of their OS security layer just to get reasonable performance from common tasks.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Getting started with Rofi + +
    May 28, 2020
    +
    + + I've been using Rofi for about a year but didn't really understand how to write my own scripts for it until recently. In this post I explain what dmenu is and Rofi's implementation of it and also show how to change audio inputs on Linux via pactl. + +
    +
  • + +
  • + + What Time Is It in London? + +
    May 22, 2020
    +
    + +
    +

    Nilay Patel asked this of Siri on his Apple Watch. After too long of a wait, he got the correct answer — for London Canada. I tried on my iPhone and got the same result. Stupid and slow is heck of a combination.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Psychic Paper + +
    May 18, 2020
    +
    + +
    +

    RIP my very first 0day and absolute best sandbox escape ever:

    +
    +
    <key>application-identifier</key>
    +<string>...</string>
    +<!---><!-->
    +<key>platform-application</key>
    +<true/>
    +<key>com .apple.private.security.no-container</key>
    +<true/>
    +<key>task_for_pid-allow</key>
    +<true/>
    +<!-- -->
    +

    Tweet that demonstrates a recent zero-day (now patched) in iOS. This serves as your annual reminder that parsing xml-like things is a fraught activity.

    + + 🔗 Permalink + +
    +
  • + +
  • + + The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet + +
    May 18, 2020
    +
    + +
    +

    Janet Hutchins had the day off from her job as a nurse at a local hospital. She had been in town catching up with friends and had just gotten home and started making dinner. So she had only the slightest sense of the crisis that her colleagues had been dealing with across the NHS. That’s when her son came upstairs and told her, a little uncertainly, that he seemed to have stopped the worst malware attack the world had ever seen.

    +
    +
    +

    “Well done, sweetheart,” Janet Hutchins said. Then she went back to chopping onions.

    +
    +

    It’s hard to pick my favorite section from this article about Marcus Hutchins — the hacker who stopped the WannaCry malware attack.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Second-guessing the modern web + +
    May 13, 2020
    +
    + +
    +

    The low performance parts don’t need to be React. Listing pages, static pages, blogs - these things are increasingly built in React, but the benefits they accrue are extremely narrow. A lot of the optimizations that are cropping up in these corners, things like bundle splitting, server-side rendering, and prerendering, are triangulating, essentially, what we had before the rise of React.

    +
    +

    This isn’t really about React but more about the over-engineering of large swaths of page-types and sites that used to “just work”. I love React and it’s been a giant leap forward for creating complex UIs on the web, that doesn’t mean it’s right for every situation.

    + + 🔗 Permalink + +
    +
  • + +
  • + + youtube-subscriptions + +
    May 8, 2020
    +
    + +

    I’ve been using youtube-subscriptions for a few months now and I really enjoy it. It’s described as a:

    +
    +

    terminal client to browse youtube subscriptions

    +
    +

    It’s great to quickly see any new videos right in the terminal and videos play via mpv or vlc!

    + + 🔗 Permalink + +
    +
  • + +
  • + + Hiking the Pacific Crest Trail in Three Minutes + +
    May 7, 2020
    +
    + +
    +

    The Pacific Crest Trail runs 2650 miles from the border of Mexico to the border of Canada through California, Oregon, and Washington. Hiking the whole thing usually takes months, but this video by Mac of Halfway Anywhere compresses the entire experience down to just three minutes presented in 1-second snippets.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Introducing oscar + +
    April 29, 2020
    +
    + + I've been working on oscar which is a small command-line utility written in Rust that polls the pbskids.org API for new episodes of any PBS show. + +
    +
  • + +
  • + + Seamless branch deploys with Kubernetes + +
    April 27, 2020
    +
    + +

    A trait of good software is the ability to quickly see and verify changes:

    +
    +

    The result is what’s in-use today for HEY: a system that (almost) immediately deploys any branch to a branch-specific endpoint that you can access right away to test your changes without having to use the claims system or talk to anyone else (along with an independent job processing fleet and Redis instance to support the environment).

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Three easy tuneups to fix video calls while working from home + +
    March 17, 2020
    +
    + + In light of COVID-19 and lots of folks working from home, I've written down the three things I try to tune on my home network to deliver the best possible video call experience. + +
    +
  • + +
  • + + ATR2100 + +
    January 29, 2020
    +
    + + I recently purchased the ATR2100 microphone and absolutely love it. + +
    +
  • + +
  • + + Understanding Rust Strings and str inside structs. + +
    January 8, 2020
    +
    + + Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here's a short breakdown of a compiler error message around Strings and ownership that stumped me for a bit. + +
    +
  • + +
  • + + Tweet stash + +
    December 12, 2019
    +
    + + Two tweets that I've had stuck in my tabs for _awhile_ and decided to stash them here. + +
    +
  • + +
  • + + Track redirects with curl + +
    October 22, 2019
    +
    + + I made a bash alias that takes a URL as an arguement and runs it through curl resuting in the Headers from each redirect, the final URL, and the number of redirects printed to the console. + +
    +
  • + +
  • + + The thing about computers + +
    September 21, 2019
    +
    + + Brent Simmons talks about what made computing so compelling and what we might be losing. + +
    +
  • + +
  • + + Dead Cells might be a perfect game + +
    September 20, 2019
    +
    + + Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it). + +
    +
  • + +
  • + + 0.14 + +
    July 30, 2019
    +
    + + I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn't worth it. + +
    +
  • + +
  • + + Solving busybox crond hanging on Alpine Linux boot + +
    May 5, 2019
    +
    + + How busybox crond hanging at startup sent me down a rabbit hole where I learned about entropy and Linux. + +
    +
  • + +
  • + + Introducing Cycle + +
    April 5, 2019
    +
    + + Cycle is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today. + +
    +
  • + +
  • + + Ajax and Rails + +
    January 28, 2019
    +
    + + This is just a short post to save a few links and document that "Server Javascript Responses" in Rails are still useful in 2018/19. + +
    +
  • + +
  • + + Blog rewrite + +
    November 20, 2018
    +
    + + I haven't posted here recently. That's largely because I did the classic "Time to rewrite the blog, I'll post when it's done" thing. Well it's not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I'm trying to rectify that now with some scant and scattered sentences. + +
    +
  • + +
  • + + Medium isn't a permanent fixture on the Internet + +
    May 21, 2018
    +
    + + If you're writing on the Internet and you aren't hosting (owning) your content you're work will disappear; it's just a matter of time. + +
    +
  • + +
  • + + Hosting assets via Github Pages + +
    May 11, 2018
    +
    + + Screenshots in README.mds are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult. + +
    +
  • + +
  • + + Pinboard popular page in Emacs + +
    April 26, 2018
    +
    + + A quick look at how I made an Ivy extension that displays the links from the pinboard.in popular page + +
    +
  • + +
  • + + Emacs lite + +
    April 19, 2018
    +
    + + A small, friendly starting point for Emacs. + +
    +
  • + +
  • + + Hello micro.blog + +
    February 1, 2018
    +
    + + Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting. + +
    +
  • + +
  • + + Apple on batteries and performance + +
    December 28, 2017
    +
    + + Apple released a statement on the battery and performance issues. + +
    +
  • + +
  • + + Git worktree + +
    December 11, 2017
    +
    + + What the heck is git-worktree? + +
    +
  • + +
  • + + Messi is re-writing the record book + +
    December 2, 2017
    +
    + + In a fantastic video the YouTube channel MagicalMessi documents all the various records that Messi has broken during his illustrious career. + +
    +
  • + +
  • + + Introducing ivy-feedwrangler + +
    November 16, 2017
    +
    + + In exploring what Ivy was capable of I had the idea to write a small package that used Ivy as the interface for my RSS service of choice, Feedwrangler. + +
    +
  • + +
  • + + A Hackintosh + +
    September 14, 2017
    +
    + + I built a PC in May to replace my Xbox One (yay no more Live fees!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh. + +
    +
  • + +
  • + + On Equifax + +
    September 8, 2017
    +
    + + I don't do many link posts but Ian Bogost sums up my feelings perfectly about the Equifax breach. + +
    +
  • + +
  • + + Before Circles 2017 + +
    September 6, 2017
    +
    + + I thought I'd list out a few of the talks I'm looking forward to and what I hope to come away with. + +
    +
  • + +
  • + + Five years + +
    September 5, 2017
    +
    + + Five years is a long time, especially working on the internet, and I've loved every stinking minute of it. + +
    +
  • + +
  • + + On diminishing modes in emacs + +
    August 17, 2017
    +
    + + An explanation of how to change or diminish major and minor modes in emacs + +
    +
  • + +
  • + + From helm to ivy + +
    August 14, 2017
    +
    + + A log of my experience switching from helm to ivy; two completion plugins for emacs. + +
    +
  • + +
  • + + The era of the screenshot + +
    June 12, 2017
    +
    + + We really couldn't have picked a worse data exchange format. + +
    +
  • + +
  • + + Format JSON in emacs + +
    May 23, 2017
    +
    + + I wrote an elisp function to yank JSON off my clipboard, prettify it. + +
    +
  • + +
  • + + Diceware + +
    April 19, 2017
    +
    + + Glenn Fleishman recently linked to a method for generating passphrases called Diceware. Being a fan of dice (d20 for life) I thought this was super cool and worth sharing. + +
    +
  • + +
  • + + Facetime Killer + +
    April 3, 2017
    +
    + + I made an app, VDCAssistant-Killer, to restart the process that manages the Facetime camera on your Mac. + +
    +
  • + +
  • + + What happens when you remove friction + +
    March 27, 2017
    +
    + + When you remove friction from a process or task, all the factors change. This seems obvious, but it's fundamental to understanding the world as it currently is. + +
    +
  • + +
  • + + Emacs tips + +
    March 27, 2017
    +
    + + A evolving collection of emacs tips aimed at someone starting out with emacs and evil-mode. + +
    +
  • + +
  • + + Be a good video call citizen + +
    March 17, 2017
    +
    + + I've been in my fair share of video calls and I thought I'd share a few tricks that help limit my contributions to the chaos. + +
    +
  • + +
  • + + Thirty + +
    March 2, 2017
    +
    + + Today I turn 30. So here is a list of 30 things I've learned in the last year (or so). + +
    +
  • + +
  • + + Lambda Talk + +
    February 23, 2017
    +
    + + Last week I gave a talk at GemCityJS about going serverless with AWS Lambda. + +
    +
  • + +
  • + + We all need a team + +
    June 28, 2016
    +
    + + We all need a team. On the right team we can go higher and be better than we ever thought we could. + +
    +
  • + +
  • + + Web scraper cookbook + +
    February 20, 2016
    +
    + + I've been on a web scraping tear lately. So, I thought I'd compile what I've learned and put together a repo as a howto/cookbook/guide thing. + +
    +
  • + +
  • + + How do we make the Web better + +
    January 29, 2016
    +
    + + My post for the Shift for January. I tackle the question within the question: how do we (internet workers) have more meaningful conversations in order to make the web better? + +
    +
  • + +
  • + + Command line notification + +
    January 16, 2016
    +
    + + This week I wrote a bash function that curls the SendGrid API and sends a Boxcar notification. + +
    +
  • + +
  • + + Verse Recall + +
    December 23, 2015
    +
    + + Whew, time to share something with the world I haven't really talked about online at all, my first and only (so far) iOS app. + +
    +
  • + +
  • + + SQLite Tips + +
    December 20, 2015
    +
    + + I've been playing around with SQLite recently and I've stumbled across a few things I want to remember, so I'm putting them here. + +
    +
  • + +
  • + + On Webpack + +
    December 7, 2015
    +
    + + I wrote a love letter to Webpack over on the Foundry. + +
    +
  • + +
  • + + Migrate an existing build process to npm scripts + +
    October 18, 2015
    +
    + + Not all projects need Grunt or Gulp, npm is a great build tool by itself. I recently replaced a Grunt task (with multiple plugins) with a npm script task. + +
    +
  • + +
  • + + CasperJs, Node, and the Raspberry Pi + +
    October 10, 2015
    +
    + + I've been working on getting my Raspberry Pi to be a dedicated screen-scraping machine with CasperJS and Node. +This post is intended to be a log for myself and hopefully a helpful resource for others. + +
    +
  • + +
  • + + AMP HTML, Terrible HTML + +
    October 8, 2015
    +
    + + Is the answer developing a subset of HTML/JS/CSS? + +
    +
  • + +
  • + + Farewell Heroku + +
    October 6, 2015
    +
    + + I've migrated my apps off Heroku and won't be using the service for personal apps going forward. + +
    +
  • + +
  • + + Parsing memory usage in htop/top + +
    October 4, 2015
    +
    + + I've been trying to figure out how much memory a node app is using on my VPS, and I've found output from top or htop to be overwhelming. + +
    +
  • + +
  • + + Three years + +
    September 4, 2015
    +
    + + The adventure is just getting started. + +
    +
  • + +
  • + + What is Medium? + +
    August 27, 2015
    +
    + + I'm curious to see how Medium continues to evolve. + +
    +
  • + +
  • + + Small things + +
    August 22, 2015
    +
    + + Recently I've come to love MicroJS. I love that I can find tiny, specific libraries that do one thing, and do it well + +
    +
  • + +
  • + + Automating SOCKS proxy + +
    August 8, 2015
    +
    + + I've used a SOCKS proxy while on public WiFi ever since reading Paul Stamatiou's article years ago. I only recently took the time to automate the process. + +
    +
  • + +
  • + + The Stream hasn't won + +
    July 17, 2015
    +
    + + Hossein Derakhshan outlines how the web as he knew it has disappeared and been replaced by "The Stream", or social media. His post is beautifully written and I highly recommend reading it. + +
    +
  • + +
  • + + Microblogging + +
    June 25, 2015
    +
    + + My microblogging setup with Twilio, Twitter, SMS, and WordPress. + +
    +
  • + +
  • + + Learning to think in React + +
    June 8, 2015
    +
    + + I outline how I built my blog using React and the WordPress API. This post covers isomorphic app structure and data flow in React with React-Router. + +
    +
  • + +
  • + + Moving away from Google + +
    June 1, 2015
    +
    + + I recently started using DuckDuckGo and Fastmail. So I thought I'd share a few thoughts on both services. + +
    +
  • + +
  • + + Benedict Evans is on fire + +
    May 18, 2015
    +
    + + Benedict Evan's last three pieces are right on the money regarding mobile, and the web versus native apps. + +
    +
  • + +
  • + + Web performance and Facebook's Instant Articles + +
    May 13, 2015
    +
    + + Crafting a high-performing web experience for mobile is not easy, but it's not so impossibly hard that Facebook's Instant Articles is the only solution. + +
    +
  • + +
  • + + Google Fi and data only plans + +
    April 30, 2015
    +
    + + Why doesn't Google just offer data? There already is already a fantastic data-only plan in America, and it's on T-Mobile. + +
    +
  • + +
  • + + iPhone checker with Capybara and Twilio + +
    October 30, 2014
    +
    + + I set up a small Heroku app that uses Capybara to check Apple's website for availability and sends a text to my phone via Twilio. + +
    +
  • + +
  • + + Vim Ramblings + +
    June 27, 2014
    +
    + + So, in the past 6 months I've switched from Sublime Text to Vim. Here are some good articles and tips on Vim. + +
    +
  • + +
  • + + S3 Security Policy + +
    April 26, 2014
    +
    + + A basic AWS S3 bucket policy that restricts access to a single bucket, and allows access via the AWS cli. + +
    +
  • + +
  • + + Keeping up + +
    April 8, 2014
    +
    + + Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week + +
    +
  • + +
  • + + Broadcast channel + +
    April 8, 2014
    +
    + + Along with the move to Siteleaf I've also set up an App.net Broadcast channel. + +
    +
  • + +
  • + + Moved to Siteleaf + +
    March 31, 2014
    +
    + + I moved to Siteleaf from Jekyll + +
    +
  • + +
  • + + Git Commit Template + +
    August 22, 2013
    +
    + + Set up a Git commit message template + +
    +
  • + +
  • + + ADN Cross-poster + +
    August 15, 2013
    +
    + + How to set up your own App.net to Twitter cross-posting app. + +
    +
  • + +
  • + + IFTTT + +
    July 21, 2013
    +
    + + Ways I use IFTTT. App.net to Twitter, App.net from Day One, and Camera Roll to FLickr. + +
    +
  • + +
  • + + JS2Coffee Alfred Workflow + +
    July 8, 2013
    +
    + + An Alfred workflow that converts Javascript to Coffeescript + +
    +
  • + +
  • + + Huffduffer + +
    July 6, 2013
    +
    + + Use Huffduffer to listen to individual podcast episodes. + +
    +
  • + +
  • + + Slanted Elements with CSS3 + +
    April 21, 2013
    +
    + + How to use CSS3 transforms to work with slanted elements + +
    +
  • + +
  • + + A Fluid Userscript that adds Read it Later to Twitter + +
    March 24, 2013
    +
    + + A simple Fluid userscript that adds a Read it Later button for Instapaper to any tweet containing a link + +
    +
  • + +
  • + + Rename utility + +
    February 13, 2013
    +
    + + A short primer on the rename command line utility. + +
    +
  • + +
  • + + What Matters + +
    January 10, 2013
    +
    + + A great quote from a post over at 37 signals. + +
    +
  • + +
  • + + Andy Budd on Time + +
    January 10, 2013
    +
    + + Great quote by Andy Budd on the value of time + +
    +
  • + +
  • + + IP Address Alfred Extension + +
    December 7, 2012
    +
    + + I enhance the previous IP bash function as an Alfred Extension + +
    +
  • + +
  • + + Bash Function - IP Address to Clipboard + +
    December 5, 2012
    +
    + + A quick post explaining a command line function to copy your IP address to your clipboard + +
    +
  • + +
  • + + A few Bash Tips + +
    November 20, 2012
    +
    + + A rundown of some of my most used bash and terminal commands and functions. + +
    +
  • + +
  • + + Rands on Email + +
    October 21, 2012
    +
    + + A fantastic post from Michael Lopp. + +
    +
  • + +
  • + + Lyza Gardner on Laying Down our Burdens + +
    October 21, 2012
    +
    + + Another great article from Lyza Gardner. + +
    +
  • + +
  • + + Family First + +
    October 21, 2012
    +
    + + Chris Bowler weighs in with some fantastic advice for those who have families. + +
    +
  • + +
  • + + Alfred and Web Development + +
    October 11, 2012
    +
    + + A quick tip on using Alfred in Web Development + +
    +
  • + +
  • + + Theme the Chrome Dev Tools + +
    October 9, 2012
    +
    + + A short post on how to theme the Chrome Dev Tools + +
    +
  • + +
  • + + Moving Tweetbot Beta to a new Mac + +
    September 21, 2012
    +
    + + How to migrate Tweetbot Beta to a new Mac. + +
    +
  • + +
  • + + Heroku and SSH Keys + +
    September 21, 2012
    +
    + + Quick solution to fixing Heroku SSH key errors using ssh config. + +
    +
  • + +
  • + + I moved to Hover + +
    September 9, 2012
    +
    + + I switched from GoDaddy to Hover. + +
    +
  • + +
  • + + How are you living + +
    September 6, 2012
    +
    + + Shawn Blanc poses some tough questions about life and purpose + +
    +
  • + +
  • + + A New Adventure + +
    September 3, 2012
    +
    + + Today I started working at Sparkbox as Front-End Dev. + +
    +
  • + +
  • + + When the Music Stops + +
    August 23, 2012
    +
    + + Dave Winer has a great post on what happens when a service disappears. + +
    +
  • + +
  • + + Tigers and Social Networks + +
    August 21, 2012
    +
    + + A response to Charlie Pratt's blog post about the problem of social networks and catering to the crowd + +
    +
  • + +
  • + + Blogs, data, and social networks + +
    August 19, 2012
    +
    + + I bring together a few different voices to illustrate the argument for blogs, open data, and open social networks. + +
    +
  • + +
  • + + Maybe you should…it's not you…move on. + +
    August 16, 2012
    +
    + + A collection of reactions to how Twitter muddled there recent API announcement. + +
    +
  • + +
  • + + Rotten Tomatoes and Launch Center + +
    August 13, 2012
    +
    + + Hack together a faster Rotten Tomatoes experience on the iPhone + +
    +
  • + +
  • + + Working with Wordpress, offset and pagination + +
    August 10, 2012
    +
    + + A code snippet to have posts offset and have pagination work. + +
    +
  • + +
  • + + Plaintext and Markdown - A Primer + +
    August 8, 2012
    +
    + + A quick introduction to the beauty of plaintext and the Markdown syntax + +
    +
  • + +
  • + + Gists, Snippets, and Sublime Text 2 + +
    August 6, 2012
    +
    + + How I now use Gists instead of snippets in Sublime Text 2. + +
    +
  • + +
  • + + Kyle Steed on rest + +
    August 3, 2012
    +
    + + Fantastic article by Kyle Steed on work, rest, and life + +
    +
  • + +
  • + + Convince the Boss + +
    August 2, 2012
    +
    + + Jeremy Keith on convincing bosses to adopt new web standards. + +
    +
  • + +
  • + + Create Passion + +
    August 2, 2012
    +
    + + Tiffani Jones Brown talks about passion in volume 3 of The Manual + +
    +
  • + +
  • + + Using the Kindle to harness the Web + +
    August 1, 2012
    +
    + + how I use Readability’s Kindle bookmarklet to harness the web. + +
    +
  • + +
  • + + Simple Account Set-up + +
    August 1, 2012
    +
    + + Simple does account set-up right. + +
    +
  • + +
  • + + The Future is Prototyping + +
    July 31, 2012
    +
    + + A fantastic quote from a fantastic article over at Big Spaceship + +
    +
  • + +
  • + + Story + +
    July 26, 2012
    +
    + + The importance of story in products, design, and development. + +
    +
  • + +
  • + + Guidelines for Data + +
    July 26, 2012
    +
    + + The guidelines for data and how it pertains to Wordpress + +
    +
  • + +
  • + + What's best for the readers + +
    July 24, 2012
    +
    + + Jonah Peretti's letter to employees and investors of Buzzfeed. + +
    +
  • + +
  • + + What it's all about + +
    July 23, 2012
    +
    + + Jonathan Christopher hits the nail on the head + +
    +
  • + +
  • + + Sparrow and the App Store + +
    July 23, 2012
    +
    + + App Cubby's take on Google's acquisition of Sparrow + +
    +
  • + +
  • + + CSS Reusability + +
    July 23, 2012
    +
    + + How much CSS am I reusing? + +
    +
  • + +
  • + + A Little Hydrofoil + +
    July 23, 2012
    +
    + + Robin Sloan's description of a programmer. + +
    +
  • + +
  • + + The Web is Not Print + +
    July 22, 2012
    +
    + + The infamous Zeldman dishses on the web and print + +
    +
  • + +
  • + + Declining Expectations + +
    July 22, 2012
    +
    + + Matthew Butterick's talk on declining expectations. + +
    +
  • + +
  • + + Someone is working harder than you + +
    July 19, 2012
    +
    + + Hard work and how to be creative + +
    +
  • + +
  • + + Just Start Over + +
    July 19, 2012
    +
    + + Sebastiaan De With describes his design process for doubleTwist's Alarm Clock + +
    +
  • + +
  • + + A Style Guide, Guide + +
    July 19, 2012
    +
    + + Elyse Holladay reveals her style guide guide. + +
    +
  • + +
  • + + Zen Garden Part 2? + +
    July 18, 2012
    +
    + + Is it time for a Return to the CSS Zen Garden? Rick Monro thinks Responsive Web Design needs it. + +
    +
  • + +
  • + + Pretty Git log + +
    July 18, 2012
    +
    + + Handy tip for pretty git logs. + +
    +
  • + +
  • + + Grow it, don't build it + +
    July 18, 2012
    +
    + + Growing software versus building it + +
    +
  • + +
  • + + Evening Edition + +
    July 18, 2012
    +
    + + The Evening Edition is a great little resource + +
    +
  • + +
  • + + Balancing Devotion + +
    July 17, 2012
    +
    + + Is it possible to create an extraordinary product and have a healthy life outside of that proudct? + +
    +
  • + +
  • + + The web, and my goal + +
    July 12, 2012
    +
    + + Thought from the Pastry Box Project's Bruce Lawson. + +
    +
  • + +
  • + + Nginx www rewrite + +
    July 12, 2012
    +
    + + How to rewrite www to non-www in Nginx + +
    +
  • + +
  • + + My First Bookmarklet + +
    July 12, 2012
    +
    + + My first bookmarklet, an ESPN Insider paywall + +
    +
  • + +
  • + + The Wordpress HTTP API is Awesome + +
    June 28, 2012
    +
    + + The title says it all. I completely forgot about the Wordpress HTTP API until today. + +
    +
  • + +
  • + + Adam versus Dropbox and oAuth + +
    June 25, 2012
    +
    + + Adam versus Dropbox and oAuth. Frustration post incoming regarding curl, php, and oAuth. + +
    +
  • + +
  • + + The Manhattan Project Time-Lapse + +
    June 24, 2012
    +
    + + An incredible time-lapse of Manhattan + +
    +
  • + +
  • + + Hello World + +
    June 24, 2012
    +
    + + I'm proud, nervous, and a little surprised that adamsimpson.net is finally live! + +
    +
  • + +
+
+ +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/archive/rss.xml b/themes/cycle/exampleSite/public/archive/rss.xml new file mode 100644 index 0000000..0ac0c36 --- /dev/null +++ b/themes/cycle/exampleSite/public/archive/rss.xml @@ -0,0 +1,9 @@ + + + adamsimpson.net Post Feed + https://adamsimpson.net/ + Last 20 posts for adamsimpson.net + Thu, 09 Oct 2025 21:22:39 +0000 + en-us + + diff --git a/themes/cycle/exampleSite/public/categories/index.html b/themes/cycle/exampleSite/public/categories/index.html new file mode 100644 index 0000000..7262a51 --- /dev/null +++ b/themes/cycle/exampleSite/public/categories/index.html @@ -0,0 +1,219 @@ + + + + + + Categories + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
    + +
+
+ +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/categories/rss.xml b/themes/cycle/exampleSite/public/categories/rss.xml new file mode 100644 index 0000000..0ac0c36 --- /dev/null +++ b/themes/cycle/exampleSite/public/categories/rss.xml @@ -0,0 +1,9 @@ + + + adamsimpson.net Post Feed + https://adamsimpson.net/ + Last 20 posts for adamsimpson.net + Thu, 09 Oct 2025 21:22:39 +0000 + en-us + + diff --git a/themes/cycle/exampleSite/public/index.html b/themes/cycle/exampleSite/public/index.html new file mode 100644 index 0000000..0a7608c --- /dev/null +++ b/themes/cycle/exampleSite/public/index.html @@ -0,0 +1,346 @@ + + + + + + + adamsimpson.net + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+

Hiya 👋

+

I'm Adam Simpson and I work on open source at Grafana and live life with my wonderful wife Christi and our daughters Ellie, Ainsley, and Margot.

+
+
+

Recent Posts

+
    + +
  • + + nixpkgs is a treasure + +
    May 10, 2024
    +
    + + Nix and NixOS continue to be the best way to manage and build software that I've found. + +
    +
  • + +
  • + + Lessons learned from integrating OpenAI into a Grafana data source + +
    July 25, 2023
    +
    + + I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! + +
    +
  • + +
  • + + Better scripting with gh + +
    July 22, 2023
    +
    + + I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. + +
    +
  • + +
  • + + End of an era + +
    June 15, 2023
    +
    + + Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. + +
    +
  • + +
  • + + Hacking on Grafana with Web Assembly + +
    August 19, 2022
    +
    + + Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. + +
    +
  • + +
  • + + New workstation + +
    May 2, 2022
    +
    + + I detail my new workstation build featuring the Intel i5-12600k. + +
    +
  • + +
  • + + 👋 Sparkbox + +
    April 1, 2022
    +
    + + I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. + +
    +
  • + +
  • + + Thirty five + +
    March 3, 2022
    +
    + + It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. + +
    +
  • + +
  • + + Windows 11 as KVM guest + +
    February 28, 2022
    +
    + + How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. + +
    +
  • + +
  • + + A few POSIX shell tips + +
    July 19, 2021
    +
    + + I wrote down a few of my most used POSIX shell commands and features. + +
    +
  • + +
+ +
+ +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/page/index.html b/themes/cycle/exampleSite/public/page/index.html new file mode 100644 index 0000000..5634e8a --- /dev/null +++ b/themes/cycle/exampleSite/public/page/index.html @@ -0,0 +1,243 @@ + + + + + + Pages + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
    + +
  • + + Support + +
    January 1, 0001
    +
    + + Ways to support me and the blog via affiliate links. + +
    +
  • + +
  • + + Uses + +
    January 1, 0001
    +
    + + A evolving list of hardware and software that I use. + +
    +
  • + +
+
+ +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/page/rss.xml b/themes/cycle/exampleSite/public/page/rss.xml new file mode 100644 index 0000000..0ac0c36 --- /dev/null +++ b/themes/cycle/exampleSite/public/page/rss.xml @@ -0,0 +1,9 @@ + + + adamsimpson.net Post Feed + https://adamsimpson.net/ + Last 20 posts for adamsimpson.net + Thu, 09 Oct 2025 21:22:39 +0000 + en-us + + diff --git a/themes/cycle/exampleSite/public/page/support/index.html b/themes/cycle/exampleSite/public/page/support/index.html new file mode 100644 index 0000000..4e273c2 --- /dev/null +++ b/themes/cycle/exampleSite/public/page/support/index.html @@ -0,0 +1,233 @@ + + + + + + Support + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+

Support

+

I use the following services just about every day and they all offer discounts or other incentives for folks to recommend the service to other people. Signing up for one of these services using the links below helps support me and this blog. Thanks!

+

Fastmail

+

I’ve been a Fastmail user for years now and I don’t have a single complaint about the service or company. Highly recommended if all you care about is IMAP service that “just works.”

+

Hover

+

Years ago I switched from GoDaddy to Hover and haven’t looked back. They’re a great, no-frills DNS service.

+

Backblaze

+

I’ve been using Backblaze for years and absolutely love the service and company. Not only is their product top-notch but the data they publish about hard drive reliability is incredibly useful.

+ +
+
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/page/uses/index.html b/themes/cycle/exampleSite/public/page/uses/index.html new file mode 100644 index 0000000..bfcb6bf --- /dev/null +++ b/themes/cycle/exampleSite/public/page/uses/index.html @@ -0,0 +1,239 @@ + + + + + + Uses + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+

Uses

+

Author’s note: I 100% stole this format from the incredible usesthis site. Check it out.

+

What hardware do you use?

+

At work I use a desktop workstation running NixOS and an Intel 12600k. I game via a Windows 11 VM and a Nvidia 3060 passed through to that VM.

+

I love typing on my Anne Pro GMMK Pro mechanical keyboard with Gazzew U4 Boba switches for a quieter feel.

+

My phone is an iPhone 14. It’s fine.

+

And what software?

+

I’m a big user of Emacs. I use mu4e for email, org-mode for tasks and notes, Ivy for auto-complete, magit for git, ivy-feedwrangler for RSS. I’ve switched to VSCode since the support for all the various LSPs and debug tools is just better at the moment.

+

Linux apps I use on my work laptop are: Signal, Tilix or Alacritty for terminals, rofi for launching, and i3wm as my window manager.

+

Mac specific apps I use: Alfred, MenuMeters, 1Password, Moom, Turbo Boost Switcher Pro, and Hammerspoon.

+

My browser of choice is Firefox.

+

I enjoy writing code in Javascript/Node, Golang, Ruby, Common Lisp, and recently Rust.

+

Any online services?

+

As far as online services go I use Netlify (at the moment) to host this site, Hover for domains, Fastmail for email, yarr manages my RSS feeds, and I use Backblaze for online backup.

+ +
+
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/post/index.html b/themes/cycle/exampleSite/public/post/index.html new file mode 100644 index 0000000..fa24c0d --- /dev/null +++ b/themes/cycle/exampleSite/public/post/index.html @@ -0,0 +1,2454 @@ + + + + + + Posts + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
    + +
  • + + nixpkgs is a treasure + +
    May 10, 2024
    +
    + + Nix and NixOS continue to be the best way to manage and build software that I've found. + +
    +
  • + +
  • + + Lessons learned from integrating OpenAI into a Grafana data source + +
    July 25, 2023
    +
    + + I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! + +
    +
  • + +
  • + + Better scripting with gh + +
    July 22, 2023
    +
    + + I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. + +
    +
  • + +
  • + + End of an era + +
    June 15, 2023
    +
    + + Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. + +
    +
  • + +
  • + + Hacking on Grafana with Web Assembly + +
    August 19, 2022
    +
    + + Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. + +
    +
  • + +
  • + + New workstation + +
    May 2, 2022
    +
    + + I detail my new workstation build featuring the Intel i5-12600k. + +
    +
  • + +
  • + + 👋 Sparkbox + +
    April 1, 2022
    +
    + + I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. + +
    +
  • + +
  • + + Thirty five + +
    March 3, 2022
    +
    + + It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. + +
    +
  • + +
  • + + Windows 11 as KVM guest + +
    February 28, 2022
    +
    + + How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. + +
    +
  • + +
  • + + A few POSIX shell tips + +
    July 19, 2021
    +
    + + I wrote down a few of my most used POSIX shell commands and features. + +
    +
  • + +
  • + + Recently + +
    April 23, 2021
    +
    + + A random assortment of links and miscellaneous updates on things. + +
    +
  • + +
  • + + A firewall in 8 lines + +
    March 31, 2021
    +
    + + You only need about 8 lines in iptables to have a great home firewall. + +
    +
  • + +
  • + + How to use Siji font on polybar + +
    November 6, 2020
    +
    + +

    Nice guide on Reddit about how to use the Siji font with polybar.

    +
    +

    [..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

    +
    +

    Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

    + + 🔗 Permalink + +
    +
  • + +
  • + + On Polybar bitmap fonts and Ubuntu + +
    November 6, 2020
    +
    + + Enable bitmap fonts on Ubuntu for an optimal polybar experience. + +
    +
  • + +
  • + + Recently + +
    October 27, 2020
    +
    + + I've written a few small tools over the last couple months and I figured it's time I post about them. + +
    +
  • + +
  • + + Four ways to approach Hacktoberfest 2020 + +
    October 1, 2020
    +
    + + I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. + +
    +
  • + +
  • + + Small tech + +
    September 25, 2020
    +
    + +

    Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

    +
      +
    • +

      curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

      +
    • +
    • +

      git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

      +
    • +
    • +

      Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

      +
    • +
    • +

      sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

      +
    • +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Indexing My Blog’s Links + +
    September 25, 2020
    +
    + +

    Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Compose key and i3 + +
    September 18, 2020
    +
    + + Here's how to bind the compose key to caps lock in i3wm. + +
    +
  • + +
  • + + cycle v0.3.0 released + +
    September 11, 2020
    +
    + + Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. + +
    +
  • + +
  • + + Setting a default browser in i3 + +
    September 11, 2020
    +
    + + Using a desktop manager like GNOME makes setting default applications easy. However when using a tiling window manager like i3 setting a default application is opaque to the newbie such as myself. + +
    +
  • + +
  • + + Eight years + +
    September 4, 2020
    +
    + + Eight years ago I started working at Sparkbox. Thank you Sparkbox team for giving me an opportunity to work with ya'll and for making me a better developer and person. + +
    +
  • + +
  • + + Uses This / Zach Beane + +
    September 1, 2020
    +
    + +

    A great interview with the creator of Quicklisp, Zach Beane. I enjoy two things about this interview:

    +
      +
    1. The inclusion of outdoor/farming tools in the list of tools.
    2. +
    3. Zach’s conservative approach to languages and software tools.
    4. +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Openring + +
    August 21, 2020
    +
    + + I've added Drew DeVault's openring project to the blog. + +
    +
  • + +
  • + + A public inbox + +
    August 17, 2020
    +
    + + I'm going to give the idea of a public inbox as a place to have discussions about things on this website and elsewhere a shot. + +
    +
  • + +
  • + + Clear explanation of Rust’s module system + +
    July 19, 2020
    +
    + +

    This is a great explanation of Rust’s module system. I wish I had this clear of a picture when I was using modules for the first time in creating oscar.

    +

    The big takeaway and deviation from npm is this:

    +
    +

    We need to explicitly build the module tree in Rust, there’s no implicit mapping to file system.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Nothing speaks like a demo + +
    July 19, 2020
    +
    + +

    Great post from my friend and co-worker Bryan Braun on the value of demoing.

    +
    +

    It didn’t matter that his demos weren’t fully built, or available for anyone to use. We simply needed to see it, in order to understand.

    +
    +

    I find this is true for any kind of project: hobby or professional. Feedback — that elusive crucial ingredient to a good product — tends to arrive when someone else can see/hear/touch/examine what you’re working on.

    + + 🔗 Permalink + +
    +
  • + +
  • + + A new website for 2020 + +
    July 16, 2020
    +
    + +
    +

    According to my Cargo.lock file, my website currently depends on 364 crates. So it’s really about standing on the shoulder of a carefully-curated set of giants.

    +
    +
    +

    364 may seem like a lot (and in a way, it is), but please reserve your judgement until after you’ve heard about everything it does.

    +
    +

    I /love/ posts like this. Amos goes in deep on the decisions he made while re-writing his website from scratch. It’s a truly awesome post.

    +

    I’m seriously tempted to copy his SQLite full-text search implementation for this blog, but that’s a decision for another time.

    + + 🔗 Permalink + +
    +
  • + +
  • + + A Moment of Clarity Regarding the Raison d’Etre for the App Store + +
    July 13, 2020
    +
    + +
    +

    I’d like to see all the vim, vigor, and vigilance Apple applies to making sure no app on the App Store is making a dime without Apple getting three cents applied instead to making sure there aren’t any scams or ripoffs, and that popular apps support good-citizen-of-the-platform features within a reasonable amount of time after those features are introduced in the OS. I don’t know exactly how long “reasonable” is, but five fucking years for split-screen support ain’t it.

    +
    +

    I’ve been thinking the same thing ever since the Hey app rejection right before WWDC. The App Store is supposed to be a place to get software that has been vetted by Apple but there seems to be a growing disconnect between what users imagine that vetting is and what Apple is doing.

    +

    I want to believe this tweet by Ben Evans is the goal of the App Store:

    + +

    If we can trust the apps that come out of the App Store:

    +
      +
    • why is the US considering banning TikTok because of its rampant data collection?
    • +
    • why do we need a new notification in iOS 14 when apps query the clipboard?
    • +
    • why do we need a microphone/camera indicator at the system level?
    • +
    +

    Maybe I was naive and alone in my assumption that Apple would root this stuff out during the review process. If they’re not rooting this out then what is the point of the review process at all?

    + + 🔗 Permalink + +
    +
  • + +
  • + + GoatCounter web analytics + +
    July 1, 2020
    +
    + +
    +

    What seems to be lacking is a “middle ground” that offers useful statistics to answer business questions, without becoming a specialized marketing tool requiring in-depth training to use effectively. Furthermore, some tools have privacy issues (especially Google Analytics). I saw there was space for a new service and ended up putting my original idea in the freezer and writing GoatCounter.

    +
    +

    I agree 100% with this assessment and I’m excited about Goatcounter. I setup a free instance of Goatcounter for this site as a way to kick the tires on it. So far, I’m enjoying that it’s privacy respecting and doesn’t drag down page performance.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Is WebP really better than JPEG? + +
    June 30, 2020
    +
    + +
    +

    If you have used tools like Google’s PageSpeed Insights, you probably have run into a suggestion to use “next-gen image formats”, namely Google’s WebP image format. Google claims that their WebP format is 25 – 34% smaller than JPEG at equivalent quality.

    +
    +
    +

    In any case, when converting images to WebP, check that they are actually smaller than the JPEG equivalent. There’s no need to serve larger images to your users than needed.

    +
    +

    Great analysis of the WebP image format and a good reminder to not blindly follow what various auditing tools are reporting. Test and verify in addition to implementing the various suggested improvements.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Britain goes coal free as renewables edge out fossil fuels + +
    June 30, 2020
    +
    + +
    +

    Britain is about to pass a significant landmark - at midnight on Wednesday it will have gone two full months without burning coal to generate power.

    +
    +
    +

    A decade ago about 40% of the country’s electricity came from coal; coronavirus is part of the story, but far from all.

    +
    +

    This is fascinating. The UK has been aggressively investing in renewable energy sources for years and it appears all that investment is starting to catch up with demand.

    + + 🔗 Permalink + +
    +
  • + +
  • + + On George Floyd + +
    June 30, 2020
    +
    + + I haven't written anything here about George Floyd's murder. I still don't have a cogent response but here's what I've been mulling over. + +
    +
  • + +
  • + + flatkill + +
    June 15, 2020
    +
    + +
    +

    And it’s not only about these security problems. Running KDE apps in fakepak? Forget about desktop integration (not even font size). Need to input Chinese/Japanese/Korean characters? Forget about that too - fcitx has been broken since flatpak 1.0, never fixed since.

    +
    +
    +

    The way we package and distribute desktop applications on Linux surely needs to be rethinked, sadly flatpak is introducing more problems than it is solving.

    +
    +

    Flatpak is an emerging alternative way to install applications on Linux that is apparently rife with security and usability issues. This is a bummer because there’s lots of room in this space for improvement. The lack of multi-lingual input is especially egregious.

    + + 🔗 Permalink + +
    +
  • + +
  • + + FFMPEG: Convert multiple files using xargs + +
    June 4, 2020
    +
    + +

    I stumbled upon this post (Google cache link) when I was trying to process multiple files via xargs.

    +
    +

    ls *.webm | xargs -I % ffmpeg -i % %.m4a

    +
    +
    +

    The key part of this one-liner is xargs -i %. This means that each line of STDIN passed to xargs is put into a variable and can be referenced as %. Hence, the following text which specifies ffmpeg -i x.webm x.m4a to make it convert.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Using SQL to Look Through All of Your iMessage Text Messages + +
    May 28, 2020
    +
    + +
    +

    If you use iMessage on your Mac, you can access the SQLite database where all of your messages are stored. With a little setup, you can use SQL’s raw power to look through your old messages.

    +
    +

    via Simon Willison

    +

    In this post Dan Kelch walks through how to access the SQLite database that backs iMessage on a Mac. He also shares a few helpful SQL snippets to demonstrate how powerful using SQL on your text messages can be.

    + + 🔗 Permalink + +
    +
  • + +
  • + + macOS 10.15: Slow by Design + +
    May 28, 2020
    +
    + +

    A few days ago Allan Odgaard wrote up the reasons for the frequent slowdowns he’s experiencing in macOS Catalina and it’s shocking:

    +
    +

    Apple has introduced notarization, setting aside the inconvenience this brings to us developers, it also results in a degraded user experience, as the first time a user runs a new executable, Apple delays execution while waiting for a reply from their server. This check for me takes close to a second.

    +
    +
    +

    This is not just for files downloaded from the internet, nor is it only when you launch them via Finder, this is everything. So even if you write a one line shell script and run it in a terminal, you will get a delay!

    +
    +
    +

    I am writing this post to call attention to what I consider a serious design problem with Apple’s most recent OS where it appears that low-level system API such as exec and getxattr now do synchronous network activity before returning to the caller.

    +
    +

    Marco Arment hit the nail on the head with his tweet summary of the post:

    +
    +

    The macOS security team needs to ask themselves hard questions about their implementation choices when very smart people are disabling huge parts of their OS security layer just to get reasonable performance from common tasks.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Getting started with Rofi + +
    May 28, 2020
    +
    + + I've been using Rofi for about a year but didn't really understand how to write my own scripts for it until recently. In this post I explain what dmenu is and Rofi's implementation of it and also show how to change audio inputs on Linux via pactl. + +
    +
  • + +
  • + + What Time Is It in London? + +
    May 22, 2020
    +
    + +
    +

    Nilay Patel asked this of Siri on his Apple Watch. After too long of a wait, he got the correct answer — for London Canada. I tried on my iPhone and got the same result. Stupid and slow is heck of a combination.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Psychic Paper + +
    May 18, 2020
    +
    + +
    +

    RIP my very first 0day and absolute best sandbox escape ever:

    +
    +
    <key>application-identifier</key>
    +<string>...</string>
    +<!---><!-->
    +<key>platform-application</key>
    +<true/>
    +<key>com .apple.private.security.no-container</key>
    +<true/>
    +<key>task_for_pid-allow</key>
    +<true/>
    +<!-- -->
    +

    Tweet that demonstrates a recent zero-day (now patched) in iOS. This serves as your annual reminder that parsing xml-like things is a fraught activity.

    + + 🔗 Permalink + +
    +
  • + +
  • + + The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet + +
    May 18, 2020
    +
    + +
    +

    Janet Hutchins had the day off from her job as a nurse at a local hospital. She had been in town catching up with friends and had just gotten home and started making dinner. So she had only the slightest sense of the crisis that her colleagues had been dealing with across the NHS. That’s when her son came upstairs and told her, a little uncertainly, that he seemed to have stopped the worst malware attack the world had ever seen.

    +
    +
    +

    “Well done, sweetheart,” Janet Hutchins said. Then she went back to chopping onions.

    +
    +

    It’s hard to pick my favorite section from this article about Marcus Hutchins — the hacker who stopped the WannaCry malware attack.

    + + 🔗 Permalink + +
    +
  • + +
  • + + Second-guessing the modern web + +
    May 13, 2020
    +
    + +
    +

    The low performance parts don’t need to be React. Listing pages, static pages, blogs - these things are increasingly built in React, but the benefits they accrue are extremely narrow. A lot of the optimizations that are cropping up in these corners, things like bundle splitting, server-side rendering, and prerendering, are triangulating, essentially, what we had before the rise of React.

    +
    +

    This isn’t really about React but more about the over-engineering of large swaths of page-types and sites that used to “just work”. I love React and it’s been a giant leap forward for creating complex UIs on the web, that doesn’t mean it’s right for every situation.

    + + 🔗 Permalink + +
    +
  • + +
  • + + youtube-subscriptions + +
    May 8, 2020
    +
    + +

    I’ve been using youtube-subscriptions for a few months now and I really enjoy it. It’s described as a:

    +
    +

    terminal client to browse youtube subscriptions

    +
    +

    It’s great to quickly see any new videos right in the terminal and videos play via mpv or vlc!

    + + 🔗 Permalink + +
    +
  • + +
  • + + Hiking the Pacific Crest Trail in Three Minutes + +
    May 7, 2020
    +
    + +
    +

    The Pacific Crest Trail runs 2650 miles from the border of Mexico to the border of Canada through California, Oregon, and Washington. Hiking the whole thing usually takes months, but this video by Mac of Halfway Anywhere compresses the entire experience down to just three minutes presented in 1-second snippets.

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Introducing oscar + +
    April 29, 2020
    +
    + + I've been working on oscar which is a small command-line utility written in Rust that polls the pbskids.org API for new episodes of any PBS show. + +
    +
  • + +
  • + + Seamless branch deploys with Kubernetes + +
    April 27, 2020
    +
    + +

    A trait of good software is the ability to quickly see and verify changes:

    +
    +

    The result is what’s in-use today for HEY: a system that (almost) immediately deploys any branch to a branch-specific endpoint that you can access right away to test your changes without having to use the claims system or talk to anyone else (along with an independent job processing fleet and Redis instance to support the environment).

    +
    + + 🔗 Permalink + +
    +
  • + +
  • + + Three easy tuneups to fix video calls while working from home + +
    March 17, 2020
    +
    + + In light of COVID-19 and lots of folks working from home, I've written down the three things I try to tune on my home network to deliver the best possible video call experience. + +
    +
  • + +
  • + + ATR2100 + +
    January 29, 2020
    +
    + + I recently purchased the ATR2100 microphone and absolutely love it. + +
    +
  • + +
  • + + Understanding Rust Strings and str inside structs. + +
    January 8, 2020
    +
    + + Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here's a short breakdown of a compiler error message around Strings and ownership that stumped me for a bit. + +
    +
  • + +
  • + + Tweet stash + +
    December 12, 2019
    +
    + + Two tweets that I've had stuck in my tabs for _awhile_ and decided to stash them here. + +
    +
  • + +
  • + + Track redirects with curl + +
    October 22, 2019
    +
    + + I made a bash alias that takes a URL as an arguement and runs it through curl resuting in the Headers from each redirect, the final URL, and the number of redirects printed to the console. + +
    +
  • + +
  • + + The thing about computers + +
    September 21, 2019
    +
    + + Brent Simmons talks about what made computing so compelling and what we might be losing. + +
    +
  • + +
  • + + Dead Cells might be a perfect game + +
    September 20, 2019
    +
    + + Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it). + +
    +
  • + +
  • + + 0.14 + +
    July 30, 2019
    +
    + + I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn't worth it. + +
    +
  • + +
  • + + Solving busybox crond hanging on Alpine Linux boot + +
    May 5, 2019
    +
    + + How busybox crond hanging at startup sent me down a rabbit hole where I learned about entropy and Linux. + +
    +
  • + +
  • + + Introducing Cycle + +
    April 5, 2019
    +
    + + Cycle is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today. + +
    +
  • + +
  • + + Ajax and Rails + +
    January 28, 2019
    +
    + + This is just a short post to save a few links and document that "Server Javascript Responses" in Rails are still useful in 2018/19. + +
    +
  • + +
  • + + Blog rewrite + +
    November 20, 2018
    +
    + + I haven't posted here recently. That's largely because I did the classic "Time to rewrite the blog, I'll post when it's done" thing. Well it's not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I'm trying to rectify that now with some scant and scattered sentences. + +
    +
  • + +
  • + + Medium isn't a permanent fixture on the Internet + +
    May 21, 2018
    +
    + + If you're writing on the Internet and you aren't hosting (owning) your content you're work will disappear; it's just a matter of time. + +
    +
  • + +
  • + + Hosting assets via Github Pages + +
    May 11, 2018
    +
    + + Screenshots in README.mds are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult. + +
    +
  • + +
  • + + Pinboard popular page in Emacs + +
    April 26, 2018
    +
    + + A quick look at how I made an Ivy extension that displays the links from the pinboard.in popular page + +
    +
  • + +
  • + + Emacs lite + +
    April 19, 2018
    +
    + + A small, friendly starting point for Emacs. + +
    +
  • + +
  • + + Hello micro.blog + +
    February 1, 2018
    +
    + + Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting. + +
    +
  • + +
  • + + Apple on batteries and performance + +
    December 28, 2017
    +
    + + Apple released a statement on the battery and performance issues. + +
    +
  • + +
  • + + Git worktree + +
    December 11, 2017
    +
    + + What the heck is git-worktree? + +
    +
  • + +
  • + + Messi is re-writing the record book + +
    December 2, 2017
    +
    + + In a fantastic video the YouTube channel MagicalMessi documents all the various records that Messi has broken during his illustrious career. + +
    +
  • + +
  • + + Introducing ivy-feedwrangler + +
    November 16, 2017
    +
    + + In exploring what Ivy was capable of I had the idea to write a small package that used Ivy as the interface for my RSS service of choice, Feedwrangler. + +
    +
  • + +
  • + + A Hackintosh + +
    September 14, 2017
    +
    + + I built a PC in May to replace my Xbox One (yay no more Live fees!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh. + +
    +
  • + +
  • + + On Equifax + +
    September 8, 2017
    +
    + + I don't do many link posts but Ian Bogost sums up my feelings perfectly about the Equifax breach. + +
    +
  • + +
  • + + Before Circles 2017 + +
    September 6, 2017
    +
    + + I thought I'd list out a few of the talks I'm looking forward to and what I hope to come away with. + +
    +
  • + +
  • + + Five years + +
    September 5, 2017
    +
    + + Five years is a long time, especially working on the internet, and I've loved every stinking minute of it. + +
    +
  • + +
  • + + On diminishing modes in emacs + +
    August 17, 2017
    +
    + + An explanation of how to change or diminish major and minor modes in emacs + +
    +
  • + +
  • + + From helm to ivy + +
    August 14, 2017
    +
    + + A log of my experience switching from helm to ivy; two completion plugins for emacs. + +
    +
  • + +
  • + + The era of the screenshot + +
    June 12, 2017
    +
    + + We really couldn't have picked a worse data exchange format. + +
    +
  • + +
  • + + Format JSON in emacs + +
    May 23, 2017
    +
    + + I wrote an elisp function to yank JSON off my clipboard, prettify it. + +
    +
  • + +
  • + + Diceware + +
    April 19, 2017
    +
    + + Glenn Fleishman recently linked to a method for generating passphrases called Diceware. Being a fan of dice (d20 for life) I thought this was super cool and worth sharing. + +
    +
  • + +
  • + + Facetime Killer + +
    April 3, 2017
    +
    + + I made an app, VDCAssistant-Killer, to restart the process that manages the Facetime camera on your Mac. + +
    +
  • + +
  • + + What happens when you remove friction + +
    March 27, 2017
    +
    + + When you remove friction from a process or task, all the factors change. This seems obvious, but it's fundamental to understanding the world as it currently is. + +
    +
  • + +
  • + + Emacs tips + +
    March 27, 2017
    +
    + + A evolving collection of emacs tips aimed at someone starting out with emacs and evil-mode. + +
    +
  • + +
  • + + Be a good video call citizen + +
    March 17, 2017
    +
    + + I've been in my fair share of video calls and I thought I'd share a few tricks that help limit my contributions to the chaos. + +
    +
  • + +
  • + + Thirty + +
    March 2, 2017
    +
    + + Today I turn 30. So here is a list of 30 things I've learned in the last year (or so). + +
    +
  • + +
  • + + Lambda Talk + +
    February 23, 2017
    +
    + + Last week I gave a talk at GemCityJS about going serverless with AWS Lambda. + +
    +
  • + +
  • + + We all need a team + +
    June 28, 2016
    +
    + + We all need a team. On the right team we can go higher and be better than we ever thought we could. + +
    +
  • + +
  • + + Web scraper cookbook + +
    February 20, 2016
    +
    + + I've been on a web scraping tear lately. So, I thought I'd compile what I've learned and put together a repo as a howto/cookbook/guide thing. + +
    +
  • + +
  • + + How do we make the Web better + +
    January 29, 2016
    +
    + + My post for the Shift for January. I tackle the question within the question: how do we (internet workers) have more meaningful conversations in order to make the web better? + +
    +
  • + +
  • + + Command line notification + +
    January 16, 2016
    +
    + + This week I wrote a bash function that curls the SendGrid API and sends a Boxcar notification. + +
    +
  • + +
  • + + Verse Recall + +
    December 23, 2015
    +
    + + Whew, time to share something with the world I haven't really talked about online at all, my first and only (so far) iOS app. + +
    +
  • + +
  • + + SQLite Tips + +
    December 20, 2015
    +
    + + I've been playing around with SQLite recently and I've stumbled across a few things I want to remember, so I'm putting them here. + +
    +
  • + +
  • + + On Webpack + +
    December 7, 2015
    +
    + + I wrote a love letter to Webpack over on the Foundry. + +
    +
  • + +
  • + + Migrate an existing build process to npm scripts + +
    October 18, 2015
    +
    + + Not all projects need Grunt or Gulp, npm is a great build tool by itself. I recently replaced a Grunt task (with multiple plugins) with a npm script task. + +
    +
  • + +
  • + + CasperJs, Node, and the Raspberry Pi + +
    October 10, 2015
    +
    + + I've been working on getting my Raspberry Pi to be a dedicated screen-scraping machine with CasperJS and Node. +This post is intended to be a log for myself and hopefully a helpful resource for others. + +
    +
  • + +
  • + + AMP HTML, Terrible HTML + +
    October 8, 2015
    +
    + + Is the answer developing a subset of HTML/JS/CSS? + +
    +
  • + +
  • + + Farewell Heroku + +
    October 6, 2015
    +
    + + I've migrated my apps off Heroku and won't be using the service for personal apps going forward. + +
    +
  • + +
  • + + Parsing memory usage in htop/top + +
    October 4, 2015
    +
    + + I've been trying to figure out how much memory a node app is using on my VPS, and I've found output from top or htop to be overwhelming. + +
    +
  • + +
  • + + Three years + +
    September 4, 2015
    +
    + + The adventure is just getting started. + +
    +
  • + +
  • + + What is Medium? + +
    August 27, 2015
    +
    + + I'm curious to see how Medium continues to evolve. + +
    +
  • + +
  • + + Small things + +
    August 22, 2015
    +
    + + Recently I've come to love MicroJS. I love that I can find tiny, specific libraries that do one thing, and do it well + +
    +
  • + +
  • + + Automating SOCKS proxy + +
    August 8, 2015
    +
    + + I've used a SOCKS proxy while on public WiFi ever since reading Paul Stamatiou's article years ago. I only recently took the time to automate the process. + +
    +
  • + +
  • + + The Stream hasn't won + +
    July 17, 2015
    +
    + + Hossein Derakhshan outlines how the web as he knew it has disappeared and been replaced by "The Stream", or social media. His post is beautifully written and I highly recommend reading it. + +
    +
  • + +
  • + + Microblogging + +
    June 25, 2015
    +
    + + My microblogging setup with Twilio, Twitter, SMS, and WordPress. + +
    +
  • + +
  • + + Learning to think in React + +
    June 8, 2015
    +
    + + I outline how I built my blog using React and the WordPress API. This post covers isomorphic app structure and data flow in React with React-Router. + +
    +
  • + +
  • + + Moving away from Google + +
    June 1, 2015
    +
    + + I recently started using DuckDuckGo and Fastmail. So I thought I'd share a few thoughts on both services. + +
    +
  • + +
  • + + Benedict Evans is on fire + +
    May 18, 2015
    +
    + + Benedict Evan's last three pieces are right on the money regarding mobile, and the web versus native apps. + +
    +
  • + +
  • + + Web performance and Facebook's Instant Articles + +
    May 13, 2015
    +
    + + Crafting a high-performing web experience for mobile is not easy, but it's not so impossibly hard that Facebook's Instant Articles is the only solution. + +
    +
  • + +
  • + + Google Fi and data only plans + +
    April 30, 2015
    +
    + + Why doesn't Google just offer data? There already is already a fantastic data-only plan in America, and it's on T-Mobile. + +
    +
  • + +
  • + + iPhone checker with Capybara and Twilio + +
    October 30, 2014
    +
    + + I set up a small Heroku app that uses Capybara to check Apple's website for availability and sends a text to my phone via Twilio. + +
    +
  • + +
  • + + Vim Ramblings + +
    June 27, 2014
    +
    + + So, in the past 6 months I've switched from Sublime Text to Vim. Here are some good articles and tips on Vim. + +
    +
  • + +
  • + + S3 Security Policy + +
    April 26, 2014
    +
    + + A basic AWS S3 bucket policy that restricts access to a single bucket, and allows access via the AWS cli. + +
    +
  • + +
  • + + Keeping up + +
    April 8, 2014
    +
    + + Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week + +
    +
  • + +
  • + + Broadcast channel + +
    April 8, 2014
    +
    + + Along with the move to Siteleaf I've also set up an App.net Broadcast channel. + +
    +
  • + +
  • + + Moved to Siteleaf + +
    March 31, 2014
    +
    + + I moved to Siteleaf from Jekyll + +
    +
  • + +
  • + + Git Commit Template + +
    August 22, 2013
    +
    + + Set up a Git commit message template + +
    +
  • + +
  • + + ADN Cross-poster + +
    August 15, 2013
    +
    + + How to set up your own App.net to Twitter cross-posting app. + +
    +
  • + +
  • + + IFTTT + +
    July 21, 2013
    +
    + + Ways I use IFTTT. App.net to Twitter, App.net from Day One, and Camera Roll to FLickr. + +
    +
  • + +
  • + + JS2Coffee Alfred Workflow + +
    July 8, 2013
    +
    + + An Alfred workflow that converts Javascript to Coffeescript + +
    +
  • + +
  • + + Huffduffer + +
    July 6, 2013
    +
    + + Use Huffduffer to listen to individual podcast episodes. + +
    +
  • + +
  • + + Slanted Elements with CSS3 + +
    April 21, 2013
    +
    + + How to use CSS3 transforms to work with slanted elements + +
    +
  • + +
  • + + A Fluid Userscript that adds Read it Later to Twitter + +
    March 24, 2013
    +
    + + A simple Fluid userscript that adds a Read it Later button for Instapaper to any tweet containing a link + +
    +
  • + +
  • + + Rename utility + +
    February 13, 2013
    +
    + + A short primer on the rename command line utility. + +
    +
  • + +
  • + + What Matters + +
    January 10, 2013
    +
    + + A great quote from a post over at 37 signals. + +
    +
  • + +
  • + + Andy Budd on Time + +
    January 10, 2013
    +
    + + Great quote by Andy Budd on the value of time + +
    +
  • + +
  • + + IP Address Alfred Extension + +
    December 7, 2012
    +
    + + I enhance the previous IP bash function as an Alfred Extension + +
    +
  • + +
  • + + Bash Function - IP Address to Clipboard + +
    December 5, 2012
    +
    + + A quick post explaining a command line function to copy your IP address to your clipboard + +
    +
  • + +
  • + + A few Bash Tips + +
    November 20, 2012
    +
    + + A rundown of some of my most used bash and terminal commands and functions. + +
    +
  • + +
  • + + Rands on Email + +
    October 21, 2012
    +
    + + A fantastic post from Michael Lopp. + +
    +
  • + +
  • + + Lyza Gardner on Laying Down our Burdens + +
    October 21, 2012
    +
    + + Another great article from Lyza Gardner. + +
    +
  • + +
  • + + Family First + +
    October 21, 2012
    +
    + + Chris Bowler weighs in with some fantastic advice for those who have families. + +
    +
  • + +
  • + + Alfred and Web Development + +
    October 11, 2012
    +
    + + A quick tip on using Alfred in Web Development + +
    +
  • + +
  • + + Theme the Chrome Dev Tools + +
    October 9, 2012
    +
    + + A short post on how to theme the Chrome Dev Tools + +
    +
  • + +
  • + + Moving Tweetbot Beta to a new Mac + +
    September 21, 2012
    +
    + + How to migrate Tweetbot Beta to a new Mac. + +
    +
  • + +
  • + + Heroku and SSH Keys + +
    September 21, 2012
    +
    + + Quick solution to fixing Heroku SSH key errors using ssh config. + +
    +
  • + +
  • + + I moved to Hover + +
    September 9, 2012
    +
    + + I switched from GoDaddy to Hover. + +
    +
  • + +
  • + + How are you living + +
    September 6, 2012
    +
    + + Shawn Blanc poses some tough questions about life and purpose + +
    +
  • + +
  • + + A New Adventure + +
    September 3, 2012
    +
    + + Today I started working at Sparkbox as Front-End Dev. + +
    +
  • + +
  • + + When the Music Stops + +
    August 23, 2012
    +
    + + Dave Winer has a great post on what happens when a service disappears. + +
    +
  • + +
  • + + Tigers and Social Networks + +
    August 21, 2012
    +
    + + A response to Charlie Pratt's blog post about the problem of social networks and catering to the crowd + +
    +
  • + +
  • + + Blogs, data, and social networks + +
    August 19, 2012
    +
    + + I bring together a few different voices to illustrate the argument for blogs, open data, and open social networks. + +
    +
  • + +
  • + + Maybe you should…it's not you…move on. + +
    August 16, 2012
    +
    + + A collection of reactions to how Twitter muddled there recent API announcement. + +
    +
  • + +
  • + + Rotten Tomatoes and Launch Center + +
    August 13, 2012
    +
    + + Hack together a faster Rotten Tomatoes experience on the iPhone + +
    +
  • + +
  • + + Working with Wordpress, offset and pagination + +
    August 10, 2012
    +
    + + A code snippet to have posts offset and have pagination work. + +
    +
  • + +
  • + + Plaintext and Markdown - A Primer + +
    August 8, 2012
    +
    + + A quick introduction to the beauty of plaintext and the Markdown syntax + +
    +
  • + +
  • + + Gists, Snippets, and Sublime Text 2 + +
    August 6, 2012
    +
    + + How I now use Gists instead of snippets in Sublime Text 2. + +
    +
  • + +
  • + + Kyle Steed on rest + +
    August 3, 2012
    +
    + + Fantastic article by Kyle Steed on work, rest, and life + +
    +
  • + +
  • + + Convince the Boss + +
    August 2, 2012
    +
    + + Jeremy Keith on convincing bosses to adopt new web standards. + +
    +
  • + +
  • + + Create Passion + +
    August 2, 2012
    +
    + + Tiffani Jones Brown talks about passion in volume 3 of The Manual + +
    +
  • + +
  • + + Using the Kindle to harness the Web + +
    August 1, 2012
    +
    + + how I use Readability’s Kindle bookmarklet to harness the web. + +
    +
  • + +
  • + + Simple Account Set-up + +
    August 1, 2012
    +
    + + Simple does account set-up right. + +
    +
  • + +
  • + + The Future is Prototyping + +
    July 31, 2012
    +
    + + A fantastic quote from a fantastic article over at Big Spaceship + +
    +
  • + +
  • + + Story + +
    July 26, 2012
    +
    + + The importance of story in products, design, and development. + +
    +
  • + +
  • + + Guidelines for Data + +
    July 26, 2012
    +
    + + The guidelines for data and how it pertains to Wordpress + +
    +
  • + +
  • + + What's best for the readers + +
    July 24, 2012
    +
    + + Jonah Peretti's letter to employees and investors of Buzzfeed. + +
    +
  • + +
  • + + What it's all about + +
    July 23, 2012
    +
    + + Jonathan Christopher hits the nail on the head + +
    +
  • + +
  • + + Sparrow and the App Store + +
    July 23, 2012
    +
    + + App Cubby's take on Google's acquisition of Sparrow + +
    +
  • + +
  • + + CSS Reusability + +
    July 23, 2012
    +
    + + How much CSS am I reusing? + +
    +
  • + +
  • + + A Little Hydrofoil + +
    July 23, 2012
    +
    + + Robin Sloan's description of a programmer. + +
    +
  • + +
  • + + The Web is Not Print + +
    July 22, 2012
    +
    + + The infamous Zeldman dishses on the web and print + +
    +
  • + +
  • + + Declining Expectations + +
    July 22, 2012
    +
    + + Matthew Butterick's talk on declining expectations. + +
    +
  • + +
  • + + Someone is working harder than you + +
    July 19, 2012
    +
    + + Hard work and how to be creative + +
    +
  • + +
  • + + Just Start Over + +
    July 19, 2012
    +
    + + Sebastiaan De With describes his design process for doubleTwist's Alarm Clock + +
    +
  • + +
  • + + A Style Guide, Guide + +
    July 19, 2012
    +
    + + Elyse Holladay reveals her style guide guide. + +
    +
  • + +
  • + + Zen Garden Part 2? + +
    July 18, 2012
    +
    + + Is it time for a Return to the CSS Zen Garden? Rick Monro thinks Responsive Web Design needs it. + +
    +
  • + +
  • + + Pretty Git log + +
    July 18, 2012
    +
    + + Handy tip for pretty git logs. + +
    +
  • + +
  • + + Grow it, don't build it + +
    July 18, 2012
    +
    + + Growing software versus building it + +
    +
  • + +
  • + + Evening Edition + +
    July 18, 2012
    +
    + + The Evening Edition is a great little resource + +
    +
  • + +
  • + + Balancing Devotion + +
    July 17, 2012
    +
    + + Is it possible to create an extraordinary product and have a healthy life outside of that proudct? + +
    +
  • + +
  • + + The web, and my goal + +
    July 12, 2012
    +
    + + Thought from the Pastry Box Project's Bruce Lawson. + +
    +
  • + +
  • + + Nginx www rewrite + +
    July 12, 2012
    +
    + + How to rewrite www to non-www in Nginx + +
    +
  • + +
  • + + My First Bookmarklet + +
    July 12, 2012
    +
    + + My first bookmarklet, an ESPN Insider paywall + +
    +
  • + +
  • + + The Wordpress HTTP API is Awesome + +
    June 28, 2012
    +
    + + The title says it all. I completely forgot about the Wordpress HTTP API until today. + +
    +
  • + +
  • + + Adam versus Dropbox and oAuth + +
    June 25, 2012
    +
    + + Adam versus Dropbox and oAuth. Frustration post incoming regarding curl, php, and oAuth. + +
    +
  • + +
  • + + The Manhattan Project Time-Lapse + +
    June 24, 2012
    +
    + + An incredible time-lapse of Manhattan + +
    +
  • + +
  • + + Hello World + +
    June 24, 2012
    +
    + + I'm proud, nervous, and a little surprised that adamsimpson.net is finally live! + +
    +
  • + +
+
+ +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/post/rss.xml b/themes/cycle/exampleSite/public/post/rss.xml new file mode 100644 index 0000000..e3fe928 --- /dev/null +++ b/themes/cycle/exampleSite/public/post/rss.xml @@ -0,0 +1,738 @@ + + + adamsimpson.net Post Feed + https://adamsimpson.net/ + Last 20 posts for adamsimpson.net + Thu, 09 Oct 2025 21:22:39 +0000 + en-us + + nixpkgs is a treasure + https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ + + https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ + Fri, 10 May 2024 14:07:43 -0400 + + <![CDATA[ Nix and NixOS continue to be the best way to manage and build software that I've found. ]]> + + <![CDATA[ +

Nix and NixOS continue to be the best way to manage and build software that I’ve found. Every project has a shell.nix file in the root where I can define the specific software needed to work on that project along with any necessary environment variables or $PATH modifications. I ran into an issue this week though where I needed an “old” version of Go (1.20) but the version had already been removed from nixpkgs. How can I pull in an “unlisted” version into my shell.nix?

+

It’s actually pretty straightforward, utilize fetchTarball to pull in nixpkgs based on a commit where the version was present sometime in the past. You can mix that import in with regular/“current” packages with no issue like so:

+
{ pkgs ? import <nixpkgs> {} }:
+
+let oldGo = import (builtins.fetchTarball {
+    url = "https://github.com/NixOS/nixpkgs/archive/33c51330782cb486764eb598d5907b43dc87b4c2.tar.gz";
+    sha256 = "sha256:0nflmpfp3pk704vhlvlgh5vgwl8qciqi18mcpl32k79qjziwmih8";
+    }) {};
+in 
+
+pkgs.mkShell {
+  buildInputs = [
+    oldGo.go_1_20
+    pkgs.gopls
+    pkgs.nodejs_18
+  ];
+  
+  hardeningDisable = [ "fortify" ];
+
+  shellHook = ''
+    mkdir -p .go .npm
+    export GOPATH=$PWD/.go
+    export NODE_PATH=$PWD/.npm
+    export NPM_CONFIG_PREFIX=$NODE_PATH
+    export PATH=$PWD/.yarn/sdks/typescript/bin:$PWD/.go/bin:$PATH:$NODE_PATH/bin
+  '';
+}
+

Notice I can reference the “nixpkgs” tarball/snapshot, oldGo, and pull in the version of Go I need?! nixpkgs is such a treasure trove of software, it’s absolutely incredible!

+ + Discuss further in my public inbox + ]]>
+
+ + Lessons learned from integrating OpenAI into a Grafana data source + https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ + + https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ + Tue, 25 Jul 2023 15:10:24 -0400 + + <![CDATA[ I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! ]]> + + <![CDATA[ +

I wrote over on the Grafana blog about a few lessons or observations we learned while integrating OpenAI into the ADX data source. It’s my first post on the Grafana blog and I’m pretty excited, so check it out!

+ + Discuss further in my public inbox + ]]>
+
+ + Better scripting with gh + https://adamsimpson.net/writing/better-scripting-with-gh/ + + https://adamsimpson.net/writing/better-scripting-with-gh/ + Sat, 22 Jul 2023 11:33:16 -0400 + + <![CDATA[ I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. ]]> + + <![CDATA[ +

I’ve become a big fan of the gh CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. Instead of using curl with a Github token and the Github API, I can simply use gh. What’s even better is that in more advanced situations where there isn’t a valid subcommand for what I want to script, I can use the gh api escape hatch to do curl-style HTTP requests to the API without messing with authentication or even pagination. Here are two recent scripts I wrote that highlight the power and convenience of gh.

+

PR Kudos

+

I created this script to help me give better kudos to folks in our retro meeting. When I provide a Github team name as an argument, it displays all PRs from members of that team. What I really like is that it only shows PRs from the last two weeks, which gives me a nice overview of recent activity.

+
#!/bin/bash
+
+start=$(date -d "2 weeks ago" +%Y-%m-%d)
+end=$(date +%Y-%m-%d)
+
+details=$(gh api /orgs/grafana/teams/$1 | jq -r '"\(.id),\(.organization.id)"')
+teamId=$(echo ${details} | cut -d , -f 1)
+orgId=$(echo ${details} | cut -d , -f 2)
+
+gh api "organizations/${orgId}/team/${teamId}/members" | \
+  jq -r '.[] | .login' | \
+  xargs -I % gh search prs --author=% --created="${start}..${end}" \
+  --json="state,repository,url,title,updatedAt,author" --template '{{range .}}{{tablerow (.author.login | autocolor "green") (hyperlink .url .title) (.repository.name | autocolor "blue") (.state | autocolor "red") (timeago .updatedAt)}}{{end}}
+{{tablerender}}'
+

Notification OCD

+

The second script focuses on managing notifications related to pull requests and issues. I usually find that about one-third of my notifications are for merged PRs, PRs created by bots, or closed Issues. I don’t care about these types of events. With this script, I can mark those notifications as done, which reduces clutter in my GitHub notifications and helps me see important updates. As I mentioned above, one cool feature of the api subcommand is that it allows me to consume all possible pages of a response using the --paginate flag, eliminating the need for a loop + token field dance!

+
#!/bin/bash
+declare -A typeLookup
+typeLookup["PullRequest"]="pull"
+typeLookup["Issue"]="issues"
+
+resp=$(gh api /notifications --paginate | jq -r '.[] | select(.subject.type == "PullRequest" or .subject.type == "Issue") | "\(.repository.full_name),\(.subject.url),\(.id),\(.subject.type)"')
+
+for x in $resp; do
+  name=$(echo "${x}" | cut -d ',' -f 1)
+  id=$(echo "${x}" | cut -d ',' -f 3)
+  number=$(basename $(echo "${x}" | cut -d ',' -f 2))
+  ofType=$(echo "${x}" | cut -d ',' -f 4)
+  urlType=$(echo ${typeLookup["${ofType}"]})
+  isBot="false"
+
+  if [ "${ofType}" == "PullRequest" ]; then
+    isMerged=$(gh pr view --repo "${name}" "${number}" --json closed | jq -r .closed)
+    isBot=$(gh pr view --repo "${name}" "${number}" --json author | jq -r .author.is_bot)
+  fi
+
+  if [ "${ofType}" == "Issue" ]; then
+    isMerged=$(gh issue view --repo "${name}" "${number}" --json closed | jq -r .closed)
+  fi
+
+  if [ "${isMerged}" == "true" ] || [ "${isBot}" == "true" ]; then
+    echo "marking https://github.com/${name}/${urlType}/${number} as done..."
+    gh api -X PATCH "/notifications/threads/${id}"
+  fi
+done
+
+ Discuss further in my public inbox + ]]>
+
+ + End of an era + https://adamsimpson.net/writing/end-of-an-era/ + + https://adamsimpson.net/writing/end-of-an-era/ + Thu, 15 Jun 2023 14:13:50 -0400 + + <![CDATA[ Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. ]]> + + <![CDATA[ +

Today I removed two of my most-used apps on my phone, Apollo and Tweetbot. It feels like the end of an era.

+

Twitter and Reddit were both social websites that are/were terrible without a lot of cultivation and effort, but over the years I had shaped my experience on those services to be pretty good thanks in large part to Apollo and Tweetbot being such powerful tools.

+

Ironically the only social web thing I still use (outside of Instagram) is RSS. I will probably spin up a Mastodon instance here eventually but for now I’ve subscribed to folks via Mastodon’s RSS support and it’s good enough for now.

+

I guess I just wanted to give a shout out to the devs of Apollo and Tweetbot: thank you for making such great apps, I will miss them.

+ + Discuss further in my public inbox + ]]>
+
+ + Hacking on Grafana with Web Assembly + https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ + + https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ + Fri, 19 Aug 2022 15:10:19 -0400 + + <![CDATA[ Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. ]]> + + <![CDATA[ + +

The original inspiration for this idea came from Simon Willison’s work with Datasette Lite. However, compiling Grafana as a WASM binary proved difficult with existing build constraints. After spending some time trying to get that to work I changed course a bit and instead focused on compiling a basic go HTTP server as a WASM module. The new goal being to have a proof of concept that bundled the HTTP server as a WASM binary and intercepted any clicked links on the page and finally passed those links to be resolved by the go server in WASM.

+

I used a Web Worker to interact with the WASM binary. This frees up the main thread of the browser. To put the WASM binary into the worker I loaded the binary and sent a message that contained the binary as a WebAssembly.Module.

+

The Web Worker can then call any go functions that have been exposed via FuncOf. Once the go function returns data, the worker posts that response back to the main thread via another message.

+
let module;
+importScripts("wasm_exec.js")
+go = new Go();
+
+self.onmessage = async (e) => {
+  if (e.data.type === "module") {
+    module = e.data.module;
+    return;
+  }
+
+  if (module) {
+    console.log('Message received: ', e.data.path);
+    const instance = await WebAssembly.instantiate(module, go.importObject);
+    go.run(instance);
+    postMessage(parsePath(e.data.path)); // parsePath is exposed via FuncOf
+  }
+}
+

Sidenote: I wish go could use the same pragma syntax tinygo uses to expose functions instead of the verbose FuncOf. There’s an issue but it has been open since 2018.

+

Obviously, there is no localhost to listen on in a WASM environment. To get around that I created a bare bones ResponseWriter and used that with the Request to run the Handler’s ServeHTTP function which consults the routes that are defined and runs the matching handler code. This allowed me to use a build constraint (setup.go and setup_js.go) and keep my HTTP server functioning normally when run from a terminal but then also worked when run in a WASM context. Here’s what those two files look like:

+

setup

+
//go:build !js
+// +build !js
+
+package main
+
+import (
+	"fmt"
+	"net/http"
+)
+
+func setup() {
+	s := NewServer()
+	err := http.ListenAndServe(":9001", s.mux)
+	if err != nil {
+		fmt.Println("error: ", err)
+	}
+}
+

setup_js

+
package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"syscall/js"
+)
+
+type ResponseWriter struct {
+	Body *bytes.Buffer
+}
+
+func (r ResponseWriter) Header() http.Header {
+	return make(http.Header)
+}
+
+func (r ResponseWriter) Write(buf []byte) (int, error) {
+	if r.Body != nil {
+		r.Body.Write(buf)
+	}
+	return len(buf), nil
+}
+
+func (r ResponseWriter) WriteHeader(statusCode int) {}
+
+func createWriter() ResponseWriter {
+	return ResponseWriter{
+		Body: new(bytes.Buffer),
+	}
+}
+
+func parsePath(this js.Value, args []js.Value) interface{} {
+	fmt.Println("args: ", args)
+	server := NewServer()
+	path := args[0].String()
+	req, err := http.NewRequest(http.MethodGet, path, nil)
+
+	if err != nil {
+		fmt.Println("request error: ", err)
+	}
+
+	h, p := server.mux.Handler(req)
+
+	fmt.Println("pattern: ", p)
+
+	w := createWriter()
+
+	h.ServeHTTP(w, req)
+
+	b, err := ioutil.ReadAll(w.Body)
+
+	if err != nil {
+		fmt.Println("ioutil error: ", err)
+	}
+
+	return string(b)
+}
+
+func setup() {
+	js.Global().Set("parsePath", js.FuncOf(parsePath))
+}
+

Conclusions

+

The PoC worked! It’s pretty slick to see a HTTP server running in WASM return back the correct data when a link is clicked. However, in my opinion, WASM continues to be a “solution in search of a problem”. Yes it’s incredibly cool technology but so are the JS engines in Chrome, Firefox, and Safari. The sheer amount of money and engineering time being spent on making JS fast is a race no other technology can win at the moment.

+

That said, Go seems to have done decent work at providing the necessary pieces to make compiling to WASM not awful.

+

Honestly, the thing that surprised and impressed me the most was working with Web Workers. They are seriously useful and seem to “just work”.

+ + + + Discuss further in my public inbox + ]]>
+
+ + New workstation + https://adamsimpson.net/writing/new-workstation/ + + https://adamsimpson.net/writing/new-workstation/ + Mon, 02 May 2022 18:14:25 +0000 + + <![CDATA[ I detail my new workstation build featuring the Intel i5-12600k. ]]> + + <![CDATA[ +

New job means time for a new workstation.

+

Some history

+

The first computer I ever purchased was the 12" Powerbook G4. Since that Powerbook I’ve always had laptops as my main machines (desktop gaming PC not withstanding). Remote working the last few years has made me realize that the portability of a laptop is largely wasted since I only travel a handful of times a year and yet I live with the downsides of a laptop the rest of the time. So, last year I started thinking about a desktop machine for my primary workstation. A desktop is appealing for a handful of reasons:

+
    +
  • More powerful CPUs
  • +
  • More expansion capabilities
  • +
  • More durable
  • +
+

The options

+

The Mac Studio was recently released to much fanfare and was really intriguing to me. However, when I started considering it I only had about a week to 10 days before my start date at Grafana and I couldn’t wait the quoted 4-6 weeks delivery time for a Mac Studio with 32GB of RAM.

+

I was also pretty unwilling to leave my comfy NixOS install + i3. Michael Stapelberg’s latest post about his new workstation proved timely and convinced me to give the new Intel Alder Lake CPUs a shot.

+

Apple’s M1 family of chips deliver incredible performance per watt but I wasn’t as concered about the power usage given this was a desktop machine not a laptop. I was however focused on at least matching the M1 chips in single-threaded performance since a good chunk of my development work (Node, build tools, etc) are still single-threaded. I ended up with the Intel i5-12600k and I really couldn’t be happier. Here’s the full parts list:

+ +

XMP issues

+

I ran into the same memory XMP issues that Michael mentions in his post so I disabled the XMP profile and the system passed the “Coding Horror burn in tests” with flying colors.

+

Cooling

+

I mounted the 140mm fan to the bottom of the case as intake and the CPU cooler is of course positioned as intake as well. Hot air rises out the top of the case quite well. During the prime95 torture test the CPU never got over 78°C and I couldn’t ever hear either fan. I run both fans in the “silent profile” in the BIOS and I use Noctua’s adapters to lower the voltage even more. Now the only fan I could hear during max load was the PSU fan which doesn’t spin at all under low to medium loads but under high load it kicks on. Day to day it’s hardly on so the system is dead quiet most of the time.

+

Case

+

I absolutely love the Cerberus case. It’s Mini-ATX but still super compact and fits on my desk quite well. All the panels are solid metal and the way all the panels pop off is really really nice. I opted for the handle mount on the top and the internal PSU moutning.

+

Linux

+

NixOS installed just fine. I’m runing the 5.17 kernel because Alder Lake needs a newer kernel for it’s graphics and CPU scheduler (coming soon?). I have WiFi and Bluetooh disabled in the BIOS since everything is hard-wired to the machine.

+

Verdict

+

This build has proven quite comfortable over the few weeks I’ve used it. I love that I have 2 free RAM slots if I ever feel the need for more RAM. I also love that I have 3 remaining Nvme slots on the motherboard for additional solid state storage in the future.

+ + Discuss further in my public inbox + ]]>
+
+ + 👋 Sparkbox + https://adamsimpson.net/writing/goodbye-sparkbox/ + + https://adamsimpson.net/writing/goodbye-sparkbox/ + Fri, 01 Apr 2022 18:20:31 +0000 + + <![CDATA[ I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. ]]> + + <![CDATA[ +

I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox.

+

Now, I know it can be problematic to think about work like your (extended) family but when you work at the same place through your twenties and early thirties, have 3 different apartments, buy a house, and have two kids it’s impossible not to view that place differently. I can confidently say Sparkbox changed my life. The team there will always have a special place in my heart.

+

deep breath

+

So where to? Well, I’m super stoked to be joining Grafana as a Senior Software Engineer on their Cloud Data team! I’m looking forward to writing more Go, solving new problems, and learning from the stellar folks there.

+

Here we go…

+ + Discuss further in my public inbox + ]]>
+
+ + Thirty five + https://adamsimpson.net/writing/thirty-five/ + + https://adamsimpson.net/writing/thirty-five/ + Thu, 03 Mar 2022 10:28:44 -0500 + + <![CDATA[ It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. ]]> + + <![CDATA[ +

Well crap.

+

It’s been 5 years since I wrote “Thirty”. So now I have to come up with 35 things as I turned 35 yesterday. If anything from Thirty is grossly wrong or really interesting I’ll update it at the same number eh?

+

Let’s go…

+
    +
  1. I still don’t have it figured out, but this isn’t such a shock anymore.
  2. +
  3. Building a house is more scary.
  4. +
  5. Minivans are awesome.
  6. +
  7. Expecting a third kid is not nearly as scary as expecting the first.
  8. +
  9. COVID sucked.
  10. +
  11. Modern medicine is pretty cool actually.
  12. +
  13. More stuff hurts, still just as healthy.
  14. +
  15. Dishwashers aren’t really as scary to repair as they seem (but that doesn’t mean you won’t lose your mind fixing one).
  16. +
  17. The feeling you get as a parent when your kid gets hurt is impossible to describe.
  18. +
  19. Being knocked out from a crazy car accident is also no fun.
  20. +
  21. Carseats are magic.
  22. +
  23. I’ve accepted that the music I liked in 2010 is going to be the music I’ll like forever.
  24. +
  25. Thanks to the internet there is an endless stream of new music that is at home with music from 2010 or even 2000 (Underoath just released a new album for crying out loud).
  26. +
  27. Open source software is incredible.
  28. +
  29. The thrill from in-progress software working for the first time will never get old for me.
  30. +
  31. Feedback loops are important in every area of life not just software.
  32. +
  33. The year of Linux on the desktop is a moving target.
  34. +
  35. RSS will never die.
  36. +
  37. Mechanical keyboards are a refreshing change and I’m not sure why.
  38. +
  39. The Aeropress is still incredible.
  40. +
  41. Computers were a mistake.
  42. +
  43. Computers are a miracle.
  44. +
  45. The Three-Body Problem trilogy continues to knock around in my brain months after finishing it.
  46. +
  47. Watching your child accomplish something for the first time that they’ve been working on is a feeling unlike any other.
  48. +
  49. I’ve realized I learn best by doing, I need to get better at accounting for the bumps along the way.
  50. +
  51. I write things down to remember them later not to look them up later which means most note systems are not worth the trouble for me.
  52. +
  53. Life will be shallow if you only hang out with people like you.
  54. +
  55. Anything is possible on an infinite timescale the trick is figuring out what do with finite time.
  56. +
  57. RIP Rdio.
  58. +
  59. Never pass on an opportunity to twirl your kids around when they’re small. They get big fast.
  60. +
  61. Hanlon’s razor explains most of social media.
  62. +
  63. If you work at a desk all day you owe it to yourself to remove as much Bluetooth from that setup as possible.
  64. +
  65. None of your peers has it all figured out. Ask them “dumb” questions.
  66. +
  67. Properly evaluating risks when your kids are involved is hard.
  68. +
  69. Keep a sweatshirt handy by your bed when your kids are young, getting up at 2am in the winter is cold.
  70. +
+

❤️ you Christi

+ + Discuss further in my public inbox + ]]>
+
+ + Windows 11 as KVM guest + https://adamsimpson.net/writing/windows-11-as-kvm-guest/ + + https://adamsimpson.net/writing/windows-11-as-kvm-guest/ + Mon, 28 Feb 2022 13:39:37 -0500 + + <![CDATA[ How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. ]]> + + <![CDATA[ +

Windows 11 famously has new, stricter requirements for installation; a TPM device and Secure Boot. Here’s how I satisfied those requirements with Windows 11 as a KVM guest with NixOS as the host. The following is pulled from my NixOS configuration.nix:

+
libvirtd.qemu = {
+  package = pkgs.qemu_kvm;
+  runAsRoot = true;
+  swtpm.enable = true;
+  ovmf = {
+    enable = true;
+    package = (pkgs.OVMFFull.override {
+      secureBoot = true;
+      tpmSupport = true;
+    });
+  };
+};
+

The most important bit is the pkgs.OVMFFull.override section where you must specify tpmSupport and secureBoot as true.

+

In virt-manager you’ll need to add “new hardware” and select TPM v2.0. Here’s the relevant XML from my config:

+
<tpm model="tpm-crb">
+  <backend type="emulator" version="2.0"/>
+</tpm>
+

With the above settings you should be able to go through the Windows 11 installer and get the machine up and running as a KVM guest.

+

Stretch goal: nested virtualization

+

If you want to use Docker or WSL 2 inside KVM you’ll need to enable “nested virtualization” in virt-manager. I couldn’t figure this out until I found this great answer on superuser.

+

My original CPU config XML looked like this:

+
<cpu mode="host-model" check="partial">
+  <topology sockets="1" dies="1" cores="2" threads="4"/>
+</cpu>
+

The new XML looks like this:

+
<cpu mode="custom" match="exact" check="partial">
+  <model fallback="allow">Skylake-Client-noTSX-IBRS</model>
+  <topology sockets="1" dies="1" cores="2" threads="4"/>
+  <feature policy="disable" name="hypervisor"/>
+  <feature policy="require" name="vmx"/>
+</cpu>
+

With this applied I could install WSL2 and get Docker Desktop for Windows installed and running.

+ + Discuss further in my public inbox + ]]>
+
+ + A few POSIX shell tips + https://adamsimpson.net/writing/a-few-posix-shell-tips/ + + https://adamsimpson.net/writing/a-few-posix-shell-tips/ + Mon, 19 Jul 2021 14:53:16 -0400 + + <![CDATA[ I wrote down a few of my most used POSIX shell commands and features. ]]> + + <![CDATA[ +

I was recently working on the release build script for sb and decided I should document a few things I find myself looking up just about every time. One of the advantages of the POSIX shell (not bash, zsh, but Bourne shell, usually /bin/sh on most unix-y systems) is that it has a specification however I’m usually frustrated trying to find the information I need.

+ +

You can check it out here: https://github.com/sparkbox/sb

+ +

I prefer the POSIX shell because it’s the default on most unix-y system. If I have to be sure if the shell is installed on the target system (like bash or zsh) I’d rather just use a higher-level scripting language like node or ruby where the same requirement exists.

+

Arrays

+

Psych! There aren’t any arrays. Bash has arrays but POSIX does not. If I need an array structure I can use a space-separated string (or another delimiter if you’ve set $IFS) as the data structure, e.g. PLATFORMS="arm64-darwin amd64-linux amd64-darwin". Now I can loop over the variable using a for loop:

+
PLATFORMS="arm64-darwin amd64-linux amd64-darwin"
+
+for PLATFORM in ${PLATFORMS}; do
+  # GOOS=FOO GOARCH=BAR go build ...
+done
+

Or I can take the lack of arrays as a signal I should stop writing a shell script and reach for a language that has the concept of arrays to solve my problem.

+

Conditional “flags”

+

I often forget the various flags one can use in a conditional (aka test/if) statement. Here’s the documentation and here are a few of my favorites:

+
    +
  • -n tests if the string is non-zero, e.g.
  • +
+
if [ -n "${UPLOAD_URL}" ]; then
+    upload_file "${PLATFORM}"
+fi
+
    +
  • -z the opposite of -n.
  • +
  • -f tests if the pathname resolves to a file.
  • +
+

Functions and args

+
    +
  • Functions must be declared before they are invoked.
  • +
  • Functions look like:
  • +
+
someFunc() {
+  echo "a func!"
+}
+
    +
  • There is no syntax for functions accepting args instead they are mapped to $n. $@ is all the args.
  • +
+
upload_file() {
+    NAME=$1
+
+    zip "${NAME}.zip" "${NAME}"
+    curl -H "Accept: application/vnd.github.v3+json" \
+         -H "Authorization: Bearer ${GITHUB_TOKEN}" \
+         -H "Content-Type: application/zip" \
+         --data-binary "@${NAME}.zip" \
+         "${UPLOAD_URL}?name=${NAME}.zip"
+}
+
+upload_file "${PLATFORM}"
+

Use shellcheck

+

This is just preference but I really love using shellcheck to avoid any footguns and enforce a consistent style with my shell scripts. I typically invoke it like this: shellcheck -o all script-name.sh.

+ + Discuss further in my public inbox + ]]>
+
+ + Recently + https://adamsimpson.net/writing/recently-16/ + + https://adamsimpson.net/writing/recently-16/ + Fri, 23 Apr 2021 11:37:19 -0400 + + <![CDATA[ A random assortment of links and miscellaneous updates on things. ]]> + + <![CDATA[ +

I’m stealing the title format of this post from Tom MacWright’s Recently posts.

+

Here’s a random assortment of links and miscellaneous updates on things.

+

autofs

+

autofs is a cool utility that watches a specific directory path and when a program tries to read or write to that path it mounts a filesystem at that location. I’m using this to auto mount my NAS via SMB for mpd. With autofs in place I can run mpd locally (in a “satellite setup”) and have its music_directory point to a path managed by autofs.

+

One thing that was helpful getting the configuration right was testing autofs by running automount -f -v directly which puts it in the foreground and gives verbose output.

+

The two files I configured were auto.master.d/foo.autofs and auto.foo.

+
    +
  • foo.autofs contains one line: /- /etc/auto.foo
  • +
  • auto.foo contains one line as well: /foo -fstype=cifs,rw,credentials=/home/me/.foo-creds ://NAS.IP/foo
  • +
+

mailpreview updates

+

mailpreview-cli is a little program I use multiple times a day to quickly see my unread email without moving from what I’m currently working on and without touching my mouse. I recently noticed it wasn’t grabbing the body of a specific type of email. In the process of fixing that I also added proper unit tests for every format I currently parse through. Yay faster feedback loops!

+

ffmpeg

+

I’ve been a fan of OBS for awhile now. I was recently doing a quick screen recording of my browser window and the browser window wasn’t full-screen so there were black bars around the edges of the recording. I didn’t love that but it’s time to touch the “ffmpeg exists and is awesome” sign again.

+

This superuser post has the answer which consists of two steps:

+
    +
  1. Get the crop parameters of the video from ffmpeg. ffmpeg will detect the black borders and report back the actual content coordinates. +ffmpeg.exe -i '.\some-video.mkv' -vf cropdetect -f null -
  2. +
  3. Re-encode and crop using the crop parameters to trim the borders. +ffmpeg.exe -i '.\some-video.mkv' -vf crop=624:704:332:10 -c:a copy output.mp4
  4. +
  5. Enjoy your pristine video.
  6. +
+ + +

Fin

+ + Discuss further in my public inbox + ]]>
+
+ + A firewall in 8 lines + https://adamsimpson.net/writing/8-line-firewall/ + + https://adamsimpson.net/writing/8-line-firewall/ + Wed, 31 Mar 2021 11:18:24 -0400 + + <![CDATA[ You only need about 8 lines in iptables to have a great home firewall. ]]> + + <![CDATA[ +

Since 2017 my home router has been a plain x86 box running Alpine Linux. I never really think about it anymore. Recently, I was helping a relative set up their own Linux-based router and took the time to appreciate how little config is needed to setup a serviceable home router firewall using iptables. You can see my base rule-sets (port forwarding omitted) below:

+
-P INPUT DROP
+-P FORWARD DROP
+-P OUTPUT ACCEPT
+-A INPUT -i lo -j ACCEPT
+-A INPUT -i eth1 -j ACCEPT
+-A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+-A FORWARD -i eth1 -o eth0 -j ACCEPT
+-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+

The benefit of running a x86 box with Alpine (or any version of Linux) is that the box will receive a steady stream of security updates and upgraded kernels as Alpine Linux releases new versions. This is a much better situation to be in than relying on OS and security updates from a vendor like TPLink or Linksys.

+

If you have ideas for how to improve the config I listed above or want to chat more about home network stuff, send an email to my public-inbox.

+ + Discuss further in my public inbox + ]]>
+
+ + How to use Siji font on polybar + https://www.reddit.com/r/Polybar/comments/ht0jnr/guide_how_to_use_the_siji_font_on_polybar/ + + https://adamsimpson.net/writing/how-to-use-siji-font-on-polybar/ + Fri, 06 Nov 2020 11:18:47 -0500 + <![CDATA[ +

Nice guide on Reddit about how to use the Siji font with polybar.

+
+

[..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

+
+

Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

+ + 🔗 + Discuss further in my public inbox + ]]>
+
+ + On Polybar bitmap fonts and Ubuntu + https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ + + https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ + Fri, 06 Nov 2020 10:15:09 -0500 + + <![CDATA[ Enable bitmap fonts on Ubuntu for an optimal polybar experience. ]]> + + <![CDATA[ +

I use polybar as my status bar in i3 and it’s been going great for months now. However, I was recently grepping through the syslog trying to figure out why a browser crash happened and the log was filled with polybar spam that looked like this: polybar|warn: Dropping unmatched character. So I started picking at solving the warning.

+

Turns out there’s a Github issue that contains the solution which is to enable bitmap fonts which I’ll paste here for posterity:

+
# "Un-disable" bitmap fonts
+sudo rm /etc/fonts/conf.d/70-no-bitmaps.conf
+# Clear the font cache
+sudo fc-cache -f -v
+

Apparently Ubuntu disables bitmap fonts by default but polybar uses bitmap fonts for icon rendering. I also needed to install the sijj icon font family which was painless.

+ + Discuss further in my public inbox + ]]>
+
+ + Recently + https://adamsimpson.net/writing/recently-44/ + + https://adamsimpson.net/writing/recently-44/ + Tue, 27 Oct 2020 23:30:46 -0400 + + <![CDATA[ I've written a few small tools over the last couple months and I figured it's time I post about them. ]]> + + <![CDATA[ +

I’ve published a few new projects in the last couple of months and I’m behind on announcing them, so I bundled them up together into this post. I’m stealing the title format of this post from Tom MacWright’s Recently posts.

+

One thing to note is that the source code for all these projects is stored on sourcehut. Sourcehut (or sr.ht) bills itself as “the hacker’s forge”. I highly recommend checking it out. It’s also where I host my public inbox.

+

hover-dns

+

Now that I have fiber internet at the house I’ve been hosting one-off services and apps on my own hardware at the house. This is great, however my residential connection is a typical dynamic IP not a static one. Instead of using a service like DynamicDNS I decided to write some Rust (shocker) and leverage the “unofficial” Hover API. The result is: hover-dns.

+

I have hover-dns running in a crontab for a few different domains to keep my domains pointed to the correct IP for my house. While I’m a little uncomfortable with how similar npm and cargo can feel, the trust-dns package is excellent. I was able to quickly read the source code to understand how to setup a Resolver for opendns. Also impressive is that hover-dns ip beats out dig in returning your public IP. I didn’t expect that!

+

podcastfilter

+

Speaking of hosting things at home, podcastfilter.com is one of those things. podcast-filter is a small Go project that allows you to filter a podcast feed by each episode’s description and return a feed of just those episodes that match.

+

mailpreview

+

The recent project I use the most day-to-day is mailpreview-cli. mailpreview-cli is very straight-forward, it accepts a Mail message and returns either the plain text version or the html version of that message. The reason I don’t just pull the Mail message directly is because a Mail message can contain several versions of the message in different encodings (start here if you’re curious: RFC-822). Instead of writing my own parser I grabbed the excellent mailparse crate and wrapped the behavior I wanted around it. On it’s own mailpreview-cli isn’t super fancy but I trigger it from rofi via a shell script which allows me to browse (and then view) all my unread emails right from rofi. Shameless plug: I wrote a short post about getting started with rofi if you’re unfamiliar. mailpreview-cli could be used with Alfred if you’re on a Mac to accomplish the same thing as I’m doing with a shell script and rofi.

+

Fin

+ + Discuss further in my public inbox + ]]>
+
+ + Four ways to approach Hacktoberfest 2020 + https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ + + https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ + Thu, 01 Oct 2020 10:26:38 -0400 + + <![CDATA[ I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. ]]> + + <![CDATA[ +

Hacktoberfest 2020 is here! I can’t believe 2020 is winding down, good riddance!

+

I’ve been talking about Hacktoberfest with my co-worker Bryan and I thought of four different approaches to Hacktoberfest this year that I wanted to share.

+ +

Dependency scrub

+

This is probably common everywhere but the Javascript/web communities are filled with npm packages. It’s packages all the way down. I think it would be interesting to approach this month looking for ways to remove third-party code from projects you love and use frequently.

+

Polygot Achievement

+

Try to submit four pull requests in four different languages. As Drew DeVault writes: Hack everything without fear!

+

Unknown lands

+

Similar to the previous one it could be fun to submit PRs against a project you’ve never been in before that’s in a language you don’t know. This could be anything from diving into Wordpress core, to working on some C for some Linux utilities, or even submitting PRs to open source Mac/iOS applications.

+

Bug doctor

+

Go into a project and find the oldest issues and try to resolve them via PR. This is inspired by Richard Schneeman’s video and post where he runs through 11 issues and 2 PRs in a hour and a half.

+

How are you approaching Hacktoberfest this year? My public inbox is open, let me know!

+ + Discuss further in my public inbox + ]]>
+
+ + Small tech + https://scattered-thoughts.net/writing/small-tech/ + + https://adamsimpson.net/writing/small-tech/ + Fri, 25 Sep 2020 15:53:06 -0400 + <![CDATA[ +

Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

+
    +
  • +

    curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

    +
  • +
  • +

    git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

    +
  • +
  • +

    Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

    +
  • +
  • +

    sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

    +
  • +
+ + 🔗 + Discuss further in my public inbox + ]]>
+
+ + Indexing My Blog’s Links + https://blog.jim-nielsen.com/2020/indexing-my-blogs-links/ + + https://adamsimpson.net/writing/indexing-my-blogs-links/ + Fri, 25 Sep 2020 15:49:21 -0400 + <![CDATA[ +

Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

+ + 🔗 + Discuss further in my public inbox + ]]>
+
+ + Compose key and i3 + https://adamsimpson.net/writing/compose-key-and-i3/ + + https://adamsimpson.net/writing/compose-key-and-i3/ + Fri, 18 Sep 2020 11:28:19 -0400 + + <![CDATA[ Here's how to bind the compose key to caps lock in i3wm. ]]> + + <![CDATA[ +

The compose key on Linux and other systems enables you to enter symbols like ™ that don’t have a dedicated key on most keyboards. GNOME makes this easy to do via Gnome Tweaks. However, using a window manager like i3 means there’s no dedicated GUI for changing the hotkey for compose.

+

This stackexchange answer sent me down the right path of adding the following config to ~/.Xmodmap to bind Caps lock to compose:

+
.keysym 66 = Mode_switch
+clear Lock
+

You can then enable the key map by running:

+
xmodmap ~/.Xmodmap
+

However, that config didn’t work because Mode_switch wasn’t the right name for the compose key (at least under Ubuntu/PopOS 20 for me). The Arch Wiki states that the name for the compose key is actually Multi_key. With this new name I was able to get Caps lock to act as the compose key by updating the config in ~/.Xmodmap to:

+
keycode 66 = Multi_key
+clear Lock
+

The final step is to set that mapping every time i3 runs by putting this inside your i3 config file like so:

+
exec --no-startup-id "xmodmap ~/.Xmodmap"
+
+ Discuss further in my public inbox + ]]>
+
+ + cycle v0.3.0 released + https://adamsimpson.net/writing/cycle-v030-released/ + + https://adamsimpson.net/writing/cycle-v030-released/ + Fri, 11 Sep 2020 12:04:16 -0400 + + <![CDATA[ Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. ]]> + + <![CDATA[ +

I just released v0.3.0 of cycle.

+

This version uses Chroma for syntax highlighting instead of Pygments. I never got Pygments running correctly in Netlify’s build environment. Chroma requires no dependencies since it’s distributed as a static binary and it’s also faster due to being written in golang.

+

This version also refactors the main function to accept an optional working directory arg. This allows me to build a site via the CL REPL. It also shortens the feedback loop to try out new features.

+ + Discuss further in my public inbox + ]]>
+
+
+
diff --git a/themes/cycle/exampleSite/public/rss.xml b/themes/cycle/exampleSite/public/rss.xml new file mode 100644 index 0000000..e3fe928 --- /dev/null +++ b/themes/cycle/exampleSite/public/rss.xml @@ -0,0 +1,738 @@ + + + adamsimpson.net Post Feed + https://adamsimpson.net/ + Last 20 posts for adamsimpson.net + Thu, 09 Oct 2025 21:22:39 +0000 + en-us + + nixpkgs is a treasure + https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ + + https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ + Fri, 10 May 2024 14:07:43 -0400 + + <![CDATA[ Nix and NixOS continue to be the best way to manage and build software that I've found. ]]> + + <![CDATA[ +

Nix and NixOS continue to be the best way to manage and build software that I’ve found. Every project has a shell.nix file in the root where I can define the specific software needed to work on that project along with any necessary environment variables or $PATH modifications. I ran into an issue this week though where I needed an “old” version of Go (1.20) but the version had already been removed from nixpkgs. How can I pull in an “unlisted” version into my shell.nix?

+

It’s actually pretty straightforward, utilize fetchTarball to pull in nixpkgs based on a commit where the version was present sometime in the past. You can mix that import in with regular/“current” packages with no issue like so:

+
{ pkgs ? import <nixpkgs> {} }:
+
+let oldGo = import (builtins.fetchTarball {
+    url = "https://github.com/NixOS/nixpkgs/archive/33c51330782cb486764eb598d5907b43dc87b4c2.tar.gz";
+    sha256 = "sha256:0nflmpfp3pk704vhlvlgh5vgwl8qciqi18mcpl32k79qjziwmih8";
+    }) {};
+in 
+
+pkgs.mkShell {
+  buildInputs = [
+    oldGo.go_1_20
+    pkgs.gopls
+    pkgs.nodejs_18
+  ];
+  
+  hardeningDisable = [ "fortify" ];
+
+  shellHook = ''
+    mkdir -p .go .npm
+    export GOPATH=$PWD/.go
+    export NODE_PATH=$PWD/.npm
+    export NPM_CONFIG_PREFIX=$NODE_PATH
+    export PATH=$PWD/.yarn/sdks/typescript/bin:$PWD/.go/bin:$PATH:$NODE_PATH/bin
+  '';
+}
+

Notice I can reference the “nixpkgs” tarball/snapshot, oldGo, and pull in the version of Go I need?! nixpkgs is such a treasure trove of software, it’s absolutely incredible!

+ + Discuss further in my public inbox + ]]>
+
+ + Lessons learned from integrating OpenAI into a Grafana data source + https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ + + https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ + Tue, 25 Jul 2023 15:10:24 -0400 + + <![CDATA[ I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! ]]> + + <![CDATA[ +

I wrote over on the Grafana blog about a few lessons or observations we learned while integrating OpenAI into the ADX data source. It’s my first post on the Grafana blog and I’m pretty excited, so check it out!

+ + Discuss further in my public inbox + ]]>
+
+ + Better scripting with gh + https://adamsimpson.net/writing/better-scripting-with-gh/ + + https://adamsimpson.net/writing/better-scripting-with-gh/ + Sat, 22 Jul 2023 11:33:16 -0400 + + <![CDATA[ I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. ]]> + + <![CDATA[ +

I’ve become a big fan of the gh CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. Instead of using curl with a Github token and the Github API, I can simply use gh. What’s even better is that in more advanced situations where there isn’t a valid subcommand for what I want to script, I can use the gh api escape hatch to do curl-style HTTP requests to the API without messing with authentication or even pagination. Here are two recent scripts I wrote that highlight the power and convenience of gh.

+

PR Kudos

+

I created this script to help me give better kudos to folks in our retro meeting. When I provide a Github team name as an argument, it displays all PRs from members of that team. What I really like is that it only shows PRs from the last two weeks, which gives me a nice overview of recent activity.

+
#!/bin/bash
+
+start=$(date -d "2 weeks ago" +%Y-%m-%d)
+end=$(date +%Y-%m-%d)
+
+details=$(gh api /orgs/grafana/teams/$1 | jq -r '"\(.id),\(.organization.id)"')
+teamId=$(echo ${details} | cut -d , -f 1)
+orgId=$(echo ${details} | cut -d , -f 2)
+
+gh api "organizations/${orgId}/team/${teamId}/members" | \
+  jq -r '.[] | .login' | \
+  xargs -I % gh search prs --author=% --created="${start}..${end}" \
+  --json="state,repository,url,title,updatedAt,author" --template '{{range .}}{{tablerow (.author.login | autocolor "green") (hyperlink .url .title) (.repository.name | autocolor "blue") (.state | autocolor "red") (timeago .updatedAt)}}{{end}}
+{{tablerender}}'
+

Notification OCD

+

The second script focuses on managing notifications related to pull requests and issues. I usually find that about one-third of my notifications are for merged PRs, PRs created by bots, or closed Issues. I don’t care about these types of events. With this script, I can mark those notifications as done, which reduces clutter in my GitHub notifications and helps me see important updates. As I mentioned above, one cool feature of the api subcommand is that it allows me to consume all possible pages of a response using the --paginate flag, eliminating the need for a loop + token field dance!

+
#!/bin/bash
+declare -A typeLookup
+typeLookup["PullRequest"]="pull"
+typeLookup["Issue"]="issues"
+
+resp=$(gh api /notifications --paginate | jq -r '.[] | select(.subject.type == "PullRequest" or .subject.type == "Issue") | "\(.repository.full_name),\(.subject.url),\(.id),\(.subject.type)"')
+
+for x in $resp; do
+  name=$(echo "${x}" | cut -d ',' -f 1)
+  id=$(echo "${x}" | cut -d ',' -f 3)
+  number=$(basename $(echo "${x}" | cut -d ',' -f 2))
+  ofType=$(echo "${x}" | cut -d ',' -f 4)
+  urlType=$(echo ${typeLookup["${ofType}"]})
+  isBot="false"
+
+  if [ "${ofType}" == "PullRequest" ]; then
+    isMerged=$(gh pr view --repo "${name}" "${number}" --json closed | jq -r .closed)
+    isBot=$(gh pr view --repo "${name}" "${number}" --json author | jq -r .author.is_bot)
+  fi
+
+  if [ "${ofType}" == "Issue" ]; then
+    isMerged=$(gh issue view --repo "${name}" "${number}" --json closed | jq -r .closed)
+  fi
+
+  if [ "${isMerged}" == "true" ] || [ "${isBot}" == "true" ]; then
+    echo "marking https://github.com/${name}/${urlType}/${number} as done..."
+    gh api -X PATCH "/notifications/threads/${id}"
+  fi
+done
+
+ Discuss further in my public inbox + ]]>
+
+ + End of an era + https://adamsimpson.net/writing/end-of-an-era/ + + https://adamsimpson.net/writing/end-of-an-era/ + Thu, 15 Jun 2023 14:13:50 -0400 + + <![CDATA[ Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. ]]> + + <![CDATA[ +

Today I removed two of my most-used apps on my phone, Apollo and Tweetbot. It feels like the end of an era.

+

Twitter and Reddit were both social websites that are/were terrible without a lot of cultivation and effort, but over the years I had shaped my experience on those services to be pretty good thanks in large part to Apollo and Tweetbot being such powerful tools.

+

Ironically the only social web thing I still use (outside of Instagram) is RSS. I will probably spin up a Mastodon instance here eventually but for now I’ve subscribed to folks via Mastodon’s RSS support and it’s good enough for now.

+

I guess I just wanted to give a shout out to the devs of Apollo and Tweetbot: thank you for making such great apps, I will miss them.

+ + Discuss further in my public inbox + ]]>
+
+ + Hacking on Grafana with Web Assembly + https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ + + https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ + Fri, 19 Aug 2022 15:10:19 -0400 + + <![CDATA[ Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. ]]> + + <![CDATA[ + +

The original inspiration for this idea came from Simon Willison’s work with Datasette Lite. However, compiling Grafana as a WASM binary proved difficult with existing build constraints. After spending some time trying to get that to work I changed course a bit and instead focused on compiling a basic go HTTP server as a WASM module. The new goal being to have a proof of concept that bundled the HTTP server as a WASM binary and intercepted any clicked links on the page and finally passed those links to be resolved by the go server in WASM.

+

I used a Web Worker to interact with the WASM binary. This frees up the main thread of the browser. To put the WASM binary into the worker I loaded the binary and sent a message that contained the binary as a WebAssembly.Module.

+

The Web Worker can then call any go functions that have been exposed via FuncOf. Once the go function returns data, the worker posts that response back to the main thread via another message.

+
let module;
+importScripts("wasm_exec.js")
+go = new Go();
+
+self.onmessage = async (e) => {
+  if (e.data.type === "module") {
+    module = e.data.module;
+    return;
+  }
+
+  if (module) {
+    console.log('Message received: ', e.data.path);
+    const instance = await WebAssembly.instantiate(module, go.importObject);
+    go.run(instance);
+    postMessage(parsePath(e.data.path)); // parsePath is exposed via FuncOf
+  }
+}
+

Sidenote: I wish go could use the same pragma syntax tinygo uses to expose functions instead of the verbose FuncOf. There’s an issue but it has been open since 2018.

+

Obviously, there is no localhost to listen on in a WASM environment. To get around that I created a bare bones ResponseWriter and used that with the Request to run the Handler’s ServeHTTP function which consults the routes that are defined and runs the matching handler code. This allowed me to use a build constraint (setup.go and setup_js.go) and keep my HTTP server functioning normally when run from a terminal but then also worked when run in a WASM context. Here’s what those two files look like:

+

setup

+
//go:build !js
+// +build !js
+
+package main
+
+import (
+	"fmt"
+	"net/http"
+)
+
+func setup() {
+	s := NewServer()
+	err := http.ListenAndServe(":9001", s.mux)
+	if err != nil {
+		fmt.Println("error: ", err)
+	}
+}
+

setup_js

+
package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"syscall/js"
+)
+
+type ResponseWriter struct {
+	Body *bytes.Buffer
+}
+
+func (r ResponseWriter) Header() http.Header {
+	return make(http.Header)
+}
+
+func (r ResponseWriter) Write(buf []byte) (int, error) {
+	if r.Body != nil {
+		r.Body.Write(buf)
+	}
+	return len(buf), nil
+}
+
+func (r ResponseWriter) WriteHeader(statusCode int) {}
+
+func createWriter() ResponseWriter {
+	return ResponseWriter{
+		Body: new(bytes.Buffer),
+	}
+}
+
+func parsePath(this js.Value, args []js.Value) interface{} {
+	fmt.Println("args: ", args)
+	server := NewServer()
+	path := args[0].String()
+	req, err := http.NewRequest(http.MethodGet, path, nil)
+
+	if err != nil {
+		fmt.Println("request error: ", err)
+	}
+
+	h, p := server.mux.Handler(req)
+
+	fmt.Println("pattern: ", p)
+
+	w := createWriter()
+
+	h.ServeHTTP(w, req)
+
+	b, err := ioutil.ReadAll(w.Body)
+
+	if err != nil {
+		fmt.Println("ioutil error: ", err)
+	}
+
+	return string(b)
+}
+
+func setup() {
+	js.Global().Set("parsePath", js.FuncOf(parsePath))
+}
+

Conclusions

+

The PoC worked! It’s pretty slick to see a HTTP server running in WASM return back the correct data when a link is clicked. However, in my opinion, WASM continues to be a “solution in search of a problem”. Yes it’s incredibly cool technology but so are the JS engines in Chrome, Firefox, and Safari. The sheer amount of money and engineering time being spent on making JS fast is a race no other technology can win at the moment.

+

That said, Go seems to have done decent work at providing the necessary pieces to make compiling to WASM not awful.

+

Honestly, the thing that surprised and impressed me the most was working with Web Workers. They are seriously useful and seem to “just work”.

+ + + + Discuss further in my public inbox + ]]>
+
+ + New workstation + https://adamsimpson.net/writing/new-workstation/ + + https://adamsimpson.net/writing/new-workstation/ + Mon, 02 May 2022 18:14:25 +0000 + + <![CDATA[ I detail my new workstation build featuring the Intel i5-12600k. ]]> + + <![CDATA[ +

New job means time for a new workstation.

+

Some history

+

The first computer I ever purchased was the 12" Powerbook G4. Since that Powerbook I’ve always had laptops as my main machines (desktop gaming PC not withstanding). Remote working the last few years has made me realize that the portability of a laptop is largely wasted since I only travel a handful of times a year and yet I live with the downsides of a laptop the rest of the time. So, last year I started thinking about a desktop machine for my primary workstation. A desktop is appealing for a handful of reasons:

+
    +
  • More powerful CPUs
  • +
  • More expansion capabilities
  • +
  • More durable
  • +
+

The options

+

The Mac Studio was recently released to much fanfare and was really intriguing to me. However, when I started considering it I only had about a week to 10 days before my start date at Grafana and I couldn’t wait the quoted 4-6 weeks delivery time for a Mac Studio with 32GB of RAM.

+

I was also pretty unwilling to leave my comfy NixOS install + i3. Michael Stapelberg’s latest post about his new workstation proved timely and convinced me to give the new Intel Alder Lake CPUs a shot.

+

Apple’s M1 family of chips deliver incredible performance per watt but I wasn’t as concered about the power usage given this was a desktop machine not a laptop. I was however focused on at least matching the M1 chips in single-threaded performance since a good chunk of my development work (Node, build tools, etc) are still single-threaded. I ended up with the Intel i5-12600k and I really couldn’t be happier. Here’s the full parts list:

+ +

XMP issues

+

I ran into the same memory XMP issues that Michael mentions in his post so I disabled the XMP profile and the system passed the “Coding Horror burn in tests” with flying colors.

+

Cooling

+

I mounted the 140mm fan to the bottom of the case as intake and the CPU cooler is of course positioned as intake as well. Hot air rises out the top of the case quite well. During the prime95 torture test the CPU never got over 78°C and I couldn’t ever hear either fan. I run both fans in the “silent profile” in the BIOS and I use Noctua’s adapters to lower the voltage even more. Now the only fan I could hear during max load was the PSU fan which doesn’t spin at all under low to medium loads but under high load it kicks on. Day to day it’s hardly on so the system is dead quiet most of the time.

+

Case

+

I absolutely love the Cerberus case. It’s Mini-ATX but still super compact and fits on my desk quite well. All the panels are solid metal and the way all the panels pop off is really really nice. I opted for the handle mount on the top and the internal PSU moutning.

+

Linux

+

NixOS installed just fine. I’m runing the 5.17 kernel because Alder Lake needs a newer kernel for it’s graphics and CPU scheduler (coming soon?). I have WiFi and Bluetooh disabled in the BIOS since everything is hard-wired to the machine.

+

Verdict

+

This build has proven quite comfortable over the few weeks I’ve used it. I love that I have 2 free RAM slots if I ever feel the need for more RAM. I also love that I have 3 remaining Nvme slots on the motherboard for additional solid state storage in the future.

+ + Discuss further in my public inbox + ]]>
+
+ + 👋 Sparkbox + https://adamsimpson.net/writing/goodbye-sparkbox/ + + https://adamsimpson.net/writing/goodbye-sparkbox/ + Fri, 01 Apr 2022 18:20:31 +0000 + + <![CDATA[ I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. ]]> + + <![CDATA[ +

I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox.

+

Now, I know it can be problematic to think about work like your (extended) family but when you work at the same place through your twenties and early thirties, have 3 different apartments, buy a house, and have two kids it’s impossible not to view that place differently. I can confidently say Sparkbox changed my life. The team there will always have a special place in my heart.

+

deep breath

+

So where to? Well, I’m super stoked to be joining Grafana as a Senior Software Engineer on their Cloud Data team! I’m looking forward to writing more Go, solving new problems, and learning from the stellar folks there.

+

Here we go…

+ + Discuss further in my public inbox + ]]>
+
+ + Thirty five + https://adamsimpson.net/writing/thirty-five/ + + https://adamsimpson.net/writing/thirty-five/ + Thu, 03 Mar 2022 10:28:44 -0500 + + <![CDATA[ It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. ]]> + + <![CDATA[ +

Well crap.

+

It’s been 5 years since I wrote “Thirty”. So now I have to come up with 35 things as I turned 35 yesterday. If anything from Thirty is grossly wrong or really interesting I’ll update it at the same number eh?

+

Let’s go…

+
    +
  1. I still don’t have it figured out, but this isn’t such a shock anymore.
  2. +
  3. Building a house is more scary.
  4. +
  5. Minivans are awesome.
  6. +
  7. Expecting a third kid is not nearly as scary as expecting the first.
  8. +
  9. COVID sucked.
  10. +
  11. Modern medicine is pretty cool actually.
  12. +
  13. More stuff hurts, still just as healthy.
  14. +
  15. Dishwashers aren’t really as scary to repair as they seem (but that doesn’t mean you won’t lose your mind fixing one).
  16. +
  17. The feeling you get as a parent when your kid gets hurt is impossible to describe.
  18. +
  19. Being knocked out from a crazy car accident is also no fun.
  20. +
  21. Carseats are magic.
  22. +
  23. I’ve accepted that the music I liked in 2010 is going to be the music I’ll like forever.
  24. +
  25. Thanks to the internet there is an endless stream of new music that is at home with music from 2010 or even 2000 (Underoath just released a new album for crying out loud).
  26. +
  27. Open source software is incredible.
  28. +
  29. The thrill from in-progress software working for the first time will never get old for me.
  30. +
  31. Feedback loops are important in every area of life not just software.
  32. +
  33. The year of Linux on the desktop is a moving target.
  34. +
  35. RSS will never die.
  36. +
  37. Mechanical keyboards are a refreshing change and I’m not sure why.
  38. +
  39. The Aeropress is still incredible.
  40. +
  41. Computers were a mistake.
  42. +
  43. Computers are a miracle.
  44. +
  45. The Three-Body Problem trilogy continues to knock around in my brain months after finishing it.
  46. +
  47. Watching your child accomplish something for the first time that they’ve been working on is a feeling unlike any other.
  48. +
  49. I’ve realized I learn best by doing, I need to get better at accounting for the bumps along the way.
  50. +
  51. I write things down to remember them later not to look them up later which means most note systems are not worth the trouble for me.
  52. +
  53. Life will be shallow if you only hang out with people like you.
  54. +
  55. Anything is possible on an infinite timescale the trick is figuring out what do with finite time.
  56. +
  57. RIP Rdio.
  58. +
  59. Never pass on an opportunity to twirl your kids around when they’re small. They get big fast.
  60. +
  61. Hanlon’s razor explains most of social media.
  62. +
  63. If you work at a desk all day you owe it to yourself to remove as much Bluetooth from that setup as possible.
  64. +
  65. None of your peers has it all figured out. Ask them “dumb” questions.
  66. +
  67. Properly evaluating risks when your kids are involved is hard.
  68. +
  69. Keep a sweatshirt handy by your bed when your kids are young, getting up at 2am in the winter is cold.
  70. +
+

❤️ you Christi

+ + Discuss further in my public inbox + ]]>
+
+ + Windows 11 as KVM guest + https://adamsimpson.net/writing/windows-11-as-kvm-guest/ + + https://adamsimpson.net/writing/windows-11-as-kvm-guest/ + Mon, 28 Feb 2022 13:39:37 -0500 + + <![CDATA[ How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. ]]> + + <![CDATA[ +

Windows 11 famously has new, stricter requirements for installation; a TPM device and Secure Boot. Here’s how I satisfied those requirements with Windows 11 as a KVM guest with NixOS as the host. The following is pulled from my NixOS configuration.nix:

+
libvirtd.qemu = {
+  package = pkgs.qemu_kvm;
+  runAsRoot = true;
+  swtpm.enable = true;
+  ovmf = {
+    enable = true;
+    package = (pkgs.OVMFFull.override {
+      secureBoot = true;
+      tpmSupport = true;
+    });
+  };
+};
+

The most important bit is the pkgs.OVMFFull.override section where you must specify tpmSupport and secureBoot as true.

+

In virt-manager you’ll need to add “new hardware” and select TPM v2.0. Here’s the relevant XML from my config:

+
<tpm model="tpm-crb">
+  <backend type="emulator" version="2.0"/>
+</tpm>
+

With the above settings you should be able to go through the Windows 11 installer and get the machine up and running as a KVM guest.

+

Stretch goal: nested virtualization

+

If you want to use Docker or WSL 2 inside KVM you’ll need to enable “nested virtualization” in virt-manager. I couldn’t figure this out until I found this great answer on superuser.

+

My original CPU config XML looked like this:

+
<cpu mode="host-model" check="partial">
+  <topology sockets="1" dies="1" cores="2" threads="4"/>
+</cpu>
+

The new XML looks like this:

+
<cpu mode="custom" match="exact" check="partial">
+  <model fallback="allow">Skylake-Client-noTSX-IBRS</model>
+  <topology sockets="1" dies="1" cores="2" threads="4"/>
+  <feature policy="disable" name="hypervisor"/>
+  <feature policy="require" name="vmx"/>
+</cpu>
+

With this applied I could install WSL2 and get Docker Desktop for Windows installed and running.

+ + Discuss further in my public inbox + ]]>
+
+ + A few POSIX shell tips + https://adamsimpson.net/writing/a-few-posix-shell-tips/ + + https://adamsimpson.net/writing/a-few-posix-shell-tips/ + Mon, 19 Jul 2021 14:53:16 -0400 + + <![CDATA[ I wrote down a few of my most used POSIX shell commands and features. ]]> + + <![CDATA[ +

I was recently working on the release build script for sb and decided I should document a few things I find myself looking up just about every time. One of the advantages of the POSIX shell (not bash, zsh, but Bourne shell, usually /bin/sh on most unix-y systems) is that it has a specification however I’m usually frustrated trying to find the information I need.

+ +

You can check it out here: https://github.com/sparkbox/sb

+ +

I prefer the POSIX shell because it’s the default on most unix-y system. If I have to be sure if the shell is installed on the target system (like bash or zsh) I’d rather just use a higher-level scripting language like node or ruby where the same requirement exists.

+

Arrays

+

Psych! There aren’t any arrays. Bash has arrays but POSIX does not. If I need an array structure I can use a space-separated string (or another delimiter if you’ve set $IFS) as the data structure, e.g. PLATFORMS="arm64-darwin amd64-linux amd64-darwin". Now I can loop over the variable using a for loop:

+
PLATFORMS="arm64-darwin amd64-linux amd64-darwin"
+
+for PLATFORM in ${PLATFORMS}; do
+  # GOOS=FOO GOARCH=BAR go build ...
+done
+

Or I can take the lack of arrays as a signal I should stop writing a shell script and reach for a language that has the concept of arrays to solve my problem.

+

Conditional “flags”

+

I often forget the various flags one can use in a conditional (aka test/if) statement. Here’s the documentation and here are a few of my favorites:

+
    +
  • -n tests if the string is non-zero, e.g.
  • +
+
if [ -n "${UPLOAD_URL}" ]; then
+    upload_file "${PLATFORM}"
+fi
+
    +
  • -z the opposite of -n.
  • +
  • -f tests if the pathname resolves to a file.
  • +
+

Functions and args

+
    +
  • Functions must be declared before they are invoked.
  • +
  • Functions look like:
  • +
+
someFunc() {
+  echo "a func!"
+}
+
    +
  • There is no syntax for functions accepting args instead they are mapped to $n. $@ is all the args.
  • +
+
upload_file() {
+    NAME=$1
+
+    zip "${NAME}.zip" "${NAME}"
+    curl -H "Accept: application/vnd.github.v3+json" \
+         -H "Authorization: Bearer ${GITHUB_TOKEN}" \
+         -H "Content-Type: application/zip" \
+         --data-binary "@${NAME}.zip" \
+         "${UPLOAD_URL}?name=${NAME}.zip"
+}
+
+upload_file "${PLATFORM}"
+

Use shellcheck

+

This is just preference but I really love using shellcheck to avoid any footguns and enforce a consistent style with my shell scripts. I typically invoke it like this: shellcheck -o all script-name.sh.

+ + Discuss further in my public inbox + ]]>
+
+ + Recently + https://adamsimpson.net/writing/recently-16/ + + https://adamsimpson.net/writing/recently-16/ + Fri, 23 Apr 2021 11:37:19 -0400 + + <![CDATA[ A random assortment of links and miscellaneous updates on things. ]]> + + <![CDATA[ +

I’m stealing the title format of this post from Tom MacWright’s Recently posts.

+

Here’s a random assortment of links and miscellaneous updates on things.

+

autofs

+

autofs is a cool utility that watches a specific directory path and when a program tries to read or write to that path it mounts a filesystem at that location. I’m using this to auto mount my NAS via SMB for mpd. With autofs in place I can run mpd locally (in a “satellite setup”) and have its music_directory point to a path managed by autofs.

+

One thing that was helpful getting the configuration right was testing autofs by running automount -f -v directly which puts it in the foreground and gives verbose output.

+

The two files I configured were auto.master.d/foo.autofs and auto.foo.

+
    +
  • foo.autofs contains one line: /- /etc/auto.foo
  • +
  • auto.foo contains one line as well: /foo -fstype=cifs,rw,credentials=/home/me/.foo-creds ://NAS.IP/foo
  • +
+

mailpreview updates

+

mailpreview-cli is a little program I use multiple times a day to quickly see my unread email without moving from what I’m currently working on and without touching my mouse. I recently noticed it wasn’t grabbing the body of a specific type of email. In the process of fixing that I also added proper unit tests for every format I currently parse through. Yay faster feedback loops!

+

ffmpeg

+

I’ve been a fan of OBS for awhile now. I was recently doing a quick screen recording of my browser window and the browser window wasn’t full-screen so there were black bars around the edges of the recording. I didn’t love that but it’s time to touch the “ffmpeg exists and is awesome” sign again.

+

This superuser post has the answer which consists of two steps:

+
    +
  1. Get the crop parameters of the video from ffmpeg. ffmpeg will detect the black borders and report back the actual content coordinates. +ffmpeg.exe -i '.\some-video.mkv' -vf cropdetect -f null -
  2. +
  3. Re-encode and crop using the crop parameters to trim the borders. +ffmpeg.exe -i '.\some-video.mkv' -vf crop=624:704:332:10 -c:a copy output.mp4
  4. +
  5. Enjoy your pristine video.
  6. +
+ + +

Fin

+ + Discuss further in my public inbox + ]]>
+
+ + A firewall in 8 lines + https://adamsimpson.net/writing/8-line-firewall/ + + https://adamsimpson.net/writing/8-line-firewall/ + Wed, 31 Mar 2021 11:18:24 -0400 + + <![CDATA[ You only need about 8 lines in iptables to have a great home firewall. ]]> + + <![CDATA[ +

Since 2017 my home router has been a plain x86 box running Alpine Linux. I never really think about it anymore. Recently, I was helping a relative set up their own Linux-based router and took the time to appreciate how little config is needed to setup a serviceable home router firewall using iptables. You can see my base rule-sets (port forwarding omitted) below:

+
-P INPUT DROP
+-P FORWARD DROP
+-P OUTPUT ACCEPT
+-A INPUT -i lo -j ACCEPT
+-A INPUT -i eth1 -j ACCEPT
+-A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+-A FORWARD -i eth1 -o eth0 -j ACCEPT
+-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+

The benefit of running a x86 box with Alpine (or any version of Linux) is that the box will receive a steady stream of security updates and upgraded kernels as Alpine Linux releases new versions. This is a much better situation to be in than relying on OS and security updates from a vendor like TPLink or Linksys.

+

If you have ideas for how to improve the config I listed above or want to chat more about home network stuff, send an email to my public-inbox.

+ + Discuss further in my public inbox + ]]>
+
+ + How to use Siji font on polybar + https://www.reddit.com/r/Polybar/comments/ht0jnr/guide_how_to_use_the_siji_font_on_polybar/ + + https://adamsimpson.net/writing/how-to-use-siji-font-on-polybar/ + Fri, 06 Nov 2020 11:18:47 -0500 + <![CDATA[ +

Nice guide on Reddit about how to use the Siji font with polybar.

+
+

[..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

+
+

Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

+ + 🔗 + Discuss further in my public inbox + ]]>
+
+ + On Polybar bitmap fonts and Ubuntu + https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ + + https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ + Fri, 06 Nov 2020 10:15:09 -0500 + + <![CDATA[ Enable bitmap fonts on Ubuntu for an optimal polybar experience. ]]> + + <![CDATA[ +

I use polybar as my status bar in i3 and it’s been going great for months now. However, I was recently grepping through the syslog trying to figure out why a browser crash happened and the log was filled with polybar spam that looked like this: polybar|warn: Dropping unmatched character. So I started picking at solving the warning.

+

Turns out there’s a Github issue that contains the solution which is to enable bitmap fonts which I’ll paste here for posterity:

+
# "Un-disable" bitmap fonts
+sudo rm /etc/fonts/conf.d/70-no-bitmaps.conf
+# Clear the font cache
+sudo fc-cache -f -v
+

Apparently Ubuntu disables bitmap fonts by default but polybar uses bitmap fonts for icon rendering. I also needed to install the sijj icon font family which was painless.

+ + Discuss further in my public inbox + ]]>
+
+ + Recently + https://adamsimpson.net/writing/recently-44/ + + https://adamsimpson.net/writing/recently-44/ + Tue, 27 Oct 2020 23:30:46 -0400 + + <![CDATA[ I've written a few small tools over the last couple months and I figured it's time I post about them. ]]> + + <![CDATA[ +

I’ve published a few new projects in the last couple of months and I’m behind on announcing them, so I bundled them up together into this post. I’m stealing the title format of this post from Tom MacWright’s Recently posts.

+

One thing to note is that the source code for all these projects is stored on sourcehut. Sourcehut (or sr.ht) bills itself as “the hacker’s forge”. I highly recommend checking it out. It’s also where I host my public inbox.

+

hover-dns

+

Now that I have fiber internet at the house I’ve been hosting one-off services and apps on my own hardware at the house. This is great, however my residential connection is a typical dynamic IP not a static one. Instead of using a service like DynamicDNS I decided to write some Rust (shocker) and leverage the “unofficial” Hover API. The result is: hover-dns.

+

I have hover-dns running in a crontab for a few different domains to keep my domains pointed to the correct IP for my house. While I’m a little uncomfortable with how similar npm and cargo can feel, the trust-dns package is excellent. I was able to quickly read the source code to understand how to setup a Resolver for opendns. Also impressive is that hover-dns ip beats out dig in returning your public IP. I didn’t expect that!

+

podcastfilter

+

Speaking of hosting things at home, podcastfilter.com is one of those things. podcast-filter is a small Go project that allows you to filter a podcast feed by each episode’s description and return a feed of just those episodes that match.

+

mailpreview

+

The recent project I use the most day-to-day is mailpreview-cli. mailpreview-cli is very straight-forward, it accepts a Mail message and returns either the plain text version or the html version of that message. The reason I don’t just pull the Mail message directly is because a Mail message can contain several versions of the message in different encodings (start here if you’re curious: RFC-822). Instead of writing my own parser I grabbed the excellent mailparse crate and wrapped the behavior I wanted around it. On it’s own mailpreview-cli isn’t super fancy but I trigger it from rofi via a shell script which allows me to browse (and then view) all my unread emails right from rofi. Shameless plug: I wrote a short post about getting started with rofi if you’re unfamiliar. mailpreview-cli could be used with Alfred if you’re on a Mac to accomplish the same thing as I’m doing with a shell script and rofi.

+

Fin

+ + Discuss further in my public inbox + ]]>
+
+ + Four ways to approach Hacktoberfest 2020 + https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ + + https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ + Thu, 01 Oct 2020 10:26:38 -0400 + + <![CDATA[ I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. ]]> + + <![CDATA[ +

Hacktoberfest 2020 is here! I can’t believe 2020 is winding down, good riddance!

+

I’ve been talking about Hacktoberfest with my co-worker Bryan and I thought of four different approaches to Hacktoberfest this year that I wanted to share.

+ +

Dependency scrub

+

This is probably common everywhere but the Javascript/web communities are filled with npm packages. It’s packages all the way down. I think it would be interesting to approach this month looking for ways to remove third-party code from projects you love and use frequently.

+

Polygot Achievement

+

Try to submit four pull requests in four different languages. As Drew DeVault writes: Hack everything without fear!

+

Unknown lands

+

Similar to the previous one it could be fun to submit PRs against a project you’ve never been in before that’s in a language you don’t know. This could be anything from diving into Wordpress core, to working on some C for some Linux utilities, or even submitting PRs to open source Mac/iOS applications.

+

Bug doctor

+

Go into a project and find the oldest issues and try to resolve them via PR. This is inspired by Richard Schneeman’s video and post where he runs through 11 issues and 2 PRs in a hour and a half.

+

How are you approaching Hacktoberfest this year? My public inbox is open, let me know!

+ + Discuss further in my public inbox + ]]>
+
+ + Small tech + https://scattered-thoughts.net/writing/small-tech/ + + https://adamsimpson.net/writing/small-tech/ + Fri, 25 Sep 2020 15:53:06 -0400 + <![CDATA[ +

Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

+
    +
  • +

    curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

    +
  • +
  • +

    git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

    +
  • +
  • +

    Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

    +
  • +
  • +

    sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

    +
  • +
+ + 🔗 + Discuss further in my public inbox + ]]>
+
+ + Indexing My Blog’s Links + https://blog.jim-nielsen.com/2020/indexing-my-blogs-links/ + + https://adamsimpson.net/writing/indexing-my-blogs-links/ + Fri, 25 Sep 2020 15:49:21 -0400 + <![CDATA[ +

Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

+ + 🔗 + Discuss further in my public inbox + ]]>
+
+ + Compose key and i3 + https://adamsimpson.net/writing/compose-key-and-i3/ + + https://adamsimpson.net/writing/compose-key-and-i3/ + Fri, 18 Sep 2020 11:28:19 -0400 + + <![CDATA[ Here's how to bind the compose key to caps lock in i3wm. ]]> + + <![CDATA[ +

The compose key on Linux and other systems enables you to enter symbols like ™ that don’t have a dedicated key on most keyboards. GNOME makes this easy to do via Gnome Tweaks. However, using a window manager like i3 means there’s no dedicated GUI for changing the hotkey for compose.

+

This stackexchange answer sent me down the right path of adding the following config to ~/.Xmodmap to bind Caps lock to compose:

+
.keysym 66 = Mode_switch
+clear Lock
+

You can then enable the key map by running:

+
xmodmap ~/.Xmodmap
+

However, that config didn’t work because Mode_switch wasn’t the right name for the compose key (at least under Ubuntu/PopOS 20 for me). The Arch Wiki states that the name for the compose key is actually Multi_key. With this new name I was able to get Caps lock to act as the compose key by updating the config in ~/.Xmodmap to:

+
keycode 66 = Multi_key
+clear Lock
+

The final step is to set that mapping every time i3 runs by putting this inside your i3 config file like so:

+
exec --no-startup-id "xmodmap ~/.Xmodmap"
+
+ Discuss further in my public inbox + ]]>
+
+ + cycle v0.3.0 released + https://adamsimpson.net/writing/cycle-v030-released/ + + https://adamsimpson.net/writing/cycle-v030-released/ + Fri, 11 Sep 2020 12:04:16 -0400 + + <![CDATA[ Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. ]]> + + <![CDATA[ +

I just released v0.3.0 of cycle.

+

This version uses Chroma for syntax highlighting instead of Pygments. I never got Pygments running correctly in Netlify’s build environment. Chroma requires no dependencies since it’s distributed as a static binary and it’s also faster due to being written in golang.

+

This version also refactors the main function to accept an optional working directory arg. This allows me to build a site via the CL REPL. It also shortens the feedback loop to try out new features.

+ + Discuss further in my public inbox + ]]>
+
+
+
diff --git a/themes/cycle/exampleSite/public/sitemap.xml b/themes/cycle/exampleSite/public/sitemap.xml new file mode 100644 index 0000000..ee85efd --- /dev/null +++ b/themes/cycle/exampleSite/public/sitemap.xml @@ -0,0 +1,539 @@ + + + + https://adamsimpson.net/ + 2024-05-10T14:07:43-04:00 + + https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ + 2024-05-10T14:07:43-04:00 + + https://adamsimpson.net/post/ + 2024-05-10T14:07:43-04:00 + + https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ + 2023-07-25T15:10:24-04:00 + + https://adamsimpson.net/writing/better-scripting-with-gh/ + 2023-07-22T11:49:30-04:00 + + https://adamsimpson.net/writing/end-of-an-era/ + 2023-06-15T14:13:50-04:00 + + https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ + 2022-08-19T15:10:19-04:00 + + https://adamsimpson.net/writing/new-workstation/ + 2022-05-02T18:14:25+00:00 + + https://adamsimpson.net/writing/goodbye-sparkbox/ + 2022-04-01T18:20:31+00:00 + + https://adamsimpson.net/writing/thirty-five/ + 2022-03-03T10:28:44-05:00 + + https://adamsimpson.net/writing/windows-11-as-kvm-guest/ + 2022-02-28T13:39:37-05:00 + + https://adamsimpson.net/writing/a-few-posix-shell-tips/ + 2021-07-19T14:53:16-04:00 + + https://adamsimpson.net/writing/recently-16/ + 2021-04-23T11:37:19-04:00 + + https://adamsimpson.net/writing/8-line-firewall/ + 2021-03-31T11:18:24-04:00 + + https://adamsimpson.net/writing/how-to-use-siji-font-on-polybar/ + 2020-11-06T11:18:47-05:00 + + https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ + 2020-11-06T10:15:09-05:00 + + https://adamsimpson.net/writing/recently-44/ + 2020-10-27T23:30:46-04:00 + + https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ + 2020-10-01T11:41:44-04:00 + + https://adamsimpson.net/writing/small-tech/ + 2020-09-25T15:53:06-04:00 + + https://adamsimpson.net/writing/indexing-my-blogs-links/ + 2020-09-25T15:49:21-04:00 + + https://adamsimpson.net/writing/compose-key-and-i3/ + 2020-09-18T11:28:19-04:00 + + https://adamsimpson.net/writing/cycle-v030-released/ + 2020-09-11T12:04:16-04:00 + + https://adamsimpson.net/writing/setting-a-default-browser-in-i3/ + 2020-09-11T00:01:05-04:00 + + https://adamsimpson.net/writing/eight-years/ + 2020-09-04T09:25:36-04:00 + + https://adamsimpson.net/writing/zach-beane/ + 2020-09-01T16:34:26-04:00 + + https://adamsimpson.net/writing/openring/ + 2020-08-21T16:09:44-04:00 + + https://adamsimpson.net/writing/a-public-inbox/ + 2020-08-17T23:14:25-04:00 + + https://adamsimpson.net/writing/rust-module-system/ + 2020-07-19T23:52:26-04:00 + + https://adamsimpson.net/writing/nothing-speaks-like-a-demo/ + 2020-07-19T23:46:14-04:00 + + https://adamsimpson.net/writing/a-new-website-for-2020/ + 2020-07-16T13:52:56-04:00 + + https://adamsimpson.net/writing/app_store_moment_of_clarity/ + 2020-07-13T14:10:09-04:00 + + https://adamsimpson.net/writing/goat-counter/ + 2020-07-01T15:49:45-04:00 + + https://adamsimpson.net/writing/is-webp-really-better-than-jpeg/ + 2020-06-30T13:13:04-04:00 + + https://adamsimpson.net/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/ + 2020-06-30T13:09:40-04:00 + + https://adamsimpson.net/writing/on-george-floyd/ + 2020-06-30T11:01:58-04:00 + + https://adamsimpson.net/writing/flatkill/ + 2020-06-15T13:03:27-04:00 + + https://adamsimpson.net/writing/ffmpeg-convert-multiple-files-using-xargs/ + 2020-06-04T14:43:26-04:00 + + https://adamsimpson.net/writing/search-imessage-sql/ + 2020-05-28T21:25:06-04:00 + + https://adamsimpson.net/writing/macos-catalina-slow-by-design/ + 2020-05-28T21:22:03-04:00 + + https://adamsimpson.net/writing/getting-started-with-rofi/ + 2020-05-28T13:35:15-04:00 + + https://adamsimpson.net/writing/what-time-is-it-in-london/ + 2020-05-22T10:44:04-04:00 + + https://adamsimpson.net/writing/psychicpaper/ + 2020-05-18T10:27:38-04:00 + + https://adamsimpson.net/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/ + 2020-05-18T10:20:08-04:00 + + https://adamsimpson.net/writing/second-guessing-the-modern-web/ + 2020-05-13T11:34:19-04:00 + + https://adamsimpson.net/writing/youtube-subscriptions/ + 2020-05-08T11:36:23-04:00 + + https://adamsimpson.net/writing/hiking-the-pacific-crest-trail-in-three-minutes/ + 2020-05-07T10:27:56-04:00 + + https://adamsimpson.net/writing/oscar/ + 2020-04-29T16:21:17-04:00 + + https://adamsimpson.net/writing/seamless-branch-deploys-with-kubernetes/ + 2020-04-27T10:10:46-04:00 + + https://adamsimpson.net/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/ + 2020-03-17T16:59:34-04:00 + + https://adamsimpson.net/writing/atr2100/ + 2020-01-29T12:55:45-05:00 + + https://adamsimpson.net/writing/rust-strings-and-str/ + 2020-07-03T23:20:47-04:00 + + https://adamsimpson.net/writing/tweet-stash/ + 2019-12-12T21:54:49-05:00 + + https://adamsimpson.net/writing/track-redirects-with-curl/ + 2019-10-22T13:25:50-04:00 + + https://adamsimpson.net/writing/the-thing-about-computers/ + 2019-09-21T13:40:51-04:00 + + https://adamsimpson.net/writing/dead-cells-might-be-a-perfect-game/ + 2019-09-20T10:23:59-04:00 + + https://adamsimpson.net/writing/0-14/ + 2019-07-30T10:31:07-04:00 + + https://adamsimpson.net/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/ + 2019-05-05T14:13:02-04:00 + + https://adamsimpson.net/writing/introducing-cycle/ + 2019-04-05T23:05:17-04:00 + + https://adamsimpson.net/writing/ajax-and-rails/ + 2019-01-28T11:25:49-05:00 + + https://adamsimpson.net/writing/blog-rewrite/ + 2018-11-20T23:02:21-05:00 + + https://adamsimpson.net/writing/medium-isnt-permanent/ + 2018-05-21T11:49:15-04:00 + + https://adamsimpson.net/writing/hosting-assets-via-github-pages/ + 2018-05-11T15:41:35-04:00 + + https://adamsimpson.net/writing/ivy-pinboard-popular/ + 2018-04-26T23:16:14-04:00 + + https://adamsimpson.net/writing/emacs-lite/ + 2018-04-19T10:42:41-04:00 + + https://adamsimpson.net/writing/hello-micro-blog/ + 2018-02-01T16:45:31-05:00 + + https://adamsimpson.net/writing/apple-on-batteries-and-performance/ + 2017-12-28T18:11:14-05:00 + + https://adamsimpson.net/writing/git-worktree/ + 2017-12-11T00:00:17-05:00 + + https://adamsimpson.net/writing/messi-is-re-writing-the-record-book/ + 2017-12-02T15:53:22-05:00 + + https://adamsimpson.net/writing/introducing-ivy-feedwrangler/ + 2017-11-16T11:06:20-05:00 + + https://adamsimpson.net/writing/a-hackintosh/ + 2017-09-14T10:11:55-04:00 + + https://adamsimpson.net/writing/on-equifax/ + 2017-09-08T16:31:42-04:00 + + https://adamsimpson.net/writing/before-circles-2017/ + 2017-09-06T11:52:29-04:00 + + https://adamsimpson.net/writing/five-years/ + 2017-09-05T23:00:18-04:00 + + https://adamsimpson.net/writing/on-diminishing-modes-in-emacs/ + 2017-08-17T12:09:25-04:00 + + https://adamsimpson.net/writing/helm-to-ivy/ + 2017-08-15T11:28:18-04:00 + + https://adamsimpson.net/writing/the-era-of-the-screenshot/ + 2017-06-12T22:56:24-04:00 + + https://adamsimpson.net/writing/format-json-in-emacs/ + 2017-05-23T14:11:28-04:00 + + https://adamsimpson.net/writing/diceware/ + 2017-04-19T21:47:54-04:00 + + https://adamsimpson.net/writing/facetime-killer/ + 2017-04-03T09:44:57-04:00 + + https://adamsimpson.net/writing/what-happens-when-you-remove-friction/ + 2017-03-27T13:33:36-04:00 + + https://adamsimpson.net/writing/emacs-tips/ + 2017-11-17T23:41:43-05:00 + + https://adamsimpson.net/writing/be-a-good-video-call-citizen/ + 2017-03-17T11:18:27-04:00 + + https://adamsimpson.net/writing/thirty/ + 2017-03-02T10:32:47-05:00 + + https://adamsimpson.net/writing/lambda-talk/ + 2017-02-23T13:04:21-05:00 + + https://adamsimpson.net/writing/we-all-need-a-team/ + 2016-06-28T13:48:38-04:00 + + https://adamsimpson.net/writing/web-scraper-cookbook/ + 2016-02-20T21:44:55-05:00 + + https://adamsimpson.net/writing/how-do-we-make-the-web-better/ + 2016-01-29T11:12:52-05:00 + + https://adamsimpson.net/writing/command-line-notification/ + 2016-01-16T15:40:26-05:00 + + https://adamsimpson.net/writing/verse-recall/ + 2015-12-23T09:31:02-05:00 + + https://adamsimpson.net/writing/sqlite-tips/ + 2020-09-17T11:53:48-04:00 + + https://adamsimpson.net/writing/on-webpack/ + 2015-12-07T14:05:04-05:00 + + https://adamsimpson.net/writing/migrate-an-existing-build-process-to-npm-scripts/ + 2017-05-23T14:05:10-04:00 + + https://adamsimpson.net/writing/casperjs-node-and-the-raspberry-pi/ + 2015-10-20T10:06:01-04:00 + + https://adamsimpson.net/writing/amp-html-terrible-html/ + 2015-10-08T09:56:38-04:00 + + https://adamsimpson.net/writing/farewell-heroku/ + 2015-10-06T14:00:52-04:00 + + https://adamsimpson.net/writing/parsing-memory-usage-in-htoptop/ + 2015-10-04T09:07:37-04:00 + + https://adamsimpson.net/writing/three-years/ + 2015-09-04T12:17:30-04:00 + + https://adamsimpson.net/writing/what-is-medium/ + 2015-08-27T14:37:02-04:00 + + https://adamsimpson.net/writing/small-things/ + 2015-08-22T16:43:26-04:00 + + https://adamsimpson.net/writing/automating-socks-proxy/ + 2017-02-24T09:41:13-05:00 + + https://adamsimpson.net/writing/the-stream-hasnt-won/ + 2015-07-17T10:37:33-04:00 + + https://adamsimpson.net/writing/microblogging/ + 2015-06-25T13:02:57-04:00 + + https://adamsimpson.net/writing/learning-to-think-in-react/ + 2015-06-24T11:42:13-04:00 + + https://adamsimpson.net/writing/moving-away-from-google/ + 2015-06-01T09:07:54-04:00 + + https://adamsimpson.net/writing/benedict-evans-in-on-fire/ + 2015-05-25T00:54:17-04:00 + + https://adamsimpson.net/writing/web-performance-and-facebooks-instant-articles/ + 2015-05-14T10:45:57-04:00 + + https://adamsimpson.net/writing/google-fi-and-data-only-plans/ + 2015-04-30T22:05:58-04:00 + + https://adamsimpson.net/writing/iphone-checker-with-capybara-and-twilio/ + 2015-04-03T11:53:41-04:00 + + https://adamsimpson.net/writing/vim-ramblings/ + 2015-03-21T19:45:36-04:00 + + https://adamsimpson.net/writing/s3-security-policy/ + 2015-03-21T19:45:36-04:00 + + https://adamsimpson.net/writing/keeping-up/ + 2015-03-21T19:45:36-04:00 + + https://adamsimpson.net/writing/broadcast-channel/ + 2015-03-21T19:45:36-04:00 + + https://adamsimpson.net/writing/moved-to-siteleaf/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/git-commit-template/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/adn-cross-poster/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/ifttt/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/js2coffee-alfred-workflow/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/huffduffer/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/slanted-elements-with-css3/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/rename-utility/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/what-matters/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/andy-budd-on-time/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/ip-address-alfred-extension/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/bash-function-ip-address-to-clipboard/ + 2015-03-24T13:11:31-04:00 + + https://adamsimpson.net/writing/a-few-bash-tips/ + 2017-02-24T09:36:16-05:00 + + https://adamsimpson.net/writing/rands-on-email/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/lyza-gardner-on-laying-down-our-burdens/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/family-first/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/alfred-and-web-development/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/theme-the-chrome-dev-tools/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/moving-tweetbot-beta-to-a-new-mac/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/heroku-and-ssh-keys/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/i-moved-to-hover/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/how-are-you-living/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/a-new-adventure/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/when-the-music-stops/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/tigers-and-social-networks/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/blogs-data-and-social-networks/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/maybe-you-shouldits-not-youmove-on/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/rotten-tomatoes-and-launch-center/ + 2017-02-24T09:38:13-05:00 + + https://adamsimpson.net/writing/working-with-wordpress-offset-and-pagination/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/plaintext-and-markdown-a-primer/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/gists-snippets-and-sublime-text-2/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/kyle-steed-on-rest/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/convince-the-boss/ + 2015-03-24T13:12:39-04:00 + + https://adamsimpson.net/writing/create-passion/ + 2015-03-24T13:12:21-04:00 + + https://adamsimpson.net/writing/using-the-kindle-to-harness-the-web/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/simple-account-set-up/ + 2017-02-24T09:39:40-05:00 + + https://adamsimpson.net/writing/the-future-is-prototyping/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/story/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/guidelines-for-data/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/whats-best-for-the-readers/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/what-its-all-about/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/sparrow-and-the-app-store/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/css-reusability/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/a-little-hydrofoil/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/the-web-is-not-print/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/declining-expectations/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/someone-is-working-harder-than-you/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/just-start-over/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/a-style-guide-guide/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/zen-garden-part-2/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/pretty-git-log/ + 2017-02-24T13:36:58-05:00 + + https://adamsimpson.net/writing/grow-it-dont-build-it/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/evening-edition/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/balancing-devotion/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/the-web-and-my-goal/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/nginx-www-rewrite/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/my-first-bookmarklet/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/the-wordpress-http-api-is-awesome/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/adam-versus-dropbox-and-oauth/ + 2015-03-24T13:08:44-04:00 + + https://adamsimpson.net/writing/the-manhattan-project-time-lapse/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/writing/hello-world/ + 2015-03-21T19:45:37-04:00 + + https://adamsimpson.net/archive/ + + https://adamsimpson.net/categories/ + + https://adamsimpson.net/page/ + + https://adamsimpson.net/page/support/ + + https://adamsimpson.net/tags/ + + https://adamsimpson.net/page/uses/ + + diff --git a/themes/cycle/exampleSite/public/tags/index.html b/themes/cycle/exampleSite/public/tags/index.html new file mode 100644 index 0000000..7ccbec8 --- /dev/null +++ b/themes/cycle/exampleSite/public/tags/index.html @@ -0,0 +1,219 @@ + + + + + + Tags + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
    + +
+
+ +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/tags/rss.xml b/themes/cycle/exampleSite/public/tags/rss.xml new file mode 100644 index 0000000..0ac0c36 --- /dev/null +++ b/themes/cycle/exampleSite/public/tags/rss.xml @@ -0,0 +1,9 @@ + + + adamsimpson.net Post Feed + https://adamsimpson.net/ + Last 20 posts for adamsimpson.net + Thu, 09 Oct 2025 21:22:39 +0000 + en-us + + diff --git a/themes/cycle/exampleSite/public/writing/0-14/index.html b/themes/cycle/exampleSite/public/writing/0-14/index.html new file mode 100644 index 0000000..00df181 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/0-14/index.html @@ -0,0 +1,267 @@ + + + + + + 0.14 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

0.14

+ + +
+

I type this on a Thinkpad t480s that I recently switched to from a lifetime of using Apple machines (literally grew up on Apple computers, shoutout to the Macintosh Classic!). I switched because it was time for a new machine and I didn’t want to be using a faulty keyboard for the next 5 years. Here are my caveats before I continue:

+
    +
  • If I wasn’t buying a laptop I would get an iMac or iMac Pro and all would be well. Apple desktop computers are in a great place right now.
  • +
  • This machine is for my work as a web developer and technical director at Sparkbox. The range of applications I need are largely all cross-platform: 1Password, Dropbox, Slack, Google Calendar, code editor, browser, terminal, email. I miss but don’t need: iMessage, Photos, Safari, Tweetbot, Sequel Pro etc.
  • +
  • I haven’t completely lost my mind, I’m not running Windows 10. I am using System76’s quite nice Pop_OS linux distro.
  • +
  • I got this Thinkpad before the latest (4th?) revision of the Macbook keyboards. I would still make this decision today given the unknown quality of these “fixed” keyboards.
  • +
+

Some of the niceties that come with the switch:

+
    +
  • User upgradeable RAM. The t480s has 1 open SO-DIMM slot and 8GB soldered to the motherboard. This feels like a nice compromise. Of course I threw in a 16GB stick to have 24GB total.
  • +
  • User upgradeable SSD. I can easily swap the stock SSD. A Samsung 970 Pro 512GB SSD that is faster than what Apple ships in the current Macbook Pro is $150 from Amazon.
  • +
  • Ports. The t480s has 2 USB-A ports and 2 USB-C ports. It also has a full size HDMI, SD card slot, and full-size Ethernet.
  • +
  • Of course, a best-in-class keyboard.
  • +
+

Here’s what stinks about it:

+
    +
  • No macOS
  • +
  • Inferior trackpad
  • +
+

The stark difference between the current Macbook Pros and this Thinkpad remind me of John Gruber’s apt comparison between iOS and macOS when the iPad was new on the scene (emphasis mine):

+
+

When I say that iOS has no baggage, that’s not because there is no baggage. It’s because the Mac is there to carry it. […] Mac OS X has an essential role in an iOS world: serving as the platform for complex, resource-intensive tasks.

+

The funny thing is, the best slogan to describe the Mac’s role is the same one it started with 25 years ago:

+

The computer for the rest of us.

+
+

Apple should apply this to hardware as well, let the iPad be the ultrathin device with limited ports. Don’t force that set of compromises on professional laptop users. Like I said above, Apple’s desktops are fantastic. Heck the Mac mini RAM is almost user serviceable. The t480s is not a thin machine compared to a 13" Macbook Pro: it’s 0.73" thick according to Lenovo’s official specs and weighs in at 2.9lbs. The Macbook Pro for comparison is 0.59" thick and weighs in at 3.02lbs. Is 0.14" difference in thinness worth access to the ports, user upgrade-ability, and the longevity of the keyboard? I certainly don’t think so and I’m disappointed Apple continues to demonstrate they care about that 0.14" more than any other single feature.

+

I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn’t worth it.

+

Update

+

Quite a bit of discussion happened over at lobste.rs. It’s easy to get hung up on which ports should be included but I think looking at Apple’s desktops is instructive: USB-A, SD Card, and USB-C/TB3 are all included (HDMI is nice in my opinion but I can see the argument for dropping it). None of those ports would cause the device to become unbearably thick and would add significant value and convenience.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/8-line-firewall/index.html b/themes/cycle/exampleSite/public/writing/8-line-firewall/index.html new file mode 100644 index 0000000..00b1d90 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/8-line-firewall/index.html @@ -0,0 +1,249 @@ + + + + + + A firewall in 8 lines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A firewall in 8 lines

+ + +
+

Since 2017 my home router has been a plain x86 box running Alpine Linux. I never really think about it anymore. Recently, I was helping a relative set up their own Linux-based router and took the time to appreciate how little config is needed to setup a serviceable home router firewall using iptables. You can see my base rule-sets (port forwarding omitted) below:

+
-P INPUT DROP
+-P FORWARD DROP
+-P OUTPUT ACCEPT
+-A INPUT -i lo -j ACCEPT
+-A INPUT -i eth1 -j ACCEPT
+-A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+-A FORWARD -i eth1 -o eth0 -j ACCEPT
+-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+

The benefit of running a x86 box with Alpine (or any version of Linux) is that the box will receive a steady stream of security updates and upgraded kernels as Alpine Linux releases new versions. This is a much better situation to be in than relying on OS and security updates from a vendor like TPLink or Linksys.

+

If you have ideas for how to improve the config I listed above or want to chat more about home network stuff, send an email to my public-inbox.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html b/themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html new file mode 100644 index 0000000..7683e5c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html @@ -0,0 +1,347 @@ + + + + + + A few Bash Tips + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A few Bash Tips

+ + +
+

Here are a few custom little functions and aliases that I use everyday, these are all pretty straightforward, you can tweak any of these to fit your specific workflow.

+

The Bash Brothers

+

MAMP Virtual Hosts

+

It’s a pain to set up virtual hosts, which is why I wrote a bash script to automate that horrible process. Here is the script, I’ll explain how it works below (or check out the Gist):

+
#!/bin/bash
+RED="\033[0;31m"
+YELLOW="\033[33m"
+REDBG="\033[0;41m"
+WHITE="\033[1;37m"
+NC="\033[0m"</p>
+
+<pre><code>mkdir -p /Applications/MAMP/Library/vhosts;
+mkdir -p /Applications/MAMP/Library/vhosts/domains;
+
+if [ "$1" = "create" ] || [ "$1" = "add" ]; then
+# Ask for document root
+echo -e "${RED}Enter the document root (relative to 'htdocs'):${NC}";
+read documentRoot;
+
+# Ask for domain name
+echo -e "${RED}Enter local domain: (eg. local.com):${NC}";
+read domain;
+
+# Ask for port number
+echo -e "${RED}Enter MAMP Port Nubmer:${NC}";
+read port;
+
+# Add vhost
+touch /Applications/MAMP/Library/vhosts/domains/$domain;
+
+echo "<VirtualHost *:$port>
+DocumentRoot "/Applications/MAMP/htdocs/$documentRoot"
+ServerName $domain
+<Directory "/Applications/MAMP/htdocs/$documentRoot">
+    Options All
+    AllowOverride All
+    Order allow,deny
+    Allow from all
+</Directory>
+</VirtualHost>" >> /Applications/MAMP/Library/vhosts/domains/$domain;
+
+echo "127.0.0.1 $domain" >> /etc/hosts;
+
+# Restart MAMP
+/Applications/MAMP/bin/apache2/bin/apachectl restart;
+
+echo -e "Finished. ${REDBG}${WHITE}$domain:$port${NC} has been copied to your clipboard.";
+echo "$domain:$port" | pbcopy;
+fi
+
+if [ "$1" = "remove" ] || [ "$1" = "delete" ]; then
+echo -e "${RED}Here are the current custom local domains:${NC}"
+for file in /Applications/MAMP/Library/vhosts/domains/*
+do
+  if [ -f "$file" ];then
+    echo -e "${YELLOW}${file##/*/}${NC}"
+  fi
+done
+echo -e "${RED}Enter the site name you wish to remove:${NC}"
+read siteName;
+
+sed -i.bak "/$siteName/d" /etc/hosts;
+rm /Applications/MAMP/Library/vhosts/domains/$siteName;
+
+echo -e "${YELLOW}$siteName removed."
+fi
+

The script is set up to work with each web project being stored in a directory under htdocs in the MAMP folder. If you want to use a different folder structure, simply change the paths in the script to reflect your particular workflow.

+

The script asks for three pieces of info, the domain you want, the directory name, and the MAMP port number. The script creates a new directory called ‘vhosts’ and a sub directory called ‘vhosts/domains’. Each file in ‘domains’ is a single domain, which makes this all easier to manage. The script then modifies your etc/hosts file with the new domain information. Finally, the script restarts MAMP apache and copies the new domain address to your clipboard.

+

The last piece to this puzzle is the function that fires this script off.

+
function vhost {
+  sudo ~/.dotfiles/osx/mamp_vh.sh $1
+}
+

Just specify the path to the script and you are set.

+

Jump to project directory

+

Another pain point is jumping to a specific project directory quickly, and without a lot of path typing. I wrote a function that lists all the folders in my htdocs directory and lets me select the one I want to go to.

+
function ht {
+  local BLUE="\033[0;34m"
+  local RED="\033[0;31m"
+  local WHITE="\033[0;37m"
+  local NC="\033[0m"
+  echo -e "${BLUE}Projects:${WHITE}"
+    for file in /Applications/MAMP/htdocs/*
+    do
+      if [ -d "$file" ];then
+        echo ${file##/*/}
+      fi
+    done
+  echo -e "${RED}Which Project?${NC}"
+  read dir;
+  cd /Applications/MAMP/htdocs/$dir
+}
+

Again, simply change the paths in the script to adapt this to your workflow.

+

Colored History Grep

+

One little alias that I snagged from the numerous dotfile repos on Github is the ‘h’ alias which simply shortcuts the ‘history’ command. I love this little command, but I found myself typing out h | grep keyword to get a list of commands specific to a keyword. I shortened this up and added color highlighting:

+
function hg {
+  history | grep --color=auto $1
+}
+

Simply pass the function the term you are looking for. Remember you can execute previous functions by typing !999 (999 being the number of the command).

+

Keep tweaking and hacking

+

Hopefully these little utilities were useful in someway, feel free to comment or offer advice by reaching out on twitter or adn.

+

Update

+

I forgot to mention that I have two documents, one called “functions” and the other “aliases”, which I source at the top of my .bash_profile like this (You can see all my dotfiles over on Github):

+
. /.dotfiles/bash/functions
+. /.dotfiles/bash/aliases
+

Sourcing these files makes the functions and aliases inside them available on the command line. To use any of the functions or aliases in this post you have to source them to your bash, then you can simply type the alias or function name plus any arguments:

+
vhost create
+hg term
+ht
+

Thanks to Jack McDade for the advice to include some examples.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html b/themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html new file mode 100644 index 0000000..145d6fe --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html @@ -0,0 +1,288 @@ + + + + + + A few POSIX shell tips + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A few POSIX shell tips

+ + +
+

I was recently working on the release build script for sb and decided I should document a few things I find myself looking up just about every time. One of the advantages of the POSIX shell (not bash, zsh, but Bourne shell, usually /bin/sh on most unix-y systems) is that it has a specification however I’m usually frustrated trying to find the information I need.

+ +

You can check it out here: https://github.com/sparkbox/sb

+ +

I prefer the POSIX shell because it’s the default on most unix-y system. If I have to be sure if the shell is installed on the target system (like bash or zsh) I’d rather just use a higher-level scripting language like node or ruby where the same requirement exists.

+

Arrays

+

Psych! There aren’t any arrays. Bash has arrays but POSIX does not. If I need an array structure I can use a space-separated string (or another delimiter if you’ve set $IFS) as the data structure, e.g. PLATFORMS="arm64-darwin amd64-linux amd64-darwin". Now I can loop over the variable using a for loop:

+
PLATFORMS="arm64-darwin amd64-linux amd64-darwin"
+
+for PLATFORM in ${PLATFORMS}; do
+  # GOOS=FOO GOARCH=BAR go build ...
+done
+

Or I can take the lack of arrays as a signal I should stop writing a shell script and reach for a language that has the concept of arrays to solve my problem.

+

Conditional “flags”

+

I often forget the various flags one can use in a conditional (aka test/if) statement. Here’s the documentation and here are a few of my favorites:

+
    +
  • -n tests if the string is non-zero, e.g.
  • +
+
if [ -n "${UPLOAD_URL}" ]; then
+    upload_file "${PLATFORM}"
+fi
+
    +
  • -z the opposite of -n.
  • +
  • -f tests if the pathname resolves to a file.
  • +
+

Functions and args

+
    +
  • Functions must be declared before they are invoked.
  • +
  • Functions look like:
  • +
+
someFunc() {
+  echo "a func!"
+}
+
    +
  • There is no syntax for functions accepting args instead they are mapped to $n. $@ is all the args.
  • +
+
upload_file() {
+    NAME=$1
+
+    zip "${NAME}.zip" "${NAME}"
+    curl -H "Accept: application/vnd.github.v3+json" \
+         -H "Authorization: Bearer ${GITHUB_TOKEN}" \
+         -H "Content-Type: application/zip" \
+         --data-binary "@${NAME}.zip" \
+         "${UPLOAD_URL}?name=${NAME}.zip"
+}
+
+upload_file "${PLATFORM}"
+

Use shellcheck

+

This is just preference but I really love using shellcheck to avoid any footguns and enforce a consistent style with my shell scripts. I typically invoke it like this: shellcheck -o all script-name.sh.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html b/themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html new file mode 100644 index 0000000..851ee36 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html @@ -0,0 +1,241 @@ + + + + + + A Fluid Userscript that adds Read it Later to Twitter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A Fluid Userscript that adds Read it Later to Twitter

+ + +
+

I use and love Craig Mod’s Twitter for Minimalists. It is a great way to experience the Twitter web client without some of the cruft. However, the biggest thing I miss from third party apps like Tweetbot is the ability to send interesting links directly to my Instapaper account with one click.

+

Since Twitter for Minimalists runs inside a Fluid instance I can set custom Userstyles (like Twitter for Minimalists) and Userscripts. I decided to write a Userscript that would parse through every tweet and determine if it had a link and - if it did - append a Send to Instapaper button to the bottom of the tweet. I was able to create the button using Instapaper’s iFrame Button API. You can find the the finished code for the Read it Later Userscript here.

+

Hope you find it useful!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-hackintosh/index.html b/themes/cycle/exampleSite/public/writing/a-hackintosh/index.html new file mode 100644 index 0000000..5c7810b --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-hackintosh/index.html @@ -0,0 +1,271 @@ + + + + + + A Hackintosh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A Hackintosh

+ + +
+

Taking the Hackintosh plunge

+

I built a PC (here’s the partslist) in May to replace my Xbox One (yay no more Live fees!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh. The process of getting a Hackintosh up and running wasn’t really that much more difficult than setting up Arch Linux. In fact I’d say you could and probably should follow most of the Arch Linux ideals about knowing what and why you’re updating as you maintain a Hackintosh.

+

Here’s a few tips and things I learned along the way. I’d also recommend reading through the tips in this reddit post.

+

Happy Path (Use Clover)

+

The ideal setup is to use Clover to add ktext and modify the config.plist in the /EFI partition. This leaves your actual macos install untouched. Avoid Unibeast and Multibeast, they try do too much and mask complexity. The truly “do-it-yourself” approach is outlined here. I ended up following a guide and using (and then modifying) their pre-made /EFI partition. Speaking of…

+

Find a guide

+

I combined and followed these two guides:

+ +

Keep it simple

+

Solve one thing at a time. Google error messages.

+

Use compatible parts

+
    +
  • I’d recommend an Intel KabyLake CPU since it’s the latest and greatest and it means you’ll need a 200 series motherboard which is recommended anyway. AMD CPUs are not really supported.
  • +
  • While my build uses the Pentium G4560 I wouldn’t recommend it as a great Hackintosh CPU. It works, but things would be smoother with an i5 or i7.
  • +
  • AMD GPUs (if you can find one at a decent price, damn you Etherium) have great native support now in 10.12.6, e.g. Metal Support!
  • +
  • Grab a WiFi/Bluetooth card from osxwifi.com, genuine Apple parts which means things just work (I’m content with no Bluetooth and Ethernet for now)
  • +
+

One OS per drive

+

Don’t try to partition a drive and install macos and Windows on it. Keep all operating systems on their own boot drives and then boot into them using Clover.

+

Disable hibernation if you’re on a Pentium

+

You’ll need to set two power management switches:

+

sudo pmset -a hibernatemode 0

+

sudo pmset -a standby 0

+
+

To disable hibernation images completely, ensure hibernatemode standby and autopoweroff are all set to 0. ~ pmset man page

+
+

I didn’t run into issues with autopoweroff.

+

Disable automatic updates.

+

You can still update through the App Store but it’s advised to wait and see if any ktexts or plist changes are needed before updating

+

That’s it. Hopefully this post helps clarify the process to create a Hackintosh of your own.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html b/themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html new file mode 100644 index 0000000..b801cac --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html @@ -0,0 +1,247 @@ + + + + + + A Little Hydrofoil + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A Little Hydrofoil

+ + +
+

While taking a short break today, I flipped over to Robin Sloan’s interview on the Setup. Now Mr. Sloan almost broke the Internet a few days ago with his book review in Javascript. In his interview for the Setup he described how he sees himself as a programmer,

+
+

I imagine professional programmers as jumbo jets, capable of cruising smoothly and swiftly at altitude for hours, no internet needed; by contrast, I’m just a little hydrofoil kinda bumping along, held shakily aloft by the ground effect of online documentation, code snippets and tutorial blog posts.

+
+

I totally identify with his analogy, and would wager most “jumbo jets” feel the same way. I think this ties into why I agree so strongly with Alex Sexton’s tweet from earlier this year (hat-tip to Motherfuton for the RT),

+
+

I think being skilled at debugging is probably more important than being skilled at coding.

+
+

Programming is problem-solving, hence my constant dips into Stackoverflow and Google. To extend Mr. Sloan’s analogy a bit more, even Jumbo Jets need maintenance and fuel.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-new-adventure/index.html b/themes/cycle/exampleSite/public/writing/a-new-adventure/index.html new file mode 100644 index 0000000..c745854 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-new-adventure/index.html @@ -0,0 +1,240 @@ + + + + + + A New Adventure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A New Adventure

+ + +
+

Today I started my new job working as a Front-End Developer at Sparkbox! I am thrilled at the opportunity to work with these guys and can’t wait for the adventures and challenges ahead.

+

Onward and upward.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html b/themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html new file mode 100644 index 0000000..6bf4fb0 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html @@ -0,0 +1,242 @@ + + + + + + A new website for 2020 + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A new website for 2020

+ + +
+
+

According to my Cargo.lock file, my website currently depends on 364 crates. So it’s really about standing on the shoulder of a carefully-curated set of giants.

+
+
+

364 may seem like a lot (and in a way, it is), but please reserve your judgement until after you’ve heard about everything it does.

+
+

I /love/ posts like this. Amos goes in deep on the decisions he made while re-writing his website from scratch. It’s a truly awesome post.

+

I’m seriously tempted to copy his SQLite full-text search implementation for this blog, but that’s a decision for another time.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-public-inbox/index.html b/themes/cycle/exampleSite/public/writing/a-public-inbox/index.html new file mode 100644 index 0000000..c0eddb5 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-public-inbox/index.html @@ -0,0 +1,248 @@ + + + + + + A public inbox + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A public inbox

+ + +
+

I’ve tried a few blog commenting systems in my day but have never really been happy with any of them. Part of the problem with comment systems is that a discussion forum is not a blog.

+

Recently I’ve noticed a few other folks (Drew, Ethan, Tom, and Jonnie) around the internet turning to email as the solution to have conversations about the things on their respective websites. I liked how Drew’s solution not only leveraged email but mailing lists! The benefits are pretty obvious to me:

+
    +
  • Folks are comfortable composing messages in their email client of choice
  • +
  • A mailing list is public
  • +
  • A mailing list is searchable
  • +
  • A mailing list facilities conversation.
  • +
+

So I’m gonna give it a spin. Here is my public inbox.

+

Of course I’ll always accept direct email at adam@adamsimpson.net.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html b/themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html new file mode 100644 index 0000000..42ebcba --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html @@ -0,0 +1,244 @@ + + + + + + A Style Guide, Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A Style Guide, Guide

+ + +
+

Thanks to @behoff for tweeting out Elyse Holladay’s blog post about a guide for style guides.

+

The post is a fantastic read, and is chock full of good information. I then clicked over to see what else Ms. Holladay had written and found her Hello World? post. It really resonated with my own reasons for starting this blog, especially this bit:

+
+

I realized two things have stopped me: the feeling of inadequacy that leads to the fear of not starting, and the need to get it perfect first.

+
+

I struggle with the same mindset. I’ve found the best way to get over it, is to just ship. So, congrats Ms. Holladay on shipping, and congrats on the blog, it’s awesome.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html b/themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html new file mode 100644 index 0000000..ed0551c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html @@ -0,0 +1,262 @@ + + + + + + Adam versus Dropbox and oAuth + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Adam versus Dropbox and oAuth

+ + +
+

Frustration post incoming. If you’d like to skip my ranting, watch this breakdancing bear. Otherwise, let’s keep going.

+

Update: I’ve posted an update below.

+

Stuck

+

I’ve never developed anything using Dropbox’s API or oAuth before. I’m assuming I’m making a horrible, noobish mistake somewhere in here. There is no official PHP SDK for Dropbox API. There are a couple libraries floating around, but they looked like overkill for the simple app idea I’m working on.

+

My problem is that when I try to request a token from Dropbox via PHP and cURL I get an ‘Error 4xx’. I’ve looked at the oAuth specs for the proper parameters to send in the header of the request, and right now my request looks like:

+

+[request_header] => POST /1/oauth/request_token HTTP/1.1
+Host: api.dropbox.com
+Accept: <em>/</em>
+Authorization: OAuth oauth_consumer_key="CONSUMERKEY", oauth_nonce="1340748835", oauth_signature_method="PLAINTEXT", oauth_timestamp="1340748835", oauth_version="1.0", oauth_signature="CONSUMERSECRET%26"
+Content-Length: -1
+Content-Type: application/x-www-form-urlencoded
+Expect: 100-continue
+

And this doesn’t yield a token, just ‘Error 4xx’.

+

Yet, when I paste in the full request in the address bar of Chrome:

+

https://api.dropbox.com/1/oauth/request_token?oauth_consumer_key=CONSUMERKEY&oauth_nonce=1340743892&oauth_signature_method=PLAINTEXT&oauth_timestamp=1340743892&oauth_version=1.0&oauth_signature=CONSUMERSECRET%26

+

I get my token back no problem. So I’m assuming something is wrong with the format of my cURL request.

+

The reason I’m using PLAINTEXT as the method is because of this post in the Dropbox forums. And, like I said, just entering in the request directly works fine.

+

Help

+

Any ideas? Let me know on Twitter @a_simpson. I’ll be sure to update this post once I get this problem sorted. So far, the lack of documentation for all this has been frustrating.

+

Update

+

Well I’ve sorted it out after sleeping on it, and breaking it all down again.

+

Turns out the cURL options array I was passing was incorrect. I was declaring CURLOPT_POST => true after several other POST-reliant options such as CURLINFO_HEADER_OUT and CURLOPT_POSTFIELDS. This mix-up was causing the request to error out. In retropect I should have realized that right away, oh well. Once I got the order straightened out, the request went through.

+

However, in my Googling to solve my problem I came across an awesome post from Wez Furlong detailing how to do HTTP requests in PHP without using cURL or any other library. I’ll let you read it, but all I’ll say is I switched to the solution he outlines, and I love it.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html b/themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html new file mode 100644 index 0000000..177d70f --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html @@ -0,0 +1,257 @@ + + + + + + ADN Cross-poster + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

ADN Cross-poster

+ + +
+

Recently I released a App.net to Twitter cross-posting app that runs via a single Heroku worker dyno (which means it’s free, gracias Heroku).

+

IFTTT Issues

+

For awhile I had been using IFTTT to crosspost any posts I made on App.net to Twitter, however there were two things I wasn’t totally thrilled with.

+

First, IFTTT automatically converts any links in your App.net post to bit.ly links, which stinks as I want the links in my intended format and style. The other thing IFTTT did poorly was how it handled posts that were longer than 140 characters. Since App.net posts can be up to 256 characters, sometimes a post will be too long for Twitter, IFTTT would simply chop your post at the 140 character point and be done.

+

Features

+

ADN-Crossposter specifically addresses these two complaints.

+

First, it leaves links alone. The app simply pushes your post text to Twitter.

+

Second, the app checks the character count of the App.net post and if it’s longer than 140 character it trims the post and adds a link to the App.net post, e.g. a read more link.

+

Get the app

+

Clone the app. Add your ADN username to the config.rb file. You can also choose how to handle @replies as well.

+

Twitter Setup

+

Since this is something that deals with Twitter there are a few steps involved in getting it up and running with their API. You will need to set up your own app within the Twitter dev panel. Your Twitter app needs to have read and write access to your Twitter account for this to work. Once you have the app created you will need to copy the four OAuth keys into the config.rb file.

+

You may need to regenerate your keys after changing your app from “Read” to “Read and Write”.

+

Heroku Setup

+

Create a Heroku app via the Heroku dashboard. Go back to your local git repo and add this Heroku app as a git remote.

+

Launch

+

Run git push HEROKU_REMOTE master after committing all the necessary changes to the config.rb file. Heroku will detect what type of app it is automatically. Now set your process or worker dyno to 1 via the Heroku dashboard or the command line, heroku ps:scale clock=1

+

Wrap Up

+

That’s it. Whew. If for some reason the app isn’t working, run heroku logs from the command line to see what the error was. If you still have issues, create an issue on Github with any log message you can.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html b/themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html new file mode 100644 index 0000000..34c15b5 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html @@ -0,0 +1,263 @@ + + + + + + Ajax and Rails + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Ajax and Rails

+ + +
+

This is just a short post to save a few links and document that “Server Javascript Responses” in Rails are still useful in 2018/19.

+

Lifecycle of SJR

+

The basic idea behind Server Javascript Responses (SJR) is diagrammed below:

+

img

+

SJR works like this:

+
    +
  1. +

    A User submits a form that has the Rails attribute remote=true on the form tag which makes the form submission happen via AJAX. See the Rails guide for more information.

    +
  2. +
  3. +

    The server receives the data payload and processes a response.

    +
  4. +
  5. +

    The Response from the server is a blob of JS not JSON that usually comes from a matching name.js.erb template.

    +
  6. +
  7. +

    The User’s browser receives the JS blog and evals the JS to update the page.

    +
  8. +
+ +
    +
  1. DHH’s original post
  2. +
  3. Medium post about eschewing fancy front-end frameworks for SJR
  4. +
  5. Ajax calls the Rails way
  6. +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html b/themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html new file mode 100644 index 0000000..1037892 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html @@ -0,0 +1,248 @@ + + + + + + Alfred and Web Development + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Alfred and Web Development

+ + +
+

Fellow web developer and all around awesome guy Adam Clark, put together two fantastic screencasts on his blog which demonstrate the power of Alfred and how to enhance common front-end workflows. Inspired by his post, I thought I would start sharing some tips on how I use Alfred throughout the day.

+

I use Alfred 57.4 times a day. It’s awesome, so awesome that it has replaced Spotlight on my Mac. I have two custom searches that relate directly to front-end development, a Mozilla Developer Documentation custom search, and a Can I use custom search. These shortcuts allow me to:

+
    +
  1. Invoke Alfred
  2. +
  3. Type “cani” or “mdn” followed by a space.
  4. +
  5. Type my query, i.e. “background-size”
  6. +
  7. Hit Enter and see the resulting documentation or caniuse page for the query.
  8. +
+

Here are the actual URLs as I set them up in Alfred: https://developer.mozilla.org/en-US/search?q={query} http://caniuse.com/#search={query}

+

This is a simple thing to setup, and it probably only saves a few seconds, but it feels friction-less which is the whole point of using Alfred.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html b/themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html new file mode 100644 index 0000000..4bea5cf --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html @@ -0,0 +1,245 @@ + + + + + + AMP HTML, Terrible HTML + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

AMP HTML, Terrible HTML

+ + +
+

Seriously, how could this possibly go wrong?!

+

AMP HTML is another middle finger to publishers and ad companies everywhere, and in the process it throws the baby out with the bath water. Essentially Google is saying to publishers and ad companies, “You can’t responsibly handle the power the web gives you. So here’s something far more limited. Enjoy.”

+

I agree with the first part, but is the answer developing a subset of HTML/JS/CSS?

+

+

Update

+

This post explores my misgivings in more detail:

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html b/themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html new file mode 100644 index 0000000..5919db8 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html @@ -0,0 +1,242 @@ + + + + + + Andy Budd on Time + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Andy Budd on Time

+ + +
+

Fantastic Pastry Box post from Andy Budd, I’ll quote the final thought here, but it’s worth it to read the entire thing

+
+

The best designers and developers rarely have more talent. They simply have more time.

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html b/themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html new file mode 100644 index 0000000..2ed731e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html @@ -0,0 +1,247 @@ + + + + + + A Moment of Clarity Regarding the Raison d’Etre for the App Store + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

A Moment of Clarity Regarding the Raison d’Etre for the App Store

+ + +
+
+

I’d like to see all the vim, vigor, and vigilance Apple applies to making sure no app on the App Store is making a dime without Apple getting three cents applied instead to making sure there aren’t any scams or ripoffs, and that popular apps support good-citizen-of-the-platform features within a reasonable amount of time after those features are introduced in the OS. I don’t know exactly how long “reasonable” is, but five fucking years for split-screen support ain’t it.

+
+

I’ve been thinking the same thing ever since the Hey app rejection right before WWDC. The App Store is supposed to be a place to get software that has been vetted by Apple but there seems to be a growing disconnect between what users imagine that vetting is and what Apple is doing.

+

I want to believe this tweet by Ben Evans is the goal of the App Store:

+ +

If we can trust the apps that come out of the App Store:

+
    +
  • why is the US considering banning TikTok because of its rampant data collection?
  • +
  • why do we need a new notification in iOS 14 when apps query the clipboard?
  • +
  • why do we need a microphone/camera indicator at the system level?
  • +
+

Maybe I was naive and alone in my assumption that Apple would root this stuff out during the review process. If they’re not rooting this out then what is the point of the review process at all?

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html b/themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html new file mode 100644 index 0000000..cf374c7 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html @@ -0,0 +1,247 @@ + + + + + + Apple on batteries and performance + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Apple on batteries and performance

+ + +
+

Apple released a statement on the battery and performance issues.

+
+

Apple is reducing the price of an out-of-warranty iPhone battery replacement by $50 — from $79 to $29 — for anyone with an iPhone 6 or later whose battery needs to be replaced, starting in late January and available worldwide through December 2018. Details will be provided soon on apple.com.

+
+

This is the penalty for not being clear with users. How and why did Apple make this so opaque? It continues to baffle me.

+
+

Early in 2018, we will issue an iOS software update with new features that give users more visibility into the health of their iPhone’s battery, so they can see for themselves if its condition is affecting performance

+
+

This is what should have been in iOS when the processor management feature was released.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/atr2100/index.html b/themes/cycle/exampleSite/public/writing/atr2100/index.html new file mode 100644 index 0000000..02288f1 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/atr2100/index.html @@ -0,0 +1,249 @@ + + + + + + ATR2100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

ATR2100

+ + +
+

I recently purchased the ATR2100 mic to use for work calls and maybe some podcasting in the future. I stumbled upon the ATR2100 via Marco Arment who has a great roundup of good podcasting mics that I highly recommend if you want to explore mics. I ended up picking up an Amazon bundle that included a Knox boom arm, Knox pop filter, and the ATR2100 for around $90. I don’t see it on the site anymore but you could cobble together the same bundle pretty easily.

+

Requirements

+

These were my requirements for upgrading from the built-in mic on my laptop/webcam:

+

Sound good with little effort

+

Obvious but important. I didn’t want to have to fiddle with things to achieve better sound. I also didn’t want to invest in a DAC or other ancillary equipment.

+

Reduce background noise

+

My office at home is in the basement right below my 3 year-old daughter’s room. Kids make noises from time to time and I wanted a mic that would not pick those up.

+

Be under $100

+

I didn’t have the budget to go get a premium mic.

+

Verdict

+

I’ve used the mic for some gaming and Zoom calls and in both cases I’ve gotten several comments that my voice sounds “radio quality” and “really clear”. I have zero complaints with the mic and I can’t recommend it enough. I will note that this type of mic requires you to be about 2-6 inches away for optimal volume and quality. This is the cost of not picking up those background noises I mentioned above in my requirements. Windows 10, Linux (Pop_OS), and macOS all recognized the mic without any drivers or needing any configuration. If you’re looking to upgrade your audio on a budget look no further than the ATR2100.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html b/themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html new file mode 100644 index 0000000..ae64e03 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html @@ -0,0 +1,253 @@ + + + + + + Automating SOCKS proxy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Automating SOCKS proxy

+ + +
+

I’ve used a SOCKS proxy while on public WiFi ever since reading Paul Stamatiou’s article years ago. I recently took the time to automate the setup process.

+

Paul’s article provides a good overview of what the heck a SOCKS proxy is and why it’s beneficial, so I won’t focus on any of that here. Just know that setting up a SOCKS proxy on a Mac is a multi-step process. This process led me to create two bash functions; one to start it and another to shut it down.

+
function tunnel_off {
+  PID="$(ps aux | grep $1 | grep -v grep | awk '{print $2}')";
+  kill ${PID} && networksetup -setsocksfirewallproxystate Wi-Fi off;
+}
+
+function tunnel {
+  ssh -D 8080 -f -q -N $1 && networksetup -setsocksfirewallproxystate Wi-Fi on
+}
+
+

I do need to pass the ssh server name (configured in ~/.ssh/config) I want to use, e.g. tunnel vpn.

+

The only setup is to manually configure which port I want to use for the SOCKS proxy, I set that in System Preferences under Network:

+

The best part is the networksetup -setsocksfirewallproxystate command. This command makes the whole thing go by toggling the proxy on and off.

+

For extra credit, I use the fantastic TextBar utility to monitor if the ssh connection is active and display the lightning emoji in my menu bar if it is. I now know when the proxy is running or not by glancing up at the menubar.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/balancing-devotion/index.html b/themes/cycle/exampleSite/public/writing/balancing-devotion/index.html new file mode 100644 index 0000000..b208101 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/balancing-devotion/index.html @@ -0,0 +1,259 @@ + + + + + + Balancing Devotion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Balancing Devotion

+ + +
+

After watching Indie Game: The Movie I couldn’t help but think of the Robert Louis Stevenson quote that Shawn Blanc used a few weeks ago:

+
+

Perpetual devotion to what a man calls his business, is only to be sustained by perpetual neglect of many other things.

+
+

In the movie, the game designers and developers pour their lives into creating these games. At one point in the movie, the creator of Fez said he would literally kill himself if he were unable to finish and release it. Thankfully, he released Fez in 2012 to wide acclaim. Despite his success, his quote still bothers me. Suicide over a game?! I don’t get it.

+

Matthew Smith of Zaarly, recently wrote for the Pastry Box Project:

+
+

Turn off your phone when you get home. Off. Don’t just put it on the counter. Turn it off for a few hours at least each day. Why? So that you’re not always available to others. Be available to yourself. Be available to your family. Then at 8am when you turn your phone back on, you can be fully available and totally present.

+
+

Matthew is talking about disconnecting from the interewbs in order to recharge, and be a better son/father/daughter/wife/mother/roommate/friend/neighbor/whatever. I struggle with disconnecting, while I don’t have the same intensity as suicide over a game, it’s the same kind of devotion, and I know how easily it creeps in.

+

This all makes me wonder if it is possible to create something truly extraordinary without causing everything else to wither? In one of the most recent entries on The Pastry Box, Molly Holzschlag tries to answer this question.

+
+

Here’s some advice from the heart: There is nothing wrong with giving your life to an ideal. I have done it, and the rewards are rich— friends from all over the world, respect from my peers, to have traveled much of the earth and been made welcome upon it—that is the miraculous part of giving your work your all, it comes back. Just don’t let what happened to me happen to you—the work, the ideal takes over too young and for too long, and you could easily end up childless or without family, with little or no life structure or real measure of how to reconcile this elusive balance.

+
+

She acknowledges that to achieve something extraordinary you have to devote yourself to it. Her solution is to not devote yourself for so long that you are left with nothing. That’s the trick.

+

I think there has to be a better way than planning to “wake up” before your 30s are gone. As I was writing this post yesterday, Jack McDade posted a short note that was exactly what I was trying to say. He wrote:

+
+

So how do you “switch off”? It’s not hard when you have perspective. You just switch off. Boy does it feel great.

+
+

Hes got it. There isn’t a secret way to achieve both a great product and a healthy life outside of it. I believe it’s possible to do both, not keeping them in balance is just much easier. Keeping that balance is a constant struggle, it’s a fight, it’s learning how to say “no” at the right times, it’s turning your phone off when you get home. Hell, merely going home at 5 or 6 helps the balance.

+

To keep it all in balance, you just have to do it.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html b/themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html new file mode 100644 index 0000000..e18c1f3 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html @@ -0,0 +1,246 @@ + + + + + + Bash Function - IP Address to Clipboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Bash Function - IP Address to Clipboard

+ + +
+

I have to admit, I am addicted to customizing my bash experience. Yesterday, I came up with a little, one-off function that smooths over a point of friction in my workflow – working with my internal IP address.

+

During any project, I am often testing in virtual machines. On my development machine I have my host file hacked to manage all the dev URLs. The friction point is constantly having to look up my IP address to test in VMs, or on other devices. This bash function simply parses out my IP address from the results of ‘ifconfig’ and copies that IP address to my clipboard. Now, instead of jumping into the Network pane to see my IP, or reading through ifconfig myself, I can simply type “ip”, and jump back to my VM and paste in the address. The function also displays the IP address on the command line ready for easy typing into a mobile device.

+
function ip {
+  IP=$(ifconfig | grep 'inet 1' | cut -c 6- | awk 'NR==2 {print $1}')
+  echo $IP
+  echo $IP | pbcopy
+}
+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html b/themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html new file mode 100644 index 0000000..ed95bfd --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html @@ -0,0 +1,248 @@ + + + + + + Be a good video call citizen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Be a good video call citizen

+ + +
+

Ah the video call. Usually fraught with 5 minutes of “Can you hear me now?”, distorted faces, or your two children in the background. I’ve been in my fair share of video calls and I thought I’d share a few tricks that help limit my contributions to the chaos.

+

Be a few minutes early.

+

If you’re there early you can get any hiccups (technical or otherwise) out of the way before the meeting actually starts. No fancy technical trick here.

+

Keep your workspace neat

+

Again, not a technical solution but a practical one. Limit the distractions you may present by having a tidy workspace. Pay special attention to what’s behind you before you get on a call. Everyone’s been laughing at poor Professor Kelly recently but notice that he clearly spent some time before the call trying to make his background look good.

+

Use a cough button (aka push-to-talk)

+

I love the Shush app. It works at the system level to mute or unmute your microphone and binds that action to a hotkey. Shush is fantastic because you don’t need to remember where each video service stashes its mute button. The ability to quickly toggle mute is a super power that goes a long way towards minimizing any distractions you may create while on the call.

+

There you have it, my top three tips for video calls. Do you have any other tips? Let me know about them on twitter and I’ll list them below.

+

Replies

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/before-circles-2017/index.html b/themes/cycle/exampleSite/public/writing/before-circles-2017/index.html new file mode 100644 index 0000000..06d77b8 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/before-circles-2017/index.html @@ -0,0 +1,253 @@ + + + + + + Before Circles 2017 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Before Circles 2017

+ + +
+

I’m currently sitting on an airplane headed to Grapevine, Texas for Circles Conf. Circles Conf is a design conference that I’ve kept an eye on for the last couple years. I specifically chose this conference because it wasn’t a development conference. As a frontend developer, I think it’s important to be well-rounded in all aspects of the frontend and that includes design. I feel like the last couple years I’ve invested deeply in Javascript and all the incredible ways frontend code is changing. However, I think it’s time to work out a different set of muscles. So, I’m headed to a design conference as a frontend developer and I don’t see a single talk about “Slack bots with Node” (or something about “Serverless and React”) on the schedule and I’m super pumped.

+

Expectations

+

I thought I’d list out a few of the talks I’m looking forward to and what I hope to come away with. I think the entire lineup looks great but there are a few TBA slots with no title so I have no idea what to think about those. I’m hoping to review this post after the conference and use it as a kind of guide to digest everything that happened.

+

Panels

+

I have no idea what to expect from the scheduled Panels. There is one each day maybe this will be some solid Q/A or good round-table discussion?

+

Dan Rubin

+

I’m excited to hear Dan Rubin. I’ve followed Dan on Twitter and Instagram for some time but I’ve never heard him speak.

+

Ash Huang

+

I’ve never heard of Ash until I saw the speaker line-up, but she’s seems like a prolific writer and deep thinker. Her talk is called “Design was supposed to be The Answer” and I can’t wait to hear it. I also think there is a talk called “Javascript was supposed to be The Answer” just waiting to be written.

+

Jay Argaet

+

I’m a fan of Hillsong’s music along with their branding and art direction. I’m curious to hear what Jay has to say about “Unlocking Creativity”.

+

Annette Neu

+

The topic for Annette’s talk resonates with me. I often feel unsure how to begin on a problem that has lots of uncertainty surrounding it. I’m confident this will apply to all creative disciplines (e.g. development as well as design).

+

Here we go

+

So there you have it. My scant expectations on what I’m looking forward to at Circles Conf. If you’re attending Circles don’t hesitate to say hi (or hit me up on twitter) and get a swanky Sparkbox business card!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html b/themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html new file mode 100644 index 0000000..11de1a9 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html @@ -0,0 +1,254 @@ + + + + + + Benedict Evans is on fire + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Benedict Evans is on fire

+ + +
+

I’ve been behind my pinboard unread queue for a few days and consequently have been missing the truth pouring out of Benedict Evans.

+

His last three pieces are right on the money regarding mobile, and the web versus native apps.

+

Starting with Mobile First, he says:

+
+

[…]the smartphone itself is an internet platform in a way that a PC was not. On a PC the web browser was the internet platform, but on a smartphone it’s the entire device and the browser is turned from ’the internet’ to one icon, just a phone calls turned from the purpose of the device to just one icon.

+
+

Then in Apps versus the web he finishes the piece by saying:

+
+

In either of these cases - whether you have an app and a website or just a website, you should presume that your customers will engage with you only on mobile.

+
+

And finally his last piece The future is mobile and apps, except that it isn’t he writes:

+
+

So the mobile experience needs to be complete. That might, paradoxically, mean that your total experience might need to be edited, to fit, but it’s dangerous to pick a subset of your offer and put just that on mobile - it might be your only touch point. Conversely, one could argue that in some cases it’s the desktop experience that should be a subset of the mobile one.

+
+

Complete

+

The mobile experience needs to be complete, and that experience can be just a website, or just an app, or both. Regardless it needs to be complete. Complete is the operative word that binds these thoughts together. As we saw last week, complete includes performance, especially performance on mobile.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html b/themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html new file mode 100644 index 0000000..c9b5dae --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html @@ -0,0 +1,286 @@ + + + + + + Better scripting with gh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Better scripting with gh

+ + +
+

I’ve become a big fan of the gh CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. Instead of using curl with a Github token and the Github API, I can simply use gh. What’s even better is that in more advanced situations where there isn’t a valid subcommand for what I want to script, I can use the gh api escape hatch to do curl-style HTTP requests to the API without messing with authentication or even pagination. Here are two recent scripts I wrote that highlight the power and convenience of gh.

+

PR Kudos

+

I created this script to help me give better kudos to folks in our retro meeting. When I provide a Github team name as an argument, it displays all PRs from members of that team. What I really like is that it only shows PRs from the last two weeks, which gives me a nice overview of recent activity.

+
#!/bin/bash
+
+start=$(date -d "2 weeks ago" +%Y-%m-%d)
+end=$(date +%Y-%m-%d)
+
+details=$(gh api /orgs/grafana/teams/$1 | jq -r '"\(.id),\(.organization.id)"')
+teamId=$(echo ${details} | cut -d , -f 1)
+orgId=$(echo ${details} | cut -d , -f 2)
+
+gh api "organizations/${orgId}/team/${teamId}/members" | \
+  jq -r '.[] | .login' | \
+  xargs -I % gh search prs --author=% --created="${start}..${end}" \
+  --json="state,repository,url,title,updatedAt,author" --template '{{range .}}{{tablerow (.author.login | autocolor "green") (hyperlink .url .title) (.repository.name | autocolor "blue") (.state | autocolor "red") (timeago .updatedAt)}}{{end}}
+{{tablerender}}'
+

Notification OCD

+

The second script focuses on managing notifications related to pull requests and issues. I usually find that about one-third of my notifications are for merged PRs, PRs created by bots, or closed Issues. I don’t care about these types of events. With this script, I can mark those notifications as done, which reduces clutter in my GitHub notifications and helps me see important updates. As I mentioned above, one cool feature of the api subcommand is that it allows me to consume all possible pages of a response using the --paginate flag, eliminating the need for a loop + token field dance!

+
#!/bin/bash
+declare -A typeLookup
+typeLookup["PullRequest"]="pull"
+typeLookup["Issue"]="issues"
+
+resp=$(gh api /notifications --paginate | jq -r '.[] | select(.subject.type == "PullRequest" or .subject.type == "Issue") | "\(.repository.full_name),\(.subject.url),\(.id),\(.subject.type)"')
+
+for x in $resp; do
+  name=$(echo "${x}" | cut -d ',' -f 1)
+  id=$(echo "${x}" | cut -d ',' -f 3)
+  number=$(basename $(echo "${x}" | cut -d ',' -f 2))
+  ofType=$(echo "${x}" | cut -d ',' -f 4)
+  urlType=$(echo ${typeLookup["${ofType}"]})
+  isBot="false"
+
+  if [ "${ofType}" == "PullRequest" ]; then
+    isMerged=$(gh pr view --repo "${name}" "${number}" --json closed | jq -r .closed)
+    isBot=$(gh pr view --repo "${name}" "${number}" --json author | jq -r .author.is_bot)
+  fi
+
+  if [ "${ofType}" == "Issue" ]; then
+    isMerged=$(gh issue view --repo "${name}" "${number}" --json closed | jq -r .closed)
+  fi
+
+  if [ "${isMerged}" == "true" ] || [ "${isBot}" == "true" ]; then
+    echo "marking https://github.com/${name}/${urlType}/${number} as done..."
+    gh api -X PATCH "/notifications/threads/${id}"
+  fi
+done
+
+
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/blog-rewrite/index.html b/themes/cycle/exampleSite/public/writing/blog-rewrite/index.html new file mode 100644 index 0000000..422bdfb --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/blog-rewrite/index.html @@ -0,0 +1,298 @@ + + + + + + Blog rewrite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Blog rewrite

+ + +
+

I haven’t posted here recently. That’s largely because I did the classic “Time to rewrite the blog, I’ll post when it’s done” thing. Well it’s not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I’m trying to rectify that now with some scant and scattered sentences.

+

Current setup

+

The blog is currently built using a custom Node app that lives inside a few AWS lambda functions.

+

To begin with I created my own auth system (insert eyeroll emoji I know) which works like this:

+

Image depicting the AWS Lambda system that provides authentication for my blog.

+

Once the user is authenticated they can create posts which looks like this:

+

Image depicting the various stages of the AWS Lambda system that creates posts.

+

Benefits

+

The benefits of my current setup are:

+
    +
  1. Entirely static.
  2. +
  3. No server to maintain.
  4. +
  5. Provides ability to post from my phone using the /admin interface in the browser.
  6. +
+

Drawbacks

+

The things pushing me to consider a re-write, are:

+
    +
  1. Local development is hard. The site generation is very tightly coupled to Lambda. There is no local server option for /admin.
  2. +
  3. Because of its disorganized nature it’s getting harder to maintain and add features (high microservices :wave:).
  4. +
  5. Fully reliant on AWS stack (Lambda, DynamoDB, Cognito, S3, CloudFront, Certificates, Route53).
  6. +
+

Where do I want to go?

+

I’m thinking of moving towards what I call “The Jekyll model”: an engine to build the site. I could then combine that engine with the following functionality to fill in the gaps:

+
    +
  1. Mobile publishing via SFTP of markdown files to a VPS/home server.
  2. +
  3. Use a file system watcher to trigger new builds when a new post is uploaded/changed.
  4. +
  5. Built site is uploaded to Netlify, S3, or Github pages. Keep it static.
  6. +
+

Going this route addresses all the Drawbacks but introduces a server to maintain. I’m OK with that change if I can iterate on design changes quicker than I can now, did I mention how painful that is currently? The one aspect of this I don’t have solved completely is post metadata (remember currently I’m using SQLite as my DB). I’m not a huge fan of the front-matter + markdown file approach because I’d rather have my data in a more standard data structure, e.g. a JSON file per post or something. If I go with a JSON file per post then I need to create something to generate that file upon post creation or modification. The other option is to keep using SQLite I guess.

+

Image outlining how a potential new system would work for the blog.

+

The Engine

+

The above should work. I just need something that consumes markdown and can match my existing URL scheme. I’ve ping-ponged back and forth between the following options:

+
    +
  • +

    Common Lisp

    +

    I initially thought I would build out the engine myself in Common Lisp (to get more experience in CL). Part of the draw of Common Lisp was that I could create an executable and send that to the server and not have to install a bunch of dependencies just to get it to run. However the lack of a markdown library that supports code-fencing (which I use extensively) has killed the idea (and my spirit).

    +
  • +
  • +

    Jekyll/Hugo/Gatsby

    +

    I toyed with just using Jekyll/Hugo but I would have to convert every post to MD + front matter. That sounded like a pain. I’ve also thought about using GatsbyJS but that introduces a ton of new tech that my site doesn’t need.

    +
  • +
  • +

    Node

    +

    I don’t really want to do Node again because:

    +
      +
    1. I’ve done a lot of Node recently
    2. +
    3. Requires installing dependencies and language runtime on server.
    4. +
    +
  • +
  • +

    Emacs

    +

    This one is the craziest idea I’ve had. Use an Emacs docker container + org-mode + some command line magic to have Emacs with org-mode be responsible for publishing the HTML for my site.

    +
  • +
  • +

    Rust

    +

    I’m currently considering upping my fledgling Rust game and writing my engine in Rust. I can then create a binary and ship that to a server. And yes, before anyone asks I already checked and there are several solid looking markdown crates (libraries).

    +
  • +
+

Now what?

+

I have no idea where this leaves me. This post has been a thinking/documentation exercise for me more than a post. I think I’ll keep exploring the Rust option and see where that leads me.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html b/themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html new file mode 100644 index 0000000..ddd71c3 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html @@ -0,0 +1,255 @@ + + + + + + Blogs, data, and social networks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Blogs, data, and social networks

+ + +
+

Anil Dash wrote a piece last week advocating for a transition from “page-centric” publishing platforms to “stream-centric”. He points to services such as Twitter, Facebook, and even Tumblr as examples for why stream-based publishing platforms are the future. His observation that the only reason the “old page model” is still around is because of advertising is spot-on and well said.

+

However, Dash misses on one big point in his post, he writes:

+
+

So: Start publishing streams. Start moving your content management system towards a future where it outputs content to simple APIs, which are consumed by stream-based apps that are either HTML5 in the browser and/or native clients on mobile devices.

+
+

These APIs already exist, we call them RSS. We don’t need a ton of VC money, and developers and designers to solve this problem; it’s already solved. What we need are those designers and developers to start creating tools that work on top of the existing RSS/Atom layer.

+

After reading Dash’s article, I stumbled across Scott Hanselman’s post on blogging. He starts off with a bang, and I’ll just post it here,

+
+

You are not blogging enough. You are pouring your words into increasingly closed and often walled gardens. You are giving control - and sometimes ownership - of your content to social media companies that will SURELY fail. These companies are profoundly overvalued, don’t care about permalinks, don’t make your content portable, and have terms of service that are so complex and obtuse that there are entire websites dedicate to explaining them.

+
+

Interesting uh? This blog right here is mine; I own the content, the URL, the design, everything. I have structured it so that each item has a permanent link for people to save, retweet, share, whatever. I don’t have to worry about this great service I use being bought by someone else and killed off as a “talent acquisition”. I still use Twitter of course, and I have an app.net account, but the “important” pieces of data, flow from this blog to those streams.

+

Scott ends his post by asking a simple question:

+
+

You want control? Buy a domain and blog there.

+
+

He’s right. Start blogging, and start re-thinking how that blog looks and functions. Mr. Dash is right too, streams are the better way to go, the beauty of it is that blogs can easily be streams. I know I have a couple ideas that I want to experiment with right here in the coming months.

+

So get to it, start a blog. Make something, stop whining, and enjoy the incredible era we live in.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html b/themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html new file mode 100644 index 0000000..eed83c5 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html @@ -0,0 +1,241 @@ + + + + + + Britain goes coal free as renewables edge out fossil fuels + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Britain goes coal free as renewables edge out fossil fuels

+ + +
+
+

Britain is about to pass a significant landmark - at midnight on Wednesday it will have gone two full months without burning coal to generate power.

+
+
+

A decade ago about 40% of the country’s electricity came from coal; coronavirus is part of the story, but far from all.

+
+

This is fascinating. The UK has been aggressively investing in renewable energy sources for years and it appears all that investment is starting to catch up with demand.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/broadcast-channel/index.html b/themes/cycle/exampleSite/public/writing/broadcast-channel/index.html new file mode 100644 index 0000000..13edb9f --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/broadcast-channel/index.html @@ -0,0 +1,239 @@ + + + + + + Broadcast channel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html b/themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html new file mode 100644 index 0000000..172dd64 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html @@ -0,0 +1,253 @@ + + + + + + CasperJs, Node, and the Raspberry Pi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

CasperJs, Node, and the Raspberry Pi

+ + +
+

So I’ve been working on a pet project today, getting my Raspberry Pi to be a dedicated screen-scraping machine.

+

I’m still in the middle of getting things working, so I’ll be updating this post as I figure more stuff out. This post is intended to be a log for myself and hopefully a helpful resource for others.

+

Boot Image

+

I’m using the Raspbian Jessie image provided by Raspberry Pi. To create and backup my SD card images I’m using the excellent ApplePi Baker app. It provides a GUI wrapper around some gnarly command line tools to flash images to the Raspberry Pi SD card.

+

Installing Node

+

This post by Conall Laverty shows exactly how to get node and npm up and running on a Pi. I tried using the apt-get manager like I do with a VPS and the Pi wasn’t liking it.

+

Installing CasperJS and Phantom

+

Another helpful post by Alexander Bilz shows how to get casperjs and a specialized version of phantomjs working on the Pi.

+

I’ve run into issues with the 1.9.8 version of phantom compared to the 2.0 version on my laptop. Finding a compiled binary of 2.0 has proven to be quite difficult. So I’m on hold for now until I can get a 2.0 version running.

+

Troubleshooting

+

Since I’m using my Pi headless, I’m configuring everything over ssh. Sometimes this just doesn’t work well. I’ve found VNC to be a nice solution in those cases. This post has simple instructions for getting a VNC server up and running on your Pi. I use Chicken VNC as the client on my Mac to connect to the Pi’s server.

+

Speed

+

The Pi is slow. Really slow. I’ve found adding some casper.waits to my code have helped iron out some random errors.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/command-line-notification/index.html b/themes/cycle/exampleSite/public/writing/command-line-notification/index.html new file mode 100644 index 0000000..c9d4efc --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/command-line-notification/index.html @@ -0,0 +1,241 @@ + + + + + + Command line notification + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Command line notification

+ + +
+

This week I wrote a bash function that curls the SendGrid API and sends a Boxcar notification. This is useful to chain to the end of long-running commands, e.g. transcoding a video. When the command finishes I get a push notification on my phone.

+

If you’re unfamiliar with the various ways to chain commands together in bash, here’s a cheatsheet. One thing I didn’t know is that you can combine the various operators like long-running command || alert "failure!" && alert "success!".

+

Happy scripting.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html b/themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html new file mode 100644 index 0000000..9c15430 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html @@ -0,0 +1,249 @@ + + + + + + Compose key and i3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Compose key and i3

+ + +
+

The compose key on Linux and other systems enables you to enter symbols like ™ that don’t have a dedicated key on most keyboards. GNOME makes this easy to do via Gnome Tweaks. However, using a window manager like i3 means there’s no dedicated GUI for changing the hotkey for compose.

+

This stackexchange answer sent me down the right path of adding the following config to ~/.Xmodmap to bind Caps lock to compose:

+
.keysym 66 = Mode_switch
+clear Lock
+

You can then enable the key map by running:

+
xmodmap ~/.Xmodmap
+

However, that config didn’t work because Mode_switch wasn’t the right name for the compose key (at least under Ubuntu/PopOS 20 for me). The Arch Wiki states that the name for the compose key is actually Multi_key. With this new name I was able to get Caps lock to act as the compose key by updating the config in ~/.Xmodmap to:

+
keycode 66 = Multi_key
+clear Lock
+

The final step is to set that mapping every time i3 runs by putting this inside your i3 config file like so:

+
exec --no-startup-id "xmodmap ~/.Xmodmap"
+
+
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html b/themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html new file mode 100644 index 0000000..9a6d18a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html @@ -0,0 +1,241 @@ + + + + + + The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet

+ + +
+
+

Janet Hutchins had the day off from her job as a nurse at a local hospital. She had been in town catching up with friends and had just gotten home and started making dinner. So she had only the slightest sense of the crisis that her colleagues had been dealing with across the NHS. That’s when her son came upstairs and told her, a little uncertainly, that he seemed to have stopped the worst malware attack the world had ever seen.

+
+
+

“Well done, sweetheart,” Janet Hutchins said. Then she went back to chopping onions.

+
+

It’s hard to pick my favorite section from this article about Marcus Hutchins — the hacker who stopped the WannaCry malware attack.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/convince-the-boss/index.html b/themes/cycle/exampleSite/public/writing/convince-the-boss/index.html new file mode 100644 index 0000000..1c4de90 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/convince-the-boss/index.html @@ -0,0 +1,247 @@ + + + + + + Convince the Boss + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Convince the Boss

+ + +
+

Speaking of cultivation and passion, Jeremy Keith wrote up a great post on how to convince one’s boss or client to adopt new web standards or methods.

+
+

I do sometimes wonder whether we use the big bad client or the big bad boss as a crutch. “Oh, I’d love to try out this technique, but the client/boss would never go for it. Something something IE6.” Maybe we’re not giving them enough credit. Given the right argument, they might just listen to reason.

+
+

Go work on getting the right arguments for your specific client or boss, go cultivate a metric-ton of data to overwhelm whoever is holding back progress. No one is going to reach out and whack your boss or client with a “Web Standards Genius” stick for you, do the whacking yourself (figuratively, I do not endorse or condone violence against one’s superiors, peers, or underlings). If after all that effort you’re still not getting anywhere, then follow Mr. Keith’s other piece of advice:

+
+

Another tactic that I’ve used in the past is to simply not ask for permission, but go ahead and use the new technologies and techniques anyway.

+
+

Go do.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/create-passion/index.html b/themes/cycle/exampleSite/public/writing/create-passion/index.html new file mode 100644 index 0000000..5eea455 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/create-passion/index.html @@ -0,0 +1,243 @@ + + + + + + Create Passion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Create Passion

+ + +
+

I’m slowly working my way through the latest edition of The Manual Vol. #3. I just finished Tiffani Jones Brown’s excellent essay on Practicing Passion. This quote really stuck with me,

+
+

Instead of asking “what will make me feel passion?” we should ask, “how can I make passion happen?” The answer is to cultivate a way of living and working that makes passion more likely.

+
+

I love this, it doesn’t leave room for me to have any excuses. Cultivation takes effort, perseverance, hard work, and purpose. Time to get to work, the passion will show up if I do.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/css-reusability/index.html b/themes/cycle/exampleSite/public/writing/css-reusability/index.html new file mode 100644 index 0000000..25d7878 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/css-reusability/index.html @@ -0,0 +1,248 @@ + + + + + + CSS Reusability + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

CSS Reusability

+ + +
+

Chris Coyier posted a great question over at CSS-Tricks.

+
+

You’ve probably coded up something like that, right? How many times? A lot? Did you do it from scratch each time?

+
+

I’ll be honest, aside from the usual normalise.css I don’t re-use much CSS. Unlike PHP or JS, where I re-use a lot of code.

+

Chris continues on in the comment thread,

+
+

If a developer needs a login function for a website, do they write it from scratch? I bet very rarely. They use an existing project (e.g. a CMS like WordPress) or a modular component to a framework (e.g. a Rails gem). What makes back-end so code much more reusable?

+
+

Chris has a great point. I know the obvious answer is that CSS deals with layout and design, which is wildly different from project to project. Yet, I think he’s on to something, I need to be more efficient with the code I write. I can be more efficient by starting to think about CSS in a more modular way, what little re-usable objects or chunks can I carry from project to project?

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html b/themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html new file mode 100644 index 0000000..14d30f3 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html @@ -0,0 +1,241 @@ + + + + + + cycle v0.3.0 released + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

cycle v0.3.0 released

+ + +
+

I just released v0.3.0 of cycle.

+

This version uses Chroma for syntax highlighting instead of Pygments. I never got Pygments running correctly in Netlify’s build environment. Chroma requires no dependencies since it’s distributed as a static binary and it’s also faster due to being written in golang.

+

This version also refactors the main function to accept an optional working directory arg. This allows me to build a site via the CL REPL. It also shortens the feedback loop to try out new features.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html b/themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html new file mode 100644 index 0000000..668313c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html @@ -0,0 +1,247 @@ + + + + + + Dead Cells might be a perfect game + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Dead Cells might be a perfect game

+ + +
+

Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it). It only took a few minutes before I felt like a total badass running around squashing baddies. However, that feeling is tempered by the fact that this game is quite fiendishly difficult.

+

It’s available on Steam for Mac, Linux, and Windows. It’s also available on most consoles, including the Switch, and recently iOS.

+

I was so impressed with this game I went hunting around for information on the creators of the game, Motion Twin. I found this documentary on Youtube about the studio and the game which is quite good:

+ + + +

There’s also this video which highlights some of the smart ways the developers made the game feel better to players:

+ +

If you’re looking for a new game or something different I highly recommend checking out Dead Cells.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/declining-expectations/index.html b/themes/cycle/exampleSite/public/writing/declining-expectations/index.html new file mode 100644 index 0000000..df6d261 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/declining-expectations/index.html @@ -0,0 +1,243 @@ + + + + + + Declining Expectations + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Declining Expectations

+ + +
+

Matthew Butterick’s talk at TYPO Berlin is a fantastic read.

+
+

And that’s really what I mean tonight by declining expectations. This idea of what happens when we defer to technology, instead of standing on its shoulders. What happens when we choose convenience over quality. Eventually, we’re going to forget what quality was like.

+
+

Chilling and inspiring.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/diceware/index.html b/themes/cycle/exampleSite/public/writing/diceware/index.html new file mode 100644 index 0000000..0952e80 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/diceware/index.html @@ -0,0 +1,249 @@ + + + + + + Diceware + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Diceware

+ + +
+

Glenn Fleishman (@GlennF) recently linked to a method for generating passphrases called Diceware.

+
+

@craigmod Switch to diceware-style ones, if you haven’t. It’s so goddamn much easier, even with 2x the characters of a random one.

+

— Glenn Fleishman (@GlennF) March 24, 2017

+
+

Being a fan of dice (d20 for life) I thought this was super cool and worth sharing.

+

The basic premise is (to quote Wikipedia):

+
+

Diceware is a method for creating passphrases, passwords, and other cryptographic variables using ordinary dice as a hardware random number generator. For each word in the passphrase, five rolls of the dice are required. The numbers from 1 to 6 that come up in the rolls are assembled as a five-digit number, e.g. 43146. That number is then used to look up a word in a word list. In the English list 43146 corresponds to munch. By generating several words in sequence, a lengthy passphrase can be constructed.

+
+

I dig this, it’s an analog solution to a digital problem. The incredible folks at the EFF have a couple wordlists to get you started. Happy rolling! 🎲

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/eight-years/index.html b/themes/cycle/exampleSite/public/writing/eight-years/index.html new file mode 100644 index 0000000..b3bb921 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/eight-years/index.html @@ -0,0 +1,246 @@ + + + + + + Eight years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Eight years

+ + +
+

Eight years ago I started working at Sparkbox. Here are some of things that have happened since I started:

+
    +
  • The Cubs won a World Series.
  • +
  • Facebook released a small Javascript library called React.
  • +
  • The iPhone 5 was unveiled the week after I started.
  • +
+

Time flies when you’re having fun.

+

Thank you Sparkbox team for giving me an opportunity to work with ya’ll and for making me a better developer and person. Let’s keep it rolling!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/emacs-lite/index.html b/themes/cycle/exampleSite/public/writing/emacs-lite/index.html new file mode 100644 index 0000000..b8876d9 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/emacs-lite/index.html @@ -0,0 +1,246 @@ + + + + + + Emacs lite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Emacs lite

+ + +
+

I really dig Emacs. I think it’s a one-of-kind computing experience. However, it’s defaults are pretty rough and some of my favorites aspects of Emacs are third party packages.

+

I wondered if I could cram the “awesome Emacs” experience into 200 lines of configuration or less. Turns out I could. I only included what I consider (as someone who writes JS most days) “essential”. I didn’t re-bind any keys except for M-x and that has the same function with an upgraded interface. I didn’t include evil-mode (Vim emulation) either, introducing Emacs and Vim keybinds to someone is a suicide mission.

+

To use this config copy and paste the config snippet into one of three config file locations (sooooo Emacs):

+
+

Emacs looks for your init file using the filenames ~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el

+
+

Then boot up Emacs (I’m assuming you already have it installed), there will be a bit of waiting the first time as packages are installed for you.

+

If you run into issues, hit me up via email, github issue, twitter, micro.blog etc. There’s also a reddit thread with some helpful discussion from the awesome /r/emacs community.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/emacs-tips/index.html b/themes/cycle/exampleSite/public/writing/emacs-tips/index.html new file mode 100644 index 0000000..f312f05 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/emacs-tips/index.html @@ -0,0 +1,268 @@ + + + + + + Emacs tips + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Emacs tips

+ + +
+

evil-mode (vim for emacs) is good but not perfect. There will be occasions where you will get dropped into regular ‘ole emacs mode for some feature or plugin. The trick is to not panic remember a few basic movement keys that will get through in 90% of cases.

+
    +
  1. C-n and C-p (C stands for the ctrl key) go down and up by line respectively.
  2. +
  3. M-f (M stands for the alt key) and M-b will go forwards and backwards by word respectively.
  4. +
  5. C-g is the universal emacs key for “STOP WHATEVER YOU’RE DOING”.
  6. +
+

There are a few other random things to keep in mind that will make life easier.

+
    +
  1. M-x (remember, M stands for the alt key) allows you to execute just about any function, e.g. kill-buffer.
  2. +
  3. F1 f will bring up documentation for any loaded function.
  4. +
  5. F1 v will bring up documentation for any variable.
  6. +
  7. F1 k will allow you to type a keybind and see what it’s bound to.
  8. +
+

Scripting tips

+

A few helpful built-in functions to know to start making your own functions.

+
    +
  1. +

    nth is a built-in which lets you pull a specific item from a list by it’s index like so: (nth 1 '("red", "blue")). Returns "blue".

    +
  2. +
  3. +

    split-string is another built-in that splits a string given a separator and returns the results in a list. (split-string "foo-bar" "-"). Returns ("foo" "bar")

    +
  4. +
  5. +

    concat also a built-in, combines strings. (concat "hello" "world"). Returns "helloworld".

    +
  6. +
  7. +

    null also a built-in. Return t if OBJECT is nil, and return nil otherwise. (null OBJECT).

    +
  8. +
+

I’ll add to this post as I think of things that helped me out when I first started using emacs. You can also check out my emacs config in my dotfiles if you want to see how I have everything setup.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/end-of-an-era/index.html b/themes/cycle/exampleSite/public/writing/end-of-an-era/index.html new file mode 100644 index 0000000..3e12a55 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/end-of-an-era/index.html @@ -0,0 +1,242 @@ + + + + + + End of an era + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

End of an era

+ + +
+

Today I removed two of my most-used apps on my phone, Apollo and Tweetbot. It feels like the end of an era.

+

Twitter and Reddit were both social websites that are/were terrible without a lot of cultivation and effort, but over the years I had shaped my experience on those services to be pretty good thanks in large part to Apollo and Tweetbot being such powerful tools.

+

Ironically the only social web thing I still use (outside of Instagram) is RSS. I will probably spin up a Mastodon instance here eventually but for now I’ve subscribed to folks via Mastodon’s RSS support and it’s good enough for now.

+

I guess I just wanted to give a shout out to the devs of Apollo and Tweetbot: thank you for making such great apps, I will miss them.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/evening-edition/index.html b/themes/cycle/exampleSite/public/writing/evening-edition/index.html new file mode 100644 index 0000000..721c9a7 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/evening-edition/index.html @@ -0,0 +1,240 @@ + + + + + + Evening Edition + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/facetime-killer/index.html b/themes/cycle/exampleSite/public/writing/facetime-killer/index.html new file mode 100644 index 0000000..6f65b59 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/facetime-killer/index.html @@ -0,0 +1,250 @@ + + + + + + Facetime Killer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Facetime Killer

+ + +
+

TLDR: I made an app, VDCAssistant-Killer, to restart the process that manages the Facetime camera on your Mac.

+

Anyone who uses a Cinema Display with their Macbook has undoubtedly noticed that occasionally the Cinema Display Facetime camera will not be available for use in Hangouts/Zoom/Facetime call. The only fix was to restart the machine which usually made me late (and is a terrible solution in 2017).

+

Since I’m on video calls quite a bit this quickly started to drive me batty. I jumped into a google deep dive and found out the culprit was the process that manages the Facetime cameras on a Mac, VDCAssistant.

+ +

This command worked fine for anyone comfortable with the command line, but what about folks who would rather have a GUI to do this? So I made VDCAssistant-Killer a menubar app that executes the exact shell command to restart the VDCAssistant process for you. You shouldn’t have to restart the computer or even the video call program, the assistant should automatically restart and make all connected cameras available to you immediately.

+

A few other notes:

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/family-first/index.html b/themes/cycle/exampleSite/public/writing/family-first/index.html new file mode 100644 index 0000000..a5209f3 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/family-first/index.html @@ -0,0 +1,243 @@ + + + + + + Family First + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Family First

+ + +
+

Chris Bowler jots down some fantastic advice in his latest post (emphasis mine).

+
+

But my purpose here is to simply encourage those with families. Please do not spend your time endlessly comparing your accomplishments or progress with those who have no family. Your setting yourself up for guilt at best, and resenting your family at worst.

+
+

I do not have any kids yet but I think this advice applies to everyone, especially those working on the web. I’ve been slowly learning that I cannot continue to compare myself to other people in my industry - it’s counterproductive.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/farewell-heroku/index.html b/themes/cycle/exampleSite/public/writing/farewell-heroku/index.html new file mode 100644 index 0000000..c07a022 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/farewell-heroku/index.html @@ -0,0 +1,269 @@ + + + + + + Farewell Heroku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Farewell Heroku

+ + +
+

I’ve migrated my apps off Heroku and won’t be using the service for personal apps going forward. Why? Let me back up a bit and explain what was so great about Heroku.

+

Haiku? Ha-who?

+

Heroku is a “hosting as a service” company. They try to take away the pain of deploying and managing web applications. They actually do this quite well, it’s a great service. The “secret sauce” that made Heroku so good was it’s free pricing tier. The free tier essentially allowed a single web or a single “worker” process to run 24/7. There was enough processing power to run apps or processes for a small number of users, perfect for apps like my six plus checker or youtuberss app.

+ +

If apps grew popular enough they would hit processing limits and I could go in and scale the app up to meet demand. Scaling an app also meant that I was no longer in the free tier and would begin paying Heroku for the additional resources. It really was an ideal setup (from my perspective as a developer).

+

Sadness

+

Sadly, Heroku announced a few months ago a pretty big shift in their pricing. The free tier would no longer run 24/7 as a single process:

+
+

Every app using free dynos can include not just a free web, but also one free worker, and free usage of heroku run and Heroku Scheduler. Free dynos can run up to eighteen hours a day, but have to “sleep” for at least the remaining six. That’s eighteen hours each of serving traffic, running a background worker, and scheduled processes

+
+

I totally get they are trying to offer more of their platform in “demo mode” but I think it’s the wrong move. To be clear, I’m not griping about a free lunch going away. I’m griping because the new pricing:

+
    +
  1. Is harder to understand and manage. Seriously, I’m supposed to monitor my app in 18 hour increments?
  2. +
  3. Doesn’t incentivize developers to try out new apps that could potentially become paying applications.
  4. +
+

Re: #2, The very impressive emojitracker was built on Heroku’s platform. Matthew Rothenberg, the project’s developer, recounts how Heroku let him easily scale to meet demand:

+
+

I did this manually. That first evening I needed a break from intense computer usage all day, so I actually spent the evening in a bar across the street from my apartment with some friends, having a drink while passively monitoring these charts on some iPhones sitting on the table. Whenever it looked like something was spiking, I used the Nezumi Heroku client to scale up instances from my phone directly. I didn’t even have to put down my drink!

+
+

This is awesome. It illustrates the ideal scenario: no money up front to try something out and a natural path to scaling it up if it takes off. Simple, it was.

+

Where to now?

+

I tweeted yesterday:

+ +

I’ve now finished moving my node apps over to Chunkhost. With Chunkhost I get 1GB of RAM for under $5/month by paying yearly and via bitcoin (I use Coinbase to purchase and manage Bitcoins). In comparison, Digital Ocean offers 512MB of RAM for $5/month. With the extra overhead from Chunkhost, I can easily host multiple apps on the same box. Plus, I’ve found that the two node apps I have running are both only using ~50MB of RAM!

+

Sysadmin

+

Yes, with Chunkhost I have to play as sysadmin and keep the VPS running. However I’m in total agreement with this quote from Marco Arment:

+
+

Modern Linux server administration is much easier than you think. If you can write a halfway decent app, you can manage a Linux VPS in your sleep.

+
+

He’s exactly right, managing a VPS isn’t beyond the abilities of anyone who can write an app and put it on Heroku. I’ve found Ansible + Bitbucket private repos + PM2 a great deployment and management combo; one that I’ll write more about later. It took some effort to set up, but now I can launch new apps in minutes.

+

Heroku’s new pricing has forced me to branch out and figure out how to host, manage, and deploy my apps. Perhaps the pricing change wasn’t all bad after all.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html b/themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html new file mode 100644 index 0000000..0105678 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html @@ -0,0 +1,241 @@ + + + + + + FFMPEG: Convert multiple files using xargs + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

FFMPEG: Convert multiple files using xargs

+ + +
+

I stumbled upon this post (Google cache link) when I was trying to process multiple files via xargs.

+
+

ls *.webm | xargs -I % ffmpeg -i % %.m4a

+
+
+

The key part of this one-liner is xargs -i %. This means that each line of STDIN passed to xargs is put into a variable and can be referenced as %. Hence, the following text which specifies ffmpeg -i x.webm x.m4a to make it convert.

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/five-years/index.html b/themes/cycle/exampleSite/public/writing/five-years/index.html new file mode 100644 index 0000000..6c09413 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/five-years/index.html @@ -0,0 +1,241 @@ + + + + + + Five years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Five years

+ + +
+

Five years

+

Today is my five year anniversary at Sparkbox! Five years is a long time, especially working on the internet, and I’ve loved every stinking minute of it.

+

To my fellow Sparkboxers: thank you for making Sparkbox such an incredible place to work. Here’s to the next five!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/flatkill/index.html b/themes/cycle/exampleSite/public/writing/flatkill/index.html new file mode 100644 index 0000000..d02ffea --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/flatkill/index.html @@ -0,0 +1,241 @@ + + + + + + flatkill + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

flatkill

+ + +
+
+

And it’s not only about these security problems. Running KDE apps in fakepak? Forget about desktop integration (not even font size). Need to input Chinese/Japanese/Korean characters? Forget about that too - fcitx has been broken since flatpak 1.0, never fixed since.

+
+
+

The way we package and distribute desktop applications on Linux surely needs to be rethinked, sadly flatpak is introducing more problems than it is solving.

+
+

Flatpak is an emerging alternative way to install applications on Linux that is apparently rife with security and usability issues. This is a bummer because there’s lots of room in this space for improvement. The lack of multi-lingual input is especially egregious.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html b/themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html new file mode 100644 index 0000000..7696bd8 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html @@ -0,0 +1,248 @@ + + + + + + Format JSON in emacs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Format JSON in emacs

+ + +
+

I wrote an elisp function to yank JSON off my clipboard, prettify it, and then return it to my clipboard ready to be pasted wherever.

+
(defun simpson-pretty-json()
+  "ideal for getting pretty JSON from JSON that is copied from a XHR request"
+  (interactive)
+  (with-temp-buffer
+    (clipboard-yank)
+    (json-pretty-print-buffer)
+    (kill-new (buffer-string))
+  )
+)
+
+
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html b/themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html new file mode 100644 index 0000000..54f5b3c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html @@ -0,0 +1,250 @@ + + + + + + Four ways to approach Hacktoberfest 2020 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Four ways to approach Hacktoberfest 2020

+ + +
+

Hacktoberfest 2020 is here! I can’t believe 2020 is winding down, good riddance!

+

I’ve been talking about Hacktoberfest with my co-worker Bryan and I thought of four different approaches to Hacktoberfest this year that I wanted to share.

+ +

Dependency scrub

+

This is probably common everywhere but the Javascript/web communities are filled with npm packages. It’s packages all the way down. I think it would be interesting to approach this month looking for ways to remove third-party code from projects you love and use frequently.

+

Polygot Achievement

+

Try to submit four pull requests in four different languages. As Drew DeVault writes: Hack everything without fear!

+

Unknown lands

+

Similar to the previous one it could be fun to submit PRs against a project you’ve never been in before that’s in a language you don’t know. This could be anything from diving into Wordpress core, to working on some C for some Linux utilities, or even submitting PRs to open source Mac/iOS applications.

+

Bug doctor

+

Go into a project and find the oldest issues and try to resolve them via PR. This is inspired by Richard Schneeman’s video and post where he runs through 11 issues and 2 PRs in a hour and a half.

+

How are you approaching Hacktoberfest this year? My public inbox is open, let me know!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html b/themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html new file mode 100644 index 0000000..3deb406 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html @@ -0,0 +1,282 @@ + + + + + + Getting started with Rofi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Getting started with Rofi

+ + +
+

Rofi is a Linux app that is a:

+
+

[..] window switcher, application launcher and dmenu replacement

+
+

I’ve been using Rofi for about a year but didn’t really understand how to write my own scripts for it until recently.

+

dmenu? Huh?

+

A key to my lack of apprecaition for Rofi’s feature set was that I didn’t understand why it billed itself as a “dmenu replacement”. What the heck is dmenu?

+
+

dmenu is a fast and lightweight dynamic menu for X. It reads arbitrary text from stdin, and creates a menu with one item for each line. The user can then select an item, through the arrow keys or typing a part of the name, and the line is printed to stdout. (emphasis mine)

+
+

Essentially dmenu lets you create and present your own menu and then act once a menu item is selected by the user. One of my favorite applications of all time is Alfred, the infinitely customizable launcher utility for macOS. The best part about Alfred was Workflows which (like dmenu) allow you to create custom menus and actions as part of the main launcher interface. How do we create a menu though?

+

STDIN STDOUT

+

dmenu will display whatever comes in on STDIN as the menu, e.g. echo "foo\nbar" | dmenu" (if you have a Linux install available install dmenu and give that command a try). Each new line in STDIN becomes a new line in the dmenu menu. The previous command creates a menu with two options: foo and bar. Once the user hits enter on a menu item the value of the selected item gets sent to STDOUT. That’s it. dmenu reads in from STDIN and prints out selections to STDOUT. dmenu is super handy to add to workflows and scripts to give them a bit of UI. You can squeeze dmenu anywhere you need feedback from the user, e.g.: echo "Hello $(echo 'World\nPeople' | dmenu)". This prints a hello world message after the users chooses “World” or “People” from dmenu.

+

Rofi + dmenu

+

Rofi adds dmenu capability plus lots of other things like selecting open windows, running ssh commands etc. To enable dmenu mode in Rofi pass it as an option -dmenu. Let’s port our previous example code snippet to Rofi: echo "foo\nbar" | rofi -dmenu. Easy enough! With the dmenu option Rofi becomes just as useful as Alfred and makes me think Alfred should gain a command line option to pop open Alfred from within scripts like dmenu or Rofi.

+

My first script

+

The motivation to write this post came a couple weeks ago when I wrote my first real Rofi script. I use Pop_OS! as my Linux distribution of choice for work and the defaults are really good. However when I want to change my audio output (headphones or external speakers) I’ve grown annoyed by having to manually mouse up to the menubar and select the desired output. I set out to write a Rofi script to handle changing the audio output. On Linux you can control everything related to the audio system via the pactl utility. The pieces of data I needed for my script were:

+
    +
  • A list of all available outputs to generate my Rofi menu
  • +
  • A way to change to the selected output
  • +
+

pactl list sinks displays all active “sinks” or available outputs (“Sinks” is the Linux audio system term for outputs). We can customize this a bit further wih pactl list short sinks which will cram relevant sink information into one line each instead of multiple lines per sink. This makes parsing the output much easier.

+

Now that I had a list of available speakers/headphones on the system I needed to change to that output. This turned out to be a two step process because of how the audio system works:

+
    +
  1. pactl move-sink-input INPUT SINK moves anything currently playing to the specified speaker/headphone.
  2. +
  3. pactl set-default-sink SINK sets the specified speaker/headphones as the default output going forward, e.g. launching a video call or playing a video.
  4. +
+

To accomplish #1 I needed to get the currently playing input which can be done via: pactl list sink-inputs. Again we can specify short to get the relevant information on a single line: pactl list short sink-inputs.

+

The finished script looks like this:

+
#!/bin/bash
+
+source="$(pactl list short sinks | cut -f 2 | rofi -dpi 1 -dmenu -p "Change audio:")";
+inputs="$(pactl list sink-inputs short | cut -f 1)";
+
+for input in $inputs; do
+  pactl move-sink-input "$input" "$source";
+done
+
+pactl set-default-sink "$source";
+

Upon invoking the script, Rofi presents me with a menu that contains all the available outputs. Once I select one the audio changes instantly.

+ +

Conclusion

+

I find Rofi so useful that I have a system-wide hotkey that invokes Rofi as a general launcher like this: rofi -combi-modi run,window,drun -show combi -modi combi -dpi 1. The flags I’m using are documented under “Combi settings” in the Rofi manpage.

+

Rofi transforms otherwise vanilla shell scripts into poweful transient workflows that allow me to control aspects of my machine without leaving whatever I’m currently working on. It’s become an essential part of my toolbox.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html b/themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html new file mode 100644 index 0000000..13e1375 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html @@ -0,0 +1,242 @@ + + + + + + Gists, Snippets, and Sublime Text 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Gists, Snippets, and Sublime Text 2

+ + +
+

I’ve been using Sublime Text 2 for a little under a year I guess, but I’ve only recently started customizing the hell out of it largely thanks to the Fetch plugin. Today I had the thought of setting up Fetch to download and insert the raw code of a Github Gist.

+

Gists are great for a couple reasons. One is that they are version controlled, it’s easy to track any changes right from the gist. Another great thing is that Gists are independent of Sublime, and more importantly my local computer, this makes them easier to share and backup. The only drawback from normal snippets I can see is that I can’t set up tab triggers, and hot keys.

+

So today I created three Worpress specific gists, and set up Fetch in Sublime Text 2 to pull them down. These are pretty basic snippets, but they are ones that I use a lot and don’t want to think about.

+

I just started messing around with this stuff today, so I’d love any comments regarding snippets or how you set up any kind of automation in Sublime Text 2. Reply to @a_simpson with your comments.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/git-commit-template/index.html b/themes/cycle/exampleSite/public/writing/git-commit-template/index.html new file mode 100644 index 0000000..ff2a9f6 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/git-commit-template/index.html @@ -0,0 +1,248 @@ + + + + + + Git Commit Template + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Git Commit Template

+ + +
+

TL;DR how do I do this?

+

At work we’ve been moving toward standardized Git commit messages. By following the pattern, it’s very easy to see what type of code is in a specific commit.

+

We use Sprint.ly and Github. Both of these services can perform actions based on what is in a commit message. Github can close or reference an issue if I type closes #144 at the end of my commit. Sprint.ly can pull a commit message into a specific ticket in much the same way.

+

The problem with all this, is remembering to actually do it in the heat of the moment, when I’m buried in code and trying to push stuff out the door. That’s why I put together a Git commit message template. All my template does is list the various flags and an example of how to reference a Sprint.ly ticket, but it shows this in my editor every time I commit. It’s been incredibly useful.

+

Add your own template

+
    +
  1. Create a file to hold your template, e.g. git-commit-template.txt. Put in whatever you want to remember, just be sure to keep everything commented out (via #) or it will be in the actual message.
  2. +
  3. Run git config --global commit.template /path/to/git-commit-template.txt or edit ~/.gitconfig and add template = /path/to/.gitmessage.txt under the [commit] block.
  4. +
  5. Done.
  6. +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/git-worktree/index.html b/themes/cycle/exampleSite/public/writing/git-worktree/index.html new file mode 100644 index 0000000..f198976 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/git-worktree/index.html @@ -0,0 +1,246 @@ + + + + + + Git worktree + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Git worktree

+ + +
+

I was happily (I had just started obviously) browsing Twitter today when I saw this tweet from the esteemed Wilfred Hughes:

+ +

Huh? What is git-worktree? A quick Google landed me on the documentation for git-worktree. The ;TLDR of git-worktree is that it breaks time and space and lets a user check out multiple branches at the same time. No more stash-checkout-stash-pop dance between branches and fixes! The example in the documentation is really really good (except for the boss part, that’s usually played by my short-attention span).

+

Magit

+

After reading the documentation, my next thought was “Does magit support this?” Yep, since last year! Let me take this moment to rave like a maniac, magit is amazing and everyone should be using it as their primary git client (irregardless of Emacs usage for text-editing). As the documentation explains, to get worktree information in the standard magit status buffer the magit-status-sections-hook needs to be updated like so:

+

(add-hook 'magit-status-sections-hook 'magit-insert-worktrees).

+

The actions for creating or checking out a worktree are (hiding) in the branches (b) popup. I don’t know why I’ve never noticed them until now!

+

git-worktree is another example of git not standing still. It’s exceptional (even under-appreciated) software that continues to improve and that’s something that doesn’t get enough praise and attention.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/goat-counter/index.html b/themes/cycle/exampleSite/public/writing/goat-counter/index.html new file mode 100644 index 0000000..773848f --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/goat-counter/index.html @@ -0,0 +1,238 @@ + + + + + + GoatCounter web analytics + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

GoatCounter web analytics

+ + +
+
+

What seems to be lacking is a “middle ground” that offers useful statistics to answer business questions, without becoming a specialized marketing tool requiring in-depth training to use effectively. Furthermore, some tools have privacy issues (especially Google Analytics). I saw there was space for a new service and ended up putting my original idea in the freezer and writing GoatCounter.

+
+

I agree 100% with this assessment and I’m excited about Goatcounter. I setup a free instance of Goatcounter for this site as a way to kick the tires on it. So far, I’m enjoying that it’s privacy respecting and doesn’t drag down page performance.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html b/themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html new file mode 100644 index 0000000..91ef61c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html @@ -0,0 +1,243 @@ + + + + + + 👋 Sparkbox + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

👋 Sparkbox

+ + +
+

I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox.

+

Now, I know it can be problematic to think about work like your (extended) family but when you work at the same place through your twenties and early thirties, have 3 different apartments, buy a house, and have two kids it’s impossible not to view that place differently. I can confidently say Sparkbox changed my life. The team there will always have a special place in my heart.

+

deep breath

+

So where to? Well, I’m super stoked to be joining Grafana as a Senior Software Engineer on their Cloud Data team! I’m looking forward to writing more Go, solving new problems, and learning from the stellar folks there.

+

Here we go…

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html b/themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html new file mode 100644 index 0000000..c9f4432 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html @@ -0,0 +1,246 @@ + + + + + + Google Fi and data only plans + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Google Fi and data only plans

+ + +
+

Last week, Google began selling wireless cellular service via a new program, Google Fi, which utilizes Sprint and T-Mobile for coverage. Fi’s pricing model is refreshingly straight-forward (following the example of T-Mobile and Ting); every plan is $20 with data billed at $10/Gb on top of that. @benthompson and @jamesallworth discussed the various aspects of Fi on a recent episode of their podcast, Exponent. At one point, James asked (I’m paraphrasing here) why the base of the Fi plan includes voice/sms. Why doesn’t Google just offer data? James went on to say that he always thought if anyone were to offer a data-only plan, it would be Google. What he didn’t know was this: there is already a fantastic data-only plan in America, and it’s on T-Mobile.

+

Data only-ish

+

On T-Mobile’s prepaid site, the company heavily advertises its main pre-paid price tiers: $40, $50, and $60. However, a quick scroll down the page will reveal two additional plans. The first one is talk and text only, with no data included. The second is the best kept secret in wireless. This second plan is $30/month for 100 minutes, unlimited SMS, and 5GB of LTE data (throttled after 5GB). 100 minutes is nothing, so this plan is essentially just data. There’s no catch - the LTE isn’t throttled at all, and the plan includes free international texting from the US. It even qualifies for Music Freedom, which doesn’t count music streaming against your 5GB LTE allowance. You can add hotspot tethering for $15/month, and this can be added and removed as you need it.

+

What are minutes for?

+

My wife and I have been on this plan for almost a year now. It’s perfect. We use FaceTime Audio if we need to call each other or anyone else that has an iOS device. We use the Vonage mobile app (any VOIP service would work) when we need to make a normal call and don’t want to use our 100 minutes. Both Vonage and FaceTime Audio use data, not voice minutes, exactly the scenario James outlined on Exponent.

+

Caveats

+

The only downside to this plan I have found is that T-Mobile’s coverage is still behind AT&T’s and Verizon’s, though it’s much closer now than it has ever been. 2015 has seen T-Mobile continue to build out its LTE reach, and it’s impressive. Living in Columbus, OH, one of the first cities to get Wideband LTE, I see speedtest results as high as 70mbps down.

+

If Google Fi isn’t as radical as you’d like, I would recommend giving this T-Mobile plan a try. It’s $30 (plus the cost of a SIM card) to give it a shot. The one “catch” is that it’s only for phones (or SIMs) activated in Walmart or online, but it’s easy enough to order a SIM card and give it a try.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html b/themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html new file mode 100644 index 0000000..57128bc --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html @@ -0,0 +1,243 @@ + + + + + + Grow it, don't build it + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Grow it, don't build it

+ + +
+

John Graham-Cumming wrote up a fantastic list of things he’s learned about programming. There all great. Yet, I really resonated with #6. So. True.

+
+

It’s easier to grow software than build it […] When you create a massive architecture from the start you (a) get it wrong and (b) have created a Byzantine maze that you’ll find hard to change. If, on the other hand, you work from small pieces that communicate with each other, refactoring will be easier when you realize you got it wrong from the start.

+
+

Hat-tip to Jonathan Christopher for the article link.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html b/themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html new file mode 100644 index 0000000..ab6163a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html @@ -0,0 +1,246 @@ + + + + + + Guidelines for Data + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Guidelines for Data

+ + +
+

The wonderful Contents Magazine released a special report entitled Data Protection. In that report they outlined three principles for Data Protection. All three principles are fantastic, but number two really stood out to me.

+
+

No upload without download. Build in export capabilities from day one.

+
+

That seems pretty straightforward, but I started thinking of this in the context of the sites I build for clients. Our platform of choice at my company is Wordpress which has a capable Import/Export tool available.

+

Is this enough? Do my clients know about it? Is the XML it exports good enough that clients can migrate platforms in a couple years? A quick bit of searching uncovered the Export to Text plugin, which allows Wordpress users to export their data as plain txt files. This certainly seems better than XML, but again will my clients know how to use it if they want to leave? Should Wordpress have more robust export options built in?

+

I don’t have any answers right now, but I think it’s important that I do.

+

Do you have a solid solution for this type of situation? Let me know @a_simpson.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html b/themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html new file mode 100644 index 0000000..c9ea5fb --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html @@ -0,0 +1,353 @@ + + + + + + Hacking on Grafana with Web Assembly + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Hacking on Grafana with Web Assembly

+ + +
+ +

The original inspiration for this idea came from Simon Willison’s work with Datasette Lite. However, compiling Grafana as a WASM binary proved difficult with existing build constraints. After spending some time trying to get that to work I changed course a bit and instead focused on compiling a basic go HTTP server as a WASM module. The new goal being to have a proof of concept that bundled the HTTP server as a WASM binary and intercepted any clicked links on the page and finally passed those links to be resolved by the go server in WASM.

+

I used a Web Worker to interact with the WASM binary. This frees up the main thread of the browser. To put the WASM binary into the worker I loaded the binary and sent a message that contained the binary as a WebAssembly.Module.

+

The Web Worker can then call any go functions that have been exposed via FuncOf. Once the go function returns data, the worker posts that response back to the main thread via another message.

+
let module;
+importScripts("wasm_exec.js")
+go = new Go();
+
+self.onmessage = async (e) => {
+  if (e.data.type === "module") {
+    module = e.data.module;
+    return;
+  }
+
+  if (module) {
+    console.log('Message received: ', e.data.path);
+    const instance = await WebAssembly.instantiate(module, go.importObject);
+    go.run(instance);
+    postMessage(parsePath(e.data.path)); // parsePath is exposed via FuncOf
+  }
+}
+

Sidenote: I wish go could use the same pragma syntax tinygo uses to expose functions instead of the verbose FuncOf. There’s an issue but it has been open since 2018.

+

Obviously, there is no localhost to listen on in a WASM environment. To get around that I created a bare bones ResponseWriter and used that with the Request to run the Handler’s ServeHTTP function which consults the routes that are defined and runs the matching handler code. This allowed me to use a build constraint (setup.go and setup_js.go) and keep my HTTP server functioning normally when run from a terminal but then also worked when run in a WASM context. Here’s what those two files look like:

+

setup

+
//go:build !js
+// +build !js
+
+package main
+
+import (
+	"fmt"
+	"net/http"
+)
+
+func setup() {
+	s := NewServer()
+	err := http.ListenAndServe(":9001", s.mux)
+	if err != nil {
+		fmt.Println("error: ", err)
+	}
+}
+

setup_js

+
package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"syscall/js"
+)
+
+type ResponseWriter struct {
+	Body *bytes.Buffer
+}
+
+func (r ResponseWriter) Header() http.Header {
+	return make(http.Header)
+}
+
+func (r ResponseWriter) Write(buf []byte) (int, error) {
+	if r.Body != nil {
+		r.Body.Write(buf)
+	}
+	return len(buf), nil
+}
+
+func (r ResponseWriter) WriteHeader(statusCode int) {}
+
+func createWriter() ResponseWriter {
+	return ResponseWriter{
+		Body: new(bytes.Buffer),
+	}
+}
+
+func parsePath(this js.Value, args []js.Value) interface{} {
+	fmt.Println("args: ", args)
+	server := NewServer()
+	path := args[0].String()
+	req, err := http.NewRequest(http.MethodGet, path, nil)
+
+	if err != nil {
+		fmt.Println("request error: ", err)
+	}
+
+	h, p := server.mux.Handler(req)
+
+	fmt.Println("pattern: ", p)
+
+	w := createWriter()
+
+	h.ServeHTTP(w, req)
+
+	b, err := ioutil.ReadAll(w.Body)
+
+	if err != nil {
+		fmt.Println("ioutil error: ", err)
+	}
+
+	return string(b)
+}
+
+func setup() {
+	js.Global().Set("parsePath", js.FuncOf(parsePath))
+}
+

Conclusions

+

The PoC worked! It’s pretty slick to see a HTTP server running in WASM return back the correct data when a link is clicked. However, in my opinion, WASM continues to be a “solution in search of a problem”. Yes it’s incredibly cool technology but so are the JS engines in Chrome, Firefox, and Safari. The sheer amount of money and engineering time being spent on making JS fast is a race no other technology can win at the moment.

+

That said, Go seems to have done decent work at providing the necessary pieces to make compiling to WASM not awful.

+

Honestly, the thing that surprised and impressed me the most was working with Web Workers. They are seriously useful and seem to “just work”.

+ + + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html b/themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html new file mode 100644 index 0000000..3e6fb61 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html @@ -0,0 +1,249 @@ + + + + + + Hello micro.blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Hello micro.blog

+ + +
+

👋 micro.blog

+

I’ve started posting my normal blog feed and a new micro feed to https://micro.blog/simpson. My motivation for integrating with micro.blog is that it feels like the right approach for the “open web”.

+

It did take me awhile to understand the core concepts of micro.blog. The description on the iOS App Store is illuminating:

+

Instead of trying to be a full social network, Micro.blog is a thin layer that glues the open web together, making it more useful. Micro.blog adds discovery and conversations on top of previously unconnected blog posts.

+

Brent Simmons (of inessential.com) had a good post today summarizing what makes micro.blog different from app.net or other social networks:

+
+

And so everyone who follows me on Micro.blog sees my blog posts, and I see theirs. Simple.

+

And anyone who wants to could just read my blog in an RSS reader instead. All good, all open.

+
+

Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting.

+

So hop on board! Follow me over at micro.blog/simpson or subscribe directly to my new micro feed.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/hello-world/index.html b/themes/cycle/exampleSite/public/writing/hello-world/index.html new file mode 100644 index 0000000..111ed0e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/hello-world/index.html @@ -0,0 +1,271 @@ + + + + + + Hello World + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Hello World

+ + +
+

I’m proud, nervous, and a little surprised that adamsimpson.net is finally live! It has been a long time in the making, and I’m relieved to have it up. Now the fun begins.

+

A Little About Me

+

To sum me up, I’ll bust out the ‘ol bullet points.

+
    +
  • I work for a small web shop, based in Pennsylvania (though I live in Ohio) and do anything from front-end development and design to “social media” and copy-writing.
  • +
  • I am twenty-five years old and married to the greatest gal there is.
  • +
  • I graduated from college with a degree in English Lit (the web is made of words, so this works, right? right?).
  • +
  • I love: the interwebs, design, development, David Foster Wallace, C.S. Lewis, Don DeLillo, and Jimmy Eat World.
  • +
  • I dislike: most vegetables, Windows (not the ones in buildings), Jane Austen, bad drivers, and when the blinds in our apartment are open at night, it just skeeves me out.
  • +
+

About This Site

+

Still here uh? Brave. Very brave. You have leveled up +1 in patience.

+

Anyway, my vision for this site is a place where I can share the things I’m learning as I do my job, so lots of nerdy posts about front-end development stuff, design stuff, and writing stuff. I’ll probably also throw in observations on the latest tech gadgetry. I may also do more general posts regarding general creative work or whatever else strikes my fancy.

+

Technical Bits

+

This site is powered by Jekyll, a static-site generator. Jekyll is fantastic for a number of reasons, but I love it because I give it text files, and it gives me my site.

+

I’ve modified my Jekyll install a bit. I added Steven Romej’s permalink changes to stop Jekyll from creating ‘post-name-as-a-folder->index.html’ to ‘post-name-as-a-file.html’. I also adopted the pagination changes from Dane Harrigan’s fork.

+

Jekyll is running on top of a Linode 512 running Unbuntu and Nginx. I added one line to my Nginx conf file to support better permalinks thanks to this great post. I just used the one line, try_files $uri.html $uri/ 404.html;.

+

My posting process is simple and straightforward, all I need is Dropbox and a text editor. Usually this means I am using iA Writer, which happily melds the two requirements (and works on my iPhone, iPad, or Mac). I simply write a post and save it in my posts folder in Dropbox. Dropbox takes care of syncing it to the Linode which has Dropbox and a shared copy of my site folder. When a new post is synced up, Jekyll builds my site with the new data and it’s done, the post is live.

+

Now I owe Ted Kulp and Tyler Hall a beer for their posts that got me going with this Dropbox to Jekyll setup. I followed Mr. Kulp’s idea and had incron fire a little bash script when a new post came in from Dropbox.

+

The other obvious benefit to having my site in Dropbox is that my site is automatically backed up.

+

Hardware

+

And now, the infamous, what-do-I-use-at-my-desk section.

+

Well, I currently use a 15" MacBook Pro circa 2009. I connect it to an old 20" Dell LCD at my desk, and also use a Apple Wireless Keyboard, and Magic Mouse.

+

I also have an iPhone 4, iPad 2, and a Kindle.

+

Overall, I’m happy with my current setup, though I do plan on picking up an SSD + 8GB of RAM in the near future.

+

Software

+

As I already mentioned, I use iA Writer to write this site, and also for any writing needs for work. I also use Simplenote & NValt for quick thoughts and to-do lists on the go.

+

I use Fireworks and Photoshop for any design related work. I use a combination of Transmit and Sublime Text 2 for my FTPing and coding needs. Terminal is usually open for Git, or server tomfoolery.

+

Finally, for my browsers I use Safari & Chrome Canary for browsing and development respectively.

+

The End

+

I hope this wall of text isn’t too intimidating and that you learned a little bit about me and what makes this site tick. Just a word of warning, the look and feel of this site may change from time to time. I love to tinker, so consider it a constant work in progress. Thanks for reading.

+

Stick around and enjoy the ride with me!

+

-Adam

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html b/themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html new file mode 100644 index 0000000..dcf4439 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html @@ -0,0 +1,251 @@ + + + + + + From helm to ivy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

From helm to ivy

+ + +
+

I started playing around with Ivy earlier today. I was motivated in part by reading through the author’s blog, oremacs. I also love his swiper plugin and figured I had to give Ivy a try.

+

Background

+

For the record I discovered Helm about 20 minutes into my initial foray into emacs. I ❤ Helm. I support the project on Patreon. It’s great. I’m all about mastering my tools though and to do that I need to at least try other tools. Enter my attempt to switch to Ivy.

+

Progress

+

This post isn’t meant to be a finished product. I’m going to try and circle back occasionally as I use Ivy for the next couple days. A few notes on my experience so far:

+
    +
  • I somehow had an old version of Ivy installed and when I went to install counsel I was getting weird errors. Deleting Ivy from my elpa directory manually cleared things up.
  • +
  • Wow, by default, Ivy feels much more sparse than Helm. The first thing I had to do was figure out the “buffers list” implementation and change my C-= binding from helm to ivy. It’s definitely more spartan, but I don’t think its a negative necessarily just a change.
  • +
  • Ivy is just a completion package, by itself it doesn’t do a ton. That’s why it comes with counsel and swiper these are the primary interfaces to the good stuff, e.g. counsel-ag searches your project with Silver Searcher.
  • +
  • Previews are incredible! Thanks to this comment on reddit. With the C-M-n and C-M-p commands you cycle through any matches and you see the entire file in the buffer. Imagine searching for a keyword in a project and then getting to see all the glorious context as you pick through the matches without having to open every single file!
  • +
  • Not sure how to completely prevent a package from loading. I don’t want helm to load while I play with Ivy. The :disabled: keyword in use-package doesn’t really prevent it from being loaded, it just prevents the use-package form from being executed. I ended up relying on git and removed the lines from my .emacs and I rm -rf the helm package directories. I looked at this again after sleeping on it. I defined two variables simpson-evil and simpson-helm and I check those values in my config to set up configurations depending on which packages is available. Easy enough.
  • +
  • I had a epiphany about how use-package works. use-package will auto load any package that has a :bind, :mode, :command, or :init keyword. If all you have is :config that package won’t load itself. However adding :defer 1 will load that package once emacs is idle for a second and then fire off the :config body. So far so good. :disabled comes into play even if you have a :after keyword because if you have :after combined with any of the “auto load” keywords above the package will try to do stuff.
  • +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html b/themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html new file mode 100644 index 0000000..cc2faec --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html @@ -0,0 +1,239 @@ + + + + + + Heroku and SSH Keys + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Heroku and SSH Keys

+ + +
+

Heroku rocks. I’ve been using it to host this blog (for free, mind you) for the last couple months. However, I’ve run into a problem where Heroku refuses to authorize a git push heroku by declaring Permission denied (publickey). After messing around deleting, creating, and re-adding SSH keys, I found these two posts that solved the problem for me. Apparently Heroku fails if you point it to any kind of custom SSH key. Simply add Heroku to your SSH config file and specify the key to use, problem solved.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html b/themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html new file mode 100644 index 0000000..7514a66 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html @@ -0,0 +1,241 @@ + + + + + + Hiking the Pacific Crest Trail in Three Minutes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html b/themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html new file mode 100644 index 0000000..aaeba3e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html @@ -0,0 +1,257 @@ + + + + + + Hosting assets via Github Pages + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Hosting assets via Github Pages

+ + +
+

Screenshots in README.mds are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult. There are a couple options:

+

The Problem

+
    +
  1. Upload the image to a image hosting service and then reference the direct URL in the README.md.
  2. +
  3. Check the image into the repo and reference its raw URL in the README.md.
  4. +
+

Both of these have their downsides. The first option means that your image is tied to the uptime of the image hosting service. If the service is down your image is now 404. Option two means you have the image mixed in with your source files which stinks from an organizational perspective.

+

The Solution

+

The solution is fairly obvious but took me awhile to realize it: use Github pages by pushing assets to the gh-pages branch.

+

Hosting assets via Github pages means I don’t have to worry about the image hosting service uptime since Github is hosting both the README.md and the asset now. I also don’t have to worry about those assets cluttering my source directories because Github pages uses a specific branch gh-pages and those assets only show up when that branch is checked out.

+

Here’s a quick walk-through of how to push an image to Github pages (assuming there isn’t a gh-pages branch yet).

+
    +
  1. Create a gh-pages branch off of master (usually).
  2. +
  3. Add the image to the repo via git add /path/to/image.
  4. +
  5. Stage, commit, and push the branch to Github.
  6. +
  7. Go to Github and head to your project settings to grab the Github pages URL. Append the asset name to the end of it and check if you can view the image in your browser.
  8. +
  9. Go back to the command line and checkout master.
  10. +
  11. Add the image to the README.md and check it in.
  12. +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/how-are-you-living/index.html b/themes/cycle/exampleSite/public/writing/how-are-you-living/index.html new file mode 100644 index 0000000..dab266a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/how-are-you-living/index.html @@ -0,0 +1,242 @@ + + + + + + How are you living + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

How are you living

+ + +
+

One of my favorite writers, Shawn Blanc recently published a short piece entitled, Most People. I highly encourage everyone to head over and read the entire essay. However, because I love the ending so much, I had to share it here as it is truly fantastic:

+
+

Here’s a metric that can help you determine if you’re on track for reaching your goals: are you spending your time, money, and attention differently than most people?

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html b/themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html new file mode 100644 index 0000000..5495694 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html @@ -0,0 +1,277 @@ + + + + + + How do we make the Web better + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

How do we make the Web better

+ + +
+

The introductory post for The Shift started with this statement about Twitter (emphasis mine):

+
+

Twitter has become a dumping ground for ill-thought-out opinions. Removing the barriers to publishing seems like a great way to encourage people to be a part of discussions they might not otherwise. Unfortunately, for all its possibilities, the platform can actually discourage well-thought-out conversation.

+
+

Ben is completely right, but I find the complaint framed around having a conversation especially apt. I’ve been reading Reclaiming Conversation: The Power of Talk in a Digital Age by Sherry Turkle and she makes the same assertion regarding social media and how it warps our understanding of the very nature of conversation. She writes that:

+
+

As we ramp up the volume and velocity of our online connections, we want immediate answers. In order to get them, we ask simpler questions; we dumb down our communications, even on the most important matters.

+
+

This is profound and terrifying. We’ve traded deeper conversations for shallow ones, as a culture we are preferring quantity over quality.

+

We’ve got to go deeper

+

So, how do we make the Web better? Simple, go deeper and have more meaningful conversations. Done. We can all go home, thanks for reading everyone.

+

Not so fast. The question within the question is how do we (internet workers) have more meaningful conversations in order to make the Web better? I don’t have the answer, but I have a few ideas:

+
    +
  1. +

    Pick better places or platforms for these conversations. Twitter, Reddit, and Hacker News seem to have proven they are not the correct venue.

    +
  2. +
  3. +

    Come with truckloads of empathy.

    +
  4. +
  5. +

    Disconnect

    +
  6. +
+

Platforms

+

I don’t want to get all hippie-dippie, but writing on a blog (with comments disabled) seems like a promising alternative to social media. This is why I think the Shift is such a great idea. Blogs require work to write and work to read. That work or friction is closer to the work of an actual conversation. It’s easier to blast out a snarky tweet, or rip someone apart in a comment thread. So let’s start writing on blogs more and reacting to half-thoughts on Twitter less.

+

Empathy

+

People always talk about empathy. It comes up everywhere, but in practice empathy is not very sexy. The dictionary definition of empathy from Merriam-Webster is:

+
+

the action of understanding, being aware of, being sensitive to, and vicariously experiencing the feelings, thoughts, and experience of another of either the past or present without having the feelings, thoughts, and experience fully communicated in an objectively explicit manner; also : the capacity for this

+
+

Empathy is making the mental effort to think from another perspective. Empathy is having patience as someone struggles through formulating a thought. Empathy is time. We need this so badly in our conversations around the Web. We can’t even begin to make the Web better if we’re not going to take the time to consider other opinions or ideas.

+

Disconnect

+

Turkle highlights another side of conversation that is fading, solitude. She writes that:

+
+

of the rewards of solitude is an increased capacity for self-reflection—the conversations we have with ourselves in the hope of greater insight about who we are and want to be. Professionally, what is our vocation? Personally, what gives us purpose and meaning? Can we forgive our transgressions and those of others? In self-reflection, we come to understand ourselves better and we nurture our capacity for relationship.

+
+

To make the Web better we may need to step back and disconnect to better understand the world and how the Web fits in it. Instead of listening to podcast after podcast in our commutes, what if we spent 20 minutes just thinking in silence? Could we even bear it? We won’t have those ideas to make the Web better without this “lonely thinking”.

+

The future

+

The Shift is a great opportunity to start formulating some of these ideas. I’m excited to see the writings and thoughts that emerge from this experiment. At its core the Web is conversations and relationships. To make it better we need to have better conversations which will enrich our relationships which will ultimately improve the Web.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html b/themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html new file mode 100644 index 0000000..1c66b89 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html @@ -0,0 +1,239 @@ + + + + + + How to use Siji font on polybar + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

How to use Siji font on polybar

+ + +
+

Nice guide on Reddit about how to use the Siji font with polybar.

+
+

[..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

+
+

Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/huffduffer/index.html b/themes/cycle/exampleSite/public/writing/huffduffer/index.html new file mode 100644 index 0000000..c90fc7e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/huffduffer/index.html @@ -0,0 +1,241 @@ + + + + + + Huffduffer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Huffduffer

+ + +
+

I have quite the commute to Sparkbox, as such I listen to a lot of podcasts (usually via Instacast on my iPhone).

+

My one pain point with this setup was when someone would recommend a specific episode of a podcast I didn’t subscribe to. In order for me to listen to that episode, I would have to either download the MP3 and send it over to my phone via iTunes, stream it via Safari on my phone, or subscribe to the whole podcast in Instacast. None of those options are very convenient.

+

Enter Huffduffer. Huffduffer is simple genius, I don’t know why I didn’t use it sooner! Once you sign up for a Huffduffer account, you get your own Huffduffer feed URL. Subscribe to that feed and you’re done. Now, when someone recommends a podcast episode, simply visit the episode page and click your Huffduffer bookmarklet to “huffduff” the episode. Your podcast app will receive the new episode via your Huffduffer feed subscription, sweet eh?

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html b/themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html new file mode 100644 index 0000000..390a42b --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html @@ -0,0 +1,241 @@ + + + + + + I moved to Hover + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

I moved to Hover

+ + +
+

In case you didn’t hear, Anonymous broke GoDaddy today. I figured now would be as good a time as any to explain why I moved away from GoDaddy a few weeks ago.

+

I chose Hover to be my GoDaddy replacement. I’ve never hosted anything through GoDaddy (I’m not a crazy person), but I did manage all my domain names through them. Hover and GoDaddy could not be more different, GoDaddy’s interface is comedically awful, Hover’s interface is relatively simple and light - two words you never, ever hear about GoDaddy’s administrative panels. I figure that 90% of using a DNS service is spent in front of their admin interface, it counts to have a good one.

+

I would highly recommend switching from GoDaddy to Hover, or Namecheap, or DNS Simple, the point is to switch away from GoDaddy not really where you switch to. So take the leap, and stop feeling sad inside when you hear another joke about GoDaddy.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/ifttt/index.html b/themes/cycle/exampleSite/public/writing/ifttt/index.html new file mode 100644 index 0000000..7f8a116 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/ifttt/index.html @@ -0,0 +1,251 @@ + + + + + + IFTTT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

IFTTT

+ + +
+

I love IFTTT. IFTTT is one of those awesome services that I desperately wished had a business plan.

+

Here are a few of my favorite IFTTT recipes.

+

App.net to Twitter

+

A few weeks ago I made the decision to give ADN another try, largely because ADN offers a RSS feed of my posts, something Twitter thought was too complicated. So I decided to funnel my original posts through ADN and then post them to Twitter. IFTTT facilities all of this with ease.

+

Get the App.net to Twitter recipe

+

Post to App.net from Day One

+

I love Day One, however it doesn’t support posting to ADN. I set up an IFTTT recipe that works off an email from Day One and posts it ADN. This recipe also gets bonus points for working in conjunction with the above ADN To Twitter Recipe.

+

Get the post to ADN via Email recipe

+

Camera Roll to Flickr

+

This recipe is only possible through the new, delightful IFTTT iOS app. Whenever a new photo is taken, IFTTT uploads the photo to my Flickr account. This recipe serves the second purpose of offloading my Camera Roll backups from iCloud to Flickr.

+

Get the Camera Roll to Flickr recipe

+

Feature Request

+

I do wish IFTTT had one additional feature, Feed actions. I would love to have a personal feed, ala Huffduffer, into which IFTTT would dump any data from the various IFTTT triggers. A Feed action would technically allow basic looping when combined with the Feed trigger, which would be super useful and interesting.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html b/themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html new file mode 100644 index 0000000..20baf94 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html @@ -0,0 +1,235 @@ + + + + + + Indexing My Blog’s Links + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/introducing-cycle/index.html b/themes/cycle/exampleSite/public/writing/introducing-cycle/index.html new file mode 100644 index 0000000..fec5e63 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/introducing-cycle/index.html @@ -0,0 +1,297 @@ + + + + + + Introducing Cycle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Introducing Cycle

+ + +
+

Cycle is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today.

+

Language choice

+

I wrote in my previous post announcing my re-write that I was considering Rust or Common Lisp because those languages allowed me to build a stand alone binary of my site builder. I got some feedback on Twitter that Common Lisp would actually be a good choice:

+ +

I ended up going with Common Lisp and I really enjoyed the experience. Common Lisp has the best REPL I’ve ever used in any language. It’s wonderful to use. Having a good REPL is a key component of not only creating new features but also fixing bugs. Once I had chosen the language it was time to figure out how I wanted my program to consume and build my site.

+

Mimic Jekyll…to a point

+

I spent some time understanding how Jekyll works to figure out which parts I wanted to emulate and which parts I wanted to leave behind or solve differently.

+

JSON > YAML

+

Jekyll relies heavily on YAML for data files and inside every post. The decision to include it in every post has always bugged me about Jekyll so I wondered what a static site generator would look like if it used JSON instead of YAML. In my implementation every post is represented as a Markdown file and data for that post is represented as a separate JSON file. The directory structure looks like this:

+
./
+├── README.md
+├── posts
+│   ├── a-few-bash-tips.json
+│   ├── a-few-bash-tips.md
+
+

While this increases the amount of files needed to build the site, I find keeping the Markdown files as “vanilla” as possible worth the trade-off.

+

The Good Parts

+

I copied Jekyll’s directory and file structure pretty closely. The site is built from these source files into a directory called site that holds the entire site. Here’s a breakdown of the required directories and files:

+
    +
  • public: anything in public is copied over verbatim to site. This is the place to put assets like images, third-party JS etc.
  • +
  • posts: contains posts that are processed through templates and dropped into site. Cycle processes all the posts into a data structure that is then available globally inside Cycle for any other part of the build process to use.
  • +
  • templates: hold the various templates for pages and posts as well as templates for RSS and Sitemap.
  • +
  • pages: holds files that are either .mustache files or .md files. If a page file is a .md file then it gets processed with a generic templates/page.mustache template. The only supported .mustache file at the moment is the archive.mustache file which is passed the entire post data object to generate paginated archive pages.
  • +
  • site.css is a file in the root of the project. Any CSS in this file is inlined into the <head> of the built site.
  • +
+

Easy to add new features and fix bugs

+

Another aspect I was hoping to solve with this re-write was to make it easier to add new features and fix bugs as they come up. Common Lisp’s previously mentioned REPL helps in this area. Slime is an Emacs extension that integrates Common Lisp’s REPL into Emacs along other functionality like debugger support. Having the ability to set breakpoints and execute portions of my program at will right inside my editor helps identify bugs. The expressiveness of Lisp also helps in ramping up on code that I wrote months ago. I’ve been using Cycle for a few months now and I’ve enjoyed that I don’t feel overwhelmed when I have to look back at the code.

+

Building binaries in Travis

+

One last thing about Common Lisp and it’s stand-alone binaries. I got Travis CI hooked up and building macOS and Linux versions of cycle without too much struggle. Now whenever I tag a new release Travis builds the binaries and attaches them to the Release in Github. Automating this build and release work has made the actual hosting and building of the site pretty painless.

+

Netlify

+

I switched from AWS S3 to Netlify not because S3 was inadequate in anyway but more because I wanted an excuse to play with Netlify’s features. I ended up writing a Makefile that Netlify can execute to download the latest version of Cycle and then build the site. Netlify is configured to run make cycle && make when a new post is pushed to the repo.

+

Some Common Lisp helper functions

+

Over the course of getting a working version of Cycle out the door I wrote a few helper functions that remove some friction in some common tasks.

+

String concat

+

The concatenate function in Common Lisp is a general purpose function that works over strings as well as lists and other data types. It’s typically used like this: (concatenate 'string "hello" "world"). Notice that concatenate requires that the type of the values to be specified. I didn’t like this so I wrote this:

+
(defun concat (&rest strings)
+  "Wrapper around the more cumbersome concatenate form."
+  (let (result)
+    (dolist (x strings)
+      (setf result (concatenate 'string result x)))
+    result))
+

concat takes any number of strings and uses the dolist macro to call concatenate on them. It’s used like this: (concat "hello" "world"). Much better in my opinion.

+

Write to file

+

Cycle writes a lot of files. That’s pretty much it’s main jam. I realized I was writing the same boilerplate to write files all over the place so I wrote a wrapper function:

+
(defun write-file (contents file)
+  "Write CONTENTS to FILE."
+  (with-open-file (stream file
+                      :direction :output
+                      :if-exists :supersede)
+    (write-sequence contents stream)))
+

Now I can write a file like this: (write-file "Hello world" "./hello-world").

+

String splitting

+

The last helper function I want to show is my wrapper around the UIOP:split-string function. Much like the concat function this mainly avoids extra typing:

+
(defun split-string (string sep)
+  "Wrapper around uiop:split-string to avoid keyword typing."
+  (uiop:split-string string :separator sep))
+

Now I can split a string like this: (split-string "Hello World" " "). Much easier.

+

Never done

+

While I may be using Cycle to publish this very site it’s not done and I don’t think it ever will be. That’s the beauty of software and specifically software written for an audience of me. I will always have new ideas and things I want to fix and Common Lisp provides some fairly unique and fun ways to keep iterating.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html b/themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html new file mode 100644 index 0000000..8c2b7b4 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html @@ -0,0 +1,258 @@ + + + + + + Introducing ivy-feedwrangler + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Introducing ivy-feedwrangler

+ + +
+

It’s not secret that I’ve become quite the Emacs fan over the past couple years. One of my favorite things about Emacs is the Ivy package (and counsel and swiper of course). In exploring what Ivy was capable of I had the idea to write a small package that used Ivy as the interface for my RSS service of choice, Feedwrangler. You can check out the repository here and install the package via melpa.

+

What is Ivy?

+

Ivy is, according to it’s Github repo, a “a generic completion mechanism for Emacs.” Quite simply Ivy is an interface for quickly working with lists of data whether that be:

+ +

Ivy-feedwrangler

+

Ivy makes manipulating and filtering lists super quick and easy. In fact, I’d say it’s the quickest way to work with this kind of data. Working with my RSS feed is now lightning fast. Here are a few features of ivy-feedwrangler:

+
    +
  • Mark individual posts as read or mark all as read
  • +
  • View text posts inside a buffer in Emacs, this supports inline images!
  • +
  • Quickly filter through unread items since Ivy can handle regex out of the box
  • +
  • Uses authinfo to handle authentication which uses GPG to encrypt credentials.
  • +
+

The other big perk to using ivy-feedwrangler is that, unlike elfeed (the package for RSS in Emacs), it interacts directly with the Feedwrangler API! That means I can read things in Emacs and that state is synced correctly to my phone and vice-versa.

+

So, if you have a Feedwrangler account, give ivy-feedwrangler a try and let me know what you think!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html b/themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html new file mode 100644 index 0000000..2651391 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html @@ -0,0 +1,241 @@ + + + + + + IP Address Alfred Extension + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

IP Address Alfred Extension

+ + +
+

I have to admit, I am addicted to customizing my bash experience. Yesterday, I came up with a little, one-off function that smooths over a point of friction in my workflow – working with my internal IP address.

+

During any project, I am often testing in virtual machines. On my development machine I have my host file hacked to manage all the dev URLs. The friction point is constantly having to look up my IP address to test in VMs, or on other devices. This bash function simply parses out my IP address from the results of ‘ifconfig’ and copies that IP address to my clipboard. Now, instead of jumping into the Network pane to see my IP, or reading through ifconfig myself, I can simply type “ip”, and jump back to my VM and paste in the address. The function also displays the IP address on the command line ready for easy typing into a mobile device.

+

function ip { IP=$(ifconfig | grep 'inet 1' | cut -c 6- | awk 'NR==2 {print $1}') echo $IP echo $IP | pbcopy }

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html b/themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html new file mode 100644 index 0000000..93836e3 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html @@ -0,0 +1,246 @@ + + + + + + iPhone checker with Capybara and Twilio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

iPhone checker with Capybara and Twilio

+ + +
+

I got my gigantic iPhone 6+ last weekend, and not via the online Apple Store where my order had been sitting for a couple weeks and wasn’t going to ship until Nov. 5th. Instead I got a friendly text message the minute the phone was available at my local Apple Store. With a few great tools it was incredibly easy to set this system up.

+

TL;DR: I set up a small Heroku app that uses Capybara to check Apple’s website for availability and sends a text to my phone using the Twilio service.

+

The entire process was pretty simple once I figured out a few Heroku oddities. The app hinges on the fact that Apple provides a “Check Availability” link during the ordering process. This link pops open a modal that take your zip code and checks nearby Apple stores for your product.

+

All I had to tell Capybara to do was visit the URL, click the check availability button, and enter my zip code. After that I loop through the store list and check the status message. If the phone is available I send myself a text with the store name, phone model, and link.

+

The toughest part of this project was figuring out how to tell Heroku where the Phantomjs executable was located. Capybara uses Phantomjs behind the scenes and without it the whole thing wouldn’t work. I initially tried to use the Phantomjs build pack but a weird thing with Heroku is that declaring a build pack seemingly removes the path for the Ruby executable. I then discovered the awesome multi build pack tool. Once I created my .buildpack document I just had to tell Heroku to load the Phantomjs build pack and the Ruby build pack like this:

+
https://github.com/stomita/heroku-buildpack-phantomjs.git  https://github.com/heroku/heroku-buildpack-ruby
+

The last piece of the app uses clockwork to kick off the scrape every 10 minutes. Clockwork is incredibly easy to setup and use. Specify the command in the Procfile and Heroku will understand exactly what to do.

+

The code for the project can be found over at Github. Reach out on Twitter or file an issue if you have any questions.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html b/themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html new file mode 100644 index 0000000..a05f83d --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html @@ -0,0 +1,241 @@ + + + + + + Is WebP really better than JPEG? + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Is WebP really better than JPEG?

+ + +
+
+

If you have used tools like Google’s PageSpeed Insights, you probably have run into a suggestion to use “next-gen image formats”, namely Google’s WebP image format. Google claims that their WebP format is 25 – 34% smaller than JPEG at equivalent quality.

+
+
+

In any case, when converting images to WebP, check that they are actually smaller than the JPEG equivalent. There’s no need to serve larger images to your users than needed.

+
+

Great analysis of the WebP image format and a good reminder to not blindly follow what various auditing tools are reporting. Test and verify in addition to implementing the various suggested improvements.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html b/themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html new file mode 100644 index 0000000..de735fd --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html @@ -0,0 +1,261 @@ + + + + + + Pinboard popular page in Emacs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Pinboard popular page in Emacs

+ + +
+

Ok, this one is still piping hot in my *scratch* buffer so remember that before you criticize the rough edges. I’ve long wanted to quickly filter through the popular links page on pinboard.in without jumping over to a browser. Ideally this page would have an RSS feed or API end point but alas it has neither. I love pulling things into Emacs (yay for text-based interfaces!); so I set out to pull these links into Emacs and display them via Ivy.

+

Feel free to skip ahead and checkout the repo if you’re so inclined.

+

Steps

+

I curled the page down and pasted the HTML into a buffer in Emacs so I could start pulling things apart. My first attempt was to use the excellent elquery library but that was choking on the DOM structure and I never could quite pin down where (sorry Adam, I need to post an issue about that!). My next attempt was to use a more “manual” scripting approach. Since Emacs possesses so many ways to manipulate buffer text I was sure there could be a programmatic way to do this (without doing a bunch of regexing which I’m terrible at and even more so in Emacs). The basic series of steps boiled down to this:

+
    +
  • Use the new-to-me keep-lines function to trim everything out of the buffer except the popular links. I used the classname of the links (bookmark_title) to identify them.
  • +
  • Use loop-for-each-line to well loop over each line. Inside this loop I would need to pull out the href and the title of each anchor link.
  • +
  • I used re-search-forward to move from target to target to figure out the point boundaries for my href and my link text.
  • +
+

I ended up breaking this functionality out into it’s own function since I used it more than once and it was cumbersome to type it all out.

+
    (defun re-capture-between(re-start re-end)
+      "Return the string between two regexes."
+      (let (start end)
+        (setq start (re-search-forward re-start))
+        (setq end (re-search-forward re-end))
+        (buffer-substring-no-properties start end)))
+
    +
  • The final step was dumping the href and the link text into a plist and push that into a larger collection I could pass onto ivy-read to generate my interface.
  • +
+

Coding string

+

One gotcha I ran into is that my titles would occasionally contain odd character sequences like \302. Turns out those are punctuation and various text symbols. The solution is to run the title through decode-coding-string for 'utf-8 to generate the proper characters.

+

❤ Emacs

+

Emacs is so powerful for this type of text manipulation because you can interactively work each step of a program out in an actual buffer and then put those steps together into a function. Each potential solution I thought of was quickly trialed via M: and frequent looks at documentation. Hopefully this has been a helpful look into how I approach solving problems in Emacs. Thanks for reading!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html b/themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html new file mode 100644 index 0000000..3427376 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html @@ -0,0 +1,241 @@ + + + + + + JS2Coffee Alfred Workflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/just-start-over/index.html b/themes/cycle/exampleSite/public/writing/just-start-over/index.html new file mode 100644 index 0000000..92f520e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/just-start-over/index.html @@ -0,0 +1,244 @@ + + + + + + Just Start Over + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Just Start Over

+ + +
+

I love when designers write about their experience and process in designing a product.

+

Recently, Sebastiaan De With wrote a post about his experience designing the doubleTwist Alarm Clock, an Android Clock app made by doubleTwist. I found myself nodding my head at this paragraph in his write up:

+
+

During the process, I threw away a ton of designs and simply started over. I also touched on this being an important part of the design process in the interview I gave on design.org: when you feel like what you’re working on really needs a little bit extra, you have to realize that — even though you spent so much time on them — your designs are just pixels, and you can probably simply do better. Throw it out. Kill your baby. Start over. It’s made this app what it is today.

+
+

Starting over is a skill, and it’s something I need to get better at.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/keeping-up/index.html b/themes/cycle/exampleSite/public/writing/keeping-up/index.html new file mode 100644 index 0000000..c13f076 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/keeping-up/index.html @@ -0,0 +1,249 @@ + + + + + + Keeping up + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Keeping up

+ + +
+

Thanks to this tweet by Adam Clark and this post by Brian Rinadli I’ve been thinking about how I keep up with changes in the web development world.

+

Brian writes in his article that

+
+

One of the biggest difficulties front-end developers face can be deciding what is worth paying attention to and what isn’t. If you follow social media, Hacker News, EchoJS or even a handful of blogs, it can be hard to decipher the tools or frameworks that are deserving of investigation versus those that maybe just aren’t there yet.

+
+

I agree; there’s good signal in those streams. However, it’s incresingly difficult to parse the good stuff from the link bait. Brian shares a great list of email newsletters that aim to help cull the noise into manageable chunks of information. I subscribe to Web Design Weekly and Web Development Reading List. I probably only click on 3-4 links in each one, but this approach has worked really well for me for quite some time.

+

Adam expressed another angle to this issue:

+ +

Personally, I gave up trying to read my entire feed a while ago; it isn’t feasible. I also try to be selective about how many folks I follow. The harsh reality is that eventually you won’t be able to keep up. I recommend News.Me which emails you the top couple links that were shared in your twitter feed the previous day.

+

I also highly recommend Pinboard’s popular page. While not specifically related to web development, I always find a good link or two perusing it every few days.

+

These tools allow me to relax. Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html b/themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html new file mode 100644 index 0000000..634d779 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html @@ -0,0 +1,243 @@ + + + + + + Kyle Steed on rest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Kyle Steed on rest

+ + +
+

Inspiring article by Mr. Kyle Steed, do yourself a favor and take a few minutes and read it.

+
+

Resting isn’t being lazy. Resting is the promise we receive by faith to believe what the Father has spoken and trusting Him to provide all the while continuing to live and work and love.

+
+

I found this quote especially important given my recent string of posts on working hard. Life is all about balance, which is hard.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/lambda-talk/index.html b/themes/cycle/exampleSite/public/writing/lambda-talk/index.html new file mode 100644 index 0000000..cda871c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/lambda-talk/index.html @@ -0,0 +1,240 @@ + + + + + + Lambda Talk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html b/themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html new file mode 100644 index 0000000..108ed1a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html @@ -0,0 +1,275 @@ + + + + + + Learning to think in React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Learning to think in React

+ + +
+

Some of you may have noticed that this blog has been going through some renovations. I’ve spent the last couple months moving off Siteleaf and towards a hosted WordPress install. My ultimate goal is to use Wordpress strictly for managing content and to attach a separate front-end written in React.js. While not completely finished, I’m at the point where all pieces are functional enough that I feel comfortable to begin sharing what I’ve learned through the process.

+

React

+

At the moment, React is definitely the cool kid on the Javascript framework block, which history tells us is a perilous and passing position. Regardless, I’ve been intrigued by its philosophy and decisions for a while. Love Facebook or hate them, you can’t deny they have a fantastic engineering team solving some of the hardest problems on the web. My interest in React stems from the fact that that, instead of setting out to solve all the problems of building a web app, it aims to solve just one: the complexity of building user-interfaces. Facebook explains how React makes building UIs easier in a perfect introductory post (which I’ve gone back to many times) that walks through building up a frontend from scratch. Because React is focused on the user interface, it isn’t a very large API to learn. This focus encourages you to use any other tooling, frameworks, or libraries for other aspects of your app.

+

Isomorphic

+

React’s other big draw for me is that it easily enables an isomorphic structure for your web application, which simply means that the same code can render HTML pages on the server and render HTML in the browser. React accomplishes this via two render methods: render and renderToString. render is the default method that inserts the React HTML into a DOM node, and renderToString does what it says on the tin by passing the HTML out as a string.

+

The biggest challenge has been learning to think “isomorphically.” Thankfully, there are several fantastic articles that walk through how to structure and reason about an isomorphic app. Nicolas Hery has a fantastic overview of what an isomorphic app structure can and should look like; I still have this one open in my browser, as I refer to it constantly. I was inspired by James Long’s excellent post on moving his blog to React. Additionally, Charlie Marsh’s post helped me get off the ground when it comes to writing an isomorphic app with React.

+

Data flow

+

Having an isomorphic app means data flow in the app is going to change, and I definitely bent my brain trying to figure out a reasonable approach. The aforementioned Hery article does a great job of outlining one possible solution. Facebook of course has its Flux architecture as the “preferred” approach, but I opted for a simpler approach more akin to James’ flow. Essentially, I defined a static function called fetchData anywhere I needed to request data. I then called this function on the router level.

+

React-router

+

Speaking of the router, I’m using the awesome and delightful React-router. React-router is a fantastic example of how to maintain an open-source project. This post announcing changes to its API reveal the depth of thinking and intentionality of React-router’s authors. I’ve poured over the docs and issues in the course of this project and have been impressed with it constantly.

+

I’m using React-router to handle routes on the server and the client (yay, isomorphic!) with React’s render and renderToString methods. This means that I have a server-routes.js file and a client-routes.js file, which are the only two files that aren’t shared between the client and the server. I’m using a vanilla Express server to kickoff the server portion of the blog. React-router simply plugs in as middleware to handle serving up the application. On the client, I have React-router using the History APIs to navigate, which greatly increases the perceived performance of the site.

+

Promises

+

This was my first experience working with Promises in Javascript. I don’t know how I could have done this project without them - I’d probably still be untangling all the callbacks. Luckily, the brilliant minds behind CujoJS have not only a great promises library, but also a rest library that returns promises. Moreover, both libraries work in the browser and on the server. The pattern I followed for my data fetching looks like this:

+
var promises = state.routes.filter(function (route) {
+  return route.handler.fetchData;
+}).reduce(function (promises, route) {
+  promises[route.name] = route.handler.fetchData(state.params);
+  return promises;
+}, {});
+
+resolveHash(promises).then(function (data) {
+  React.render(<Handler data={data}/>, container);
+});
+
+

Sidenote: For a fantastic primer on .map, .reduce, and .filter, check out Elijah Manor’s post.

+

These functions go in react-router’s run callback. The state.routes object contains the matching route components, so you can filter over them and get all the necessary fetchData functions. We massage this object of functions into a key:value structure to use with the resolveHash method that ships with whenjs. resolveHash will call all the fetchData methods, and once all data has been fetched it calls back to React to render with the new data. This is all possible because, thanks to rest, every fetchData method returns a promise. Here is an example of what a fetchData function looks like:

+
fetchData: function(pageNumber) {
+  var fetchPosts = rest(url).then(function(response) {
+    var postInfo = {
+    };
+    return postInfo;
+  });
+  return fetchPosts;
+}
+
+

Going Forward

+

I think that covers the React portion for now. I’ve pulled the React portion out of my private repo and published it on Github, feel free to browse around. I hope to outline other interesting pieces of the blog, including the WordPress side of things, soon. Feel free to ping me on twitter with any questions.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html b/themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html new file mode 100644 index 0000000..ce18f1c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html @@ -0,0 +1,239 @@ + + + + + + Lessons learned from integrating OpenAI into a Grafana data source + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html b/themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html new file mode 100644 index 0000000..1b59969 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html @@ -0,0 +1,242 @@ + + + + + + Lyza Gardner on Laying Down our Burdens + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Lyza Gardner on Laying Down our Burdens

+ + +
+
+

Part of being successful on the pan-device web is relinquishing control of things we never had control of in the first place. Some of this you have probably heard. Web design processes are being re-imagined with an emphasis on adaptation and a rejection of pixel-perfect mockups. Content is increasingly given a position of centrality, and design flows around it.

+
+

Just go read the whole thing.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html b/themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html new file mode 100644 index 0000000..524cac1 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html @@ -0,0 +1,248 @@ + + + + + + macOS 10.15: Slow by Design + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

macOS 10.15: Slow by Design

+ + +
+

A few days ago Allan Odgaard wrote up the reasons for the frequent slowdowns he’s experiencing in macOS Catalina and it’s shocking:

+
+

Apple has introduced notarization, setting aside the inconvenience this brings to us developers, it also results in a degraded user experience, as the first time a user runs a new executable, Apple delays execution while waiting for a reply from their server. This check for me takes close to a second.

+
+
+

This is not just for files downloaded from the internet, nor is it only when you launch them via Finder, this is everything. So even if you write a one line shell script and run it in a terminal, you will get a delay!

+
+
+

I am writing this post to call attention to what I consider a serious design problem with Apple’s most recent OS where it appears that low-level system API such as exec and getxattr now do synchronous network activity before returning to the caller.

+
+

Marco Arment hit the nail on the head with his tweet summary of the post:

+
+

The macOS security team needs to ask themselves hard questions about their implementation choices when very smart people are disabling huge parts of their OS security layer just to get reasonable performance from common tasks.

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html b/themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html new file mode 100644 index 0000000..ee434f5 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html @@ -0,0 +1,247 @@ + + + + + + Maybe you should…it's not you…move on. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Maybe you should…it's not you…move on.

+ + +
+

Twitter’s recent API changes and announcements seem to be purposefully obtuse. I don’t know why they can’t just make an announcement telling third-party, client developers to “kick rocks” and turn off the API? It would be easier, their brand probably wouldn’t suffer as much. Maybe they think that any publicity is good publicity? Or maybe Twitter has been incompetent from the start (the fail whale was fun right?), and we forget how they really didn’t contribute any meaningful features or innovations to their own platform, users did.

+

Don’t get me wrong, I’m not ganging up on Twitter (wouldn’t want to hurt a companies feelings right?) or anything. I’m not upset with Twitter for changing how their platform works, it is their platform after all. I’m just amazed at the lack of clear, direct communication.

+

So, here is a list of other writers who have attempted to unravel what Twitter’s recent announcements actually mean. Enjoy.

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html b/themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html new file mode 100644 index 0000000..0b24bbc --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html @@ -0,0 +1,244 @@ + + + + + + Medium isn't a permanent fixture on the Internet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Medium isn't a permanent fixture on the Internet

+ + +
+

Owen Williams just realized Medium isn’t a permanent fixture on the Internet:

+
+

It’s not difficult to imagine an acquisition on the horizon (by who, one would wonder) or some other sort of exit. It doesn’t feel like Medium has a strategy, living on borrowed time and money; what happens if this beautiful, simple central store of content just disappears?

+
+

No offense to Owen but this has been Medium’s problem from day one. If you’re writing on the Internet and you aren’t hosting (owning) your content you’re work will disappear; it’s just a matter of time.

+

Owning your content is why micro.blog is so interesting to me. Owning your content is why RSS is never going away. Owning your content is why things like Wordpress, Moveable Type, and the JAM stack are much better choices than yet another online service.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html b/themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html new file mode 100644 index 0000000..0bf76f8 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html @@ -0,0 +1,240 @@ + + + + + + Messi is re-writing the record book + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Messi is re-writing the record book

+ + +
+

In a fantastic video the YouTube channel MagicalMessi documents all the various records that Messi has broken during his illustrious career. It’s a fantastic video. Messi is one of a kind and we’ll never see someone like him again.

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/microblogging/index.html b/themes/cycle/exampleSite/public/writing/microblogging/index.html new file mode 100644 index 0000000..4c39a3b --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/microblogging/index.html @@ -0,0 +1,248 @@ + + + + + + Microblogging + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Microblogging

+ + +
+

Manton Reece recently shared his microblogging setup with WordPress. I have a similar system that was inspired by Jeremy Keith’s example. Like Manton, I had to figure out the quickest way to create a new post. I eventually settled on SMS-to-post thanks (once again) to Twilio. SMS-to-post lets me text my Twilio number which sends the text to WordPress where it becomes a new “note”. Publishing that “note” to Twitter is just a matter of hooking into the WordPress publish_post action and sending the post to Twitter via its API.

+

Here are a few other implementation notes:

+
    +
  • I created a custom post type in WordPress called “Notes”.
  • +
  • The post status API makes this entire process smooth.
  • +
  • SMS-to-post has a few gotchas, the biggest one is that SMS with emoji are limited to 70 characters.
  • +
  • I don’t have an RSS feed for my Notes…yet
  • +
  • I save the tweet ID of every post that gets posted to Twitter. I use that ID to pull in the favorite and retweet counts and display them next to each “note” in the WordPress dashboard.
  • +
  • Twilio needs an endpoint to POST incoming texts to WordPress. Creating custom endpoints is trivial thanks to this great guide. I also recommend the rewrite rules inspector plugin for working with rewrite rules.
  • +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html b/themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html new file mode 100644 index 0000000..a671f93 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html @@ -0,0 +1,312 @@ + + + + + + Migrate an existing build process to npm scripts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Migrate an existing build process to npm scripts

+ + +
+

Last week I gave a short introduction to using npm as a build tool at GemCity JS.

+ +

Rewrite?

+

There were a few questions about how to start using npm as a build tool on an existing project. The short answer is: start abstracting tasks behind npm scripts. This weekend I migrated this blog to my new favorite host and ended up replacing a grunt task with a npm task. Here’s how it went down.

+

Pick a task

+

I was using two plugins, grunt-usemin and grunt-rev, to “fingerprint” or rev my asset files. It barely worked (only some files were properly rev’d and inserted) and it was awkward. Usemin requires specific HTML comments so that it knows what files to replace. I finally decided to write my own rev task.

+

The old

+

For reference here is my old Grunt config:

+
 rev:
+  files:
+    src: ["public/js/browser.js", "public/css/base.css"]
+
+  usemin:
+    html: 'server/app.hbs'
+    options:
+    assetsDirs: 'public/'
+
+  useminPrepare:
+    html: ['server/app-tmp.hbs']`
+

These tasks were run in this order during deployment: rev, useminPrepare, usemin.

+

The plan

+

I stared off by jotting down the flow and transformations required for revving my assets. I came up with this list:

+
    +
  1. Compile assets (sass, babel)
  2. +
  3. Rev them (this is just magic right?)
  4. +
  5. Overwrite non-rev’d paths in app.hbs.
  6. +
+

That list was terribly shortsighted. Here’s how it actually turned out:

+
    +
  1. Compile assets
  2. +
  3. Generate rev filename for each asset
  4. +
  5. Write new asset file with rev’d filename for each asset.
  6. +
  7. Create (force if necessary) app.hbs from app-tmp.hbs (-tmp for template)
  8. +
  9. Read app.hbs as a string.
  10. +
  11. Replace non-rev’d paths with rev’d paths in app.hbs using String.replace().
  12. +
+

Seem like this might be more code and trouble than it’s worth? Not at all.

+

The new task

+

Since we’re going to replace a grunt task with a npm script task, lets use ES6 goodness. I installed babel which lets me execute scripts using babel-node instead of node. I then created a new directory called tasks/ and named my new task file, tasks/rev.js. I also installed the super awesome rev-file package to handle the reving.

+

The code turns out to be fairly succicent:

+
import rev from "rev-file";
+import path from "path";
+import fs from "fs-extra";
+
+const projectPath= path.dirname(__dirname);
+const tmp = `${projectPath}/server/app-tmp.hbs`;
+const app = `${projectPath}/server/app.hbs`;
+
+fs.copySync(tmp, app, {'clobber': true});
+
+const assets = [
+  `${projectPath}/public/css/base.css`,
+  `${projectPath}/public/js/browser.js`
+];
+
+assets.forEach((f) => {
+  const revPath = rev.sync(f);
+  fs.copySync(f, revPath);
+  const appString = fs.readFileSync(app, 'utf8');
+  fs.writeFileSync(app, appString.replace( path.basename(f), path.basename(revPath) ));
+});
+

Wrap it up

+

Now I have a task. How do I integrate this into my existing Grunt process? npm scripts to the rescue. I created a new script entry in my package.json like this:

+

+"scripts": {
+  "start": "node ./bin/www",
+  "rev": "babel-node tasks/rev.js"
+}
+

npm scripts can be called directly using npm run, npm run rev in this case. The final step is to modify my Gruntfile to run the rev command using the handy grunt shell plugin:

+

+  shell:
+    rev:
+      command: "npm run rev"
+

And that’s all I had to do. Now I can continue to replace pieces of my build system with npm scripts without having to do a big re-write. Using npm as a build tool also illustrates the simplicity of some of these tasks. It’s much easier to maintain a 20 line task than to keep multiple plugins up to date.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html b/themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html new file mode 100644 index 0000000..b9350fe --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html @@ -0,0 +1,244 @@ + + + + + + Moved to Siteleaf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Moved to Siteleaf

+ + +
+

I’ve moved this blog from Jekyll on Heroku to Siteleaf on S3. I did this for a couple reasons:

+
    +
  1. Siteleaf gives me more control without having to be on my computer. The ability to post from my phone is the secret sauce in my opinion.
  2. +
  3. Siteleaf is just an API. I was able to easily convert my Jekyll posts to Siteleaf with a simple Ruby script. I can just as easily switch to another platform in the future.
  4. +
+

I’m excited by the move, I also took the opportunity to freshen the design up around here too. Hopefully you’ll see more posts, more regularly.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html b/themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html new file mode 100644 index 0000000..75750cc --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html @@ -0,0 +1,242 @@ + + + + + + Moving away from Google + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Moving away from Google

+ + +
+

Marco and Gruber shared last week that they both use DuckDuckGo and Fastmail(referral link) instead of Google search and Gmail. Since I just started using both services, here are a few of my thoughts on them.

+

I previously had Google Apps set up for my domain email (adam@adamsimpson.net). By far the best thing I can say about Fastmail is that I haven’t noticed anything different since switching. Fastmail’s spam protection, speed, and reliability all seem on par with Google’s and I appreciate the superior incentives of Fastmail when it comes to privacy.

+

It’s the same story with DuckDuckGo, I haven’t noticed a drop-off in the quality of the search results. One of my favorite features is the ability to send search queries as POST requests instead of GET requests. I love this because it prevents my history from getting polluted with DuckDuckGo pages that have terms in the URL; a little thing for sure, but one I appreciate.

+

I was skeptical about how happy I would be with things outside of Google’s ecosystem, but I’ve been pleasantly surprised. Fastmail and DuckDuckGo offer a great alternative to Google’s apps.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html b/themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html new file mode 100644 index 0000000..d117f7d --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html @@ -0,0 +1,241 @@ + + + + + + Moving Tweetbot Beta to a new Mac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Moving Tweetbot Beta to a new Mac

+ + +
+

Tweetbot for Mac entered Beta a few weeks ago, and also cut off new users from trying out the Beta to comply with new API changes from Twitter.

+

I love Tweetbot, and the Mac client is no exception. However I ran into a snag when I tried to set up the Tweetbot Beta on my new MacBook Air. The app kept redirecting me to the Tweetbot Beta blog post. Now to be fair, I think if I had used the Migration Assistant built into OS X I wouldn’t have run into this issue. However I had already decided to “start fresh” on this new machine and only bring things over from my old MacBook Pro when needed. After spending a couple minutes Googling around for a solution, I gave up and reverted to my trusty, stand-by Twitterific.

+

After a couple days of this I got the bug again to see if I could get Tweetbot Beta up and running on my new machine. New comments on the Tweetbot Beta blog post revealed the solution. Check out these two answers, Tweetbot Beta is now happily running on my new MacBook Air. To move Tweetbot Beta to a new machine copy the Tweetbot Keychain item, Application Support folder, and Container folder to your new Mac and you should be good to go.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html b/themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html new file mode 100644 index 0000000..3bd9b7e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html @@ -0,0 +1,246 @@ + + + + + + My First Bookmarklet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

My First Bookmarklet

+ + +
+

Update

+

ESPN has wisely fixed this workaround as of 08/10. I’ll leave the rest of the post up for posterity though.

+

Original Post

+

It all started when I was doing my daily sports news catch-up, and clicked on a link that lead me to an ESPN Insider article, only without the Insider paywall. I clicked on another Insider article and hit the paywall. I wondered if the Insider paywall simply checked the URL scheme, and didn’t have any session or cookie security.

+

I compared the two links and noticed some minor differences, I decided to match the paywalled link to the structure of the non-paywalled link and it worked! Now, I’m assuming ESPN knows this is one way around their Insider paywall, most paywalls seem to have holes (see NYT, WSJ, etc.).

+

Anyway, like any good geek, I went ahead and made my first ever bookmarklet to automate the URL matching. The code is below.

+

javascript:(function(){ var pathArray = window.location.href; var newValue = pathArray.split('&action='); var firstUrl = newValue[0]+newValue[1]+newValue[1]; var secondUrl = firstUrl.split('login&'); var finalUrl = firstUrl+'login%26'+secondUrl[2]; function readInsider() { windowObjectReference = window.open(finalUrl, "_blank"); } readInsider(); })();

+

You may have to hit the bookmarklet more than once for it to work. Despite the hacky nature of the code and skittish performance, the success of my quick little project has me thinking of how I can BOOKMARKLET ALL THE THINGS!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/new-workstation/index.html b/themes/cycle/exampleSite/public/writing/new-workstation/index.html new file mode 100644 index 0000000..d5b32e7 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/new-workstation/index.html @@ -0,0 +1,261 @@ + + + + + + New workstation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

New workstation

+ + +
+

New job means time for a new workstation.

+

Some history

+

The first computer I ever purchased was the 12" Powerbook G4. Since that Powerbook I’ve always had laptops as my main machines (desktop gaming PC not withstanding). Remote working the last few years has made me realize that the portability of a laptop is largely wasted since I only travel a handful of times a year and yet I live with the downsides of a laptop the rest of the time. So, last year I started thinking about a desktop machine for my primary workstation. A desktop is appealing for a handful of reasons:

+
    +
  • More powerful CPUs
  • +
  • More expansion capabilities
  • +
  • More durable
  • +
+

The options

+

The Mac Studio was recently released to much fanfare and was really intriguing to me. However, when I started considering it I only had about a week to 10 days before my start date at Grafana and I couldn’t wait the quoted 4-6 weeks delivery time for a Mac Studio with 32GB of RAM.

+

I was also pretty unwilling to leave my comfy NixOS install + i3. Michael Stapelberg’s latest post about his new workstation proved timely and convinced me to give the new Intel Alder Lake CPUs a shot.

+

Apple’s M1 family of chips deliver incredible performance per watt but I wasn’t as concered about the power usage given this was a desktop machine not a laptop. I was however focused on at least matching the M1 chips in single-threaded performance since a good chunk of my development work (Node, build tools, etc) are still single-threaded. I ended up with the Intel i5-12600k and I really couldn’t be happier. Here’s the full parts list:

+ +

XMP issues

+

I ran into the same memory XMP issues that Michael mentions in his post so I disabled the XMP profile and the system passed the “Coding Horror burn in tests” with flying colors.

+

Cooling

+

I mounted the 140mm fan to the bottom of the case as intake and the CPU cooler is of course positioned as intake as well. Hot air rises out the top of the case quite well. During the prime95 torture test the CPU never got over 78°C and I couldn’t ever hear either fan. I run both fans in the “silent profile” in the BIOS and I use Noctua’s adapters to lower the voltage even more. Now the only fan I could hear during max load was the PSU fan which doesn’t spin at all under low to medium loads but under high load it kicks on. Day to day it’s hardly on so the system is dead quiet most of the time.

+

Case

+

I absolutely love the Cerberus case. It’s Mini-ATX but still super compact and fits on my desk quite well. All the panels are solid metal and the way all the panels pop off is really really nice. I opted for the handle mount on the top and the internal PSU moutning.

+

Linux

+

NixOS installed just fine. I’m runing the 5.17 kernel because Alder Lake needs a newer kernel for it’s graphics and CPU scheduler (coming soon?). I have WiFi and Bluetooh disabled in the BIOS since everything is hard-wired to the machine.

+

Verdict

+

This build has proven quite comfortable over the few weeks I’ve used it. I love that I have 2 free RAM slots if I ever feel the need for more RAM. I also love that I have 3 remaining Nvme slots on the motherboard for additional solid state storage in the future.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html b/themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html new file mode 100644 index 0000000..630e266 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html @@ -0,0 +1,247 @@ + + + + + + Nginx www rewrite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Nginx www rewrite

+ + +
+

Quick tip for rewriting www.example.com to example.com or vice versa in Nginx.

+

My conf file originally looked like:

+

server { server_name www.example.com example.com; }

+

I had to create another server block, and move all the conf information to the new block. In my case I was rewriting www to non-www.

+

server { server_name www.example.com; //rewrite here; } server { server_name http://example.com; //all the server stuff goes in this block; }

+

Update

+

Instead of mucking around with rewriting, I should have just used return, like so:

+

server { server_name www.example.com; return 301 http://example.org$request_uri; }

+

The lesson is, always check out the official docs before Google.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html b/themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html new file mode 100644 index 0000000..f5c9e68 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html @@ -0,0 +1,266 @@ + + + + + + nixpkgs is a treasure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

nixpkgs is a treasure

+ + +
+

Nix and NixOS continue to be the best way to manage and build software that I’ve found. Every project has a shell.nix file in the root where I can define the specific software needed to work on that project along with any necessary environment variables or $PATH modifications. I ran into an issue this week though where I needed an “old” version of Go (1.20) but the version had already been removed from nixpkgs. How can I pull in an “unlisted” version into my shell.nix?

+

It’s actually pretty straightforward, utilize fetchTarball to pull in nixpkgs based on a commit where the version was present sometime in the past. You can mix that import in with regular/“current” packages with no issue like so:

+
{ pkgs ? import <nixpkgs> {} }:
+
+let oldGo = import (builtins.fetchTarball {
+    url = "https://github.com/NixOS/nixpkgs/archive/33c51330782cb486764eb598d5907b43dc87b4c2.tar.gz";
+    sha256 = "sha256:0nflmpfp3pk704vhlvlgh5vgwl8qciqi18mcpl32k79qjziwmih8";
+    }) {};
+in 
+
+pkgs.mkShell {
+  buildInputs = [
+    oldGo.go_1_20
+    pkgs.gopls
+    pkgs.nodejs_18
+  ];
+  
+  hardeningDisable = [ "fortify" ];
+
+  shellHook = ''
+    mkdir -p .go .npm
+    export GOPATH=$PWD/.go
+    export NODE_PATH=$PWD/.npm
+    export NPM_CONFIG_PREFIX=$NODE_PATH
+    export PATH=$PWD/.yarn/sdks/typescript/bin:$PWD/.go/bin:$PATH:$NODE_PATH/bin
+  '';
+}
+

Notice I can reference the “nixpkgs” tarball/snapshot, oldGo, and pull in the version of Go I need?! nixpkgs is such a treasure trove of software, it’s absolutely incredible!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html b/themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html new file mode 100644 index 0000000..147f636 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html @@ -0,0 +1,239 @@ + + + + + + Nothing speaks like a demo + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Nothing speaks like a demo

+ + +
+

Great post from my friend and co-worker Bryan Braun on the value of demoing.

+
+

It didn’t matter that his demos weren’t fully built, or available for anyone to use. We simply needed to see it, in order to understand.

+
+

I find this is true for any kind of project: hobby or professional. Feedback — that elusive crucial ingredient to a good product — tends to arrive when someone else can see/hear/touch/examine what you’re working on.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html b/themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html new file mode 100644 index 0000000..c47c07a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html @@ -0,0 +1,265 @@ + + + + + + On diminishing modes in emacs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

On diminishing modes in emacs

+ + +
+

“Diminishing modes” in Emacs is a popular topic. It took me a while to understand the basic (and simple) rules around how to customize the display of the various mode names.

+

What are modes

+

Modes in Emacs come in two flavors, major and minor modes. The Emacs manual explains modes like this:

+
+

Emacs contains many editing modes that alter its basic behavior in useful ways.

+
+

Major modes:

+
+

[…] provide specialized facilities for working on a particular file type […] Major modes are mutually exclusive; each buffer has one and only one major mode at any time.

+
+

Minor modes are:

+
+

[…] optional features which you can turn on or off, not necessarily specific to a type of file or buffer. […] Minor modes are independent of one another, and of the selected major mode.

+
+

Customize the mode line

+

Modes are great, yet they fill up the mode line. I only really want to know about a handful of minor modes and the major mode. On top of that I don’t like how some modes name themselves (e.g. all caps, too long, etc.). Changing the display or completely hiding a mode is different for major and minor modes.

+

Changing minor mode names

+

Minor mode names are stored in a list variable called minor-mode-alist. You can customize that directly or use the fantastic package diminish as a wrapper around that functionality, like so:

+

(diminish 'flyspell "spell")

+

Changing major mode names

+

Major mode names are not stored in a simple list variable. Yet, fear not! In reading the source of the diminish package, I stumbled across this comment:

+
+

To diminish a major mode, (setq mode-name “whatever”) in the mode hook.

+
+

The variable mode-name couldn’t be correct could it? Yes, yes it is. Here’s an example of changing the mode name for the default elisp-mode:

+

(add-hook 'emacs-lisp-mode-hook (λ () (setq mode-name "λ")))

+

Now you have all the tools at your disposal to change every mode’s name in your mode line.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/on-equifax/index.html b/themes/cycle/exampleSite/public/writing/on-equifax/index.html new file mode 100644 index 0000000..4b84760 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/on-equifax/index.html @@ -0,0 +1,242 @@ + + + + + + On Equifax + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

On Equifax

+ + +
+
+

In the end, the truth of the Equifax breach—who was affected, and how, and what the company will do to help, and what the terms of such assistance entail—might not be the most important lesson from this incident. More than anything, it suggests that a corner has been turned in corporate consumer data responsibility. Like severe weather, breaches have become so frequent and severe that they can begin receding from prominence. No matter their grievous effects, Equifax’s response suggests that fatalism might replace responsibility, planning, and foresight. This is just what happens now.

+
+

I don’t do many link posts but Ian Bogost sums up my feelings perfectly about the Equifax breach.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/on-george-floyd/index.html b/themes/cycle/exampleSite/public/writing/on-george-floyd/index.html new file mode 100644 index 0000000..49192b4 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/on-george-floyd/index.html @@ -0,0 +1,256 @@ + + + + + + On George Floyd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

On George Floyd

+ + +
+

I haven’t written anything here about George Floyd’s murder. I still don’t have a cogent response but here’s what I’ve been mulling over:

+
    +
  • America has a problem when year after year the very institution put in place to serve folks in our communities ends up killing and harassing them and even goes out of its way to target Black people in those communities.
  • +
  • Like everything in America today the response to Floyd’s murder has become politicized. We all need to make the effort to move past our collective politics and biases and grapple with what changes need to be made both personally and collectively.
  • +
+

I’ve collected three links that have stuck with me over the last handful of weeks.

+

Unsurprisingly Dave Chappelle’s 8:46 special on George Floyd is insightful, gripping, and poignant.

+ +

Around the 5:40 mark he breaks down the problem:

+
+

What are you signifying — that you can kneel on a man’s neck for eight minutes and 46 seconds and feel like you wouldn’t get the wrath of God? That’s what is happening right now. It’s not for a single cop. It’s for all of it. Fucking all of it.

+
+

Elsewhere, McSweeney’s, in typical fashion, cast the issue in a new light:

+
+

This initiative, also known as Skynet, was created by Cyberdyne Systems for the Department of Defense as a way to keep Americans safe. Critics have said that spending half of our country’s GDP on developing an army of state-of-the-art cyborgs with advanced weapons systems and an AI specifically trained to neutralize threats was a bad idea. And while the recent killings might seem to confirm that, we feel that, despite a few stumbles here and there, this program has still been an overwhelming success.

+
+

Finally, Chris Rock has this great segment about “bad apples”.

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/on-webpack/index.html b/themes/cycle/exampleSite/public/writing/on-webpack/index.html new file mode 100644 index 0000000..65c76e6 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/on-webpack/index.html @@ -0,0 +1,239 @@ + + + + + + On Webpack + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/openring/index.html b/themes/cycle/exampleSite/public/writing/openring/index.html new file mode 100644 index 0000000..53695a0 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/openring/index.html @@ -0,0 +1,253 @@ + + + + + + Openring + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Openring

+ + +
+

I’ve added Drew DeVault’s openring project to the blog. openring is a nice utility (written in Golang) that parses RSS feeds and generates an HTML template file to include on your website. I love things that utilize RSS feeds and things that make indie sites better and openring does both! Thanks to Drew for the tool.

+

It was pretty easy to integrate into my build system. I added a new Makefile task that looks like this:

+
openring.mustache:
+	./bin/openring \
+	-s https://drewdevault.com/feed.xml \
+	-s https://fasterthanli.me/index.xml \
+	-s https://endler.dev/rss.xml \
+	-s https://inessential.com/xml/rss.xml \
+	-s https://www.bryanbraun.com/rss.xml \
+	< openring.html \
+	> ./templates/partials/openring.mustache
+

I then added this new task as a dependency on my build/generate step and I was done.

+

You can view my template file here.

+

I also added the openring binary directly to the repo. It’s not pretty but it beats compiling the binary every time my site deploys (Note: I do pull down a new cycle binary every time the site deploys but I can control that flow whereas I can’t control where openring builds.)

+

For now I’m only displaying my openring on the home page of the blog but if folks think it would be useful on other pages (like this post page) shoot me a message in my public inbox (link below).

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/oscar/index.html b/themes/cycle/exampleSite/public/writing/oscar/index.html new file mode 100644 index 0000000..663bb96 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/oscar/index.html @@ -0,0 +1,241 @@ + + + + + + Introducing oscar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Introducing oscar

+ + +
+

I’ve been working on a small command-line utility written in Rust called oscar. oscar polls the pbskids.org API for new episodes of any PBS show. If it finds an episode it hasn’t seen before it downloads the episode to the specified directory.

+

I run oscar via the cron scheduler on my home server and over the past few months it’s been largely invisible and maintenance-free. Whenever new episodes show up, oscar downloads them and my 3 year-old can stream it on any of the devices in the house via Plex or Infuse.

+

To get started I recommend pulling down the latest release from Github (if it’s not broken) or building locally via cargo build --release. To view the available shows run oscar list. Once you have found a show tell oscar to find episodes by invoking it with the --show-slug option and the destination directory option like: oscar --show-slug SHOW_SLUG --output /path/to/video/folder.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html b/themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html new file mode 100644 index 0000000..7f0292f --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html @@ -0,0 +1,243 @@ + + + + + + Parsing memory usage in htop/top + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Parsing memory usage in htop/top

+ + +
+

I’ve been trying to figure out how much memory a node app is using on my VPS, and output from top or htop is fairly overwhelming. In searching around I found Mugurel Sumanariu’s post clearly explaining each column related to memory usage.

+

The column I should be paying attention to is RES, which

+
+

[..] stands for the resident size, which is an accurate representation of how much actual physical memory a process is consuming. (This also corresponds directly to the %MEM column.)

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html b/themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html new file mode 100644 index 0000000..bd4fa86 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html @@ -0,0 +1,262 @@ + + + + + + Plaintext and Markdown - A Primer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Plaintext and Markdown - A Primer

+ + +
+

My little sister is headed for her freshmen year of college, and so of course she asked me the classic question, “Should I get Word or Pages for my Mac?”. I told her to get Pages and call it good, but inside I wanted to tell her go get a copy of Byword, iA Writer, Write Room, or any of the other fabulous text editors on the Mac and iOS. I didn’t say any of these things, but I did decide to write it all down.

+

Plaintext

+

Plaintext is all the little .txt files TextEdit saves (but only if you’re in Plaintext mode, naturally). A Plaintext file is the most basic kind of text document. The format is literally just text, there is no formatting aside from basic paragraphs and indents, and no compatibility requirements. None. Read it again. No. Compatibility. Requirements. Last year David Sparks wrote up a fantastic article for Macworld explaining the benefits of Plaintext, he wrote (emphasis mine):

+
+

Although modern word processing programs can do some amazing things—adding charts, tables, and images, applying sophisticated formatting—there’s one thing they can’t do: Guarantee that the words I write today will be readable ten years from now.

+

That’s just one of the reasons I prefer to work in plain text: It’s timeless. My grandchildren will be able to read a text file I create today, long after anybody can remember what the heck a .docx file is.

+
+

Plaintext will last (at least much longer than .doc will), you can count on it. If you need to apply some arcane formatting for a research paper, fire up a copy of Pages or Word and copy and paste your text in. Keep the plaintext file around though, let the actual text live on in those .txt files.

+

Markdown

+

The jelly to Plaintext’s peanut butter is Markdown by John Gruber. Markdown extends Plaintext by adding basic formatting such as headings, unordered and order lists, block quotes, and italics and bolding. Markdown allows you to add inline images, external and internal hyperlinks, and even tables, without compromising the integrity of your Plaintext documents.

+

Every post on this blog is written in Markdown. The blog engine, Jekyll, interprets the Markdown and spits out the appropriate HTML. If I ever wanted to switch to another blog engine, I have a bunch of simple plaintext files that are very portable.

+

If you want to see Markdown in action, or want to practice with the syntax, head over to Markdownr by the indefatigable Mr. Sam Soffes. Markdownr lets you input Markdown on the left side and instantly see the formatted text on the right side. Check it out.

+

If you want the Markdownr experience on your desktop, check out Brett Terpstra’s app Marked.

+

A Few Bullet Points

+

Other benefits of Plaintext and Markdown are:

+
    +
  • Easy for modern Operating Systems to index and search
  • +
  • Simple to backup
  • +
  • Simple to move
  • +
  • Easy to edit on any device
  • +
  • Format agnostic.
  • +
+

Plaintext and Markdown make a great pair, they are unrestricted by compatibility, specific software, or corporate governance. I’ve moved all my text-related work to plaintext and Markdown and it has added a lightness to working with text that is just perfect.

+

Give Markdown + Plaintext a shot, there is literally no barrier to entry. Hopefully you will realize that getting out of heavy word processors like Word or Pages frees up your text, mind, and words.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html b/themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html new file mode 100644 index 0000000..21f4a7e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html @@ -0,0 +1,245 @@ + + + + + + On Polybar bitmap fonts and Ubuntu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

On Polybar bitmap fonts and Ubuntu

+ + +
+

I use polybar as my status bar in i3 and it’s been going great for months now. However, I was recently grepping through the syslog trying to figure out why a browser crash happened and the log was filled with polybar spam that looked like this: polybar|warn: Dropping unmatched character. So I started picking at solving the warning.

+

Turns out there’s a Github issue that contains the solution which is to enable bitmap fonts which I’ll paste here for posterity:

+
# "Un-disable" bitmap fonts
+sudo rm /etc/fonts/conf.d/70-no-bitmaps.conf
+# Clear the font cache
+sudo fc-cache -f -v
+

Apparently Ubuntu disables bitmap fonts by default but polybar uses bitmap fonts for icon rendering. I also needed to install the sijj icon font family which was painless.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/pretty-git-log/index.html b/themes/cycle/exampleSite/public/writing/pretty-git-log/index.html new file mode 100644 index 0000000..93c4dde --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/pretty-git-log/index.html @@ -0,0 +1,242 @@ + + + + + + Pretty Git log + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/psychicpaper/index.html b/themes/cycle/exampleSite/public/writing/psychicpaper/index.html new file mode 100644 index 0000000..b3ecc08 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/psychicpaper/index.html @@ -0,0 +1,248 @@ + + + + + + Psychic Paper + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Psychic Paper

+ + +
+
+

RIP my very first 0day and absolute best sandbox escape ever:

+
+
<key>application-identifier</key>
+<string>...</string>
+<!---><!-->
+<key>platform-application</key>
+<true/>
+<key>com .apple.private.security.no-container</key>
+<true/>
+<key>task_for_pid-allow</key>
+<true/>
+<!-- -->
+

Tweet that demonstrates a recent zero-day (now patched) in iOS. This serves as your annual reminder that parsing xml-like things is a fraught activity.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/rands-on-email/index.html b/themes/cycle/exampleSite/public/writing/rands-on-email/index.html new file mode 100644 index 0000000..10eea13 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/rands-on-email/index.html @@ -0,0 +1,243 @@ + + + + + + Rands on Email + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Rands on Email

+ + +
+

Michael Lopp delivers a great piece on dealing with Email. I especially loved this quote:

+
+

Email is imprecise. It is easy to misinterpret. Email is a digital force of nature. It’s not going anywhere, but email, while convenient and sometimes efficient, is dehumanizing.

+
+

Do yourself a favor and read the whole thing.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/recently-16/index.html b/themes/cycle/exampleSite/public/writing/recently-16/index.html new file mode 100644 index 0000000..a108d1b --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/recently-16/index.html @@ -0,0 +1,270 @@ + + + + + + Recently + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Recently

+ + +
+

I’m stealing the title format of this post from Tom MacWright’s Recently posts.

+

Here’s a random assortment of links and miscellaneous updates on things.

+

autofs

+

autofs is a cool utility that watches a specific directory path and when a program tries to read or write to that path it mounts a filesystem at that location. I’m using this to auto mount my NAS via SMB for mpd. With autofs in place I can run mpd locally (in a “satellite setup”) and have its music_directory point to a path managed by autofs.

+

One thing that was helpful getting the configuration right was testing autofs by running automount -f -v directly which puts it in the foreground and gives verbose output.

+

The two files I configured were auto.master.d/foo.autofs and auto.foo.

+
    +
  • foo.autofs contains one line: /- /etc/auto.foo
  • +
  • auto.foo contains one line as well: /foo -fstype=cifs,rw,credentials=/home/me/.foo-creds ://NAS.IP/foo
  • +
+

mailpreview updates

+

mailpreview-cli is a little program I use multiple times a day to quickly see my unread email without moving from what I’m currently working on and without touching my mouse. I recently noticed it wasn’t grabbing the body of a specific type of email. In the process of fixing that I also added proper unit tests for every format I currently parse through. Yay faster feedback loops!

+

ffmpeg

+

I’ve been a fan of OBS for awhile now. I was recently doing a quick screen recording of my browser window and the browser window wasn’t full-screen so there were black bars around the edges of the recording. I didn’t love that but it’s time to touch the “ffmpeg exists and is awesome” sign again.

+

This superuser post has the answer which consists of two steps:

+
    +
  1. Get the crop parameters of the video from ffmpeg. ffmpeg will detect the black borders and report back the actual content coordinates. +ffmpeg.exe -i '.\some-video.mkv' -vf cropdetect -f null -
  2. +
  3. Re-encode and crop using the crop parameters to trim the borders. +ffmpeg.exe -i '.\some-video.mkv' -vf crop=624:704:332:10 -c:a copy output.mp4
  4. +
  5. Enjoy your pristine video.
  6. +
+ + +

Fin

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/recently-44/index.html b/themes/cycle/exampleSite/public/writing/recently-44/index.html new file mode 100644 index 0000000..fc7f342 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/recently-44/index.html @@ -0,0 +1,248 @@ + + + + + + Recently + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Recently

+ + +
+

I’ve published a few new projects in the last couple of months and I’m behind on announcing them, so I bundled them up together into this post. I’m stealing the title format of this post from Tom MacWright’s Recently posts.

+

One thing to note is that the source code for all these projects is stored on sourcehut. Sourcehut (or sr.ht) bills itself as “the hacker’s forge”. I highly recommend checking it out. It’s also where I host my public inbox.

+

hover-dns

+

Now that I have fiber internet at the house I’ve been hosting one-off services and apps on my own hardware at the house. This is great, however my residential connection is a typical dynamic IP not a static one. Instead of using a service like DynamicDNS I decided to write some Rust (shocker) and leverage the “unofficial” Hover API. The result is: hover-dns.

+

I have hover-dns running in a crontab for a few different domains to keep my domains pointed to the correct IP for my house. While I’m a little uncomfortable with how similar npm and cargo can feel, the trust-dns package is excellent. I was able to quickly read the source code to understand how to setup a Resolver for opendns. Also impressive is that hover-dns ip beats out dig in returning your public IP. I didn’t expect that!

+

podcastfilter

+

Speaking of hosting things at home, podcastfilter.com is one of those things. podcast-filter is a small Go project that allows you to filter a podcast feed by each episode’s description and return a feed of just those episodes that match.

+

mailpreview

+

The recent project I use the most day-to-day is mailpreview-cli. mailpreview-cli is very straight-forward, it accepts a Mail message and returns either the plain text version or the html version of that message. The reason I don’t just pull the Mail message directly is because a Mail message can contain several versions of the message in different encodings (start here if you’re curious: RFC-822). Instead of writing my own parser I grabbed the excellent mailparse crate and wrapped the behavior I wanted around it. On it’s own mailpreview-cli isn’t super fancy but I trigger it from rofi via a shell script which allows me to browse (and then view) all my unread emails right from rofi. Shameless plug: I wrote a short post about getting started with rofi if you’re unfamiliar. mailpreview-cli could be used with Alfred if you’re on a Mac to accomplish the same thing as I’m doing with a shell script and rofi.

+

Fin

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/rename-utility/index.html b/themes/cycle/exampleSite/public/writing/rename-utility/index.html new file mode 100644 index 0000000..d694805 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/rename-utility/index.html @@ -0,0 +1,241 @@ + + + + + + Rename utility + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Rename utility

+ + +
+

I often find myself needing to rename batches of files. I find myself doing this when I have a set of images that are named image-2x.png, and I duplicate them for 1x assests. I tried Automator to see if I could whip up a quick service that would remove the ‘-2x’ from my 1x assests. I couldn’t figure it out in 5 minutes, so I gave up (par for the course with these types of things). I then googled around a bit and turned up several tutorials using awk, sed, or some other custom function. None of that sounded very fun or easy; I then stumbled upon rename.

+

Rename is a standard Unix utility that simply renames files given a pattern to search for and something (or nothing) to replace the pattern with. It supports standard things like globbing, and even supports testing your query to see the results! A basic command looks like this: rename 's/2x copy//g' *.jpg Simple and perfect. In this case rename is going to strip out ‘2x copy’ from any files that have that pattern and replace it with nothing, hence the double slashes at the end. That’s all there is to it. Hopefully this helps someone else who just wants to rename a batch of files.

+

To get rename on a Mac, just brew it, brew install rename.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html b/themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html new file mode 100644 index 0000000..7f2d277 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html @@ -0,0 +1,244 @@ + + + + + + Rotten Tomatoes and Launch Center + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Rotten Tomatoes and Launch Center

+ + +
+

I appreciate Rotten Tomatoes, I don’t always agree with the ratings, but I like how they can add to an argument or conversation about a movie.

+

I hate the Rotten Tomatoes experience on an iPhone. It starts with this horrible app pop-up: Rotten Tomatoes Nag

+

Then it nags you to add the site to your homescreen, my home screen is meticulously planned out and I don’t have the room for non-apps, so Rotten Tomatoes can go kick rocks.

+

A month or so ago I decided to do something about these things that bug me about Rotten Tomatoes. I spent an hour or two poking around the API and cobbled together Diet Rotten Tomatoes. It’s a quick, lightweight way to get a movie’s ratings, a full-size movie poster (click the thumbnail), and a link to the movie on Rotten Tomatoes.

+

I also added a way to search using Alfred or Launch Center Pro. Simple append your search term to the URL like #die hard and it’ll fire off a search as the page loads.

+

Hopefully you find it useful.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/rust-module-system/index.html b/themes/cycle/exampleSite/public/writing/rust-module-system/index.html new file mode 100644 index 0000000..a8fea95 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/rust-module-system/index.html @@ -0,0 +1,239 @@ + + + + + + Clear explanation of Rust’s module system + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Clear explanation of Rust’s module system

+ + +
+

This is a great explanation of Rust’s module system. I wish I had this clear of a picture when I was using modules for the first time in creating oscar.

+

The big takeaway and deviation from npm is this:

+
+

We need to explicitly build the module tree in Rust, there’s no implicit mapping to file system.

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html b/themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html new file mode 100644 index 0000000..8dbaa8c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html @@ -0,0 +1,321 @@ + + + + + + Understanding Rust Strings and str inside structs. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Understanding Rust Strings and str inside structs.

+ + +
+

Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here’s a short breakdown of a compiler error message that stumped me for a bit.

+

Background

+

First, some background about Rust. Rust is a strongly-typed language, which means variables and return values from functions usually require a type annotation that looks like this:

+
let favorite_number: u32 = 12;
+

The type annotation on the variable favorite_number is u32. This should look familiar to anyone who has used a strongly typed language before.

+

A struct in Rust is a way for the user to define any data type. Here’s an example:

+
struct Config {
+  name: String,
+  id: u32
+}
+

Here is how we would approximate this in Javascript:

+
const config = {
+  name: "Adam",
+  id: 4
+}
+

Notice how, in Javascript, we use an Object named config to hold some config for our application. In Rust, we create a struct called Config and define the various fields we need. Rust is strongly typed, so even the fields in the Config struct are type-annotated. Let’s move to where I got tripped up.

+

Stumped

+

I created a Vector (a mutable Array data structure) that contained a couple of instances of a struct. It looked something like this:

+
struct Example {
+    id: String
+}
+
+fn main() {
+    let example: Vec<Example> = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}];
+    println!("{:?}", example);
+}
+

So far, so good. However, I now wanted to map over the collection and create a new collection that just contained the id. Here’s what I tried and what failed:

+
struct Example {
+    id: String
+}
+
+fn main() {
+    let example: Vec<Example> = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}];
+    let map_fail: Vec<String> = example.iter().map(|item| item.id).collect();
+    println!("{:?}", map_fail);
+}
+

Rust playground

+

Understanding the problem

+

What’s happening here? Well, the compiler message is instructive:

+
  error[E0507]: cannot move out of `item.id` which is behind a shared reference
+    --> src/main.rs:10:59
+      |
+  10 |     let map_fail: Vec<String> = example.iter().map(|item| item.id).collect();
+      |                                                           ^^^^^^^ move occurs because `item.id` has type `std::string::String`, which does not implement the `Copy` trait
+
+  error: aborting due to previous error
+
+  For more information about this error, try `rustc --explain E0507`.
+

In Rust there is no Garbage collection (automatic memory management). Instead, Rust requires you, the programmer, to indicate to the Rust compiler what variables have ownership over the value they represent. If that ownership moves in an invalid way, Rust will throw a compile error to prevent a memory error at runtime. The benefit in not having Garbage Collection is two-fold:

+
    +
  1. Faster code without a GC process.
  2. +
  3. Whole classes of bugs are impossible due to Rust’s ownership rules.
  4. +
+

In our error case, mapping over our vector moves the data stored at id to a new Vector. This shift to a new Vector means Rust can no longer guarantee the safety of that portion of memory. Let’s look at the documentation around this error code from the compiler.

+

The explainer page for this error gives us three options:

+
+
    +
  1. Try to avoid moving the variable.
  2. +
  3. Somehow reclaim the ownership.
  4. +
  5. Implement the Copy trait on the type.
  6. +
+
+

#3 sounded like too much for this specific case. #2 also seemed like the wrong approach because I didn’t want to change the ownership, I just wanted a copy or reference to it. #1 was the right answer, but how do I avoid moving the variable?

+

The Solution

+

This is where it’s important to understand the two basic types for strings in Rust, String and str. The doc page for String states (I added the underlines for emphasis):

+
+

The String type is the most common string type that has ownership over the contents of the string. It has a close relationship with its borrowed counterpart, the primitive str.

+
+

Aha, so we’re dealing with a String here, and it sounds like we need a str. A quick glance at the String doc page again reveals just the function we need: as_str. as_str gives us a reference called a slice to the value of a String. Armed with this new knowledge, here’s the solution to this compiler error:

+
struct Example {
+    id: String
+}
+
+fn main() {
+    let example: Vec<Example> = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}];
+    println!("{:?}", example);
+
+    let map_str: Vec<&str> = example.iter().map(|item| item.id.as_str()).collect();
+    println!("{:?}", map_str);
+}
+

Rust playground

+

Fin

+

Rust has proven challenging to learn, but I think the journey and difficulty is worth it. Ownership, the type-system, and the excellent performance continue to impress me. I hope this post encourages folks to give Rust a try! I’m happy to answer any questions via the comments or twitter or wherever else.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/s3-security-policy/index.html b/themes/cycle/exampleSite/public/writing/s3-security-policy/index.html new file mode 100644 index 0000000..87512fb --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/s3-security-policy/index.html @@ -0,0 +1,243 @@ + + + + + + S3 Security Policy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

S3 Security Policy

+ + +
+

I love S3, I use it with Arq, I use it to host this site, backup configs on VPSs, and to transfer random files that are too big for e-mail.

+

As my S3 usage has grown I’ve started creating seperate AMI users for each task, e.g. a siteleaf user for this blog. It wasn’t until tonight that I took the time to craft a better security policy for some of these users.

+

I struggled finding good policy examples until I stumbled across this one over on the AWS Security blog. I highly recommend reading it all the way through.

+

Here’s the basic policy I came up with. This policy restricts access to a single bucket, and allows access via the AWS cli.

+

Note: I had to move the policy to a gist as prismjs was having a hard time with it.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html b/themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html new file mode 100644 index 0000000..9f01763 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html @@ -0,0 +1,238 @@ + + + + + + Seamless branch deploys with Kubernetes + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Seamless branch deploys with Kubernetes

+ + +
+

A trait of good software is the ability to quickly see and verify changes:

+
+

The result is what’s in-use today for HEY: a system that (almost) immediately deploys any branch to a branch-specific endpoint that you can access right away to test your changes without having to use the claims system or talk to anyone else (along with an independent job processing fleet and Redis instance to support the environment).

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html b/themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html new file mode 100644 index 0000000..cc4b4d5 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html @@ -0,0 +1,239 @@ + + + + + + Using SQL to Look Through All of Your iMessage Text Messages + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Using SQL to Look Through All of Your iMessage Text Messages

+ + +
+
+

If you use iMessage on your Mac, you can access the SQLite database where all of your messages are stored. With a little setup, you can use SQL’s raw power to look through your old messages.

+
+

via Simon Willison

+

In this post Dan Kelch walks through how to access the SQLite database that backs iMessage on a Mac. He also shares a few helpful SQL snippets to demonstrate how powerful using SQL on your text messages can be.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html b/themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html new file mode 100644 index 0000000..f20f1b9 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html @@ -0,0 +1,238 @@ + + + + + + Second-guessing the modern web + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Second-guessing the modern web

+ + +
+
+

The low performance parts don’t need to be React. Listing pages, static pages, blogs - these things are increasingly built in React, but the benefits they accrue are extremely narrow. A lot of the optimizations that are cropping up in these corners, things like bundle splitting, server-side rendering, and prerendering, are triangulating, essentially, what we had before the rise of React.

+
+

This isn’t really about React but more about the over-engineering of large swaths of page-types and sites that used to “just work”. I love React and it’s been a giant leap forward for creating complex UIs on the web, that doesn’t mean it’s right for every situation.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html b/themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html new file mode 100644 index 0000000..03d2881 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html @@ -0,0 +1,256 @@ + + + + + + Setting a default browser in i3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Setting a default browser in i3

+ + +
+

The problem

+

I’ve been using the excellent qutebrowser for a few weeks now and I really enjoy it’s minimal approach to web browsing. I still reach for Firefox or Chrome for web development purposes but qutebrowser shines as a daily driver. An issue I ran into is I didn’t know how to set qutebrowser as my default web browser when using i3wm (or any tiling window manager really).

+

The Solution

+

Here’s the solution if you don’t care about the process of figuring it out:

+
xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop
+

The Yak

+

Thankfully there’s an issue on the qutebrowser repo where folks discussed this very thing. Let’s pull the solution apart to gain some understanding of the systems at play here.

+

The first part of the solution in the issue thread is:

+
ls /usr/share/applications/ | grep qutebrowser
+

which lists all the files in /usr/share/applications and then greps that list for entries that contain the word qutebrowser. The Arch Wiki entry on “Desktop entries” explains what the files inside /usr/share/applications are and why that directory is important.

+
+

Desktop entries for applications, or .desktop files, are generally a combination of meta information resources and a shortcut of an application. These files usually reside in /usr/share/applications/ or /usr/local/share/applications/ for applications installed system-wide, or ~/.local/share/applications/ for user-specific applications.

+
+

So by looking for qutebrowser in /usr/share/applications we’re looking for its .desktop file which is important for the next step.

+

Looking at the next part of the solution involves running a program called xdg-settings. What is that? The man page declares that xdg-settings is used to “get various settings from the desktop environment”. OK, so it’s a tool to get (and apparently set?) desktop environment settings. This seems like the right thing. Let’s keep reading the man page.

+

Further on in the man page we find an example on how to set Chrome as the default web browser: xdg-settings set default-web-browser google-chrome.desktop. Notice the .desktop file at the end of the command? XDG uses that file name to figure out which app to use for certain file and link types like text/html or x-scheme-handler/http. Back to our specific case, we need the full name of the desktop file to pass to xdg-settings which is org.qutebrowser.qutebrowser.desktop. With this information we can change the default browser to qutebrowser by running:

+
xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop
+

This tells the desktop environment to launch whatever process is defined in that .desktop file for “browser things”.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html b/themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html new file mode 100644 index 0000000..44ba322 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html @@ -0,0 +1,245 @@ + + + + + + Simple Account Set-up + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Simple Account Set-up

+ + +
+

I recently received my invite to Simple, a new banking service that has taken the design and development communities by storm with the promise of intelligently designed banking apps and interfaces. Now, I’m still waiting for my card to come, so I can’t comment on the service itself. But, during the account set-up process, I was struck by how “right” it all felt, I took some screenshots as I went through to share.

+

Once you fill in your personal info and are approved for an account, you are taken to a page to set up a username and passphrase. Yes, you read that correctly, not a password, a passphrase. Simple claims a passphrase is easier to remember and improves the security of the account.

+

Once your passphrase and username are set up, Simple moves you to the next stage of the process, as pictured below: download the simple app

+

I elected to have a SMS sent to my iPhone to download the Simple app, sure enough in a few seconds there it was. I left the browser window open and proceeded to install the app which had me pick a 4 digit PIN as part of its setup.

+

Once I selected my PIN, the app presented the various user agreements and banking terms with a signature box to sign with my finger. After signing the box and poking around the app a bit more, I looked up at my computer screen and saw that the Simple page had changed to this: signature complete

+

Slick! The app had sent my signature to the page! In doing so, Simple infused a little bit of magic into a typically mundane sign-up process. The other key point of this process is that it ensures the focal point of the service, the Simple app, is set up and ready to go on every customer’s phone.

+

I’m excited to get my Simple card and start using the service, I hope every other bank in the world is paying attention, these little details matter!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html b/themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html new file mode 100644 index 0000000..4962ea4 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html @@ -0,0 +1,239 @@ + + + + + + Slanted Elements with CSS3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/small-tech/index.html b/themes/cycle/exampleSite/public/writing/small-tech/index.html new file mode 100644 index 0000000..4b88b5d --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/small-tech/index.html @@ -0,0 +1,249 @@ + + + + + + Small tech + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Small tech

+ + +
+

Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

+
    +
  • +

    curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

    +
  • +
  • +

    git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

    +
  • +
  • +

    Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

    +
  • +
  • +

    sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

    +
  • +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/small-things/index.html b/themes/cycle/exampleSite/public/writing/small-things/index.html new file mode 100644 index 0000000..5e1f249 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/small-things/index.html @@ -0,0 +1,244 @@ + + + + + + Small things + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Small things

+ + +
+

Recently I’ve come to love MicroJS. I love that I can find tiny, specific libraries that do one thing, and do it well. I think my affection for MicroJS is fueled by my current fascination, React. React bills itself as:

+
+

A Javascript library for building user interfaces.

+
+

I think this focus on building user interfaces pushes me to seek out complimentary tools that focus on solving singular problems. React’s narrowly-defined API and reliance on Javascript’s primitives leaves lots of space for me to cobble together the stack that best solves the current problem(s).

+

As I’ve thought about this more, I’ve realized just how powerful a framework’s aspirations can be. They trickle in and bend my perspective when I use them. It is a small thing that developers, myself included, often overlook.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html b/themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html new file mode 100644 index 0000000..52d8fb4 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html @@ -0,0 +1,256 @@ + + + + + + Solving busybox crond hanging on Alpine Linux boot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Solving busybox crond hanging on Alpine Linux boot

+ + +
+

I recently clean installed Alpine Linux 3.9.3 on my home router (more to come on that in a future post) and ran into a weird bug. Once I successfully installed Alpine and rebooted, the system would start and then hang for over a half hour(!) with the message “Starting busybox crond…”. I tried downgrading to 3.8.0 without any luck. I did some quick Googling and didn’t find anything about busybox crond hanging.

+

Stumped I headed over to the #alpine-linux IRC and posted my situation there. A friendly user suggested it might have something to do with “entropy changes” and to switch the daemons in question to use /dev/urandom. I didn’t feel like switching the daemons was going to be a good long-term solution but I was intrigued by the entropy angle. I looked it up and stumbled upon this reply to a bug thread about “Startup hangs (aports: sshd?)”:

+
+
+

Hello.

+

After upgrading to [edge] i see a possibly endless hang upon +startup, which seems to be caused by PRNG init.

+
+

Try add random.trust_cpu=1 as boot option.

+

See: +https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.19.y&id=39a8883a2b989d1d21bd8dd99f5557f0c5e89694

+

and: +https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.19.y&id=9b25436662d5fb4c66eb527ead53cab15f596ee0

+

-nc

+
+

Interesting. Entropy and boot time are related. Remember I had installed Alpine on a router: a headless PC without any I/O other than two Ethernet NICs and a SSD. Not much there for Linux to generate entropy with, especially since the default was to not trust my CPU.

+

I searched for entropy on the excellent Alpine wiki and found this page. This lead me to Haveged. Haveged is a service that generates additional entropy. I stared it up, enabled it to run at boot, and I no longer had any hang time at boot!

+

I later found this bug report that outlined my problem exactly. Turns out I was too focused on the crond aspect of my boot problem and not the general delay in booting. Oh well, TIL.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html b/themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html new file mode 100644 index 0000000..f9f6dd9 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html @@ -0,0 +1,246 @@ + + + + + + Someone is working harder than you + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Someone is working harder than you

+ + +
+

When I was in junior high I attended a basketball camp. The camp moto for the week went something like: “There’s always more one can do, always someone working harder than you”.

+

At the time I thought this meant Michael Jordan was working harder than me (he was!), but that I was right up there cause I was at camp, duh!

+

Scott Berkun wrote a few days ago:

+
+

Few people in history that we call creatives today read books or took courses on creativity. Instead they apprenticed with masters in a craft and worked with them. They did the grunt work until they had the skills needed to do more sophisticated work. They learned how to develop ideas and deliver finished work by working. There is no other way.

+
+

Go work.

+

As the youths say, ’nough said.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html b/themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html new file mode 100644 index 0000000..3e63548 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html @@ -0,0 +1,243 @@ + + + + + + Sparrow and the App Store + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Sparrow and the App Store

+ + +
+

David Barnard writes up his take on why Sparrow sold out. I found the end of his post fascinating:

+
+

The age of selling software to users at a fixed, one-time price is coming to an end. It’s just not sustainable at the absurdly low prices users have come to expect. Sure, independent developers may scrap it out one app at a time, and some may even do quite well and be the exception to the rule, but I don’t think Sparrow would have sold-out if the team — and their investors — believed they could build a substantially profitable company on their own. The gold rush is well and truly over.

+
+

We are witnessing so many changes on the web and in the mobile industry. Software pricing and sustainability is just another item on a long list of things that are evolving.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/sqlite-tips/index.html b/themes/cycle/exampleSite/public/writing/sqlite-tips/index.html new file mode 100644 index 0000000..baa083c --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/sqlite-tips/index.html @@ -0,0 +1,263 @@ + + + + + + SQLite Tips + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

SQLite Tips

+ + +
+

I’ve been playing around with SQLite recently and I’ve stumbled across a few things I want to remember, so I’m putting them here.

+
    +
  1. +

    The SQLite CLI is pretty darn good. Just remember to read in the SQLite DB file first, e.g. .open /path/to/file. After that, any SQLite command is valid. Specific CLI commands are prefixed with a period.

    +
  2. +
  3. +

    Set the the .mode to line to visually grep the results.

    +
  4. +
  5. +

    To see the rowid include it specifically in SELECT statements on the CLI, e.g. SELECT rowid,* from table.

    +
  6. +
  7. +

    Delete an entry by rowid like this, DELETE FROM table WHERE rowid=7;

    +
  8. +
  9. +

    When structuring a database, create a unique ID for each row like so: create table foo (id INTEGER AUTO_INCREMENT PRIMARY KEY UNIQUE NOT NULL, other_column TEXT).

    +
  10. +
  11. +

    View all tables via .tables.

    +
  12. +
  13. +

    View schema for a table via .schema TABLENAME.

    +
  14. +
+

That’s all I got for now. I’ll drop more tips in this post as I come across them.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/story/index.html b/themes/cycle/exampleSite/public/writing/story/index.html new file mode 100644 index 0000000..5cdd349 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/story/index.html @@ -0,0 +1,245 @@ + + + + + + Story + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Story

+ + +
+
+

Before a technologist writes a line of code, or a marketer writes a line of copy, or a designer creates a single wireframe or design, you have to establish the story that your product is going to tell.

+
+

-UX Mag

+

Story is essential for many things, beyond just products. Stories are how we as humans define our memories and explain our world.

+

A product without a good story - a story that explains where something came from and where it is going - inspires apathy and disinterest.

+

Stories not only affect the consumer and the success of the product, they also affect the people working on the product. If you are feeling “disinterested” or “unmotivated” in your work, examine the story behind your work or product.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html b/themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html new file mode 100644 index 0000000..197188b --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html @@ -0,0 +1,249 @@ + + + + + + The era of the screenshot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The era of the screenshot

+ + +
+

From Benedict Evan’s weekly newsletter on the new screenshot features in iOS11:

+
+

Finally, screenshots. It’s pretty clear that smartphone screenshots are the new PDF - a universal data exchange format.

+
+

:facepalm: We really couldn’t have picked a worse data exchange format.

+

-1000 internets everybody.

+
    +
  • How do those with vision handicaps parse the data in a screenshot?
  • +
  • How do machines reliably parse screenshot information?
  • +
+

-100 more internets after I’ve thought about it some more.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html b/themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html new file mode 100644 index 0000000..7649a76 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html @@ -0,0 +1,243 @@ + + + + + + The Future is Prototyping + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The Future is Prototyping

+ + +
+

First off, you need to read this entire post, Try and Try Again – Why Prototyping Matters over at Big Spaceship. It’s fantastic, awesome, informative, funny, and best of all correct! I’ll be posting more on my personal experience with this topic eventually, but for now here is my favorite quote from the post,

+
+

If action speaks louder than words, then prototyping must be doing the death-metal guttural scream right in speculation’s ear. Instead of spending time discussing possibilities, we can spend time actually making something work. The earlier you get to the trying, the better you can inform the design – from font choices and colors to advanced interaction and mental models.

+
+

Go read the whole thing.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html b/themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html new file mode 100644 index 0000000..549f9fc --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html @@ -0,0 +1,241 @@ + + + + + + The Manhattan Project Time-Lapse + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html b/themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html new file mode 100644 index 0000000..d2c7417 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html @@ -0,0 +1,243 @@ + + + + + + The Stream hasn't won + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The Stream hasn't won

+ + +
+

Hossein Derakhshan wrote a fascinating piece over on Medium that speaks about the web and his relation to it before and after his time in an Iranian prison. He outlines how the web as he knew it has disappeared and been replaced by “The Stream”, or social media. His post is beautifully written and I highly recommend reading it. However, I disagree with some of his conclusions:

+
+

I miss when people took time to be exposed to different opinions, and bothered to read more than a paragraph or 140 characters. I miss the days when I could write something on my own blog, publish on my own domain, without taking an equal time to promote it on numerous social networks; when nobody cared about likes and reshares.

+
+

Nothing in this statement has gone away! The rise of social networks does not mean “the blog” or “the web” is in decline. “The Stream” hasn’t won, I’m not convinced there’s even a fight.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html b/themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html new file mode 100644 index 0000000..9ba73b7 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html @@ -0,0 +1,244 @@ + + + + + + The thing about computers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The thing about computers

+ + +
+
+

Maybe because I lived through this — maybe because I’m a certain age — I believe that that freedom to use my computer exactly how I want to, to make it do any crazy thing I can think of — is the thing about computers.

+
+

Brent Simmons

+

I literally cannot agree with this more strongly! It’s been open in a tab on my phone since Brent published it and I can’t stop thinking about it.

+

I think there’s a line somewhere where convenience and ease-of-use meets this freedom to do anything computing ideal. I think I will always bend toward the freedom side over convenience when it comes to my personal computers. Conversely, I think I bend towards the convenience side over freedom when it comes to my phone. I’m not sure why that is.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html b/themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html new file mode 100644 index 0000000..4668c3d --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html @@ -0,0 +1,244 @@ + + + + + + The web, and my goal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The web, and my goal

+ + +
+

The Pastry Box Project is a fantastic collaboration that is updated once every day with entries regarding the web, development, best practices, or life.

+

Today, Bruce Lawson wrote:

+
+

[…]So the next time you hit upon a clever technique, blog about it. Or if you write some code that could be useful to someone else, put it on Github. Put something back into the community.

+
+

That is my motivation for starting this blog. I glean so much information from fellow web workers that I thought it was high-time I began giving back.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html b/themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html new file mode 100644 index 0000000..fc11e48 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html @@ -0,0 +1,243 @@ + + + + + + The Web is Not Print + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The Web is Not Print

+ + +
+

Zeldman’s notes from Luke Wroblewski’s talk, “Mobile to the Future” at Austin, AEA.

+
+

Likewise, we still have ingrained print characteristics impacting how we think about web and mobile. (Page/canvas, grid layouts, typography, graphical ads.) As many people will tell you — but not many people practice — the web is not print.

+
+

It’s exciting to be working on the web when some of these “print ideas” are starting to give way as the web matures.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html b/themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html new file mode 100644 index 0000000..2387d74 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html @@ -0,0 +1,241 @@ + + + + + + The Wordpress HTTP API is Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

The Wordpress HTTP API is Awesome

+ + +
+

The title says it all. I completely forgot about the Wordpress HTTP API until today, when I was working with HTTP requests in a plugin. I stumbled upon the wp_remote_post function and it immediately replaced my custom HTTP function.

+

Hidden Gem

+

One of the hidden gems in the wp_remote_post function is in the optional arguments you can pass along, specifically the “blocking” option. This option allows you to block script execution while it waits for the response or allows the script to continue on. So simple!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html b/themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html new file mode 100644 index 0000000..48ac485 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html @@ -0,0 +1,242 @@ + + + + + + Theme the Chrome Dev Tools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Theme the Chrome Dev Tools

+ + +
+

Let me start by explaining that the Chrome Developer Tools are incredible, and that I consider them essential to doing my job. What I did not know about these awesome tools is that they are essentially a web app; an app that I can tweak, change, and even inspect with itself.

+

Last week, I stumbled across this post by Mr. Clarke where he explains how to theme the Dev Tools using a single CSS file. This blew my mind and led to a fury of Googling for different themes. I eventually found the exact same theme I use in Sublime, only for the Dev Tools. The Tomorrow Theme for Chrome by Ben Truyman was almost perfect, I made a few slight modifications to it and posted my own gist here.

+

Some of you may be wondering, “Wait, how did you make modifications? Guesswork?”. Nope. Paul Irish explains in this thread how to inspect the Dev Tools…using the Dev Tools! With this little hint, you can easily tweak or completely theme the Chrome Dev Tools.

+

I hope this post was helpful to someone who was unaware of all this functionality a mere stylesheet away.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/thirty-five/index.html b/themes/cycle/exampleSite/public/writing/thirty-five/index.html new file mode 100644 index 0000000..cd85ee9 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/thirty-five/index.html @@ -0,0 +1,279 @@ + + + + + + Thirty five + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Thirty five

+ + +
+

Well crap.

+

It’s been 5 years since I wrote “Thirty”. So now I have to come up with 35 things as I turned 35 yesterday. If anything from Thirty is grossly wrong or really interesting I’ll update it at the same number eh?

+

Let’s go…

+
    +
  1. I still don’t have it figured out, but this isn’t such a shock anymore.
  2. +
  3. Building a house is more scary.
  4. +
  5. Minivans are awesome.
  6. +
  7. Expecting a third kid is not nearly as scary as expecting the first.
  8. +
  9. COVID sucked.
  10. +
  11. Modern medicine is pretty cool actually.
  12. +
  13. More stuff hurts, still just as healthy.
  14. +
  15. Dishwashers aren’t really as scary to repair as they seem (but that doesn’t mean you won’t lose your mind fixing one).
  16. +
  17. The feeling you get as a parent when your kid gets hurt is impossible to describe.
  18. +
  19. Being knocked out from a crazy car accident is also no fun.
  20. +
  21. Carseats are magic.
  22. +
  23. I’ve accepted that the music I liked in 2010 is going to be the music I’ll like forever.
  24. +
  25. Thanks to the internet there is an endless stream of new music that is at home with music from 2010 or even 2000 (Underoath just released a new album for crying out loud).
  26. +
  27. Open source software is incredible.
  28. +
  29. The thrill from in-progress software working for the first time will never get old for me.
  30. +
  31. Feedback loops are important in every area of life not just software.
  32. +
  33. The year of Linux on the desktop is a moving target.
  34. +
  35. RSS will never die.
  36. +
  37. Mechanical keyboards are a refreshing change and I’m not sure why.
  38. +
  39. The Aeropress is still incredible.
  40. +
  41. Computers were a mistake.
  42. +
  43. Computers are a miracle.
  44. +
  45. The Three-Body Problem trilogy continues to knock around in my brain months after finishing it.
  46. +
  47. Watching your child accomplish something for the first time that they’ve been working on is a feeling unlike any other.
  48. +
  49. I’ve realized I learn best by doing, I need to get better at accounting for the bumps along the way.
  50. +
  51. I write things down to remember them later not to look them up later which means most note systems are not worth the trouble for me.
  52. +
  53. Life will be shallow if you only hang out with people like you.
  54. +
  55. Anything is possible on an infinite timescale the trick is figuring out what do with finite time.
  56. +
  57. RIP Rdio.
  58. +
  59. Never pass on an opportunity to twirl your kids around when they’re small. They get big fast.
  60. +
  61. Hanlon’s razor explains most of social media.
  62. +
  63. If you work at a desk all day you owe it to yourself to remove as much Bluetooth from that setup as possible.
  64. +
  65. None of your peers has it all figured out. Ask them “dumb” questions.
  66. +
  67. Properly evaluating risks when your kids are involved is hard.
  68. +
  69. Keep a sweatshirt handy by your bed when your kids are young, getting up at 2am in the winter is cold.
  70. +
+

❤️ you Christi

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/thirty/index.html b/themes/cycle/exampleSite/public/writing/thirty/index.html new file mode 100644 index 0000000..0ac1721 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/thirty/index.html @@ -0,0 +1,272 @@ + + + + + + Thirty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Thirty

+ + +
+

Today I turn 30. For the last couple birthdays I’ve wanted to do a “X things I’ve learned” post like the incomparable Mr. Noah Stokes but I kept forgetting. Not this year! This past year has been exceptionally full. In my mind, turning 30 has always been a milestone. Turns out (spoilers!) the day is just a that, a marker; all the exciting stuff is ahead and behind. I’m so thankful I get to navigate it all with a great partner in crime/life/adventure, my wife Christi 😍.

+

Without further ado, I present to you my list of 30 things I’ve learned in the past year (or so).

+
    +
  1. You won’t have it figured out by the time you turn 30.
  2. +
  3. Buying a house is scary.
  4. +
  5. Buying a house is amazing.
  6. +
  7. Expecting a kid is scary.
  8. +
  9. Expecting a kid is amazing.
  10. +
  11. Problems in software are usually never software problems.
  12. +
  13. When something hurts sometimes your not dying, it just hurts.
  14. +
  15. You can take your dryer apart and put it back together and it will be ok.
  16. +
  17. Vim is better inside emacs.
  18. +
  19. Passing out is no fun.
  20. +
  21. JavaScript is everywhere, get used to it.
  22. +
  23. We all need a team
  24. +
  25. The command line will never die.
  26. +
  27. Drywall molleys are amazing.
  28. +
  29. You can’t keep water out, you can only redirect it.
  30. +
  31. Remembering what is Real™ is vital.
  32. +
  33. Relationships are a #1 priority. I forget this too often.
  34. +
  35. Nothing beats pen and paper.
  36. +
  37. Physical fitness involves way more sleeping and eating well than pumping iron.
  38. +
  39. There is no better coffee maker than the Aeropress.
  40. +
  41. Setting aside time for reading and writing is difficult.
  42. +
  43. I need to spend more time reading and writing.
  44. +
  45. Two opposing things can both be True at the same time. Dealing with that is adulthood.
  46. +
  47. I will always enjoy the Fast and the Furious franchise.
  48. +
  49. LeBron is under-rated.
  50. +
  51. Never give up, even when your down 3-1.
  52. +
  53. No one makes it on their own.
  54. +
  55. I need to read more novels.
  56. +
  57. I still miss Rdio.
  58. +
  59. Read a little C.S. Lewis every morning (start here). It’s good for you.
  60. +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html b/themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html new file mode 100644 index 0000000..d6e1fd6 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html @@ -0,0 +1,264 @@ + + + + + + Three easy tuneups to fix video calls while working from home + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Three easy tuneups to fix video calls while working from home

+ + +
+

Thanks to the COVID-19 virus (aka the coronavirus) lots of folks are experiencing the joys and existential terror of working from home. There’s many things to tackle when optimizing a work from home setup like:

+
    +
  • Proper workspace ergonomics
  • +
  • Proper lighting for video calls
  • +
  • Proper audio for video/audio calls
  • +
  • Picking up the dirty laundry/toys/pizza boxes that are visible in the background on video calls
  • +
+

These are all important but pale in comparison to this one: tuning your network for peak performance in video calls and remote screen sharing.

+

Three problems

+

There is usually some combination of the following three problems going on when Zoom pops up the dreaded “Your connection is unstable”:

+
    +
  1. Your internet speed is too slow
  2. +
  3. You’re Wifi signal is bad
  4. +
  5. Your router/modem from the ISP is suffering from bufferbloat.
  6. +
+

Speed

+

The first one is easy to fix: speed. Zoom lists their bandwidth requirements and the highest requirement is 3.0 Mbps (up/down) which is for sending 1080p video. For consumer broadband that is nothing, heck for DSL that’s nothing. However, it’s the first and easiest thing to check: do you have 3.0 Mbps+? Head over to fast.com and run a speed test.

+

Wifi

+

The second one, wifi signal strength, is more difficult to nail down. I check two things: the connection bit rate and the connection frequency. Bit rate will tell you the speed of the connection; it should be above 3 Mbps (honestly it should be above 100 Mbps if you have ac wifi). I also always choose to connect to the 5Ghz band if I can. 2.4Ghz suffers from interference much more so than 5Ghz and that interference will result in an unstable connection. An easy check to see if your Wifi is causing the problem, connect directly to the router with an Ethernet cord if you have one. If the problems goes away, it’s the wifi if not keep reading. To view connection and bitrate on a Mac: Option + click on the WiFi icon and you’ll be able to see the bit rate and connection frequency. On Linux iwconfig in the terminal will print the relevant info.

+

Bufferbloat

+

A very long explanation (and solution) of bufferbloat can be found here. The gist of it is that most routers/modems are (mis-)configured out of the box to prioritize speed over everything else. The software will stuff as many packets as it can and then once it’s full things start getting laggy. To see if you are suffering from bufferbloat head over to fast.com again and click on the “Show more info” button after the test. You want the difference between “loaded” and “unloaded” to be as small as possible. If you see a difference over 100, e.g. 25 unloaded and 150 loaded, you are probably suffering from bufferbloat.

+

+

The solution here is to poke around in your modem/router admin interface and look for something like “QoS” or “Codel” settings. QoS stands for Quality of Service and it typically allows you to either setup device prioritization or better yet implement fq_codel. The beauty of fq_codel is that it’s pretty transparent to everyone on the network. Kiddos can stream Frozen 2 until their eyes bleed and your Zoom will never stutter. Device prioritization QoS works but other devices on the network feel the squeeze.

+

If you’re modem/router doesn’t have QoS settings then it’s time to look into buying some new equipment (or yes flash your existing router with OpenWRT but that’s outside the scope of this post). If you already have your own router/wifi, that is separate from your modem, then I’d recommend picking up a Ubiquiti EdgeRouter X and placing that between your modem and your existing router/wifi. The EdgeRouter X has built-in support for fq_codel as a QoS setting. Adding QoS at any point in the chain between your computer and the public internet will fix bufferbloat as the traffic only needs to be shaped once.

+

+

Addressing the three primary culprits for unstable connections should dramatically improve your conference call experience. Please reach out if you have questions or I was incorrect about anything. I’ll try to respond as quickly as I can.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/three-years/index.html b/themes/cycle/exampleSite/public/writing/three-years/index.html new file mode 100644 index 0000000..9875413 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/three-years/index.html @@ -0,0 +1,240 @@ + + + + + + Three years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html b/themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html new file mode 100644 index 0000000..1e1a964 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html @@ -0,0 +1,245 @@ + + + + + + Tigers and Social Networks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Tigers and Social Networks

+ + +
+

Charlie Pratt published a post today giving his take on current happenings with both Twitter and Facebook. One company that has a history of ignoring any outside feedback, and one that he leaves out of his post, is Apple. While not a social network (R.I.P. Ping), Apple still sells multiple products to a massive, global consumer base. The difference between Apple and Twitbook is that Apple makes money from their consumers, something Twitter and Facebook are currently trying to put together.

+

Mr. Pratt goes on to observe:

+
+

As we watch Facebook and Twitter peak, one can’t help but notice that they suddenly seem incredibly vulnerable to the whim of the crowd. Crowds are finicky[…]

+
+

This only happens when you try to turn your consumer base, your crowd, into the product your selling.

+

Tigers don’t like being sold, feeling captive, or turned into anything other than tigers.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html b/themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html new file mode 100644 index 0000000..982903f --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html @@ -0,0 +1,272 @@ + + + + + + Track redirects with curl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Track redirects with curl

+ + +
+

I was recently debugging some .htaccess redirects and wanted to know two things:

+
    +
  1. How was my URL changing as it went through the redirects?
  2. +
  3. How many redirects occurred?
  4. +
+

I quickly got fed up with testing in the browser because of 301/302 redirect caching issues. With my limited curl knowledge I knew I could dump headers and that would show me the redirect code and the URL but figuring out how many hops occurred was frustrating.

+

I searched around and found this very helpful post by Chris Latta. The curl command from the post introduced me to the fact that curl has basic templating support! I read through man curl and noticed there were other built-in variables besides url_effective, like num_redirects! This was exactly what I wanted. Below is what I eventually ended up with:

+
curl -LSs -D - -o /dev/null -w 'Final URL: %{url_effective} \nNumber of Redirects: %{num_redirects} '
+

I added this to my dotfiles as an alias called redirects, here is a sample of what the output looks like:

+
❯ redirects "http://adamsimpson.net/uses"
+HTTP/1.1 301 Moved Permanently
+Cache-Control: public, max-age=0, must-revalidate
+Content-Length: 44
+Content-Type: text/plain
+Date: Tue, 22 Oct 2019 17:39:10 GMT
+Location: https://adamsimpson.net/uses
+Age: 0
+Connection: keep-alive
+Server: Netlify
+X-NF-Request-ID: de179b0f-db8b-401a-97ad-7ce523020763-108626
+
+HTTP/2 200
+cache-control: public, max-age=0, must-revalidate
+content-type: text/html; charset=UTF-8
+date: Tue, 22 Oct 2019 17:39:10 GMT
+etag: "3f4bb560fd31e7328aedc7bc08a9c541-ssl"
+strict-transport-security: max-age=31536000
+age: 0
+server: Netlify
+x-nf-request-id: de179b0f-db8b-401a-97ad-7ce523020763-108794
+
+Final URL: https://adamsimpson.net/uses
+Number of Redirects: 1 %
+

curl might be one of the most important tools I have at my disposal for working with HTTP requests and I feel like I’ve only begun to scratch the surface of what it can do.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/tweet-stash/index.html b/themes/cycle/exampleSite/public/writing/tweet-stash/index.html new file mode 100644 index 0000000..bc5c99e --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/tweet-stash/index.html @@ -0,0 +1,245 @@ + + + + + + Tweet stash + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Tweet stash

+ + +
+

Two tweets that I’ve had stuck in my tabs for awhile and decided to stash them here.

+

Dismal laptops

+

The first one is a tweet from Dave Nanian, creator of SuperDuper, which paints a good picture of how bad Apple laptops had gotten from 2016-2019.

+ +

Talk show entrances

+

This next tweet is hysterical. It’s a clip of Nic Cage being hyped in the 90s when he’s introduced to on a talk show in England. The thread is worth reading as you’ll also see Chris Farley’s Letterman entrance which is even more incredible.

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html b/themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html new file mode 100644 index 0000000..2dbd2b4 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html @@ -0,0 +1,243 @@ + + + + + + Using the Kindle to harness the Web + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Using the Kindle to harness the Web

+ + +
+

Currently, I have the cheapest Kindle you can buy and I love it. I love it for reasons entirely different from my iPad. I love this Kindle cause it’s super cheap and durable, and I never worry about its battery life or wether it’s getting smashed in a bag when I travel.

+

I also love this Kindle for reading. I set up my Instapaper account to send me a digest of my Unread list every weekend, perfect for traveling, the pool, or even the beach – you know, places the iPad shouldn’t and can’t go. The Kindle feature in Instapaper got me excited about other possibilities for reading web stuffs on my Kindle.

+

The first thing I stumbled upon shortly after setting up my Instapaper to Kindle connection was Readlists. Readlists are brought to you by the same folks behind Readability. Readlists allows you to cobble together a list of articles from all over the web that they then compile into a Kindle digest. Rad!

+

After I discovered Readlists, I started finding several fantastic guides or books on JavaScript and Javascript best practices. Prominent members of the developer community are releasing these materials for free via Github or personal sites. I wanted to convert these excellent resources into documents on my Kindle. It was then that I discovered another fantastic resource from the Readability folks.

+

Readability released a simple bookmarklet that takes whatever page you’re viewing in your browser and sends it to your Kindle. Problem solved! I now have a couple Kindle “books” that are sourced from the web, how awesome is that? Try it out for yourself and start utilizing the incredible resources out there.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/verse-recall/index.html b/themes/cycle/exampleSite/public/writing/verse-recall/index.html new file mode 100644 index 0000000..a883487 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/verse-recall/index.html @@ -0,0 +1,250 @@ + + + + + + Verse Recall + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Verse Recall

+ + +
+

Whew, time to share something with the world I haven’t really talked about online at all, my first and only (so far) iOS app. I did manage to find this tweet celebrating the launch (thanks to Twitter’s advanced search):

+ +

Verse Recall was a Christmas gift to my Dad in 2013. He got a TestFlight beta, and it actually shipped in March. I’m pretty proud of it. The app was simple. It let you look up a Bible verse, save it locally to the device and schedule a local notification with the text of the verse. The goal was to help memorize verses.

+

When I started I didn’t know Obj-C (no Swift at the time), had never used Xcode, and had no real clue where to start. Despite all that I shipped it and I’m proud of the 30-odd copies I sold ($0.99 big money!). I never would have made it without these awesome tools:

+ +

A few days ago I let my Apple Developer account “expire” therefore removing Verse Recall from the App Store. I’ve gone back and forth the last couple months on wether to renew again. There’s more I’d like to do with it, bugs I’d like to fix and features I’d like to add (like maybe port it to React Native?!), but I never spent the time to do those things for whatever reason. It works fine for now and my Dad still uses it so I’m content. If and when it breaks with an iOS update, I’ll either update it and side-load the fix onto my Dad’s phone or we’ll let it die.

+

This morning I moved the current state of the project from my private Bitbucket repo to Github. I wanted to share the entire project history because the commits are hilarious to read (they range from rage to despair and back again), but I foolishly committed API keys and the like that were too difficult to clean out of Git’s history. I doubt the code will be that useful to anyone at this point, but I like having it out there so I can point to it as a thing I did.

+

So ends Verse Recall, I’m proud of it and I learned a ton making it. In my mind it was a raging success.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/vim-ramblings/index.html b/themes/cycle/exampleSite/public/writing/vim-ramblings/index.html new file mode 100644 index 0000000..01df647 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/vim-ramblings/index.html @@ -0,0 +1,252 @@ + + + + + + Vim Ramblings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Vim Ramblings

+ + +
+

So, in the past 6 months I’ve switched from Sublime Text to Vim.

+

And just like that I’ve fulfilled Harry Robert’s tweet:

+ +

Whelp. Anyway, onwards and upwards I guess.

+

Speaking of Harry, if your looking to get started with Vim, checkout his awesome guide that he wrote to save me the trouble of writing one myself!

+

Earlier tonight I was perusing the interwebs (shocker right?) and wound up on Wynn Netherland’s archives, because he’s an awesome dude and wicked smart. I came across a few really good Vim posts that I thought I’d highlight here:

+ +

I totally agree with the anti-patterns and vimrc posts. I also need to try the relative numbers approach.

+

To finish up this hode-podge of links and rambling, my buddy @seanwashington recently pointed me to vimawesome, and holy crap it’s awesome, I highly recommend checking out the awesome plugins on that site.

+

Anyway, back to your regularly scheduled internets.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html b/themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html new file mode 100644 index 0000000..4c87f00 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html @@ -0,0 +1,244 @@ + + + + + + We all need a team + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

We all need a team

+ + +
+

Bill Simmons’ latest piece on Pat Riley is full of great Riley stories. One particular moment where Riley talks to Kevin Garnett really resonated with me (italics mine):

+
+

It happened to everyone. You won’t truly know how outstanding you are, Riley promised him, until you’re surrounded by elite teammates who make you better. He told stories about Magic’s Lakers teams, how special they were, how many battles they fought, how those postseasons bonded them for life. There was a higher level of basketball. It was out there. You wouldn’t understand until you’ve experienced it. And until you’ve lost it, too.

+
+

We all need a team. On the right team we can go higher and be better than we ever thought we could.

+

To put it another way, we can only go so far alone.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html b/themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html new file mode 100644 index 0000000..f4c5b02 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html @@ -0,0 +1,247 @@ + + + + + + Web performance and Facebook's Instant Articles + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Web performance and Facebook's Instant Articles

+ + +
+

John Gruber wrote down his initial thoughts on Facebook’s Instant Articles. This portion regarding performance stood out:

+
+

I’m intrigued by the emphasis on speed. Not only is native mobile code winning for app development, but with things like Instant Articles, native is making the browser-based web look like a relic even just for publishing articles. If I’m right about that, it might pose a problem even for my overwhelmingly-text work at Daring Fireball. Daring Fireball pages load fast, but the pages I link to often don’t. I worry that the inherent slowness of the web and ill-considered trend toward over-produced web design is going to start hurting traffic to DF.

+
+

Maybe I can’t see past my web developer bias, but I don’t believe this is a death knell for the “open web.” I think this is a wake-up call; there is no reason that Instant Articles should have such a speed advantage over a webpage.

+

Crafting a high-performing web experience for mobile is not easy, but it’s not so impossibly hard that Instant Articles is the only solution. With Instant Articles, Facebook is saving publishers from themselves - notice the lack of advertising, over-the-top branding, or massive image slideshows. Instant Articles isn’t faster because native beats the web. It’s faster because disciplined, curated content wins over content shoved between 1MB of advertisements.

+
+

Update:

+ + +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html b/themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html new file mode 100644 index 0000000..8e0054a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html @@ -0,0 +1,240 @@ + + + + + + Web scraper cookbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Web scraper cookbook

+ + +
+

I’ve been on a web scraping tear lately. So, I thought I’d compile what I’ve learned and put together a repo as a howto/cookbook/guide thing. So, here it is: introducing the Node web scraper cookbook.

+

I hope it’s useful. It’s nice to have this stuff written down just for my own sake. If you find it useful, awful, or confusing feel free to create an issue on the repo and I’ll try to update things.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html b/themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html new file mode 100644 index 0000000..67035eb --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html @@ -0,0 +1,243 @@ + + + + + + What happens when you remove friction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

What happens when you remove friction

+ + +
+

When you remove friction from a process or task, all the factors change. This seems obvious, but it’s fundamental to understanding the world as it currently is. Polygon has a post up about the rash of “Youtuber burnouts” lately. The conclusion of the article stuck out to me (emphasis mine):

+
+

YouTube has a speed and quantity problem, and it affects all aspects of the business. If you are a content creator, take a little time with controversial stuff. It really is fun to make things, but irreverent, boundary-breaking stuff is high-risk/high-reward. Don’t just spit it out: run things by friends and people not in the business. Test the tone before you go live. Sleep on it.

+
+

Youtube is entertainment without traditional support mechanisms (i.e. friction). It’s relentless and there are no structures in place to push back at all. I think this lack of friction is at the root of the majority of problems in tech. Things move quickly and because of that speed safeguards and checks haven’t been instantiated yet. Not everything that pushes back is bad, that push-back can be life-saving.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/what-is-medium/index.html b/themes/cycle/exampleSite/public/writing/what-is-medium/index.html new file mode 100644 index 0000000..5299c31 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/what-is-medium/index.html @@ -0,0 +1,245 @@ + + + + + + What is Medium? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

What is Medium?

+ + +
+

Manton Reece in a post about Medium wondered:

+
+

Is it a blogging tool? Sort of. Is it a social network? Not exactly.

+
+

I’ve found Medium incredibly useful for browsing a community’s current thoughts and ideas. For instance, I love browsing the React tag on Medium. It’s filled with various posts about build tools, upcoming libraries, and thought pieces that I would never have found via RSS or Twitter.

+ +

Regardless of what Medium intends to be, they at least seem to have stumbled upon something interesting with tags (from my perspective). I’m curious to see how Medium continues to evolve.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/what-its-all-about/index.html b/themes/cycle/exampleSite/public/writing/what-its-all-about/index.html new file mode 100644 index 0000000..988f88d --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/what-its-all-about/index.html @@ -0,0 +1,244 @@ + + + + + + What it's all about + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

What it's all about

+ + +
+

Wordpress Pro, and all around Nice Guy, Jonathan Christopher posted one of his many asides. This little snippet stuck out to me so much, I decided to post what is essentially an aside about an aside. Blogging has no rules right? Cool.

+

Jonathan wrote this about writing code,

+
+

The real joy comes from struggling to figure something out for way longer than you thought it would take and then actually seeing it work. That’s what it’s all about!

+
+

Spot on.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/what-matters/index.html b/themes/cycle/exampleSite/public/writing/what-matters/index.html new file mode 100644 index 0000000..bf5f3cf --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/what-matters/index.html @@ -0,0 +1,243 @@ + + + + + + What Matters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

What Matters

+ + +
+

A post from David Heinemeier Hansson over at 37 Signals on settling into your work for the long term. This is something I’ve been thinking about lately, largely because I’ve found a place at Sparkbox that is such a fantastic place to work.

+

David provides two solid reasons for why it’s worth it to stay put at an organization for both the employee and the employeer. This one stuck out to me the most.

+
+

[Focus] on the residue of knowledge and practices carried over from game to game is far more important than worrying about the output of any one game.

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html b/themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html new file mode 100644 index 0000000..a8e3933 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html @@ -0,0 +1,237 @@ + + + + + + What Time Is It in London? + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

What Time Is It in London?

+ + +
+
+

Nilay Patel asked this of Siri on his Apple Watch. After too long of a wait, he got the correct answer — for London Canada. I tried on my iPhone and got the same result. Stupid and slow is heck of a combination.

+
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html b/themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html new file mode 100644 index 0000000..976739a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html @@ -0,0 +1,244 @@ + + + + + + What's best for the readers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

What's best for the readers

+ + +
+

So good, it doesn’t need an intro.

+
+

For the same reason, we don’t show crappy display ads and we make all our revenue from social advertising that users love and share. We never launched one of those “frictionless sharing” apps on Facebook that automatically shares the stories you click because those apps are super annoying. We don’t post deceptive, manipulative headlines that trick people into reading a story. We don’t focus on SEO or gaming search engines or filling our pages with millions of keywords and tags that only a robot will read. We avoid anything that is bad for our readers and can only be justified by short term business interests. Instead, we focus on publishing content our readers love so much they think it is worth sharing. It sounds simple but it’s hard to do and it is the metric that aligns our company with our readers. In the long term is good for readers and good for business.

+
+

This excerpt is from Chris Dixon’s post where he published Jonah Peretti’s letter to employees and investors of Buzzfeed.

+

You should read all of it.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html b/themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html new file mode 100644 index 0000000..3d5ac21 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html @@ -0,0 +1,243 @@ + + + + + + When the Music Stops + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

When the Music Stops

+ + +
+

Dave Winer wrote a great post last week; he describes what happens when a piece of web software (i.e. Tumblr, Wordpress, etc) disappears. I decided to link to his post because I think it relates to my own Plaintext and Blogs, Data, and Social Networks posts. Ultimately we are each responsible for our own data, or as Winer writes:

+
+

I’m writing this […] to the users to wise up and also to stop being such children. If you feel there’s value in your writing, then treat it like it has value. If you depend on strangers to pay your rent, you have to know that isn’t going to work, long-term.

+
+

Start owning.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html b/themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html new file mode 100644 index 0000000..0460f0a --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html @@ -0,0 +1,271 @@ + + + + + + Windows 11 as KVM guest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Windows 11 as KVM guest

+ + +
+

Windows 11 famously has new, stricter requirements for installation; a TPM device and Secure Boot. Here’s how I satisfied those requirements with Windows 11 as a KVM guest with NixOS as the host. The following is pulled from my NixOS configuration.nix:

+
libvirtd.qemu = {
+  package = pkgs.qemu_kvm;
+  runAsRoot = true;
+  swtpm.enable = true;
+  ovmf = {
+    enable = true;
+    package = (pkgs.OVMFFull.override {
+      secureBoot = true;
+      tpmSupport = true;
+    });
+  };
+};
+

The most important bit is the pkgs.OVMFFull.override section where you must specify tpmSupport and secureBoot as true.

+

In virt-manager you’ll need to add “new hardware” and select TPM v2.0. Here’s the relevant XML from my config:

+
<tpm model="tpm-crb">
+  <backend type="emulator" version="2.0"/>
+</tpm>
+

With the above settings you should be able to go through the Windows 11 installer and get the machine up and running as a KVM guest.

+

Stretch goal: nested virtualization

+

If you want to use Docker or WSL 2 inside KVM you’ll need to enable “nested virtualization” in virt-manager. I couldn’t figure this out until I found this great answer on superuser.

+

My original CPU config XML looked like this:

+
<cpu mode="host-model" check="partial">
+  <topology sockets="1" dies="1" cores="2" threads="4"/>
+</cpu>
+

The new XML looks like this:

+
<cpu mode="custom" match="exact" check="partial">
+  <model fallback="allow">Skylake-Client-noTSX-IBRS</model>
+  <topology sockets="1" dies="1" cores="2" threads="4"/>
+  <feature policy="disable" name="hypervisor"/>
+  <feature policy="require" name="vmx"/>
+</cpu>
+

With this applied I could install WSL2 and get Docker Desktop for Windows installed and running.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html b/themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html new file mode 100644 index 0000000..ea77de8 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html @@ -0,0 +1,257 @@ + + + + + + Working with Wordpress, offset and pagination + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Working with Wordpress, offset and pagination

+ + +
+

Yesterday I was working on a project (that will hopefully be released soon) that displays the most recent post differently than the rest of the posts on the page. This project also calls for pagination-like behavior on the second set of posts, while the feature post (most recent post) should be static and have no pagination.

+

I initially tried to use the offset parameter for the second post query to remove the most recent post from that loop. This however didn’t seem to work with the pagination.

+

Turns out Wordpress’ offset and pagination features collide, as the note says (always read those little notes!),

+
+

Note: Setting offset parameter will ignore the paged parameter.

+
+

I think the pagination feature uses offset internally which is why an explicit offset breaks the pagination.

+

Anyway, after hunting around a bit to see if anyone had a quick fix for this, I stumbled upon a post which had a quite complex question and an equally complex answer. Yet, it confirmed what I thought I’d have to do.

+

I simplified the solution quite a bit for my particular scenario, here is my code (note I am using verbose variable names here to help clarify):

+
$number_of_feature_posts = 1;
+$number_of_secondary_posts = 3;
+$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
+$how_many_secondary_posts_past = ($number_of_secondary_posts * ($paged - 1));
+$off = $number_of_feature_posts + (($paged > 1) ? $how_many_secondary_posts_past : 0);
+
+

I then used a simple WP_Query loop for the first loop, the featured (most recent) post, and then just used the normal query_posts with the additional arguments from the above snippet, for the second loop

+

+query_posts( "posts_per_page=$number_of_secondary_posts&offset=$off&showposts=$number_of_secondary_posts" );
+

This basically keeps the offset dynamic and relative to the page we are on. Hope you find it useful.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html b/themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html new file mode 100644 index 0000000..64bb8d7 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html @@ -0,0 +1,243 @@ + + + + + + youtube-subscriptions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

youtube-subscriptions

+ + +
+

I’ve been using youtube-subscriptions for a few months now and I really enjoy it. It’s described as a:

+
+

terminal client to browse youtube subscriptions

+
+

It’s great to quickly see any new videos right in the terminal and videos play via mpv or vlc!

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/zach-beane/index.html b/themes/cycle/exampleSite/public/writing/zach-beane/index.html new file mode 100644 index 0000000..88c6b43 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/zach-beane/index.html @@ -0,0 +1,239 @@ + + + + + + Uses This / Zach Beane + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Uses This / Zach Beane

+ + +
+

A great interview with the creator of Quicklisp, Zach Beane. I enjoy two things about this interview:

+
    +
  1. The inclusion of outdoor/farming tools in the list of tools.
  2. +
  3. Zach’s conservative approach to languages and software tools.
  4. +
+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html b/themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html new file mode 100644 index 0000000..5229231 --- /dev/null +++ b/themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html @@ -0,0 +1,252 @@ + + + + + + Zen Garden Part 2? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +

Zen Garden Part 2?

+ + +
+

Remember the glorious days of the CSS Zen Garden before all of this CSS3 @font-face crazyness and @media resizing insanity?

+

I do, and probably most web designers and developers do to. Rick Monro definitely does, and he wrote yesterday that we need to create another CSS Garden, this time for Responsive Web Design (RWD).

+

Now, I think that’s a great idea, the more RWD resources, the better in my opinion. Of course we already have the RWD Book, which is a must read for any web designer or developer. And Trent Walton, Brad Frost, Mark Boulton, and Jordan Moore are all chronicling their experiences and solutions with Responsive Web Design as they use it in the real world. Hell, Brad Frost even has an e-mail newsletter dedicated entirely to RWD, so it’s not like resources on RWD don’t exist. I think Mr. Monro knows this, but he’s seeking a resource that mimics the Zen Garden and goes beyond the Mediaqueri.es gallery approach. Again, I think this is a great idea.

+

Yet, I take issue with how he frames the need for a RWD Garden. His claims make it sound like a “RWD Garden” is needed to finish the argument that RWD is the next advancement in our practice. In my opinion and the opinion of many in our industry, Responsive Web Design is the future, period. We’re past the convincing point with RWD, the web is changing.

+

I want to note that Responsive Web Design is not only concerned with fluid-width design. RWD incorporates other principles for developing sites, such as sites that are responsive to: mobile-sized screens, low bandwidth situations, and HD / Retina graphics. The entire package, this package called Responsive Web Design, is what is pushing the web forward. If all we are concerned with is narrow and wide views then Mr. Monro is quite right when he says:

+
+

Designers and developers are the only people I know who sit and accordion their browser window to see how a site will respond. We’re too in love with technique because we know that somewhere, another designer or developer is going to think it’s cool. And folks, when it gets to the point when we are designing for other designers, that should ring some pretty loud alarm bells

+
+

I think as a community we are still figuring out what this Responsive Web Design thing is, what it looks like, how we design for it, where Photoshop fits (does it?!), etc. We’ve had years to figure out how to design with and for CSS, we’re only just getting started with RWD. It’s an exciting time to be working on the web, yet Mr. Monro thinks there is too much “pressure” to use RWD:

+
+

The overwhelmingly positive spin accompanying a responsive site launch creates a subtle (but tangible) pressure on conscientious designers to ‘step up’ and deliver RWD on their own projects. Which would be fine, but the inference that RWD is desirable at any cost.

+
+

Of course, I’m not advocating an eyes-closed acceptance of Responsive Web Design for every client project. Tables are still used on the web, mostly in emails now, but there not gone; the same holds true for a site designed without applying RWD. However, “Positive spin” implies that we’re all trying to cover up something bad, which isn’t true. Any “spin” or “pressure” is simply the same encouragement as when moving from tables to CSS, that this is the right way to go. That “pressure” is what makes this industry so incredible. The web thrives on action, learning, pushing, and experimenting.

+

We shouldn’t slow down because the web is changing and things are all new and scary again. New and scary does not mean we’re going in the wrong direction. We are headed in the right direction, and that is why I fully support the creation of as many additional resources as possible to educate each other, as well as push RWD further.

+ +
+ Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. +
+
+
+
+ +
+ +
+ + +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ + + + diff --git a/themes/cycle/exampleSite/themes/cycle b/themes/cycle/exampleSite/themes/cycle new file mode 120000 index 0000000..15f4884 --- /dev/null +++ b/themes/cycle/exampleSite/themes/cycle @@ -0,0 +1 @@ +/home/runner/work/cycle/cycle/themes/cycle \ No newline at end of file diff --git a/themes/cycle/layouts/_default/baseof.html b/themes/cycle/layouts/_default/baseof.html new file mode 100644 index 0000000..79697bb --- /dev/null +++ b/themes/cycle/layouts/_default/baseof.html @@ -0,0 +1,9 @@ + + + {{ partial "head.html" . }} + + {{ partial "header.html" . }} + {{ block "main" . }}{{ end }} + {{ partial "footer.html" . }} + + diff --git a/themes/cycle/layouts/_default/list.html b/themes/cycle/layouts/_default/list.html new file mode 100644 index 0000000..acabc20 --- /dev/null +++ b/themes/cycle/layouts/_default/list.html @@ -0,0 +1,24 @@ +{{ define "main" }} +
+
    + {{ range .Pages }} +
  • + {{ if .Params.link }} + {{ .Title }} + {{ else }} + {{ .Title }} + {{ end }} +
    {{ .Date.Format "January 2, 2006" }}
    +
    + {{ if .Params.link }} + {{ .Content }} + 🔗 Permalink + {{ else }} + {{ .Params.excerpt }} + {{ end }} +
    +
  • + {{ end }} +
+
+{{ end }} diff --git a/themes/cycle/layouts/_default/rss.xml b/themes/cycle/layouts/_default/rss.xml new file mode 100644 index 0000000..6e4d58b --- /dev/null +++ b/themes/cycle/layouts/_default/rss.xml @@ -0,0 +1,51 @@ +{{- $pctx := . -}} +{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}} +{{- $pages := slice -}} +{{- if or $.IsHome $.IsSection -}} +{{- $pages = (where $pctx.RegularPages "Type" "post") -}} +{{- end -}} +{{- $limit := .Site.Config.Services.RSS.Limit -}} +{{- if ge $limit 1 -}} +{{- $pages = $pages | first $limit -}} +{{- else -}} +{{- $pages = $pages | first 20 -}} +{{- end -}} + + + {{ .Site.Title }} Post Feed + {{ .Site.BaseURL }} + Last 20 posts for {{ .Site.Title }} + {{ now.Format "Mon, 02 Jan 2006 15:04:05 -0700" }} + en-us + + {{- range $pages }} + + {{ .Title }} + {{- if .Params.link }} + {{ .Params.link }} + {{- else }} + {{ .Permalink }} + {{- end }} + + {{ .Permalink }} + {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" }} + + {{- if not .Params.link }} + + + + Discuss further in my public inbox + ]]> + {{- else }} + 🔗 + Discuss further in my public inbox + ]]> + {{- end }} + + {{- end }} + + diff --git a/themes/cycle/layouts/_default/single.html b/themes/cycle/layouts/_default/single.html new file mode 100644 index 0000000..3974f47 --- /dev/null +++ b/themes/cycle/layouts/_default/single.html @@ -0,0 +1,14 @@ +{{ define "main" }} + {{ if eq .Type "post" }} + {{ partial "post_body.html" . }} +
+ +
+ {{ else }} +
+
+ {{ .Content }} +
+
+ {{ end }} +{{ end }} diff --git a/themes/cycle/layouts/archive/list.html b/themes/cycle/layouts/archive/list.html new file mode 100644 index 0000000..ce243b6 --- /dev/null +++ b/themes/cycle/layouts/archive/list.html @@ -0,0 +1,24 @@ +{{ define "main" }} +
+
    + {{ range (where .Site.RegularPages "Type" "post") }} +
  • + {{ if .Params.link }} + {{ .Title }} + {{ else }} + {{ .Title }} + {{ end }} +
    {{ .Date.Format "January 2, 2006" }}
    +
    + {{ if .Params.link }} + {{ .Content }} + 🔗 Permalink + {{ else }} + {{ .Params.excerpt }} + {{ end }} +
    +
  • + {{ end }} +
+
+{{ end }} diff --git a/themes/cycle/layouts/index.html b/themes/cycle/layouts/index.html new file mode 100644 index 0000000..118b50c --- /dev/null +++ b/themes/cycle/layouts/index.html @@ -0,0 +1,32 @@ +{{ define "main" }} +
+

Hiya 👋

+

I'm Adam Simpson and I work on open source at Grafana and live life with my wonderful wife Christi and our daughters Ellie, Ainsley, and Margot.

+
+
+

Recent Posts

+
    + {{ range first 10 (where .Site.RegularPages "Type" "post") }} +
  • + {{ if .Params.link }} + + {{ else }} + {{ .Title }} + {{ end }} +
    {{ .Date.Format "January 2, 2006" }}
    +
    + {{ if .Params.link }} + {{ .Content }} + 🔗 Permalink + {{ else }} + {{ .Params.excerpt }} + {{ end }} +
    +
  • + {{ end }} +
+ +
+{{ end }} diff --git a/themes/cycle/layouts/partials/footer.html b/themes/cycle/layouts/partials/footer.html new file mode 100644 index 0000000..c5841c3 --- /dev/null +++ b/themes/cycle/layouts/partials/footer.html @@ -0,0 +1,4 @@ +
+

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

+
+ diff --git a/themes/cycle/layouts/partials/head.html b/themes/cycle/layouts/partials/head.html new file mode 100644 index 0000000..8e88cb5 --- /dev/null +++ b/themes/cycle/layouts/partials/head.html @@ -0,0 +1,48 @@ + + + {{ if .Title }} + {{ .Title }} + {{ else }} + {{ .Site.Title }} + {{ end }} + {{ with .Params.excerpt }} + {{ if $.Params.link }} + + {{ else }} + + {{ end }} + {{ else }} + + {{ end }} + + + + + + + + + + + {{ if .Title }} + + {{ else }} + + {{ end }} + {{ with .Params.excerpt }} + {{ if $.Params.link }} + + {{ else }} + + {{ end }} + {{ else }} + + {{ end }} + + + diff --git a/themes/cycle/layouts/partials/header.html b/themes/cycle/layouts/partials/header.html new file mode 100644 index 0000000..e2e1478 --- /dev/null +++ b/themes/cycle/layouts/partials/header.html @@ -0,0 +1,11 @@ +
+ + +
diff --git a/themes/cycle/layouts/partials/logo.html b/themes/cycle/layouts/partials/logo.html new file mode 100644 index 0000000..bf9ff07 --- /dev/null +++ b/themes/cycle/layouts/partials/logo.html @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/cycle/layouts/partials/post_body.html b/themes/cycle/layouts/partials/post_body.html new file mode 100644 index 0000000..797dccd --- /dev/null +++ b/themes/cycle/layouts/partials/post_body.html @@ -0,0 +1,16 @@ + diff --git a/themes/cycle/theme.toml b/themes/cycle/theme.toml new file mode 100644 index 0000000..eb30116 --- /dev/null +++ b/themes/cycle/theme.toml @@ -0,0 +1,12 @@ +name = "Cycle" +license = "GPLv3" +licenselink = "https://github.com/asimpson/cycle/blob/master/LICENSE" +description = "A Hugo theme ported from the Cycle static site generator" +homepage = "https://github.com/asimpson/cycle" +tags = ["blog", "minimal"] +features = ["rss"] +min_version = "0.110.0" + +[author] + name = "Adam Simpson" + homepage = "https://adamsimpson.net" From 7b34b9f5cd6284160dca6561cbd569b3ccf1dfcf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:26:20 +0000 Subject: [PATCH 3/3] Update README and add gitignore for Hugo theme Co-authored-by: asimpson <1048831+asimpson@users.noreply.github.com> --- README.org | 78 +- themes/cycle/README.md | 138 + themes/cycle/exampleSite/.gitignore | 1 + .../exampleSite/public/archive/index.html | 2454 ----------------- .../cycle/exampleSite/public/archive/rss.xml | 9 - .../exampleSite/public/categories/index.html | 219 -- .../exampleSite/public/categories/rss.xml | 9 - themes/cycle/exampleSite/public/index.html | 346 --- .../cycle/exampleSite/public/page/index.html | 243 -- themes/cycle/exampleSite/public/page/rss.xml | 9 - .../public/page/support/index.html | 233 -- .../exampleSite/public/page/uses/index.html | 239 -- .../cycle/exampleSite/public/post/index.html | 2454 ----------------- themes/cycle/exampleSite/public/post/rss.xml | 738 ----- themes/cycle/exampleSite/public/rss.xml | 738 ----- themes/cycle/exampleSite/public/sitemap.xml | 539 ---- .../cycle/exampleSite/public/tags/index.html | 219 -- themes/cycle/exampleSite/public/tags/rss.xml | 9 - .../public/writing/0-14/index.html | 267 -- .../public/writing/8-line-firewall/index.html | 249 -- .../public/writing/a-few-bash-tips/index.html | 347 --- .../writing/a-few-posix-shell-tips/index.html | 288 -- .../index.html | 241 -- .../public/writing/a-hackintosh/index.html | 271 -- .../writing/a-little-hydrofoil/index.html | 247 -- .../public/writing/a-new-adventure/index.html | 240 -- .../writing/a-new-website-for-2020/index.html | 242 -- .../public/writing/a-public-inbox/index.html | 248 -- .../writing/a-style-guide-guide/index.html | 244 -- .../adam-versus-dropbox-and-oauth/index.html | 262 -- .../writing/adn-cross-poster/index.html | 257 -- .../public/writing/ajax-and-rails/index.html | 263 -- .../alfred-and-web-development/index.html | 248 -- .../writing/amp-html-terrible-html/index.html | 245 -- .../writing/andy-budd-on-time/index.html | 242 -- .../app_store_moment_of_clarity/index.html | 247 -- .../index.html | 247 -- .../public/writing/atr2100/index.html | 249 -- .../writing/automating-socks-proxy/index.html | 253 -- .../writing/balancing-devotion/index.html | 259 -- .../index.html | 246 -- .../be-a-good-video-call-citizen/index.html | 248 -- .../writing/before-circles-2017/index.html | 253 -- .../benedict-evans-in-on-fire/index.html | 254 -- .../better-scripting-with-gh/index.html | 286 -- .../public/writing/blog-rewrite/index.html | 298 -- .../blogs-data-and-social-networks/index.html | 255 -- .../index.html | 241 -- .../writing/broadcast-channel/index.html | 239 -- .../index.html | 253 -- .../command-line-notification/index.html | 241 -- .../writing/compose-key-and-i3/index.html | 249 -- .../index.html | 241 -- .../writing/convince-the-boss/index.html | 247 -- .../public/writing/create-passion/index.html | 243 -- .../public/writing/css-reusability/index.html | 248 -- .../writing/cycle-v030-released/index.html | 241 -- .../index.html | 247 -- .../writing/declining-expectations/index.html | 243 -- .../public/writing/diceware/index.html | 249 -- .../public/writing/eight-years/index.html | 246 -- .../public/writing/emacs-lite/index.html | 246 -- .../public/writing/emacs-tips/index.html | 268 -- .../public/writing/end-of-an-era/index.html | 242 -- .../public/writing/evening-edition/index.html | 240 -- .../public/writing/facetime-killer/index.html | 250 -- .../public/writing/family-first/index.html | 243 -- .../public/writing/farewell-heroku/index.html | 269 -- .../index.html | 241 -- .../public/writing/five-years/index.html | 241 -- .../public/writing/flatkill/index.html | 241 -- .../writing/format-json-in-emacs/index.html | 248 -- .../index.html | 250 -- .../getting-started-with-rofi/index.html | 282 -- .../index.html | 242 -- .../writing/git-commit-template/index.html | 248 -- .../public/writing/git-worktree/index.html | 246 -- .../public/writing/goat-counter/index.html | 238 -- .../writing/goodbye-sparkbox/index.html | 243 -- .../google-fi-and-data-only-plans/index.html | 246 -- .../writing/grow-it-dont-build-it/index.html | 243 -- .../writing/guidelines-for-data/index.html | 246 -- .../index.html | 353 --- .../writing/hello-micro-blog/index.html | 249 -- .../public/writing/hello-world/index.html | 271 -- .../public/writing/helm-to-ivy/index.html | 251 -- .../writing/heroku-and-ssh-keys/index.html | 239 -- .../index.html | 241 -- .../index.html | 257 -- .../writing/how-are-you-living/index.html | 242 -- .../how-do-we-make-the-web-better/index.html | 277 -- .../index.html | 239 -- .../public/writing/huffduffer/index.html | 241 -- .../writing/i-moved-to-hover/index.html | 241 -- .../public/writing/ifttt/index.html | 251 -- .../indexing-my-blogs-links/index.html | 235 -- .../writing/introducing-cycle/index.html | 297 -- .../introducing-ivy-feedwrangler/index.html | 258 -- .../ip-address-alfred-extension/index.html | 241 -- .../index.html | 246 -- .../index.html | 241 -- .../writing/ivy-pinboard-popular/index.html | 261 -- .../js2coffee-alfred-workflow/index.html | 241 -- .../public/writing/just-start-over/index.html | 244 -- .../public/writing/keeping-up/index.html | 249 -- .../writing/kyle-steed-on-rest/index.html | 243 -- .../public/writing/lambda-talk/index.html | 240 -- .../learning-to-think-in-react/index.html | 275 -- .../index.html | 239 -- .../index.html | 242 -- .../macos-catalina-slow-by-design/index.html | 248 -- .../index.html | 247 -- .../writing/medium-isnt-permanent/index.html | 244 -- .../index.html | 240 -- .../public/writing/microblogging/index.html | 248 -- .../index.html | 312 --- .../writing/moved-to-siteleaf/index.html | 244 -- .../moving-away-from-google/index.html | 242 -- .../index.html | 241 -- .../writing/my-first-bookmarklet/index.html | 246 -- .../public/writing/new-workstation/index.html | 261 -- .../writing/nginx-www-rewrite/index.html | 247 -- .../writing/nixpkgs-is-a-treasure/index.html | 266 -- .../nothing-speaks-like-a-demo/index.html | 239 -- .../on-diminishing-modes-in-emacs/index.html | 265 -- .../public/writing/on-equifax/index.html | 242 -- .../public/writing/on-george-floyd/index.html | 256 -- .../public/writing/on-webpack/index.html | 239 -- .../public/writing/openring/index.html | 253 -- .../public/writing/oscar/index.html | 241 -- .../index.html | 243 -- .../index.html | 262 -- .../polybar-fonts-and-ubuntu/index.html | 245 -- .../public/writing/pretty-git-log/index.html | 242 -- .../public/writing/psychicpaper/index.html | 248 -- .../public/writing/rands-on-email/index.html | 243 -- .../public/writing/recently-16/index.html | 270 -- .../public/writing/recently-44/index.html | 248 -- .../public/writing/rename-utility/index.html | 241 -- .../index.html | 244 -- .../writing/rust-module-system/index.html | 239 -- .../writing/rust-strings-and-str/index.html | 321 --- .../writing/s3-security-policy/index.html | 243 -- .../index.html | 238 -- .../writing/search-imessage-sql/index.html | 239 -- .../second-guessing-the-modern-web/index.html | 238 -- .../index.html | 256 -- .../writing/simple-account-set-up/index.html | 245 -- .../slanted-elements-with-css3/index.html | 239 -- .../public/writing/small-tech/index.html | 249 -- .../public/writing/small-things/index.html | 244 -- .../index.html | 256 -- .../index.html | 246 -- .../sparrow-and-the-app-store/index.html | 243 -- .../public/writing/sqlite-tips/index.html | 263 -- .../public/writing/story/index.html | 245 -- .../the-era-of-the-screenshot/index.html | 249 -- .../the-future-is-prototyping/index.html | 243 -- .../index.html | 241 -- .../writing/the-stream-hasnt-won/index.html | 243 -- .../the-thing-about-computers/index.html | 244 -- .../writing/the-web-and-my-goal/index.html | 244 -- .../writing/the-web-is-not-print/index.html | 243 -- .../index.html | 241 -- .../theme-the-chrome-dev-tools/index.html | 242 -- .../public/writing/thirty-five/index.html | 279 -- .../public/writing/thirty/index.html | 272 -- .../index.html | 264 -- .../public/writing/three-years/index.html | 240 -- .../tigers-and-social-networks/index.html | 245 -- .../track-redirects-with-curl/index.html | 272 -- .../public/writing/tweet-stash/index.html | 245 -- .../index.html | 243 -- .../public/writing/verse-recall/index.html | 250 -- .../public/writing/vim-ramblings/index.html | 252 -- .../writing/we-all-need-a-team/index.html | 244 -- .../index.html | 247 -- .../writing/web-scraper-cookbook/index.html | 240 -- .../index.html | 243 -- .../public/writing/what-is-medium/index.html | 245 -- .../writing/what-its-all-about/index.html | 244 -- .../public/writing/what-matters/index.html | 243 -- .../what-time-is-it-in-london/index.html | 237 -- .../whats-best-for-the-readers/index.html | 244 -- .../writing/when-the-music-stops/index.html | 243 -- .../windows-11-as-kvm-guest/index.html | 271 -- .../index.html | 257 -- .../writing/youtube-subscriptions/index.html | 243 -- .../public/writing/zach-beane/index.html | 239 -- .../writing/zen-garden-part-2/index.html | 252 -- 190 files changed, 200 insertions(+), 51671 deletions(-) create mode 100644 themes/cycle/README.md create mode 100644 themes/cycle/exampleSite/.gitignore delete mode 100644 themes/cycle/exampleSite/public/archive/index.html delete mode 100644 themes/cycle/exampleSite/public/archive/rss.xml delete mode 100644 themes/cycle/exampleSite/public/categories/index.html delete mode 100644 themes/cycle/exampleSite/public/categories/rss.xml delete mode 100644 themes/cycle/exampleSite/public/index.html delete mode 100644 themes/cycle/exampleSite/public/page/index.html delete mode 100644 themes/cycle/exampleSite/public/page/rss.xml delete mode 100644 themes/cycle/exampleSite/public/page/support/index.html delete mode 100644 themes/cycle/exampleSite/public/page/uses/index.html delete mode 100644 themes/cycle/exampleSite/public/post/index.html delete mode 100644 themes/cycle/exampleSite/public/post/rss.xml delete mode 100644 themes/cycle/exampleSite/public/rss.xml delete mode 100644 themes/cycle/exampleSite/public/sitemap.xml delete mode 100644 themes/cycle/exampleSite/public/tags/index.html delete mode 100644 themes/cycle/exampleSite/public/tags/rss.xml delete mode 100644 themes/cycle/exampleSite/public/writing/0-14/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/8-line-firewall/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-hackintosh/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-new-adventure/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-public-inbox/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/atr2100/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/balancing-devotion/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/before-circles-2017/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/blog-rewrite/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/broadcast-channel/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/command-line-notification/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/convince-the-boss/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/create-passion/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/css-reusability/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/declining-expectations/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/diceware/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/eight-years/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/emacs-lite/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/emacs-tips/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/end-of-an-era/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/evening-edition/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/facetime-killer/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/family-first/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/farewell-heroku/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/five-years/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/flatkill/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/git-commit-template/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/git-worktree/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/goat-counter/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/hello-world/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/how-are-you-living/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/huffduffer/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/ifttt/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/introducing-cycle/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/just-start-over/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/keeping-up/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/lambda-talk/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/microblogging/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/new-workstation/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/on-equifax/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/on-george-floyd/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/on-webpack/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/openring/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/oscar/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/pretty-git-log/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/psychicpaper/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/rands-on-email/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/recently-16/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/recently-44/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/rename-utility/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/rust-module-system/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/s3-security-policy/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/small-tech/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/small-things/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/sqlite-tips/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/story/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/thirty-five/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/thirty/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/three-years/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/tweet-stash/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/verse-recall/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/vim-ramblings/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/what-is-medium/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/what-its-all-about/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/what-matters/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/zach-beane/index.html delete mode 100644 themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html diff --git a/README.org b/README.org index 916ac62..842a4b9 100644 --- a/README.org +++ b/README.org @@ -1,23 +1,67 @@ ** Cycle [[https://travis-ci.org/asimpson/cycle.svg?branch=master]] -♻ A static site generator written in Common Lisp that works for me and probably no one else. - -*** Folder structure -#+BEGIN_SRC -. -├── pages -├── posts -├── public -│   ├── images -│   └── js -└── templates - └── partials +♻ A Hugo theme ported from the Cycle static site generator. + +*** Overview +Cycle is now a Hugo theme that maintains the same clean, minimal design as the original Common Lisp static site generator. The theme includes support for: +- Blog posts with RSS feeds +- Custom pages (e.g., /uses, /support) +- Archive page listing all posts +- Link posts with external URLs +- Responsive design using Tachyons CSS + +*** Installation + +**** Using the theme in your Hugo site +1. Add the theme to your Hugo site: + #+BEGIN_SRC bash + cd your-hugo-site + git submodule add https://github.com/asimpson/cycle.git themes/cycle + #+END_SRC + +2. Update your ~hugo.toml~ or ~config.toml~: + #+BEGIN_SRC toml + theme = "cycle" + + [permalinks] + post = "/writing/:slug/" + #+END_SRC + +3. Add CSS files to your site's ~assets/~ directory: + - ~tachyons.css~ - Main CSS framework + - ~custom.css~ - Site-specific styles + +**** Running the example site +#+BEGIN_SRC bash +cd themes/cycle/exampleSite +hugo server #+END_SRC -*** Pre-built binaries -Currently there are pre-built binaries for Linux and macOS in [[https://github.com/asimpson/cycle/releases][Releases]]. +*** Content Structure +- Posts go in ~content/post/~ with frontmatter: + #+BEGIN_SRC yaml + --- + title: "Post Title" + date: 2024-01-01T10:00:00-05:00 + slug: post-slug + excerpt: "Post excerpt for listings and RSS" + --- + #+END_SRC + +- Pages go in ~content/page/~ with similar frontmatter +- The archive page is created by adding ~content/archive/_index.md~ + +*** Link Posts +To create a link post (external link), add a ~link~ parameter to the frontmatter: +#+BEGIN_SRC yaml +--- +title: "External Article" +date: 2024-01-01T10:00:00-05:00 +slug: external-article +link: "https://example.com/article" +--- +#+END_SRC -*** Compile binary -**** sbcl -~make~ +*** Original Common Lisp Version +The original Common Lisp static site generator has been replaced by this Hugo theme. If you need the legacy version, see git history or releases. diff --git a/themes/cycle/README.md b/themes/cycle/README.md new file mode 100644 index 0000000..7d6b0be --- /dev/null +++ b/themes/cycle/README.md @@ -0,0 +1,138 @@ +# Cycle Hugo Theme + +A minimal, clean Hugo theme ported from the [Cycle static site generator](https://github.com/asimpson/cycle). + +## Features + +- Clean, minimal design using Tachyons CSS +- RSS feed support +- Archive page for all posts +- Support for link posts (external URLs) +- Responsive layout +- Custom pages (e.g., /uses, /support) + +## Installation + +### As a Git Submodule + +```bash +cd your-hugo-site +git submodule add https://github.com/asimpson/cycle.git themes/cycle +``` + +### Configuration + +Update your `hugo.toml`: + +```toml +baseURL = "https://example.com/" +languageCode = "en-us" +title = "Your Site Title" +theme = "cycle" + +[params] + description = "Your site description" + +[permalinks] + post = "/writing/:slug/" + +[outputs] + home = ["HTML", "RSS"] + +[outputFormats.RSS] + mediatype = "application/rss+xml" + baseName = "rss" + +[services.rss] + limit = 20 +``` + +### CSS Files + +Copy or create these CSS files in your site's `assets/` directory: +- `tachyons.css` - Main CSS framework +- `custom.css` - Site-specific styles + +You can find example CSS files in `themes/cycle/assets/`. + +## Content Structure + +### Posts + +Posts go in `content/post/` with YAML frontmatter: + +```yaml +--- +title: "Post Title" +date: 2024-01-01T10:00:00-05:00 +lastmod: 2024-01-01T10:00:00-05:00 +slug: post-slug +excerpt: "Post excerpt for listings and RSS" +--- + +Your post content here... +``` + +### Link Posts + +To create a link post (pointing to external content): + +```yaml +--- +title: "External Article" +date: 2024-01-01T10:00:00-05:00 +slug: external-article +excerpt: "Description of the external article" +link: "https://example.com/article" +--- + +Optional commentary about the link... +``` + +### Pages + +Regular pages go in `content/page/`: + +```yaml +--- +title: "About" +permalink: "/about" +excerpt: "About this site" +type: "page" +--- + +Page content... +``` + +### Archive Page + +Create an archive section by adding `content/archive/_index.md`: + +```yaml +--- +title: "Archive" +--- +``` + +## Example Site + +An example site with sample content is available in `exampleSite/`. To run it: + +```bash +cd themes/cycle/exampleSite +hugo server +``` + +## Customization + +The theme uses several partials that can be overridden: + +- `layouts/partials/head.html` - HTML head content +- `layouts/partials/header.html` - Site header with navigation +- `layouts/partials/footer.html` - Site footer +- `layouts/partials/logo.html` - Site logo SVG +- `layouts/partials/post_body.html` - Individual post layout + +## License + +GPLv3 - See LICENSE file for details. diff --git a/themes/cycle/exampleSite/.gitignore b/themes/cycle/exampleSite/.gitignore new file mode 100644 index 0000000..364fdec --- /dev/null +++ b/themes/cycle/exampleSite/.gitignore @@ -0,0 +1 @@ +public/ diff --git a/themes/cycle/exampleSite/public/archive/index.html b/themes/cycle/exampleSite/public/archive/index.html deleted file mode 100644 index 3867421..0000000 --- a/themes/cycle/exampleSite/public/archive/index.html +++ /dev/null @@ -1,2454 +0,0 @@ - - - - - - Archive - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
    - -
  • - - nixpkgs is a treasure - -
    May 10, 2024
    -
    - - Nix and NixOS continue to be the best way to manage and build software that I've found. - -
    -
  • - -
  • - - Lessons learned from integrating OpenAI into a Grafana data source - -
    July 25, 2023
    -
    - - I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! - -
    -
  • - -
  • - - Better scripting with gh - -
    July 22, 2023
    -
    - - I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. - -
    -
  • - -
  • - - End of an era - -
    June 15, 2023
    -
    - - Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. - -
    -
  • - -
  • - - Hacking on Grafana with Web Assembly - -
    August 19, 2022
    -
    - - Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. - -
    -
  • - -
  • - - New workstation - -
    May 2, 2022
    -
    - - I detail my new workstation build featuring the Intel i5-12600k. - -
    -
  • - -
  • - - 👋 Sparkbox - -
    April 1, 2022
    -
    - - I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. - -
    -
  • - -
  • - - Thirty five - -
    March 3, 2022
    -
    - - It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. - -
    -
  • - -
  • - - Windows 11 as KVM guest - -
    February 28, 2022
    -
    - - How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. - -
    -
  • - -
  • - - A few POSIX shell tips - -
    July 19, 2021
    -
    - - I wrote down a few of my most used POSIX shell commands and features. - -
    -
  • - -
  • - - Recently - -
    April 23, 2021
    -
    - - A random assortment of links and miscellaneous updates on things. - -
    -
  • - -
  • - - A firewall in 8 lines - -
    March 31, 2021
    -
    - - You only need about 8 lines in iptables to have a great home firewall. - -
    -
  • - -
  • - - How to use Siji font on polybar - -
    November 6, 2020
    -
    - -

    Nice guide on Reddit about how to use the Siji font with polybar.

    -
    -

    [..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

    -
    -

    Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

    - - 🔗 Permalink - -
    -
  • - -
  • - - On Polybar bitmap fonts and Ubuntu - -
    November 6, 2020
    -
    - - Enable bitmap fonts on Ubuntu for an optimal polybar experience. - -
    -
  • - -
  • - - Recently - -
    October 27, 2020
    -
    - - I've written a few small tools over the last couple months and I figured it's time I post about them. - -
    -
  • - -
  • - - Four ways to approach Hacktoberfest 2020 - -
    October 1, 2020
    -
    - - I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. - -
    -
  • - -
  • - - Small tech - -
    September 25, 2020
    -
    - -

    Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

    -
      -
    • -

      curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

      -
    • -
    • -

      git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

      -
    • -
    • -

      Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

      -
    • -
    • -

      sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

      -
    • -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Indexing My Blog’s Links - -
    September 25, 2020
    -
    - -

    Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Compose key and i3 - -
    September 18, 2020
    -
    - - Here's how to bind the compose key to caps lock in i3wm. - -
    -
  • - -
  • - - cycle v0.3.0 released - -
    September 11, 2020
    -
    - - Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. - -
    -
  • - -
  • - - Setting a default browser in i3 - -
    September 11, 2020
    -
    - - Using a desktop manager like GNOME makes setting default applications easy. However when using a tiling window manager like i3 setting a default application is opaque to the newbie such as myself. - -
    -
  • - -
  • - - Eight years - -
    September 4, 2020
    -
    - - Eight years ago I started working at Sparkbox. Thank you Sparkbox team for giving me an opportunity to work with ya'll and for making me a better developer and person. - -
    -
  • - -
  • - - Uses This / Zach Beane - -
    September 1, 2020
    -
    - -

    A great interview with the creator of Quicklisp, Zach Beane. I enjoy two things about this interview:

    -
      -
    1. The inclusion of outdoor/farming tools in the list of tools.
    2. -
    3. Zach’s conservative approach to languages and software tools.
    4. -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Openring - -
    August 21, 2020
    -
    - - I've added Drew DeVault's openring project to the blog. - -
    -
  • - -
  • - - A public inbox - -
    August 17, 2020
    -
    - - I'm going to give the idea of a public inbox as a place to have discussions about things on this website and elsewhere a shot. - -
    -
  • - -
  • - - Clear explanation of Rust’s module system - -
    July 19, 2020
    -
    - -

    This is a great explanation of Rust’s module system. I wish I had this clear of a picture when I was using modules for the first time in creating oscar.

    -

    The big takeaway and deviation from npm is this:

    -
    -

    We need to explicitly build the module tree in Rust, there’s no implicit mapping to file system.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Nothing speaks like a demo - -
    July 19, 2020
    -
    - -

    Great post from my friend and co-worker Bryan Braun on the value of demoing.

    -
    -

    It didn’t matter that his demos weren’t fully built, or available for anyone to use. We simply needed to see it, in order to understand.

    -
    -

    I find this is true for any kind of project: hobby or professional. Feedback — that elusive crucial ingredient to a good product — tends to arrive when someone else can see/hear/touch/examine what you’re working on.

    - - 🔗 Permalink - -
    -
  • - -
  • - - A new website for 2020 - -
    July 16, 2020
    -
    - -
    -

    According to my Cargo.lock file, my website currently depends on 364 crates. So it’s really about standing on the shoulder of a carefully-curated set of giants.

    -
    -
    -

    364 may seem like a lot (and in a way, it is), but please reserve your judgement until after you’ve heard about everything it does.

    -
    -

    I /love/ posts like this. Amos goes in deep on the decisions he made while re-writing his website from scratch. It’s a truly awesome post.

    -

    I’m seriously tempted to copy his SQLite full-text search implementation for this blog, but that’s a decision for another time.

    - - 🔗 Permalink - -
    -
  • - -
  • - - A Moment of Clarity Regarding the Raison d’Etre for the App Store - -
    July 13, 2020
    -
    - -
    -

    I’d like to see all the vim, vigor, and vigilance Apple applies to making sure no app on the App Store is making a dime without Apple getting three cents applied instead to making sure there aren’t any scams or ripoffs, and that popular apps support good-citizen-of-the-platform features within a reasonable amount of time after those features are introduced in the OS. I don’t know exactly how long “reasonable” is, but five fucking years for split-screen support ain’t it.

    -
    -

    I’ve been thinking the same thing ever since the Hey app rejection right before WWDC. The App Store is supposed to be a place to get software that has been vetted by Apple but there seems to be a growing disconnect between what users imagine that vetting is and what Apple is doing.

    -

    I want to believe this tweet by Ben Evans is the goal of the App Store:

    - -

    If we can trust the apps that come out of the App Store:

    -
      -
    • why is the US considering banning TikTok because of its rampant data collection?
    • -
    • why do we need a new notification in iOS 14 when apps query the clipboard?
    • -
    • why do we need a microphone/camera indicator at the system level?
    • -
    -

    Maybe I was naive and alone in my assumption that Apple would root this stuff out during the review process. If they’re not rooting this out then what is the point of the review process at all?

    - - 🔗 Permalink - -
    -
  • - -
  • - - GoatCounter web analytics - -
    July 1, 2020
    -
    - -
    -

    What seems to be lacking is a “middle ground” that offers useful statistics to answer business questions, without becoming a specialized marketing tool requiring in-depth training to use effectively. Furthermore, some tools have privacy issues (especially Google Analytics). I saw there was space for a new service and ended up putting my original idea in the freezer and writing GoatCounter.

    -
    -

    I agree 100% with this assessment and I’m excited about Goatcounter. I setup a free instance of Goatcounter for this site as a way to kick the tires on it. So far, I’m enjoying that it’s privacy respecting and doesn’t drag down page performance.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Is WebP really better than JPEG? - -
    June 30, 2020
    -
    - -
    -

    If you have used tools like Google’s PageSpeed Insights, you probably have run into a suggestion to use “next-gen image formats”, namely Google’s WebP image format. Google claims that their WebP format is 25 – 34% smaller than JPEG at equivalent quality.

    -
    -
    -

    In any case, when converting images to WebP, check that they are actually smaller than the JPEG equivalent. There’s no need to serve larger images to your users than needed.

    -
    -

    Great analysis of the WebP image format and a good reminder to not blindly follow what various auditing tools are reporting. Test and verify in addition to implementing the various suggested improvements.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Britain goes coal free as renewables edge out fossil fuels - -
    June 30, 2020
    -
    - -
    -

    Britain is about to pass a significant landmark - at midnight on Wednesday it will have gone two full months without burning coal to generate power.

    -
    -
    -

    A decade ago about 40% of the country’s electricity came from coal; coronavirus is part of the story, but far from all.

    -
    -

    This is fascinating. The UK has been aggressively investing in renewable energy sources for years and it appears all that investment is starting to catch up with demand.

    - - 🔗 Permalink - -
    -
  • - -
  • - - On George Floyd - -
    June 30, 2020
    -
    - - I haven't written anything here about George Floyd's murder. I still don't have a cogent response but here's what I've been mulling over. - -
    -
  • - -
  • - - flatkill - -
    June 15, 2020
    -
    - -
    -

    And it’s not only about these security problems. Running KDE apps in fakepak? Forget about desktop integration (not even font size). Need to input Chinese/Japanese/Korean characters? Forget about that too - fcitx has been broken since flatpak 1.0, never fixed since.

    -
    -
    -

    The way we package and distribute desktop applications on Linux surely needs to be rethinked, sadly flatpak is introducing more problems than it is solving.

    -
    -

    Flatpak is an emerging alternative way to install applications on Linux that is apparently rife with security and usability issues. This is a bummer because there’s lots of room in this space for improvement. The lack of multi-lingual input is especially egregious.

    - - 🔗 Permalink - -
    -
  • - -
  • - - FFMPEG: Convert multiple files using xargs - -
    June 4, 2020
    -
    - -

    I stumbled upon this post (Google cache link) when I was trying to process multiple files via xargs.

    -
    -

    ls *.webm | xargs -I % ffmpeg -i % %.m4a

    -
    -
    -

    The key part of this one-liner is xargs -i %. This means that each line of STDIN passed to xargs is put into a variable and can be referenced as %. Hence, the following text which specifies ffmpeg -i x.webm x.m4a to make it convert.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Using SQL to Look Through All of Your iMessage Text Messages - -
    May 28, 2020
    -
    - -
    -

    If you use iMessage on your Mac, you can access the SQLite database where all of your messages are stored. With a little setup, you can use SQL’s raw power to look through your old messages.

    -
    -

    via Simon Willison

    -

    In this post Dan Kelch walks through how to access the SQLite database that backs iMessage on a Mac. He also shares a few helpful SQL snippets to demonstrate how powerful using SQL on your text messages can be.

    - - 🔗 Permalink - -
    -
  • - -
  • - - macOS 10.15: Slow by Design - -
    May 28, 2020
    -
    - -

    A few days ago Allan Odgaard wrote up the reasons for the frequent slowdowns he’s experiencing in macOS Catalina and it’s shocking:

    -
    -

    Apple has introduced notarization, setting aside the inconvenience this brings to us developers, it also results in a degraded user experience, as the first time a user runs a new executable, Apple delays execution while waiting for a reply from their server. This check for me takes close to a second.

    -
    -
    -

    This is not just for files downloaded from the internet, nor is it only when you launch them via Finder, this is everything. So even if you write a one line shell script and run it in a terminal, you will get a delay!

    -
    -
    -

    I am writing this post to call attention to what I consider a serious design problem with Apple’s most recent OS where it appears that low-level system API such as exec and getxattr now do synchronous network activity before returning to the caller.

    -
    -

    Marco Arment hit the nail on the head with his tweet summary of the post:

    -
    -

    The macOS security team needs to ask themselves hard questions about their implementation choices when very smart people are disabling huge parts of their OS security layer just to get reasonable performance from common tasks.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Getting started with Rofi - -
    May 28, 2020
    -
    - - I've been using Rofi for about a year but didn't really understand how to write my own scripts for it until recently. In this post I explain what dmenu is and Rofi's implementation of it and also show how to change audio inputs on Linux via pactl. - -
    -
  • - -
  • - - What Time Is It in London? - -
    May 22, 2020
    -
    - -
    -

    Nilay Patel asked this of Siri on his Apple Watch. After too long of a wait, he got the correct answer — for London Canada. I tried on my iPhone and got the same result. Stupid and slow is heck of a combination.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Psychic Paper - -
    May 18, 2020
    -
    - -
    -

    RIP my very first 0day and absolute best sandbox escape ever:

    -
    -
    <key>application-identifier</key>
    -<string>...</string>
    -<!---><!-->
    -<key>platform-application</key>
    -<true/>
    -<key>com .apple.private.security.no-container</key>
    -<true/>
    -<key>task_for_pid-allow</key>
    -<true/>
    -<!-- -->
    -

    Tweet that demonstrates a recent zero-day (now patched) in iOS. This serves as your annual reminder that parsing xml-like things is a fraught activity.

    - - 🔗 Permalink - -
    -
  • - -
  • - - The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet - -
    May 18, 2020
    -
    - -
    -

    Janet Hutchins had the day off from her job as a nurse at a local hospital. She had been in town catching up with friends and had just gotten home and started making dinner. So she had only the slightest sense of the crisis that her colleagues had been dealing with across the NHS. That’s when her son came upstairs and told her, a little uncertainly, that he seemed to have stopped the worst malware attack the world had ever seen.

    -
    -
    -

    “Well done, sweetheart,” Janet Hutchins said. Then she went back to chopping onions.

    -
    -

    It’s hard to pick my favorite section from this article about Marcus Hutchins — the hacker who stopped the WannaCry malware attack.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Second-guessing the modern web - -
    May 13, 2020
    -
    - -
    -

    The low performance parts don’t need to be React. Listing pages, static pages, blogs - these things are increasingly built in React, but the benefits they accrue are extremely narrow. A lot of the optimizations that are cropping up in these corners, things like bundle splitting, server-side rendering, and prerendering, are triangulating, essentially, what we had before the rise of React.

    -
    -

    This isn’t really about React but more about the over-engineering of large swaths of page-types and sites that used to “just work”. I love React and it’s been a giant leap forward for creating complex UIs on the web, that doesn’t mean it’s right for every situation.

    - - 🔗 Permalink - -
    -
  • - -
  • - - youtube-subscriptions - -
    May 8, 2020
    -
    - -

    I’ve been using youtube-subscriptions for a few months now and I really enjoy it. It’s described as a:

    -
    -

    terminal client to browse youtube subscriptions

    -
    -

    It’s great to quickly see any new videos right in the terminal and videos play via mpv or vlc!

    - - 🔗 Permalink - -
    -
  • - -
  • - - Hiking the Pacific Crest Trail in Three Minutes - -
    May 7, 2020
    -
    - -
    -

    The Pacific Crest Trail runs 2650 miles from the border of Mexico to the border of Canada through California, Oregon, and Washington. Hiking the whole thing usually takes months, but this video by Mac of Halfway Anywhere compresses the entire experience down to just three minutes presented in 1-second snippets.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Introducing oscar - -
    April 29, 2020
    -
    - - I've been working on oscar which is a small command-line utility written in Rust that polls the pbskids.org API for new episodes of any PBS show. - -
    -
  • - -
  • - - Seamless branch deploys with Kubernetes - -
    April 27, 2020
    -
    - -

    A trait of good software is the ability to quickly see and verify changes:

    -
    -

    The result is what’s in-use today for HEY: a system that (almost) immediately deploys any branch to a branch-specific endpoint that you can access right away to test your changes without having to use the claims system or talk to anyone else (along with an independent job processing fleet and Redis instance to support the environment).

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Three easy tuneups to fix video calls while working from home - -
    March 17, 2020
    -
    - - In light of COVID-19 and lots of folks working from home, I've written down the three things I try to tune on my home network to deliver the best possible video call experience. - -
    -
  • - -
  • - - ATR2100 - -
    January 29, 2020
    -
    - - I recently purchased the ATR2100 microphone and absolutely love it. - -
    -
  • - -
  • - - Understanding Rust Strings and str inside structs. - -
    January 8, 2020
    -
    - - Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here's a short breakdown of a compiler error message around Strings and ownership that stumped me for a bit. - -
    -
  • - -
  • - - Tweet stash - -
    December 12, 2019
    -
    - - Two tweets that I've had stuck in my tabs for _awhile_ and decided to stash them here. - -
    -
  • - -
  • - - Track redirects with curl - -
    October 22, 2019
    -
    - - I made a bash alias that takes a URL as an arguement and runs it through curl resuting in the Headers from each redirect, the final URL, and the number of redirects printed to the console. - -
    -
  • - -
  • - - The thing about computers - -
    September 21, 2019
    -
    - - Brent Simmons talks about what made computing so compelling and what we might be losing. - -
    -
  • - -
  • - - Dead Cells might be a perfect game - -
    September 20, 2019
    -
    - - Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it). - -
    -
  • - -
  • - - 0.14 - -
    July 30, 2019
    -
    - - I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn't worth it. - -
    -
  • - -
  • - - Solving busybox crond hanging on Alpine Linux boot - -
    May 5, 2019
    -
    - - How busybox crond hanging at startup sent me down a rabbit hole where I learned about entropy and Linux. - -
    -
  • - -
  • - - Introducing Cycle - -
    April 5, 2019
    -
    - - Cycle is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today. - -
    -
  • - -
  • - - Ajax and Rails - -
    January 28, 2019
    -
    - - This is just a short post to save a few links and document that "Server Javascript Responses" in Rails are still useful in 2018/19. - -
    -
  • - -
  • - - Blog rewrite - -
    November 20, 2018
    -
    - - I haven't posted here recently. That's largely because I did the classic "Time to rewrite the blog, I'll post when it's done" thing. Well it's not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I'm trying to rectify that now with some scant and scattered sentences. - -
    -
  • - -
  • - - Medium isn't a permanent fixture on the Internet - -
    May 21, 2018
    -
    - - If you're writing on the Internet and you aren't hosting (owning) your content you're work will disappear; it's just a matter of time. - -
    -
  • - -
  • - - Hosting assets via Github Pages - -
    May 11, 2018
    -
    - - Screenshots in README.mds are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult. - -
    -
  • - -
  • - - Pinboard popular page in Emacs - -
    April 26, 2018
    -
    - - A quick look at how I made an Ivy extension that displays the links from the pinboard.in popular page - -
    -
  • - -
  • - - Emacs lite - -
    April 19, 2018
    -
    - - A small, friendly starting point for Emacs. - -
    -
  • - -
  • - - Hello micro.blog - -
    February 1, 2018
    -
    - - Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting. - -
    -
  • - -
  • - - Apple on batteries and performance - -
    December 28, 2017
    -
    - - Apple released a statement on the battery and performance issues. - -
    -
  • - -
  • - - Git worktree - -
    December 11, 2017
    -
    - - What the heck is git-worktree? - -
    -
  • - -
  • - - Messi is re-writing the record book - -
    December 2, 2017
    -
    - - In a fantastic video the YouTube channel MagicalMessi documents all the various records that Messi has broken during his illustrious career. - -
    -
  • - -
  • - - Introducing ivy-feedwrangler - -
    November 16, 2017
    -
    - - In exploring what Ivy was capable of I had the idea to write a small package that used Ivy as the interface for my RSS service of choice, Feedwrangler. - -
    -
  • - -
  • - - A Hackintosh - -
    September 14, 2017
    -
    - - I built a PC in May to replace my Xbox One (yay no more Live fees!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh. - -
    -
  • - -
  • - - On Equifax - -
    September 8, 2017
    -
    - - I don't do many link posts but Ian Bogost sums up my feelings perfectly about the Equifax breach. - -
    -
  • - -
  • - - Before Circles 2017 - -
    September 6, 2017
    -
    - - I thought I'd list out a few of the talks I'm looking forward to and what I hope to come away with. - -
    -
  • - -
  • - - Five years - -
    September 5, 2017
    -
    - - Five years is a long time, especially working on the internet, and I've loved every stinking minute of it. - -
    -
  • - -
  • - - On diminishing modes in emacs - -
    August 17, 2017
    -
    - - An explanation of how to change or diminish major and minor modes in emacs - -
    -
  • - -
  • - - From helm to ivy - -
    August 14, 2017
    -
    - - A log of my experience switching from helm to ivy; two completion plugins for emacs. - -
    -
  • - -
  • - - The era of the screenshot - -
    June 12, 2017
    -
    - - We really couldn't have picked a worse data exchange format. - -
    -
  • - -
  • - - Format JSON in emacs - -
    May 23, 2017
    -
    - - I wrote an elisp function to yank JSON off my clipboard, prettify it. - -
    -
  • - -
  • - - Diceware - -
    April 19, 2017
    -
    - - Glenn Fleishman recently linked to a method for generating passphrases called Diceware. Being a fan of dice (d20 for life) I thought this was super cool and worth sharing. - -
    -
  • - -
  • - - Facetime Killer - -
    April 3, 2017
    -
    - - I made an app, VDCAssistant-Killer, to restart the process that manages the Facetime camera on your Mac. - -
    -
  • - -
  • - - What happens when you remove friction - -
    March 27, 2017
    -
    - - When you remove friction from a process or task, all the factors change. This seems obvious, but it's fundamental to understanding the world as it currently is. - -
    -
  • - -
  • - - Emacs tips - -
    March 27, 2017
    -
    - - A evolving collection of emacs tips aimed at someone starting out with emacs and evil-mode. - -
    -
  • - -
  • - - Be a good video call citizen - -
    March 17, 2017
    -
    - - I've been in my fair share of video calls and I thought I'd share a few tricks that help limit my contributions to the chaos. - -
    -
  • - -
  • - - Thirty - -
    March 2, 2017
    -
    - - Today I turn 30. So here is a list of 30 things I've learned in the last year (or so). - -
    -
  • - -
  • - - Lambda Talk - -
    February 23, 2017
    -
    - - Last week I gave a talk at GemCityJS about going serverless with AWS Lambda. - -
    -
  • - -
  • - - We all need a team - -
    June 28, 2016
    -
    - - We all need a team. On the right team we can go higher and be better than we ever thought we could. - -
    -
  • - -
  • - - Web scraper cookbook - -
    February 20, 2016
    -
    - - I've been on a web scraping tear lately. So, I thought I'd compile what I've learned and put together a repo as a howto/cookbook/guide thing. - -
    -
  • - -
  • - - How do we make the Web better - -
    January 29, 2016
    -
    - - My post for the Shift for January. I tackle the question within the question: how do we (internet workers) have more meaningful conversations in order to make the web better? - -
    -
  • - -
  • - - Command line notification - -
    January 16, 2016
    -
    - - This week I wrote a bash function that curls the SendGrid API and sends a Boxcar notification. - -
    -
  • - -
  • - - Verse Recall - -
    December 23, 2015
    -
    - - Whew, time to share something with the world I haven't really talked about online at all, my first and only (so far) iOS app. - -
    -
  • - -
  • - - SQLite Tips - -
    December 20, 2015
    -
    - - I've been playing around with SQLite recently and I've stumbled across a few things I want to remember, so I'm putting them here. - -
    -
  • - -
  • - - On Webpack - -
    December 7, 2015
    -
    - - I wrote a love letter to Webpack over on the Foundry. - -
    -
  • - -
  • - - Migrate an existing build process to npm scripts - -
    October 18, 2015
    -
    - - Not all projects need Grunt or Gulp, npm is a great build tool by itself. I recently replaced a Grunt task (with multiple plugins) with a npm script task. - -
    -
  • - -
  • - - CasperJs, Node, and the Raspberry Pi - -
    October 10, 2015
    -
    - - I've been working on getting my Raspberry Pi to be a dedicated screen-scraping machine with CasperJS and Node. -This post is intended to be a log for myself and hopefully a helpful resource for others. - -
    -
  • - -
  • - - AMP HTML, Terrible HTML - -
    October 8, 2015
    -
    - - Is the answer developing a subset of HTML/JS/CSS? - -
    -
  • - -
  • - - Farewell Heroku - -
    October 6, 2015
    -
    - - I've migrated my apps off Heroku and won't be using the service for personal apps going forward. - -
    -
  • - -
  • - - Parsing memory usage in htop/top - -
    October 4, 2015
    -
    - - I've been trying to figure out how much memory a node app is using on my VPS, and I've found output from top or htop to be overwhelming. - -
    -
  • - -
  • - - Three years - -
    September 4, 2015
    -
    - - The adventure is just getting started. - -
    -
  • - -
  • - - What is Medium? - -
    August 27, 2015
    -
    - - I'm curious to see how Medium continues to evolve. - -
    -
  • - -
  • - - Small things - -
    August 22, 2015
    -
    - - Recently I've come to love MicroJS. I love that I can find tiny, specific libraries that do one thing, and do it well - -
    -
  • - -
  • - - Automating SOCKS proxy - -
    August 8, 2015
    -
    - - I've used a SOCKS proxy while on public WiFi ever since reading Paul Stamatiou's article years ago. I only recently took the time to automate the process. - -
    -
  • - -
  • - - The Stream hasn't won - -
    July 17, 2015
    -
    - - Hossein Derakhshan outlines how the web as he knew it has disappeared and been replaced by "The Stream", or social media. His post is beautifully written and I highly recommend reading it. - -
    -
  • - -
  • - - Microblogging - -
    June 25, 2015
    -
    - - My microblogging setup with Twilio, Twitter, SMS, and WordPress. - -
    -
  • - -
  • - - Learning to think in React - -
    June 8, 2015
    -
    - - I outline how I built my blog using React and the WordPress API. This post covers isomorphic app structure and data flow in React with React-Router. - -
    -
  • - -
  • - - Moving away from Google - -
    June 1, 2015
    -
    - - I recently started using DuckDuckGo and Fastmail. So I thought I'd share a few thoughts on both services. - -
    -
  • - -
  • - - Benedict Evans is on fire - -
    May 18, 2015
    -
    - - Benedict Evan's last three pieces are right on the money regarding mobile, and the web versus native apps. - -
    -
  • - -
  • - - Web performance and Facebook's Instant Articles - -
    May 13, 2015
    -
    - - Crafting a high-performing web experience for mobile is not easy, but it's not so impossibly hard that Facebook's Instant Articles is the only solution. - -
    -
  • - -
  • - - Google Fi and data only plans - -
    April 30, 2015
    -
    - - Why doesn't Google just offer data? There already is already a fantastic data-only plan in America, and it's on T-Mobile. - -
    -
  • - -
  • - - iPhone checker with Capybara and Twilio - -
    October 30, 2014
    -
    - - I set up a small Heroku app that uses Capybara to check Apple's website for availability and sends a text to my phone via Twilio. - -
    -
  • - -
  • - - Vim Ramblings - -
    June 27, 2014
    -
    - - So, in the past 6 months I've switched from Sublime Text to Vim. Here are some good articles and tips on Vim. - -
    -
  • - -
  • - - S3 Security Policy - -
    April 26, 2014
    -
    - - A basic AWS S3 bucket policy that restricts access to a single bucket, and allows access via the AWS cli. - -
    -
  • - -
  • - - Keeping up - -
    April 8, 2014
    -
    - - Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week - -
    -
  • - -
  • - - Broadcast channel - -
    April 8, 2014
    -
    - - Along with the move to Siteleaf I've also set up an App.net Broadcast channel. - -
    -
  • - -
  • - - Moved to Siteleaf - -
    March 31, 2014
    -
    - - I moved to Siteleaf from Jekyll - -
    -
  • - -
  • - - Git Commit Template - -
    August 22, 2013
    -
    - - Set up a Git commit message template - -
    -
  • - -
  • - - ADN Cross-poster - -
    August 15, 2013
    -
    - - How to set up your own App.net to Twitter cross-posting app. - -
    -
  • - -
  • - - IFTTT - -
    July 21, 2013
    -
    - - Ways I use IFTTT. App.net to Twitter, App.net from Day One, and Camera Roll to FLickr. - -
    -
  • - -
  • - - JS2Coffee Alfred Workflow - -
    July 8, 2013
    -
    - - An Alfred workflow that converts Javascript to Coffeescript - -
    -
  • - -
  • - - Huffduffer - -
    July 6, 2013
    -
    - - Use Huffduffer to listen to individual podcast episodes. - -
    -
  • - -
  • - - Slanted Elements with CSS3 - -
    April 21, 2013
    -
    - - How to use CSS3 transforms to work with slanted elements - -
    -
  • - -
  • - - A Fluid Userscript that adds Read it Later to Twitter - -
    March 24, 2013
    -
    - - A simple Fluid userscript that adds a Read it Later button for Instapaper to any tweet containing a link - -
    -
  • - -
  • - - Rename utility - -
    February 13, 2013
    -
    - - A short primer on the rename command line utility. - -
    -
  • - -
  • - - What Matters - -
    January 10, 2013
    -
    - - A great quote from a post over at 37 signals. - -
    -
  • - -
  • - - Andy Budd on Time - -
    January 10, 2013
    -
    - - Great quote by Andy Budd on the value of time - -
    -
  • - -
  • - - IP Address Alfred Extension - -
    December 7, 2012
    -
    - - I enhance the previous IP bash function as an Alfred Extension - -
    -
  • - -
  • - - Bash Function - IP Address to Clipboard - -
    December 5, 2012
    -
    - - A quick post explaining a command line function to copy your IP address to your clipboard - -
    -
  • - -
  • - - A few Bash Tips - -
    November 20, 2012
    -
    - - A rundown of some of my most used bash and terminal commands and functions. - -
    -
  • - -
  • - - Rands on Email - -
    October 21, 2012
    -
    - - A fantastic post from Michael Lopp. - -
    -
  • - -
  • - - Lyza Gardner on Laying Down our Burdens - -
    October 21, 2012
    -
    - - Another great article from Lyza Gardner. - -
    -
  • - -
  • - - Family First - -
    October 21, 2012
    -
    - - Chris Bowler weighs in with some fantastic advice for those who have families. - -
    -
  • - -
  • - - Alfred and Web Development - -
    October 11, 2012
    -
    - - A quick tip on using Alfred in Web Development - -
    -
  • - -
  • - - Theme the Chrome Dev Tools - -
    October 9, 2012
    -
    - - A short post on how to theme the Chrome Dev Tools - -
    -
  • - -
  • - - Moving Tweetbot Beta to a new Mac - -
    September 21, 2012
    -
    - - How to migrate Tweetbot Beta to a new Mac. - -
    -
  • - -
  • - - Heroku and SSH Keys - -
    September 21, 2012
    -
    - - Quick solution to fixing Heroku SSH key errors using ssh config. - -
    -
  • - -
  • - - I moved to Hover - -
    September 9, 2012
    -
    - - I switched from GoDaddy to Hover. - -
    -
  • - -
  • - - How are you living - -
    September 6, 2012
    -
    - - Shawn Blanc poses some tough questions about life and purpose - -
    -
  • - -
  • - - A New Adventure - -
    September 3, 2012
    -
    - - Today I started working at Sparkbox as Front-End Dev. - -
    -
  • - -
  • - - When the Music Stops - -
    August 23, 2012
    -
    - - Dave Winer has a great post on what happens when a service disappears. - -
    -
  • - -
  • - - Tigers and Social Networks - -
    August 21, 2012
    -
    - - A response to Charlie Pratt's blog post about the problem of social networks and catering to the crowd - -
    -
  • - -
  • - - Blogs, data, and social networks - -
    August 19, 2012
    -
    - - I bring together a few different voices to illustrate the argument for blogs, open data, and open social networks. - -
    -
  • - -
  • - - Maybe you should…it's not you…move on. - -
    August 16, 2012
    -
    - - A collection of reactions to how Twitter muddled there recent API announcement. - -
    -
  • - -
  • - - Rotten Tomatoes and Launch Center - -
    August 13, 2012
    -
    - - Hack together a faster Rotten Tomatoes experience on the iPhone - -
    -
  • - -
  • - - Working with Wordpress, offset and pagination - -
    August 10, 2012
    -
    - - A code snippet to have posts offset and have pagination work. - -
    -
  • - -
  • - - Plaintext and Markdown - A Primer - -
    August 8, 2012
    -
    - - A quick introduction to the beauty of plaintext and the Markdown syntax - -
    -
  • - -
  • - - Gists, Snippets, and Sublime Text 2 - -
    August 6, 2012
    -
    - - How I now use Gists instead of snippets in Sublime Text 2. - -
    -
  • - -
  • - - Kyle Steed on rest - -
    August 3, 2012
    -
    - - Fantastic article by Kyle Steed on work, rest, and life - -
    -
  • - -
  • - - Convince the Boss - -
    August 2, 2012
    -
    - - Jeremy Keith on convincing bosses to adopt new web standards. - -
    -
  • - -
  • - - Create Passion - -
    August 2, 2012
    -
    - - Tiffani Jones Brown talks about passion in volume 3 of The Manual - -
    -
  • - -
  • - - Using the Kindle to harness the Web - -
    August 1, 2012
    -
    - - how I use Readability’s Kindle bookmarklet to harness the web. - -
    -
  • - -
  • - - Simple Account Set-up - -
    August 1, 2012
    -
    - - Simple does account set-up right. - -
    -
  • - -
  • - - The Future is Prototyping - -
    July 31, 2012
    -
    - - A fantastic quote from a fantastic article over at Big Spaceship - -
    -
  • - -
  • - - Story - -
    July 26, 2012
    -
    - - The importance of story in products, design, and development. - -
    -
  • - -
  • - - Guidelines for Data - -
    July 26, 2012
    -
    - - The guidelines for data and how it pertains to Wordpress - -
    -
  • - -
  • - - What's best for the readers - -
    July 24, 2012
    -
    - - Jonah Peretti's letter to employees and investors of Buzzfeed. - -
    -
  • - -
  • - - What it's all about - -
    July 23, 2012
    -
    - - Jonathan Christopher hits the nail on the head - -
    -
  • - -
  • - - Sparrow and the App Store - -
    July 23, 2012
    -
    - - App Cubby's take on Google's acquisition of Sparrow - -
    -
  • - -
  • - - CSS Reusability - -
    July 23, 2012
    -
    - - How much CSS am I reusing? - -
    -
  • - -
  • - - A Little Hydrofoil - -
    July 23, 2012
    -
    - - Robin Sloan's description of a programmer. - -
    -
  • - -
  • - - The Web is Not Print - -
    July 22, 2012
    -
    - - The infamous Zeldman dishses on the web and print - -
    -
  • - -
  • - - Declining Expectations - -
    July 22, 2012
    -
    - - Matthew Butterick's talk on declining expectations. - -
    -
  • - -
  • - - Someone is working harder than you - -
    July 19, 2012
    -
    - - Hard work and how to be creative - -
    -
  • - -
  • - - Just Start Over - -
    July 19, 2012
    -
    - - Sebastiaan De With describes his design process for doubleTwist's Alarm Clock - -
    -
  • - -
  • - - A Style Guide, Guide - -
    July 19, 2012
    -
    - - Elyse Holladay reveals her style guide guide. - -
    -
  • - -
  • - - Zen Garden Part 2? - -
    July 18, 2012
    -
    - - Is it time for a Return to the CSS Zen Garden? Rick Monro thinks Responsive Web Design needs it. - -
    -
  • - -
  • - - Pretty Git log - -
    July 18, 2012
    -
    - - Handy tip for pretty git logs. - -
    -
  • - -
  • - - Grow it, don't build it - -
    July 18, 2012
    -
    - - Growing software versus building it - -
    -
  • - -
  • - - Evening Edition - -
    July 18, 2012
    -
    - - The Evening Edition is a great little resource - -
    -
  • - -
  • - - Balancing Devotion - -
    July 17, 2012
    -
    - - Is it possible to create an extraordinary product and have a healthy life outside of that proudct? - -
    -
  • - -
  • - - The web, and my goal - -
    July 12, 2012
    -
    - - Thought from the Pastry Box Project's Bruce Lawson. - -
    -
  • - -
  • - - Nginx www rewrite - -
    July 12, 2012
    -
    - - How to rewrite www to non-www in Nginx - -
    -
  • - -
  • - - My First Bookmarklet - -
    July 12, 2012
    -
    - - My first bookmarklet, an ESPN Insider paywall - -
    -
  • - -
  • - - The Wordpress HTTP API is Awesome - -
    June 28, 2012
    -
    - - The title says it all. I completely forgot about the Wordpress HTTP API until today. - -
    -
  • - -
  • - - Adam versus Dropbox and oAuth - -
    June 25, 2012
    -
    - - Adam versus Dropbox and oAuth. Frustration post incoming regarding curl, php, and oAuth. - -
    -
  • - -
  • - - The Manhattan Project Time-Lapse - -
    June 24, 2012
    -
    - - An incredible time-lapse of Manhattan - -
    -
  • - -
  • - - Hello World - -
    June 24, 2012
    -
    - - I'm proud, nervous, and a little surprised that adamsimpson.net is finally live! - -
    -
  • - -
-
- -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/archive/rss.xml b/themes/cycle/exampleSite/public/archive/rss.xml deleted file mode 100644 index 0ac0c36..0000000 --- a/themes/cycle/exampleSite/public/archive/rss.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - adamsimpson.net Post Feed - https://adamsimpson.net/ - Last 20 posts for adamsimpson.net - Thu, 09 Oct 2025 21:22:39 +0000 - en-us - - diff --git a/themes/cycle/exampleSite/public/categories/index.html b/themes/cycle/exampleSite/public/categories/index.html deleted file mode 100644 index 7262a51..0000000 --- a/themes/cycle/exampleSite/public/categories/index.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - Categories - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
    - -
-
- -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/categories/rss.xml b/themes/cycle/exampleSite/public/categories/rss.xml deleted file mode 100644 index 0ac0c36..0000000 --- a/themes/cycle/exampleSite/public/categories/rss.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - adamsimpson.net Post Feed - https://adamsimpson.net/ - Last 20 posts for adamsimpson.net - Thu, 09 Oct 2025 21:22:39 +0000 - en-us - - diff --git a/themes/cycle/exampleSite/public/index.html b/themes/cycle/exampleSite/public/index.html deleted file mode 100644 index 0a7608c..0000000 --- a/themes/cycle/exampleSite/public/index.html +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - adamsimpson.net - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-

Hiya 👋

-

I'm Adam Simpson and I work on open source at Grafana and live life with my wonderful wife Christi and our daughters Ellie, Ainsley, and Margot.

-
-
-

Recent Posts

-
    - -
  • - - nixpkgs is a treasure - -
    May 10, 2024
    -
    - - Nix and NixOS continue to be the best way to manage and build software that I've found. - -
    -
  • - -
  • - - Lessons learned from integrating OpenAI into a Grafana data source - -
    July 25, 2023
    -
    - - I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! - -
    -
  • - -
  • - - Better scripting with gh - -
    July 22, 2023
    -
    - - I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. - -
    -
  • - -
  • - - End of an era - -
    June 15, 2023
    -
    - - Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. - -
    -
  • - -
  • - - Hacking on Grafana with Web Assembly - -
    August 19, 2022
    -
    - - Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. - -
    -
  • - -
  • - - New workstation - -
    May 2, 2022
    -
    - - I detail my new workstation build featuring the Intel i5-12600k. - -
    -
  • - -
  • - - 👋 Sparkbox - -
    April 1, 2022
    -
    - - I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. - -
    -
  • - -
  • - - Thirty five - -
    March 3, 2022
    -
    - - It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. - -
    -
  • - -
  • - - Windows 11 as KVM guest - -
    February 28, 2022
    -
    - - How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. - -
    -
  • - -
  • - - A few POSIX shell tips - -
    July 19, 2021
    -
    - - I wrote down a few of my most used POSIX shell commands and features. - -
    -
  • - -
- -
- -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/page/index.html b/themes/cycle/exampleSite/public/page/index.html deleted file mode 100644 index 5634e8a..0000000 --- a/themes/cycle/exampleSite/public/page/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Pages - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
    - -
  • - - Support - -
    January 1, 0001
    -
    - - Ways to support me and the blog via affiliate links. - -
    -
  • - -
  • - - Uses - -
    January 1, 0001
    -
    - - A evolving list of hardware and software that I use. - -
    -
  • - -
-
- -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/page/rss.xml b/themes/cycle/exampleSite/public/page/rss.xml deleted file mode 100644 index 0ac0c36..0000000 --- a/themes/cycle/exampleSite/public/page/rss.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - adamsimpson.net Post Feed - https://adamsimpson.net/ - Last 20 posts for adamsimpson.net - Thu, 09 Oct 2025 21:22:39 +0000 - en-us - - diff --git a/themes/cycle/exampleSite/public/page/support/index.html b/themes/cycle/exampleSite/public/page/support/index.html deleted file mode 100644 index 4e273c2..0000000 --- a/themes/cycle/exampleSite/public/page/support/index.html +++ /dev/null @@ -1,233 +0,0 @@ - - - - - - Support - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
-

Support

-

I use the following services just about every day and they all offer discounts or other incentives for folks to recommend the service to other people. Signing up for one of these services using the links below helps support me and this blog. Thanks!

-

Fastmail

-

I’ve been a Fastmail user for years now and I don’t have a single complaint about the service or company. Highly recommended if all you care about is IMAP service that “just works.”

-

Hover

-

Years ago I switched from GoDaddy to Hover and haven’t looked back. They’re a great, no-frills DNS service.

-

Backblaze

-

I’ve been using Backblaze for years and absolutely love the service and company. Not only is their product top-notch but the data they publish about hard drive reliability is incredibly useful.

- -
-
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/page/uses/index.html b/themes/cycle/exampleSite/public/page/uses/index.html deleted file mode 100644 index bfcb6bf..0000000 --- a/themes/cycle/exampleSite/public/page/uses/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Uses - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
-

Uses

-

Author’s note: I 100% stole this format from the incredible usesthis site. Check it out.

-

What hardware do you use?

-

At work I use a desktop workstation running NixOS and an Intel 12600k. I game via a Windows 11 VM and a Nvidia 3060 passed through to that VM.

-

I love typing on my Anne Pro GMMK Pro mechanical keyboard with Gazzew U4 Boba switches for a quieter feel.

-

My phone is an iPhone 14. It’s fine.

-

And what software?

-

I’m a big user of Emacs. I use mu4e for email, org-mode for tasks and notes, Ivy for auto-complete, magit for git, ivy-feedwrangler for RSS. I’ve switched to VSCode since the support for all the various LSPs and debug tools is just better at the moment.

-

Linux apps I use on my work laptop are: Signal, Tilix or Alacritty for terminals, rofi for launching, and i3wm as my window manager.

-

Mac specific apps I use: Alfred, MenuMeters, 1Password, Moom, Turbo Boost Switcher Pro, and Hammerspoon.

-

My browser of choice is Firefox.

-

I enjoy writing code in Javascript/Node, Golang, Ruby, Common Lisp, and recently Rust.

-

Any online services?

-

As far as online services go I use Netlify (at the moment) to host this site, Hover for domains, Fastmail for email, yarr manages my RSS feeds, and I use Backblaze for online backup.

- -
-
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/post/index.html b/themes/cycle/exampleSite/public/post/index.html deleted file mode 100644 index fa24c0d..0000000 --- a/themes/cycle/exampleSite/public/post/index.html +++ /dev/null @@ -1,2454 +0,0 @@ - - - - - - Posts - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
    - -
  • - - nixpkgs is a treasure - -
    May 10, 2024
    -
    - - Nix and NixOS continue to be the best way to manage and build software that I've found. - -
    -
  • - -
  • - - Lessons learned from integrating OpenAI into a Grafana data source - -
    July 25, 2023
    -
    - - I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! - -
    -
  • - -
  • - - Better scripting with gh - -
    July 22, 2023
    -
    - - I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. - -
    -
  • - -
  • - - End of an era - -
    June 15, 2023
    -
    - - Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. - -
    -
  • - -
  • - - Hacking on Grafana with Web Assembly - -
    August 19, 2022
    -
    - - Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. - -
    -
  • - -
  • - - New workstation - -
    May 2, 2022
    -
    - - I detail my new workstation build featuring the Intel i5-12600k. - -
    -
  • - -
  • - - 👋 Sparkbox - -
    April 1, 2022
    -
    - - I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. - -
    -
  • - -
  • - - Thirty five - -
    March 3, 2022
    -
    - - It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. - -
    -
  • - -
  • - - Windows 11 as KVM guest - -
    February 28, 2022
    -
    - - How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. - -
    -
  • - -
  • - - A few POSIX shell tips - -
    July 19, 2021
    -
    - - I wrote down a few of my most used POSIX shell commands and features. - -
    -
  • - -
  • - - Recently - -
    April 23, 2021
    -
    - - A random assortment of links and miscellaneous updates on things. - -
    -
  • - -
  • - - A firewall in 8 lines - -
    March 31, 2021
    -
    - - You only need about 8 lines in iptables to have a great home firewall. - -
    -
  • - -
  • - - How to use Siji font on polybar - -
    November 6, 2020
    -
    - -

    Nice guide on Reddit about how to use the Siji font with polybar.

    -
    -

    [..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

    -
    -

    Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

    - - 🔗 Permalink - -
    -
  • - -
  • - - On Polybar bitmap fonts and Ubuntu - -
    November 6, 2020
    -
    - - Enable bitmap fonts on Ubuntu for an optimal polybar experience. - -
    -
  • - -
  • - - Recently - -
    October 27, 2020
    -
    - - I've written a few small tools over the last couple months and I figured it's time I post about them. - -
    -
  • - -
  • - - Four ways to approach Hacktoberfest 2020 - -
    October 1, 2020
    -
    - - I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. - -
    -
  • - -
  • - - Small tech - -
    September 25, 2020
    -
    - -

    Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

    -
      -
    • -

      curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

      -
    • -
    • -

      git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

      -
    • -
    • -

      Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

      -
    • -
    • -

      sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

      -
    • -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Indexing My Blog’s Links - -
    September 25, 2020
    -
    - -

    Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Compose key and i3 - -
    September 18, 2020
    -
    - - Here's how to bind the compose key to caps lock in i3wm. - -
    -
  • - -
  • - - cycle v0.3.0 released - -
    September 11, 2020
    -
    - - Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. - -
    -
  • - -
  • - - Setting a default browser in i3 - -
    September 11, 2020
    -
    - - Using a desktop manager like GNOME makes setting default applications easy. However when using a tiling window manager like i3 setting a default application is opaque to the newbie such as myself. - -
    -
  • - -
  • - - Eight years - -
    September 4, 2020
    -
    - - Eight years ago I started working at Sparkbox. Thank you Sparkbox team for giving me an opportunity to work with ya'll and for making me a better developer and person. - -
    -
  • - -
  • - - Uses This / Zach Beane - -
    September 1, 2020
    -
    - -

    A great interview with the creator of Quicklisp, Zach Beane. I enjoy two things about this interview:

    -
      -
    1. The inclusion of outdoor/farming tools in the list of tools.
    2. -
    3. Zach’s conservative approach to languages and software tools.
    4. -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Openring - -
    August 21, 2020
    -
    - - I've added Drew DeVault's openring project to the blog. - -
    -
  • - -
  • - - A public inbox - -
    August 17, 2020
    -
    - - I'm going to give the idea of a public inbox as a place to have discussions about things on this website and elsewhere a shot. - -
    -
  • - -
  • - - Clear explanation of Rust’s module system - -
    July 19, 2020
    -
    - -

    This is a great explanation of Rust’s module system. I wish I had this clear of a picture when I was using modules for the first time in creating oscar.

    -

    The big takeaway and deviation from npm is this:

    -
    -

    We need to explicitly build the module tree in Rust, there’s no implicit mapping to file system.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Nothing speaks like a demo - -
    July 19, 2020
    -
    - -

    Great post from my friend and co-worker Bryan Braun on the value of demoing.

    -
    -

    It didn’t matter that his demos weren’t fully built, or available for anyone to use. We simply needed to see it, in order to understand.

    -
    -

    I find this is true for any kind of project: hobby or professional. Feedback — that elusive crucial ingredient to a good product — tends to arrive when someone else can see/hear/touch/examine what you’re working on.

    - - 🔗 Permalink - -
    -
  • - -
  • - - A new website for 2020 - -
    July 16, 2020
    -
    - -
    -

    According to my Cargo.lock file, my website currently depends on 364 crates. So it’s really about standing on the shoulder of a carefully-curated set of giants.

    -
    -
    -

    364 may seem like a lot (and in a way, it is), but please reserve your judgement until after you’ve heard about everything it does.

    -
    -

    I /love/ posts like this. Amos goes in deep on the decisions he made while re-writing his website from scratch. It’s a truly awesome post.

    -

    I’m seriously tempted to copy his SQLite full-text search implementation for this blog, but that’s a decision for another time.

    - - 🔗 Permalink - -
    -
  • - -
  • - - A Moment of Clarity Regarding the Raison d’Etre for the App Store - -
    July 13, 2020
    -
    - -
    -

    I’d like to see all the vim, vigor, and vigilance Apple applies to making sure no app on the App Store is making a dime without Apple getting three cents applied instead to making sure there aren’t any scams or ripoffs, and that popular apps support good-citizen-of-the-platform features within a reasonable amount of time after those features are introduced in the OS. I don’t know exactly how long “reasonable” is, but five fucking years for split-screen support ain’t it.

    -
    -

    I’ve been thinking the same thing ever since the Hey app rejection right before WWDC. The App Store is supposed to be a place to get software that has been vetted by Apple but there seems to be a growing disconnect between what users imagine that vetting is and what Apple is doing.

    -

    I want to believe this tweet by Ben Evans is the goal of the App Store:

    - -

    If we can trust the apps that come out of the App Store:

    -
      -
    • why is the US considering banning TikTok because of its rampant data collection?
    • -
    • why do we need a new notification in iOS 14 when apps query the clipboard?
    • -
    • why do we need a microphone/camera indicator at the system level?
    • -
    -

    Maybe I was naive and alone in my assumption that Apple would root this stuff out during the review process. If they’re not rooting this out then what is the point of the review process at all?

    - - 🔗 Permalink - -
    -
  • - -
  • - - GoatCounter web analytics - -
    July 1, 2020
    -
    - -
    -

    What seems to be lacking is a “middle ground” that offers useful statistics to answer business questions, without becoming a specialized marketing tool requiring in-depth training to use effectively. Furthermore, some tools have privacy issues (especially Google Analytics). I saw there was space for a new service and ended up putting my original idea in the freezer and writing GoatCounter.

    -
    -

    I agree 100% with this assessment and I’m excited about Goatcounter. I setup a free instance of Goatcounter for this site as a way to kick the tires on it. So far, I’m enjoying that it’s privacy respecting and doesn’t drag down page performance.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Is WebP really better than JPEG? - -
    June 30, 2020
    -
    - -
    -

    If you have used tools like Google’s PageSpeed Insights, you probably have run into a suggestion to use “next-gen image formats”, namely Google’s WebP image format. Google claims that their WebP format is 25 – 34% smaller than JPEG at equivalent quality.

    -
    -
    -

    In any case, when converting images to WebP, check that they are actually smaller than the JPEG equivalent. There’s no need to serve larger images to your users than needed.

    -
    -

    Great analysis of the WebP image format and a good reminder to not blindly follow what various auditing tools are reporting. Test and verify in addition to implementing the various suggested improvements.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Britain goes coal free as renewables edge out fossil fuels - -
    June 30, 2020
    -
    - -
    -

    Britain is about to pass a significant landmark - at midnight on Wednesday it will have gone two full months without burning coal to generate power.

    -
    -
    -

    A decade ago about 40% of the country’s electricity came from coal; coronavirus is part of the story, but far from all.

    -
    -

    This is fascinating. The UK has been aggressively investing in renewable energy sources for years and it appears all that investment is starting to catch up with demand.

    - - 🔗 Permalink - -
    -
  • - -
  • - - On George Floyd - -
    June 30, 2020
    -
    - - I haven't written anything here about George Floyd's murder. I still don't have a cogent response but here's what I've been mulling over. - -
    -
  • - -
  • - - flatkill - -
    June 15, 2020
    -
    - -
    -

    And it’s not only about these security problems. Running KDE apps in fakepak? Forget about desktop integration (not even font size). Need to input Chinese/Japanese/Korean characters? Forget about that too - fcitx has been broken since flatpak 1.0, never fixed since.

    -
    -
    -

    The way we package and distribute desktop applications on Linux surely needs to be rethinked, sadly flatpak is introducing more problems than it is solving.

    -
    -

    Flatpak is an emerging alternative way to install applications on Linux that is apparently rife with security and usability issues. This is a bummer because there’s lots of room in this space for improvement. The lack of multi-lingual input is especially egregious.

    - - 🔗 Permalink - -
    -
  • - -
  • - - FFMPEG: Convert multiple files using xargs - -
    June 4, 2020
    -
    - -

    I stumbled upon this post (Google cache link) when I was trying to process multiple files via xargs.

    -
    -

    ls *.webm | xargs -I % ffmpeg -i % %.m4a

    -
    -
    -

    The key part of this one-liner is xargs -i %. This means that each line of STDIN passed to xargs is put into a variable and can be referenced as %. Hence, the following text which specifies ffmpeg -i x.webm x.m4a to make it convert.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Using SQL to Look Through All of Your iMessage Text Messages - -
    May 28, 2020
    -
    - -
    -

    If you use iMessage on your Mac, you can access the SQLite database where all of your messages are stored. With a little setup, you can use SQL’s raw power to look through your old messages.

    -
    -

    via Simon Willison

    -

    In this post Dan Kelch walks through how to access the SQLite database that backs iMessage on a Mac. He also shares a few helpful SQL snippets to demonstrate how powerful using SQL on your text messages can be.

    - - 🔗 Permalink - -
    -
  • - -
  • - - macOS 10.15: Slow by Design - -
    May 28, 2020
    -
    - -

    A few days ago Allan Odgaard wrote up the reasons for the frequent slowdowns he’s experiencing in macOS Catalina and it’s shocking:

    -
    -

    Apple has introduced notarization, setting aside the inconvenience this brings to us developers, it also results in a degraded user experience, as the first time a user runs a new executable, Apple delays execution while waiting for a reply from their server. This check for me takes close to a second.

    -
    -
    -

    This is not just for files downloaded from the internet, nor is it only when you launch them via Finder, this is everything. So even if you write a one line shell script and run it in a terminal, you will get a delay!

    -
    -
    -

    I am writing this post to call attention to what I consider a serious design problem with Apple’s most recent OS where it appears that low-level system API such as exec and getxattr now do synchronous network activity before returning to the caller.

    -
    -

    Marco Arment hit the nail on the head with his tweet summary of the post:

    -
    -

    The macOS security team needs to ask themselves hard questions about their implementation choices when very smart people are disabling huge parts of their OS security layer just to get reasonable performance from common tasks.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Getting started with Rofi - -
    May 28, 2020
    -
    - - I've been using Rofi for about a year but didn't really understand how to write my own scripts for it until recently. In this post I explain what dmenu is and Rofi's implementation of it and also show how to change audio inputs on Linux via pactl. - -
    -
  • - -
  • - - What Time Is It in London? - -
    May 22, 2020
    -
    - -
    -

    Nilay Patel asked this of Siri on his Apple Watch. After too long of a wait, he got the correct answer — for London Canada. I tried on my iPhone and got the same result. Stupid and slow is heck of a combination.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Psychic Paper - -
    May 18, 2020
    -
    - -
    -

    RIP my very first 0day and absolute best sandbox escape ever:

    -
    -
    <key>application-identifier</key>
    -<string>...</string>
    -<!---><!-->
    -<key>platform-application</key>
    -<true/>
    -<key>com .apple.private.security.no-container</key>
    -<true/>
    -<key>task_for_pid-allow</key>
    -<true/>
    -<!-- -->
    -

    Tweet that demonstrates a recent zero-day (now patched) in iOS. This serves as your annual reminder that parsing xml-like things is a fraught activity.

    - - 🔗 Permalink - -
    -
  • - -
  • - - The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet - -
    May 18, 2020
    -
    - -
    -

    Janet Hutchins had the day off from her job as a nurse at a local hospital. She had been in town catching up with friends and had just gotten home and started making dinner. So she had only the slightest sense of the crisis that her colleagues had been dealing with across the NHS. That’s when her son came upstairs and told her, a little uncertainly, that he seemed to have stopped the worst malware attack the world had ever seen.

    -
    -
    -

    “Well done, sweetheart,” Janet Hutchins said. Then she went back to chopping onions.

    -
    -

    It’s hard to pick my favorite section from this article about Marcus Hutchins — the hacker who stopped the WannaCry malware attack.

    - - 🔗 Permalink - -
    -
  • - -
  • - - Second-guessing the modern web - -
    May 13, 2020
    -
    - -
    -

    The low performance parts don’t need to be React. Listing pages, static pages, blogs - these things are increasingly built in React, but the benefits they accrue are extremely narrow. A lot of the optimizations that are cropping up in these corners, things like bundle splitting, server-side rendering, and prerendering, are triangulating, essentially, what we had before the rise of React.

    -
    -

    This isn’t really about React but more about the over-engineering of large swaths of page-types and sites that used to “just work”. I love React and it’s been a giant leap forward for creating complex UIs on the web, that doesn’t mean it’s right for every situation.

    - - 🔗 Permalink - -
    -
  • - -
  • - - youtube-subscriptions - -
    May 8, 2020
    -
    - -

    I’ve been using youtube-subscriptions for a few months now and I really enjoy it. It’s described as a:

    -
    -

    terminal client to browse youtube subscriptions

    -
    -

    It’s great to quickly see any new videos right in the terminal and videos play via mpv or vlc!

    - - 🔗 Permalink - -
    -
  • - -
  • - - Hiking the Pacific Crest Trail in Three Minutes - -
    May 7, 2020
    -
    - -
    -

    The Pacific Crest Trail runs 2650 miles from the border of Mexico to the border of Canada through California, Oregon, and Washington. Hiking the whole thing usually takes months, but this video by Mac of Halfway Anywhere compresses the entire experience down to just three minutes presented in 1-second snippets.

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Introducing oscar - -
    April 29, 2020
    -
    - - I've been working on oscar which is a small command-line utility written in Rust that polls the pbskids.org API for new episodes of any PBS show. - -
    -
  • - -
  • - - Seamless branch deploys with Kubernetes - -
    April 27, 2020
    -
    - -

    A trait of good software is the ability to quickly see and verify changes:

    -
    -

    The result is what’s in-use today for HEY: a system that (almost) immediately deploys any branch to a branch-specific endpoint that you can access right away to test your changes without having to use the claims system or talk to anyone else (along with an independent job processing fleet and Redis instance to support the environment).

    -
    - - 🔗 Permalink - -
    -
  • - -
  • - - Three easy tuneups to fix video calls while working from home - -
    March 17, 2020
    -
    - - In light of COVID-19 and lots of folks working from home, I've written down the three things I try to tune on my home network to deliver the best possible video call experience. - -
    -
  • - -
  • - - ATR2100 - -
    January 29, 2020
    -
    - - I recently purchased the ATR2100 microphone and absolutely love it. - -
    -
  • - -
  • - - Understanding Rust Strings and str inside structs. - -
    January 8, 2020
    -
    - - Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here's a short breakdown of a compiler error message around Strings and ownership that stumped me for a bit. - -
    -
  • - -
  • - - Tweet stash - -
    December 12, 2019
    -
    - - Two tweets that I've had stuck in my tabs for _awhile_ and decided to stash them here. - -
    -
  • - -
  • - - Track redirects with curl - -
    October 22, 2019
    -
    - - I made a bash alias that takes a URL as an arguement and runs it through curl resuting in the Headers from each redirect, the final URL, and the number of redirects printed to the console. - -
    -
  • - -
  • - - The thing about computers - -
    September 21, 2019
    -
    - - Brent Simmons talks about what made computing so compelling and what we might be losing. - -
    -
  • - -
  • - - Dead Cells might be a perfect game - -
    September 20, 2019
    -
    - - Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it). - -
    -
  • - -
  • - - 0.14 - -
    July 30, 2019
    -
    - - I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn't worth it. - -
    -
  • - -
  • - - Solving busybox crond hanging on Alpine Linux boot - -
    May 5, 2019
    -
    - - How busybox crond hanging at startup sent me down a rabbit hole where I learned about entropy and Linux. - -
    -
  • - -
  • - - Introducing Cycle - -
    April 5, 2019
    -
    - - Cycle is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today. - -
    -
  • - -
  • - - Ajax and Rails - -
    January 28, 2019
    -
    - - This is just a short post to save a few links and document that "Server Javascript Responses" in Rails are still useful in 2018/19. - -
    -
  • - -
  • - - Blog rewrite - -
    November 20, 2018
    -
    - - I haven't posted here recently. That's largely because I did the classic "Time to rewrite the blog, I'll post when it's done" thing. Well it's not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I'm trying to rectify that now with some scant and scattered sentences. - -
    -
  • - -
  • - - Medium isn't a permanent fixture on the Internet - -
    May 21, 2018
    -
    - - If you're writing on the Internet and you aren't hosting (owning) your content you're work will disappear; it's just a matter of time. - -
    -
  • - -
  • - - Hosting assets via Github Pages - -
    May 11, 2018
    -
    - - Screenshots in README.mds are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult. - -
    -
  • - -
  • - - Pinboard popular page in Emacs - -
    April 26, 2018
    -
    - - A quick look at how I made an Ivy extension that displays the links from the pinboard.in popular page - -
    -
  • - -
  • - - Emacs lite - -
    April 19, 2018
    -
    - - A small, friendly starting point for Emacs. - -
    -
  • - -
  • - - Hello micro.blog - -
    February 1, 2018
    -
    - - Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting. - -
    -
  • - -
  • - - Apple on batteries and performance - -
    December 28, 2017
    -
    - - Apple released a statement on the battery and performance issues. - -
    -
  • - -
  • - - Git worktree - -
    December 11, 2017
    -
    - - What the heck is git-worktree? - -
    -
  • - -
  • - - Messi is re-writing the record book - -
    December 2, 2017
    -
    - - In a fantastic video the YouTube channel MagicalMessi documents all the various records that Messi has broken during his illustrious career. - -
    -
  • - -
  • - - Introducing ivy-feedwrangler - -
    November 16, 2017
    -
    - - In exploring what Ivy was capable of I had the idea to write a small package that used Ivy as the interface for my RSS service of choice, Feedwrangler. - -
    -
  • - -
  • - - A Hackintosh - -
    September 14, 2017
    -
    - - I built a PC in May to replace my Xbox One (yay no more Live fees!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh. - -
    -
  • - -
  • - - On Equifax - -
    September 8, 2017
    -
    - - I don't do many link posts but Ian Bogost sums up my feelings perfectly about the Equifax breach. - -
    -
  • - -
  • - - Before Circles 2017 - -
    September 6, 2017
    -
    - - I thought I'd list out a few of the talks I'm looking forward to and what I hope to come away with. - -
    -
  • - -
  • - - Five years - -
    September 5, 2017
    -
    - - Five years is a long time, especially working on the internet, and I've loved every stinking minute of it. - -
    -
  • - -
  • - - On diminishing modes in emacs - -
    August 17, 2017
    -
    - - An explanation of how to change or diminish major and minor modes in emacs - -
    -
  • - -
  • - - From helm to ivy - -
    August 14, 2017
    -
    - - A log of my experience switching from helm to ivy; two completion plugins for emacs. - -
    -
  • - -
  • - - The era of the screenshot - -
    June 12, 2017
    -
    - - We really couldn't have picked a worse data exchange format. - -
    -
  • - -
  • - - Format JSON in emacs - -
    May 23, 2017
    -
    - - I wrote an elisp function to yank JSON off my clipboard, prettify it. - -
    -
  • - -
  • - - Diceware - -
    April 19, 2017
    -
    - - Glenn Fleishman recently linked to a method for generating passphrases called Diceware. Being a fan of dice (d20 for life) I thought this was super cool and worth sharing. - -
    -
  • - -
  • - - Facetime Killer - -
    April 3, 2017
    -
    - - I made an app, VDCAssistant-Killer, to restart the process that manages the Facetime camera on your Mac. - -
    -
  • - -
  • - - What happens when you remove friction - -
    March 27, 2017
    -
    - - When you remove friction from a process or task, all the factors change. This seems obvious, but it's fundamental to understanding the world as it currently is. - -
    -
  • - -
  • - - Emacs tips - -
    March 27, 2017
    -
    - - A evolving collection of emacs tips aimed at someone starting out with emacs and evil-mode. - -
    -
  • - -
  • - - Be a good video call citizen - -
    March 17, 2017
    -
    - - I've been in my fair share of video calls and I thought I'd share a few tricks that help limit my contributions to the chaos. - -
    -
  • - -
  • - - Thirty - -
    March 2, 2017
    -
    - - Today I turn 30. So here is a list of 30 things I've learned in the last year (or so). - -
    -
  • - -
  • - - Lambda Talk - -
    February 23, 2017
    -
    - - Last week I gave a talk at GemCityJS about going serverless with AWS Lambda. - -
    -
  • - -
  • - - We all need a team - -
    June 28, 2016
    -
    - - We all need a team. On the right team we can go higher and be better than we ever thought we could. - -
    -
  • - -
  • - - Web scraper cookbook - -
    February 20, 2016
    -
    - - I've been on a web scraping tear lately. So, I thought I'd compile what I've learned and put together a repo as a howto/cookbook/guide thing. - -
    -
  • - -
  • - - How do we make the Web better - -
    January 29, 2016
    -
    - - My post for the Shift for January. I tackle the question within the question: how do we (internet workers) have more meaningful conversations in order to make the web better? - -
    -
  • - -
  • - - Command line notification - -
    January 16, 2016
    -
    - - This week I wrote a bash function that curls the SendGrid API and sends a Boxcar notification. - -
    -
  • - -
  • - - Verse Recall - -
    December 23, 2015
    -
    - - Whew, time to share something with the world I haven't really talked about online at all, my first and only (so far) iOS app. - -
    -
  • - -
  • - - SQLite Tips - -
    December 20, 2015
    -
    - - I've been playing around with SQLite recently and I've stumbled across a few things I want to remember, so I'm putting them here. - -
    -
  • - -
  • - - On Webpack - -
    December 7, 2015
    -
    - - I wrote a love letter to Webpack over on the Foundry. - -
    -
  • - -
  • - - Migrate an existing build process to npm scripts - -
    October 18, 2015
    -
    - - Not all projects need Grunt or Gulp, npm is a great build tool by itself. I recently replaced a Grunt task (with multiple plugins) with a npm script task. - -
    -
  • - -
  • - - CasperJs, Node, and the Raspberry Pi - -
    October 10, 2015
    -
    - - I've been working on getting my Raspberry Pi to be a dedicated screen-scraping machine with CasperJS and Node. -This post is intended to be a log for myself and hopefully a helpful resource for others. - -
    -
  • - -
  • - - AMP HTML, Terrible HTML - -
    October 8, 2015
    -
    - - Is the answer developing a subset of HTML/JS/CSS? - -
    -
  • - -
  • - - Farewell Heroku - -
    October 6, 2015
    -
    - - I've migrated my apps off Heroku and won't be using the service for personal apps going forward. - -
    -
  • - -
  • - - Parsing memory usage in htop/top - -
    October 4, 2015
    -
    - - I've been trying to figure out how much memory a node app is using on my VPS, and I've found output from top or htop to be overwhelming. - -
    -
  • - -
  • - - Three years - -
    September 4, 2015
    -
    - - The adventure is just getting started. - -
    -
  • - -
  • - - What is Medium? - -
    August 27, 2015
    -
    - - I'm curious to see how Medium continues to evolve. - -
    -
  • - -
  • - - Small things - -
    August 22, 2015
    -
    - - Recently I've come to love MicroJS. I love that I can find tiny, specific libraries that do one thing, and do it well - -
    -
  • - -
  • - - Automating SOCKS proxy - -
    August 8, 2015
    -
    - - I've used a SOCKS proxy while on public WiFi ever since reading Paul Stamatiou's article years ago. I only recently took the time to automate the process. - -
    -
  • - -
  • - - The Stream hasn't won - -
    July 17, 2015
    -
    - - Hossein Derakhshan outlines how the web as he knew it has disappeared and been replaced by "The Stream", or social media. His post is beautifully written and I highly recommend reading it. - -
    -
  • - -
  • - - Microblogging - -
    June 25, 2015
    -
    - - My microblogging setup with Twilio, Twitter, SMS, and WordPress. - -
    -
  • - -
  • - - Learning to think in React - -
    June 8, 2015
    -
    - - I outline how I built my blog using React and the WordPress API. This post covers isomorphic app structure and data flow in React with React-Router. - -
    -
  • - -
  • - - Moving away from Google - -
    June 1, 2015
    -
    - - I recently started using DuckDuckGo and Fastmail. So I thought I'd share a few thoughts on both services. - -
    -
  • - -
  • - - Benedict Evans is on fire - -
    May 18, 2015
    -
    - - Benedict Evan's last three pieces are right on the money regarding mobile, and the web versus native apps. - -
    -
  • - -
  • - - Web performance and Facebook's Instant Articles - -
    May 13, 2015
    -
    - - Crafting a high-performing web experience for mobile is not easy, but it's not so impossibly hard that Facebook's Instant Articles is the only solution. - -
    -
  • - -
  • - - Google Fi and data only plans - -
    April 30, 2015
    -
    - - Why doesn't Google just offer data? There already is already a fantastic data-only plan in America, and it's on T-Mobile. - -
    -
  • - -
  • - - iPhone checker with Capybara and Twilio - -
    October 30, 2014
    -
    - - I set up a small Heroku app that uses Capybara to check Apple's website for availability and sends a text to my phone via Twilio. - -
    -
  • - -
  • - - Vim Ramblings - -
    June 27, 2014
    -
    - - So, in the past 6 months I've switched from Sublime Text to Vim. Here are some good articles and tips on Vim. - -
    -
  • - -
  • - - S3 Security Policy - -
    April 26, 2014
    -
    - - A basic AWS S3 bucket policy that restricts access to a single bucket, and allows access via the AWS cli. - -
    -
  • - -
  • - - Keeping up - -
    April 8, 2014
    -
    - - Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week - -
    -
  • - -
  • - - Broadcast channel - -
    April 8, 2014
    -
    - - Along with the move to Siteleaf I've also set up an App.net Broadcast channel. - -
    -
  • - -
  • - - Moved to Siteleaf - -
    March 31, 2014
    -
    - - I moved to Siteleaf from Jekyll - -
    -
  • - -
  • - - Git Commit Template - -
    August 22, 2013
    -
    - - Set up a Git commit message template - -
    -
  • - -
  • - - ADN Cross-poster - -
    August 15, 2013
    -
    - - How to set up your own App.net to Twitter cross-posting app. - -
    -
  • - -
  • - - IFTTT - -
    July 21, 2013
    -
    - - Ways I use IFTTT. App.net to Twitter, App.net from Day One, and Camera Roll to FLickr. - -
    -
  • - -
  • - - JS2Coffee Alfred Workflow - -
    July 8, 2013
    -
    - - An Alfred workflow that converts Javascript to Coffeescript - -
    -
  • - -
  • - - Huffduffer - -
    July 6, 2013
    -
    - - Use Huffduffer to listen to individual podcast episodes. - -
    -
  • - -
  • - - Slanted Elements with CSS3 - -
    April 21, 2013
    -
    - - How to use CSS3 transforms to work with slanted elements - -
    -
  • - -
  • - - A Fluid Userscript that adds Read it Later to Twitter - -
    March 24, 2013
    -
    - - A simple Fluid userscript that adds a Read it Later button for Instapaper to any tweet containing a link - -
    -
  • - -
  • - - Rename utility - -
    February 13, 2013
    -
    - - A short primer on the rename command line utility. - -
    -
  • - -
  • - - What Matters - -
    January 10, 2013
    -
    - - A great quote from a post over at 37 signals. - -
    -
  • - -
  • - - Andy Budd on Time - -
    January 10, 2013
    -
    - - Great quote by Andy Budd on the value of time - -
    -
  • - -
  • - - IP Address Alfred Extension - -
    December 7, 2012
    -
    - - I enhance the previous IP bash function as an Alfred Extension - -
    -
  • - -
  • - - Bash Function - IP Address to Clipboard - -
    December 5, 2012
    -
    - - A quick post explaining a command line function to copy your IP address to your clipboard - -
    -
  • - -
  • - - A few Bash Tips - -
    November 20, 2012
    -
    - - A rundown of some of my most used bash and terminal commands and functions. - -
    -
  • - -
  • - - Rands on Email - -
    October 21, 2012
    -
    - - A fantastic post from Michael Lopp. - -
    -
  • - -
  • - - Lyza Gardner on Laying Down our Burdens - -
    October 21, 2012
    -
    - - Another great article from Lyza Gardner. - -
    -
  • - -
  • - - Family First - -
    October 21, 2012
    -
    - - Chris Bowler weighs in with some fantastic advice for those who have families. - -
    -
  • - -
  • - - Alfred and Web Development - -
    October 11, 2012
    -
    - - A quick tip on using Alfred in Web Development - -
    -
  • - -
  • - - Theme the Chrome Dev Tools - -
    October 9, 2012
    -
    - - A short post on how to theme the Chrome Dev Tools - -
    -
  • - -
  • - - Moving Tweetbot Beta to a new Mac - -
    September 21, 2012
    -
    - - How to migrate Tweetbot Beta to a new Mac. - -
    -
  • - -
  • - - Heroku and SSH Keys - -
    September 21, 2012
    -
    - - Quick solution to fixing Heroku SSH key errors using ssh config. - -
    -
  • - -
  • - - I moved to Hover - -
    September 9, 2012
    -
    - - I switched from GoDaddy to Hover. - -
    -
  • - -
  • - - How are you living - -
    September 6, 2012
    -
    - - Shawn Blanc poses some tough questions about life and purpose - -
    -
  • - -
  • - - A New Adventure - -
    September 3, 2012
    -
    - - Today I started working at Sparkbox as Front-End Dev. - -
    -
  • - -
  • - - When the Music Stops - -
    August 23, 2012
    -
    - - Dave Winer has a great post on what happens when a service disappears. - -
    -
  • - -
  • - - Tigers and Social Networks - -
    August 21, 2012
    -
    - - A response to Charlie Pratt's blog post about the problem of social networks and catering to the crowd - -
    -
  • - -
  • - - Blogs, data, and social networks - -
    August 19, 2012
    -
    - - I bring together a few different voices to illustrate the argument for blogs, open data, and open social networks. - -
    -
  • - -
  • - - Maybe you should…it's not you…move on. - -
    August 16, 2012
    -
    - - A collection of reactions to how Twitter muddled there recent API announcement. - -
    -
  • - -
  • - - Rotten Tomatoes and Launch Center - -
    August 13, 2012
    -
    - - Hack together a faster Rotten Tomatoes experience on the iPhone - -
    -
  • - -
  • - - Working with Wordpress, offset and pagination - -
    August 10, 2012
    -
    - - A code snippet to have posts offset and have pagination work. - -
    -
  • - -
  • - - Plaintext and Markdown - A Primer - -
    August 8, 2012
    -
    - - A quick introduction to the beauty of plaintext and the Markdown syntax - -
    -
  • - -
  • - - Gists, Snippets, and Sublime Text 2 - -
    August 6, 2012
    -
    - - How I now use Gists instead of snippets in Sublime Text 2. - -
    -
  • - -
  • - - Kyle Steed on rest - -
    August 3, 2012
    -
    - - Fantastic article by Kyle Steed on work, rest, and life - -
    -
  • - -
  • - - Convince the Boss - -
    August 2, 2012
    -
    - - Jeremy Keith on convincing bosses to adopt new web standards. - -
    -
  • - -
  • - - Create Passion - -
    August 2, 2012
    -
    - - Tiffani Jones Brown talks about passion in volume 3 of The Manual - -
    -
  • - -
  • - - Using the Kindle to harness the Web - -
    August 1, 2012
    -
    - - how I use Readability’s Kindle bookmarklet to harness the web. - -
    -
  • - -
  • - - Simple Account Set-up - -
    August 1, 2012
    -
    - - Simple does account set-up right. - -
    -
  • - -
  • - - The Future is Prototyping - -
    July 31, 2012
    -
    - - A fantastic quote from a fantastic article over at Big Spaceship - -
    -
  • - -
  • - - Story - -
    July 26, 2012
    -
    - - The importance of story in products, design, and development. - -
    -
  • - -
  • - - Guidelines for Data - -
    July 26, 2012
    -
    - - The guidelines for data and how it pertains to Wordpress - -
    -
  • - -
  • - - What's best for the readers - -
    July 24, 2012
    -
    - - Jonah Peretti's letter to employees and investors of Buzzfeed. - -
    -
  • - -
  • - - What it's all about - -
    July 23, 2012
    -
    - - Jonathan Christopher hits the nail on the head - -
    -
  • - -
  • - - Sparrow and the App Store - -
    July 23, 2012
    -
    - - App Cubby's take on Google's acquisition of Sparrow - -
    -
  • - -
  • - - CSS Reusability - -
    July 23, 2012
    -
    - - How much CSS am I reusing? - -
    -
  • - -
  • - - A Little Hydrofoil - -
    July 23, 2012
    -
    - - Robin Sloan's description of a programmer. - -
    -
  • - -
  • - - The Web is Not Print - -
    July 22, 2012
    -
    - - The infamous Zeldman dishses on the web and print - -
    -
  • - -
  • - - Declining Expectations - -
    July 22, 2012
    -
    - - Matthew Butterick's talk on declining expectations. - -
    -
  • - -
  • - - Someone is working harder than you - -
    July 19, 2012
    -
    - - Hard work and how to be creative - -
    -
  • - -
  • - - Just Start Over - -
    July 19, 2012
    -
    - - Sebastiaan De With describes his design process for doubleTwist's Alarm Clock - -
    -
  • - -
  • - - A Style Guide, Guide - -
    July 19, 2012
    -
    - - Elyse Holladay reveals her style guide guide. - -
    -
  • - -
  • - - Zen Garden Part 2? - -
    July 18, 2012
    -
    - - Is it time for a Return to the CSS Zen Garden? Rick Monro thinks Responsive Web Design needs it. - -
    -
  • - -
  • - - Pretty Git log - -
    July 18, 2012
    -
    - - Handy tip for pretty git logs. - -
    -
  • - -
  • - - Grow it, don't build it - -
    July 18, 2012
    -
    - - Growing software versus building it - -
    -
  • - -
  • - - Evening Edition - -
    July 18, 2012
    -
    - - The Evening Edition is a great little resource - -
    -
  • - -
  • - - Balancing Devotion - -
    July 17, 2012
    -
    - - Is it possible to create an extraordinary product and have a healthy life outside of that proudct? - -
    -
  • - -
  • - - The web, and my goal - -
    July 12, 2012
    -
    - - Thought from the Pastry Box Project's Bruce Lawson. - -
    -
  • - -
  • - - Nginx www rewrite - -
    July 12, 2012
    -
    - - How to rewrite www to non-www in Nginx - -
    -
  • - -
  • - - My First Bookmarklet - -
    July 12, 2012
    -
    - - My first bookmarklet, an ESPN Insider paywall - -
    -
  • - -
  • - - The Wordpress HTTP API is Awesome - -
    June 28, 2012
    -
    - - The title says it all. I completely forgot about the Wordpress HTTP API until today. - -
    -
  • - -
  • - - Adam versus Dropbox and oAuth - -
    June 25, 2012
    -
    - - Adam versus Dropbox and oAuth. Frustration post incoming regarding curl, php, and oAuth. - -
    -
  • - -
  • - - The Manhattan Project Time-Lapse - -
    June 24, 2012
    -
    - - An incredible time-lapse of Manhattan - -
    -
  • - -
  • - - Hello World - -
    June 24, 2012
    -
    - - I'm proud, nervous, and a little surprised that adamsimpson.net is finally live! - -
    -
  • - -
-
- -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/post/rss.xml b/themes/cycle/exampleSite/public/post/rss.xml deleted file mode 100644 index e3fe928..0000000 --- a/themes/cycle/exampleSite/public/post/rss.xml +++ /dev/null @@ -1,738 +0,0 @@ - - - adamsimpson.net Post Feed - https://adamsimpson.net/ - Last 20 posts for adamsimpson.net - Thu, 09 Oct 2025 21:22:39 +0000 - en-us - - nixpkgs is a treasure - https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ - - https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ - Fri, 10 May 2024 14:07:43 -0400 - - <![CDATA[ Nix and NixOS continue to be the best way to manage and build software that I've found. ]]> - - <![CDATA[ -

Nix and NixOS continue to be the best way to manage and build software that I’ve found. Every project has a shell.nix file in the root where I can define the specific software needed to work on that project along with any necessary environment variables or $PATH modifications. I ran into an issue this week though where I needed an “old” version of Go (1.20) but the version had already been removed from nixpkgs. How can I pull in an “unlisted” version into my shell.nix?

-

It’s actually pretty straightforward, utilize fetchTarball to pull in nixpkgs based on a commit where the version was present sometime in the past. You can mix that import in with regular/“current” packages with no issue like so:

-
{ pkgs ? import <nixpkgs> {} }:
-
-let oldGo = import (builtins.fetchTarball {
-    url = "https://github.com/NixOS/nixpkgs/archive/33c51330782cb486764eb598d5907b43dc87b4c2.tar.gz";
-    sha256 = "sha256:0nflmpfp3pk704vhlvlgh5vgwl8qciqi18mcpl32k79qjziwmih8";
-    }) {};
-in 
-
-pkgs.mkShell {
-  buildInputs = [
-    oldGo.go_1_20
-    pkgs.gopls
-    pkgs.nodejs_18
-  ];
-  
-  hardeningDisable = [ "fortify" ];
-
-  shellHook = ''
-    mkdir -p .go .npm
-    export GOPATH=$PWD/.go
-    export NODE_PATH=$PWD/.npm
-    export NPM_CONFIG_PREFIX=$NODE_PATH
-    export PATH=$PWD/.yarn/sdks/typescript/bin:$PWD/.go/bin:$PATH:$NODE_PATH/bin
-  '';
-}
-

Notice I can reference the “nixpkgs” tarball/snapshot, oldGo, and pull in the version of Go I need?! nixpkgs is such a treasure trove of software, it’s absolutely incredible!

- - Discuss further in my public inbox - ]]>
-
- - Lessons learned from integrating OpenAI into a Grafana data source - https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ - - https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ - Tue, 25 Jul 2023 15:10:24 -0400 - - <![CDATA[ I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! ]]> - - <![CDATA[ -

I wrote over on the Grafana blog about a few lessons or observations we learned while integrating OpenAI into the ADX data source. It’s my first post on the Grafana blog and I’m pretty excited, so check it out!

- - Discuss further in my public inbox - ]]>
-
- - Better scripting with gh - https://adamsimpson.net/writing/better-scripting-with-gh/ - - https://adamsimpson.net/writing/better-scripting-with-gh/ - Sat, 22 Jul 2023 11:33:16 -0400 - - <![CDATA[ I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. ]]> - - <![CDATA[ -

I’ve become a big fan of the gh CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. Instead of using curl with a Github token and the Github API, I can simply use gh. What’s even better is that in more advanced situations where there isn’t a valid subcommand for what I want to script, I can use the gh api escape hatch to do curl-style HTTP requests to the API without messing with authentication or even pagination. Here are two recent scripts I wrote that highlight the power and convenience of gh.

-

PR Kudos

-

I created this script to help me give better kudos to folks in our retro meeting. When I provide a Github team name as an argument, it displays all PRs from members of that team. What I really like is that it only shows PRs from the last two weeks, which gives me a nice overview of recent activity.

-
#!/bin/bash
-
-start=$(date -d "2 weeks ago" +%Y-%m-%d)
-end=$(date +%Y-%m-%d)
-
-details=$(gh api /orgs/grafana/teams/$1 | jq -r '"\(.id),\(.organization.id)"')
-teamId=$(echo ${details} | cut -d , -f 1)
-orgId=$(echo ${details} | cut -d , -f 2)
-
-gh api "organizations/${orgId}/team/${teamId}/members" | \
-  jq -r '.[] | .login' | \
-  xargs -I % gh search prs --author=% --created="${start}..${end}" \
-  --json="state,repository,url,title,updatedAt,author" --template '{{range .}}{{tablerow (.author.login | autocolor "green") (hyperlink .url .title) (.repository.name | autocolor "blue") (.state | autocolor "red") (timeago .updatedAt)}}{{end}}
-{{tablerender}}'
-

Notification OCD

-

The second script focuses on managing notifications related to pull requests and issues. I usually find that about one-third of my notifications are for merged PRs, PRs created by bots, or closed Issues. I don’t care about these types of events. With this script, I can mark those notifications as done, which reduces clutter in my GitHub notifications and helps me see important updates. As I mentioned above, one cool feature of the api subcommand is that it allows me to consume all possible pages of a response using the --paginate flag, eliminating the need for a loop + token field dance!

-
#!/bin/bash
-declare -A typeLookup
-typeLookup["PullRequest"]="pull"
-typeLookup["Issue"]="issues"
-
-resp=$(gh api /notifications --paginate | jq -r '.[] | select(.subject.type == "PullRequest" or .subject.type == "Issue") | "\(.repository.full_name),\(.subject.url),\(.id),\(.subject.type)"')
-
-for x in $resp; do
-  name=$(echo "${x}" | cut -d ',' -f 1)
-  id=$(echo "${x}" | cut -d ',' -f 3)
-  number=$(basename $(echo "${x}" | cut -d ',' -f 2))
-  ofType=$(echo "${x}" | cut -d ',' -f 4)
-  urlType=$(echo ${typeLookup["${ofType}"]})
-  isBot="false"
-
-  if [ "${ofType}" == "PullRequest" ]; then
-    isMerged=$(gh pr view --repo "${name}" "${number}" --json closed | jq -r .closed)
-    isBot=$(gh pr view --repo "${name}" "${number}" --json author | jq -r .author.is_bot)
-  fi
-
-  if [ "${ofType}" == "Issue" ]; then
-    isMerged=$(gh issue view --repo "${name}" "${number}" --json closed | jq -r .closed)
-  fi
-
-  if [ "${isMerged}" == "true" ] || [ "${isBot}" == "true" ]; then
-    echo "marking https://github.com/${name}/${urlType}/${number} as done..."
-    gh api -X PATCH "/notifications/threads/${id}"
-  fi
-done
-
- Discuss further in my public inbox - ]]>
-
- - End of an era - https://adamsimpson.net/writing/end-of-an-era/ - - https://adamsimpson.net/writing/end-of-an-era/ - Thu, 15 Jun 2023 14:13:50 -0400 - - <![CDATA[ Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. ]]> - - <![CDATA[ -

Today I removed two of my most-used apps on my phone, Apollo and Tweetbot. It feels like the end of an era.

-

Twitter and Reddit were both social websites that are/were terrible without a lot of cultivation and effort, but over the years I had shaped my experience on those services to be pretty good thanks in large part to Apollo and Tweetbot being such powerful tools.

-

Ironically the only social web thing I still use (outside of Instagram) is RSS. I will probably spin up a Mastodon instance here eventually but for now I’ve subscribed to folks via Mastodon’s RSS support and it’s good enough for now.

-

I guess I just wanted to give a shout out to the devs of Apollo and Tweetbot: thank you for making such great apps, I will miss them.

- - Discuss further in my public inbox - ]]>
-
- - Hacking on Grafana with Web Assembly - https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ - - https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ - Fri, 19 Aug 2022 15:10:19 -0400 - - <![CDATA[ Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. ]]> - - <![CDATA[ - -

The original inspiration for this idea came from Simon Willison’s work with Datasette Lite. However, compiling Grafana as a WASM binary proved difficult with existing build constraints. After spending some time trying to get that to work I changed course a bit and instead focused on compiling a basic go HTTP server as a WASM module. The new goal being to have a proof of concept that bundled the HTTP server as a WASM binary and intercepted any clicked links on the page and finally passed those links to be resolved by the go server in WASM.

-

I used a Web Worker to interact with the WASM binary. This frees up the main thread of the browser. To put the WASM binary into the worker I loaded the binary and sent a message that contained the binary as a WebAssembly.Module.

-

The Web Worker can then call any go functions that have been exposed via FuncOf. Once the go function returns data, the worker posts that response back to the main thread via another message.

-
let module;
-importScripts("wasm_exec.js")
-go = new Go();
-
-self.onmessage = async (e) => {
-  if (e.data.type === "module") {
-    module = e.data.module;
-    return;
-  }
-
-  if (module) {
-    console.log('Message received: ', e.data.path);
-    const instance = await WebAssembly.instantiate(module, go.importObject);
-    go.run(instance);
-    postMessage(parsePath(e.data.path)); // parsePath is exposed via FuncOf
-  }
-}
-

Sidenote: I wish go could use the same pragma syntax tinygo uses to expose functions instead of the verbose FuncOf. There’s an issue but it has been open since 2018.

-

Obviously, there is no localhost to listen on in a WASM environment. To get around that I created a bare bones ResponseWriter and used that with the Request to run the Handler’s ServeHTTP function which consults the routes that are defined and runs the matching handler code. This allowed me to use a build constraint (setup.go and setup_js.go) and keep my HTTP server functioning normally when run from a terminal but then also worked when run in a WASM context. Here’s what those two files look like:

-

setup

-
//go:build !js
-// +build !js
-
-package main
-
-import (
-	"fmt"
-	"net/http"
-)
-
-func setup() {
-	s := NewServer()
-	err := http.ListenAndServe(":9001", s.mux)
-	if err != nil {
-		fmt.Println("error: ", err)
-	}
-}
-

setup_js

-
package main
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"syscall/js"
-)
-
-type ResponseWriter struct {
-	Body *bytes.Buffer
-}
-
-func (r ResponseWriter) Header() http.Header {
-	return make(http.Header)
-}
-
-func (r ResponseWriter) Write(buf []byte) (int, error) {
-	if r.Body != nil {
-		r.Body.Write(buf)
-	}
-	return len(buf), nil
-}
-
-func (r ResponseWriter) WriteHeader(statusCode int) {}
-
-func createWriter() ResponseWriter {
-	return ResponseWriter{
-		Body: new(bytes.Buffer),
-	}
-}
-
-func parsePath(this js.Value, args []js.Value) interface{} {
-	fmt.Println("args: ", args)
-	server := NewServer()
-	path := args[0].String()
-	req, err := http.NewRequest(http.MethodGet, path, nil)
-
-	if err != nil {
-		fmt.Println("request error: ", err)
-	}
-
-	h, p := server.mux.Handler(req)
-
-	fmt.Println("pattern: ", p)
-
-	w := createWriter()
-
-	h.ServeHTTP(w, req)
-
-	b, err := ioutil.ReadAll(w.Body)
-
-	if err != nil {
-		fmt.Println("ioutil error: ", err)
-	}
-
-	return string(b)
-}
-
-func setup() {
-	js.Global().Set("parsePath", js.FuncOf(parsePath))
-}
-

Conclusions

-

The PoC worked! It’s pretty slick to see a HTTP server running in WASM return back the correct data when a link is clicked. However, in my opinion, WASM continues to be a “solution in search of a problem”. Yes it’s incredibly cool technology but so are the JS engines in Chrome, Firefox, and Safari. The sheer amount of money and engineering time being spent on making JS fast is a race no other technology can win at the moment.

-

That said, Go seems to have done decent work at providing the necessary pieces to make compiling to WASM not awful.

-

Honestly, the thing that surprised and impressed me the most was working with Web Workers. They are seriously useful and seem to “just work”.

- - - - Discuss further in my public inbox - ]]>
-
- - New workstation - https://adamsimpson.net/writing/new-workstation/ - - https://adamsimpson.net/writing/new-workstation/ - Mon, 02 May 2022 18:14:25 +0000 - - <![CDATA[ I detail my new workstation build featuring the Intel i5-12600k. ]]> - - <![CDATA[ -

New job means time for a new workstation.

-

Some history

-

The first computer I ever purchased was the 12" Powerbook G4. Since that Powerbook I’ve always had laptops as my main machines (desktop gaming PC not withstanding). Remote working the last few years has made me realize that the portability of a laptop is largely wasted since I only travel a handful of times a year and yet I live with the downsides of a laptop the rest of the time. So, last year I started thinking about a desktop machine for my primary workstation. A desktop is appealing for a handful of reasons:

-
    -
  • More powerful CPUs
  • -
  • More expansion capabilities
  • -
  • More durable
  • -
-

The options

-

The Mac Studio was recently released to much fanfare and was really intriguing to me. However, when I started considering it I only had about a week to 10 days before my start date at Grafana and I couldn’t wait the quoted 4-6 weeks delivery time for a Mac Studio with 32GB of RAM.

-

I was also pretty unwilling to leave my comfy NixOS install + i3. Michael Stapelberg’s latest post about his new workstation proved timely and convinced me to give the new Intel Alder Lake CPUs a shot.

-

Apple’s M1 family of chips deliver incredible performance per watt but I wasn’t as concered about the power usage given this was a desktop machine not a laptop. I was however focused on at least matching the M1 chips in single-threaded performance since a good chunk of my development work (Node, build tools, etc) are still single-threaded. I ended up with the Intel i5-12600k and I really couldn’t be happier. Here’s the full parts list:

- -

XMP issues

-

I ran into the same memory XMP issues that Michael mentions in his post so I disabled the XMP profile and the system passed the “Coding Horror burn in tests” with flying colors.

-

Cooling

-

I mounted the 140mm fan to the bottom of the case as intake and the CPU cooler is of course positioned as intake as well. Hot air rises out the top of the case quite well. During the prime95 torture test the CPU never got over 78°C and I couldn’t ever hear either fan. I run both fans in the “silent profile” in the BIOS and I use Noctua’s adapters to lower the voltage even more. Now the only fan I could hear during max load was the PSU fan which doesn’t spin at all under low to medium loads but under high load it kicks on. Day to day it’s hardly on so the system is dead quiet most of the time.

-

Case

-

I absolutely love the Cerberus case. It’s Mini-ATX but still super compact and fits on my desk quite well. All the panels are solid metal and the way all the panels pop off is really really nice. I opted for the handle mount on the top and the internal PSU moutning.

-

Linux

-

NixOS installed just fine. I’m runing the 5.17 kernel because Alder Lake needs a newer kernel for it’s graphics and CPU scheduler (coming soon?). I have WiFi and Bluetooh disabled in the BIOS since everything is hard-wired to the machine.

-

Verdict

-

This build has proven quite comfortable over the few weeks I’ve used it. I love that I have 2 free RAM slots if I ever feel the need for more RAM. I also love that I have 3 remaining Nvme slots on the motherboard for additional solid state storage in the future.

- - Discuss further in my public inbox - ]]>
-
- - 👋 Sparkbox - https://adamsimpson.net/writing/goodbye-sparkbox/ - - https://adamsimpson.net/writing/goodbye-sparkbox/ - Fri, 01 Apr 2022 18:20:31 +0000 - - <![CDATA[ I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. ]]> - - <![CDATA[ -

I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox.

-

Now, I know it can be problematic to think about work like your (extended) family but when you work at the same place through your twenties and early thirties, have 3 different apartments, buy a house, and have two kids it’s impossible not to view that place differently. I can confidently say Sparkbox changed my life. The team there will always have a special place in my heart.

-

deep breath

-

So where to? Well, I’m super stoked to be joining Grafana as a Senior Software Engineer on their Cloud Data team! I’m looking forward to writing more Go, solving new problems, and learning from the stellar folks there.

-

Here we go…

- - Discuss further in my public inbox - ]]>
-
- - Thirty five - https://adamsimpson.net/writing/thirty-five/ - - https://adamsimpson.net/writing/thirty-five/ - Thu, 03 Mar 2022 10:28:44 -0500 - - <![CDATA[ It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. ]]> - - <![CDATA[ -

Well crap.

-

It’s been 5 years since I wrote “Thirty”. So now I have to come up with 35 things as I turned 35 yesterday. If anything from Thirty is grossly wrong or really interesting I’ll update it at the same number eh?

-

Let’s go…

-
    -
  1. I still don’t have it figured out, but this isn’t such a shock anymore.
  2. -
  3. Building a house is more scary.
  4. -
  5. Minivans are awesome.
  6. -
  7. Expecting a third kid is not nearly as scary as expecting the first.
  8. -
  9. COVID sucked.
  10. -
  11. Modern medicine is pretty cool actually.
  12. -
  13. More stuff hurts, still just as healthy.
  14. -
  15. Dishwashers aren’t really as scary to repair as they seem (but that doesn’t mean you won’t lose your mind fixing one).
  16. -
  17. The feeling you get as a parent when your kid gets hurt is impossible to describe.
  18. -
  19. Being knocked out from a crazy car accident is also no fun.
  20. -
  21. Carseats are magic.
  22. -
  23. I’ve accepted that the music I liked in 2010 is going to be the music I’ll like forever.
  24. -
  25. Thanks to the internet there is an endless stream of new music that is at home with music from 2010 or even 2000 (Underoath just released a new album for crying out loud).
  26. -
  27. Open source software is incredible.
  28. -
  29. The thrill from in-progress software working for the first time will never get old for me.
  30. -
  31. Feedback loops are important in every area of life not just software.
  32. -
  33. The year of Linux on the desktop is a moving target.
  34. -
  35. RSS will never die.
  36. -
  37. Mechanical keyboards are a refreshing change and I’m not sure why.
  38. -
  39. The Aeropress is still incredible.
  40. -
  41. Computers were a mistake.
  42. -
  43. Computers are a miracle.
  44. -
  45. The Three-Body Problem trilogy continues to knock around in my brain months after finishing it.
  46. -
  47. Watching your child accomplish something for the first time that they’ve been working on is a feeling unlike any other.
  48. -
  49. I’ve realized I learn best by doing, I need to get better at accounting for the bumps along the way.
  50. -
  51. I write things down to remember them later not to look them up later which means most note systems are not worth the trouble for me.
  52. -
  53. Life will be shallow if you only hang out with people like you.
  54. -
  55. Anything is possible on an infinite timescale the trick is figuring out what do with finite time.
  56. -
  57. RIP Rdio.
  58. -
  59. Never pass on an opportunity to twirl your kids around when they’re small. They get big fast.
  60. -
  61. Hanlon’s razor explains most of social media.
  62. -
  63. If you work at a desk all day you owe it to yourself to remove as much Bluetooth from that setup as possible.
  64. -
  65. None of your peers has it all figured out. Ask them “dumb” questions.
  66. -
  67. Properly evaluating risks when your kids are involved is hard.
  68. -
  69. Keep a sweatshirt handy by your bed when your kids are young, getting up at 2am in the winter is cold.
  70. -
-

❤️ you Christi

- - Discuss further in my public inbox - ]]>
-
- - Windows 11 as KVM guest - https://adamsimpson.net/writing/windows-11-as-kvm-guest/ - - https://adamsimpson.net/writing/windows-11-as-kvm-guest/ - Mon, 28 Feb 2022 13:39:37 -0500 - - <![CDATA[ How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. ]]> - - <![CDATA[ -

Windows 11 famously has new, stricter requirements for installation; a TPM device and Secure Boot. Here’s how I satisfied those requirements with Windows 11 as a KVM guest with NixOS as the host. The following is pulled from my NixOS configuration.nix:

-
libvirtd.qemu = {
-  package = pkgs.qemu_kvm;
-  runAsRoot = true;
-  swtpm.enable = true;
-  ovmf = {
-    enable = true;
-    package = (pkgs.OVMFFull.override {
-      secureBoot = true;
-      tpmSupport = true;
-    });
-  };
-};
-

The most important bit is the pkgs.OVMFFull.override section where you must specify tpmSupport and secureBoot as true.

-

In virt-manager you’ll need to add “new hardware” and select TPM v2.0. Here’s the relevant XML from my config:

-
<tpm model="tpm-crb">
-  <backend type="emulator" version="2.0"/>
-</tpm>
-

With the above settings you should be able to go through the Windows 11 installer and get the machine up and running as a KVM guest.

-

Stretch goal: nested virtualization

-

If you want to use Docker or WSL 2 inside KVM you’ll need to enable “nested virtualization” in virt-manager. I couldn’t figure this out until I found this great answer on superuser.

-

My original CPU config XML looked like this:

-
<cpu mode="host-model" check="partial">
-  <topology sockets="1" dies="1" cores="2" threads="4"/>
-</cpu>
-

The new XML looks like this:

-
<cpu mode="custom" match="exact" check="partial">
-  <model fallback="allow">Skylake-Client-noTSX-IBRS</model>
-  <topology sockets="1" dies="1" cores="2" threads="4"/>
-  <feature policy="disable" name="hypervisor"/>
-  <feature policy="require" name="vmx"/>
-</cpu>
-

With this applied I could install WSL2 and get Docker Desktop for Windows installed and running.

- - Discuss further in my public inbox - ]]>
-
- - A few POSIX shell tips - https://adamsimpson.net/writing/a-few-posix-shell-tips/ - - https://adamsimpson.net/writing/a-few-posix-shell-tips/ - Mon, 19 Jul 2021 14:53:16 -0400 - - <![CDATA[ I wrote down a few of my most used POSIX shell commands and features. ]]> - - <![CDATA[ -

I was recently working on the release build script for sb and decided I should document a few things I find myself looking up just about every time. One of the advantages of the POSIX shell (not bash, zsh, but Bourne shell, usually /bin/sh on most unix-y systems) is that it has a specification however I’m usually frustrated trying to find the information I need.

- -

You can check it out here: https://github.com/sparkbox/sb

- -

I prefer the POSIX shell because it’s the default on most unix-y system. If I have to be sure if the shell is installed on the target system (like bash or zsh) I’d rather just use a higher-level scripting language like node or ruby where the same requirement exists.

-

Arrays

-

Psych! There aren’t any arrays. Bash has arrays but POSIX does not. If I need an array structure I can use a space-separated string (or another delimiter if you’ve set $IFS) as the data structure, e.g. PLATFORMS="arm64-darwin amd64-linux amd64-darwin". Now I can loop over the variable using a for loop:

-
PLATFORMS="arm64-darwin amd64-linux amd64-darwin"
-
-for PLATFORM in ${PLATFORMS}; do
-  # GOOS=FOO GOARCH=BAR go build ...
-done
-

Or I can take the lack of arrays as a signal I should stop writing a shell script and reach for a language that has the concept of arrays to solve my problem.

-

Conditional “flags”

-

I often forget the various flags one can use in a conditional (aka test/if) statement. Here’s the documentation and here are a few of my favorites:

-
    -
  • -n tests if the string is non-zero, e.g.
  • -
-
if [ -n "${UPLOAD_URL}" ]; then
-    upload_file "${PLATFORM}"
-fi
-
    -
  • -z the opposite of -n.
  • -
  • -f tests if the pathname resolves to a file.
  • -
-

Functions and args

-
    -
  • Functions must be declared before they are invoked.
  • -
  • Functions look like:
  • -
-
someFunc() {
-  echo "a func!"
-}
-
    -
  • There is no syntax for functions accepting args instead they are mapped to $n. $@ is all the args.
  • -
-
upload_file() {
-    NAME=$1
-
-    zip "${NAME}.zip" "${NAME}"
-    curl -H "Accept: application/vnd.github.v3+json" \
-         -H "Authorization: Bearer ${GITHUB_TOKEN}" \
-         -H "Content-Type: application/zip" \
-         --data-binary "@${NAME}.zip" \
-         "${UPLOAD_URL}?name=${NAME}.zip"
-}
-
-upload_file "${PLATFORM}"
-

Use shellcheck

-

This is just preference but I really love using shellcheck to avoid any footguns and enforce a consistent style with my shell scripts. I typically invoke it like this: shellcheck -o all script-name.sh.

- - Discuss further in my public inbox - ]]>
-
- - Recently - https://adamsimpson.net/writing/recently-16/ - - https://adamsimpson.net/writing/recently-16/ - Fri, 23 Apr 2021 11:37:19 -0400 - - <![CDATA[ A random assortment of links and miscellaneous updates on things. ]]> - - <![CDATA[ -

I’m stealing the title format of this post from Tom MacWright’s Recently posts.

-

Here’s a random assortment of links and miscellaneous updates on things.

-

autofs

-

autofs is a cool utility that watches a specific directory path and when a program tries to read or write to that path it mounts a filesystem at that location. I’m using this to auto mount my NAS via SMB for mpd. With autofs in place I can run mpd locally (in a “satellite setup”) and have its music_directory point to a path managed by autofs.

-

One thing that was helpful getting the configuration right was testing autofs by running automount -f -v directly which puts it in the foreground and gives verbose output.

-

The two files I configured were auto.master.d/foo.autofs and auto.foo.

-
    -
  • foo.autofs contains one line: /- /etc/auto.foo
  • -
  • auto.foo contains one line as well: /foo -fstype=cifs,rw,credentials=/home/me/.foo-creds ://NAS.IP/foo
  • -
-

mailpreview updates

-

mailpreview-cli is a little program I use multiple times a day to quickly see my unread email without moving from what I’m currently working on and without touching my mouse. I recently noticed it wasn’t grabbing the body of a specific type of email. In the process of fixing that I also added proper unit tests for every format I currently parse through. Yay faster feedback loops!

-

ffmpeg

-

I’ve been a fan of OBS for awhile now. I was recently doing a quick screen recording of my browser window and the browser window wasn’t full-screen so there were black bars around the edges of the recording. I didn’t love that but it’s time to touch the “ffmpeg exists and is awesome” sign again.

-

This superuser post has the answer which consists of two steps:

-
    -
  1. Get the crop parameters of the video from ffmpeg. ffmpeg will detect the black borders and report back the actual content coordinates. -ffmpeg.exe -i '.\some-video.mkv' -vf cropdetect -f null -
  2. -
  3. Re-encode and crop using the crop parameters to trim the borders. -ffmpeg.exe -i '.\some-video.mkv' -vf crop=624:704:332:10 -c:a copy output.mp4
  4. -
  5. Enjoy your pristine video.
  6. -
- - -

Fin

- - Discuss further in my public inbox - ]]>
-
- - A firewall in 8 lines - https://adamsimpson.net/writing/8-line-firewall/ - - https://adamsimpson.net/writing/8-line-firewall/ - Wed, 31 Mar 2021 11:18:24 -0400 - - <![CDATA[ You only need about 8 lines in iptables to have a great home firewall. ]]> - - <![CDATA[ -

Since 2017 my home router has been a plain x86 box running Alpine Linux. I never really think about it anymore. Recently, I was helping a relative set up their own Linux-based router and took the time to appreciate how little config is needed to setup a serviceable home router firewall using iptables. You can see my base rule-sets (port forwarding omitted) below:

-
-P INPUT DROP
--P FORWARD DROP
--P OUTPUT ACCEPT
--A INPUT -i lo -j ACCEPT
--A INPUT -i eth1 -j ACCEPT
--A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
--A FORWARD -i eth1 -o eth0 -j ACCEPT
--A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-

The benefit of running a x86 box with Alpine (or any version of Linux) is that the box will receive a steady stream of security updates and upgraded kernels as Alpine Linux releases new versions. This is a much better situation to be in than relying on OS and security updates from a vendor like TPLink or Linksys.

-

If you have ideas for how to improve the config I listed above or want to chat more about home network stuff, send an email to my public-inbox.

- - Discuss further in my public inbox - ]]>
-
- - How to use Siji font on polybar - https://www.reddit.com/r/Polybar/comments/ht0jnr/guide_how_to_use_the_siji_font_on_polybar/ - - https://adamsimpson.net/writing/how-to-use-siji-font-on-polybar/ - Fri, 06 Nov 2020 11:18:47 -0500 - <![CDATA[ -

Nice guide on Reddit about how to use the Siji font with polybar.

-
-

[..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

-
-

Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

- - 🔗 - Discuss further in my public inbox - ]]>
-
- - On Polybar bitmap fonts and Ubuntu - https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ - - https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ - Fri, 06 Nov 2020 10:15:09 -0500 - - <![CDATA[ Enable bitmap fonts on Ubuntu for an optimal polybar experience. ]]> - - <![CDATA[ -

I use polybar as my status bar in i3 and it’s been going great for months now. However, I was recently grepping through the syslog trying to figure out why a browser crash happened and the log was filled with polybar spam that looked like this: polybar|warn: Dropping unmatched character. So I started picking at solving the warning.

-

Turns out there’s a Github issue that contains the solution which is to enable bitmap fonts which I’ll paste here for posterity:

-
# "Un-disable" bitmap fonts
-sudo rm /etc/fonts/conf.d/70-no-bitmaps.conf
-# Clear the font cache
-sudo fc-cache -f -v
-

Apparently Ubuntu disables bitmap fonts by default but polybar uses bitmap fonts for icon rendering. I also needed to install the sijj icon font family which was painless.

- - Discuss further in my public inbox - ]]>
-
- - Recently - https://adamsimpson.net/writing/recently-44/ - - https://adamsimpson.net/writing/recently-44/ - Tue, 27 Oct 2020 23:30:46 -0400 - - <![CDATA[ I've written a few small tools over the last couple months and I figured it's time I post about them. ]]> - - <![CDATA[ -

I’ve published a few new projects in the last couple of months and I’m behind on announcing them, so I bundled them up together into this post. I’m stealing the title format of this post from Tom MacWright’s Recently posts.

-

One thing to note is that the source code for all these projects is stored on sourcehut. Sourcehut (or sr.ht) bills itself as “the hacker’s forge”. I highly recommend checking it out. It’s also where I host my public inbox.

-

hover-dns

-

Now that I have fiber internet at the house I’ve been hosting one-off services and apps on my own hardware at the house. This is great, however my residential connection is a typical dynamic IP not a static one. Instead of using a service like DynamicDNS I decided to write some Rust (shocker) and leverage the “unofficial” Hover API. The result is: hover-dns.

-

I have hover-dns running in a crontab for a few different domains to keep my domains pointed to the correct IP for my house. While I’m a little uncomfortable with how similar npm and cargo can feel, the trust-dns package is excellent. I was able to quickly read the source code to understand how to setup a Resolver for opendns. Also impressive is that hover-dns ip beats out dig in returning your public IP. I didn’t expect that!

-

podcastfilter

-

Speaking of hosting things at home, podcastfilter.com is one of those things. podcast-filter is a small Go project that allows you to filter a podcast feed by each episode’s description and return a feed of just those episodes that match.

-

mailpreview

-

The recent project I use the most day-to-day is mailpreview-cli. mailpreview-cli is very straight-forward, it accepts a Mail message and returns either the plain text version or the html version of that message. The reason I don’t just pull the Mail message directly is because a Mail message can contain several versions of the message in different encodings (start here if you’re curious: RFC-822). Instead of writing my own parser I grabbed the excellent mailparse crate and wrapped the behavior I wanted around it. On it’s own mailpreview-cli isn’t super fancy but I trigger it from rofi via a shell script which allows me to browse (and then view) all my unread emails right from rofi. Shameless plug: I wrote a short post about getting started with rofi if you’re unfamiliar. mailpreview-cli could be used with Alfred if you’re on a Mac to accomplish the same thing as I’m doing with a shell script and rofi.

-

Fin

- - Discuss further in my public inbox - ]]>
-
- - Four ways to approach Hacktoberfest 2020 - https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ - - https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ - Thu, 01 Oct 2020 10:26:38 -0400 - - <![CDATA[ I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. ]]> - - <![CDATA[ -

Hacktoberfest 2020 is here! I can’t believe 2020 is winding down, good riddance!

-

I’ve been talking about Hacktoberfest with my co-worker Bryan and I thought of four different approaches to Hacktoberfest this year that I wanted to share.

- -

Dependency scrub

-

This is probably common everywhere but the Javascript/web communities are filled with npm packages. It’s packages all the way down. I think it would be interesting to approach this month looking for ways to remove third-party code from projects you love and use frequently.

-

Polygot Achievement

-

Try to submit four pull requests in four different languages. As Drew DeVault writes: Hack everything without fear!

-

Unknown lands

-

Similar to the previous one it could be fun to submit PRs against a project you’ve never been in before that’s in a language you don’t know. This could be anything from diving into Wordpress core, to working on some C for some Linux utilities, or even submitting PRs to open source Mac/iOS applications.

-

Bug doctor

-

Go into a project and find the oldest issues and try to resolve them via PR. This is inspired by Richard Schneeman’s video and post where he runs through 11 issues and 2 PRs in a hour and a half.

-

How are you approaching Hacktoberfest this year? My public inbox is open, let me know!

- - Discuss further in my public inbox - ]]>
-
- - Small tech - https://scattered-thoughts.net/writing/small-tech/ - - https://adamsimpson.net/writing/small-tech/ - Fri, 25 Sep 2020 15:53:06 -0400 - <![CDATA[ -

Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

-
    -
  • -

    curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

    -
  • -
  • -

    git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

    -
  • -
  • -

    Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

    -
  • -
  • -

    sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

    -
  • -
- - 🔗 - Discuss further in my public inbox - ]]>
-
- - Indexing My Blog’s Links - https://blog.jim-nielsen.com/2020/indexing-my-blogs-links/ - - https://adamsimpson.net/writing/indexing-my-blogs-links/ - Fri, 25 Sep 2020 15:49:21 -0400 - <![CDATA[ -

Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

- - 🔗 - Discuss further in my public inbox - ]]>
-
- - Compose key and i3 - https://adamsimpson.net/writing/compose-key-and-i3/ - - https://adamsimpson.net/writing/compose-key-and-i3/ - Fri, 18 Sep 2020 11:28:19 -0400 - - <![CDATA[ Here's how to bind the compose key to caps lock in i3wm. ]]> - - <![CDATA[ -

The compose key on Linux and other systems enables you to enter symbols like ™ that don’t have a dedicated key on most keyboards. GNOME makes this easy to do via Gnome Tweaks. However, using a window manager like i3 means there’s no dedicated GUI for changing the hotkey for compose.

-

This stackexchange answer sent me down the right path of adding the following config to ~/.Xmodmap to bind Caps lock to compose:

-
.keysym 66 = Mode_switch
-clear Lock
-

You can then enable the key map by running:

-
xmodmap ~/.Xmodmap
-

However, that config didn’t work because Mode_switch wasn’t the right name for the compose key (at least under Ubuntu/PopOS 20 for me). The Arch Wiki states that the name for the compose key is actually Multi_key. With this new name I was able to get Caps lock to act as the compose key by updating the config in ~/.Xmodmap to:

-
keycode 66 = Multi_key
-clear Lock
-

The final step is to set that mapping every time i3 runs by putting this inside your i3 config file like so:

-
exec --no-startup-id "xmodmap ~/.Xmodmap"
-
- Discuss further in my public inbox - ]]>
-
- - cycle v0.3.0 released - https://adamsimpson.net/writing/cycle-v030-released/ - - https://adamsimpson.net/writing/cycle-v030-released/ - Fri, 11 Sep 2020 12:04:16 -0400 - - <![CDATA[ Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. ]]> - - <![CDATA[ -

I just released v0.3.0 of cycle.

-

This version uses Chroma for syntax highlighting instead of Pygments. I never got Pygments running correctly in Netlify’s build environment. Chroma requires no dependencies since it’s distributed as a static binary and it’s also faster due to being written in golang.

-

This version also refactors the main function to accept an optional working directory arg. This allows me to build a site via the CL REPL. It also shortens the feedback loop to try out new features.

- - Discuss further in my public inbox - ]]>
-
-
-
diff --git a/themes/cycle/exampleSite/public/rss.xml b/themes/cycle/exampleSite/public/rss.xml deleted file mode 100644 index e3fe928..0000000 --- a/themes/cycle/exampleSite/public/rss.xml +++ /dev/null @@ -1,738 +0,0 @@ - - - adamsimpson.net Post Feed - https://adamsimpson.net/ - Last 20 posts for adamsimpson.net - Thu, 09 Oct 2025 21:22:39 +0000 - en-us - - nixpkgs is a treasure - https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ - - https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ - Fri, 10 May 2024 14:07:43 -0400 - - <![CDATA[ Nix and NixOS continue to be the best way to manage and build software that I've found. ]]> - - <![CDATA[ -

Nix and NixOS continue to be the best way to manage and build software that I’ve found. Every project has a shell.nix file in the root where I can define the specific software needed to work on that project along with any necessary environment variables or $PATH modifications. I ran into an issue this week though where I needed an “old” version of Go (1.20) but the version had already been removed from nixpkgs. How can I pull in an “unlisted” version into my shell.nix?

-

It’s actually pretty straightforward, utilize fetchTarball to pull in nixpkgs based on a commit where the version was present sometime in the past. You can mix that import in with regular/“current” packages with no issue like so:

-
{ pkgs ? import <nixpkgs> {} }:
-
-let oldGo = import (builtins.fetchTarball {
-    url = "https://github.com/NixOS/nixpkgs/archive/33c51330782cb486764eb598d5907b43dc87b4c2.tar.gz";
-    sha256 = "sha256:0nflmpfp3pk704vhlvlgh5vgwl8qciqi18mcpl32k79qjziwmih8";
-    }) {};
-in 
-
-pkgs.mkShell {
-  buildInputs = [
-    oldGo.go_1_20
-    pkgs.gopls
-    pkgs.nodejs_18
-  ];
-  
-  hardeningDisable = [ "fortify" ];
-
-  shellHook = ''
-    mkdir -p .go .npm
-    export GOPATH=$PWD/.go
-    export NODE_PATH=$PWD/.npm
-    export NPM_CONFIG_PREFIX=$NODE_PATH
-    export PATH=$PWD/.yarn/sdks/typescript/bin:$PWD/.go/bin:$PATH:$NODE_PATH/bin
-  '';
-}
-

Notice I can reference the “nixpkgs” tarball/snapshot, oldGo, and pull in the version of Go I need?! nixpkgs is such a treasure trove of software, it’s absolutely incredible!

- - Discuss further in my public inbox - ]]>
-
- - Lessons learned from integrating OpenAI into a Grafana data source - https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ - - https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ - Tue, 25 Jul 2023 15:10:24 -0400 - - <![CDATA[ I wrote over on the <a href="https://grafana.com/blog/">Grafana blog</a> about a few <a href="https://grafana.com/blog/2023/07/25/lessons-learned-from-integrating-openai-into-a-grafana-data-source/">lessons or observations we learned while integrating OpenAI into the ADX data source</a>. It's my first post on the Grafana blog and I'm pretty excited, so check it out! ]]> - - <![CDATA[ -

I wrote over on the Grafana blog about a few lessons or observations we learned while integrating OpenAI into the ADX data source. It’s my first post on the Grafana blog and I’m pretty excited, so check it out!

- - Discuss further in my public inbox - ]]>
-
- - Better scripting with gh - https://adamsimpson.net/writing/better-scripting-with-gh/ - - https://adamsimpson.net/writing/better-scripting-with-gh/ - Sat, 22 Jul 2023 11:33:16 -0400 - - <![CDATA[ I've become a big fan of the <a href="https://cli.github.com/">gh</a> CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. ]]> - - <![CDATA[ -

I’ve become a big fan of the gh CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. Instead of using curl with a Github token and the Github API, I can simply use gh. What’s even better is that in more advanced situations where there isn’t a valid subcommand for what I want to script, I can use the gh api escape hatch to do curl-style HTTP requests to the API without messing with authentication or even pagination. Here are two recent scripts I wrote that highlight the power and convenience of gh.

-

PR Kudos

-

I created this script to help me give better kudos to folks in our retro meeting. When I provide a Github team name as an argument, it displays all PRs from members of that team. What I really like is that it only shows PRs from the last two weeks, which gives me a nice overview of recent activity.

-
#!/bin/bash
-
-start=$(date -d "2 weeks ago" +%Y-%m-%d)
-end=$(date +%Y-%m-%d)
-
-details=$(gh api /orgs/grafana/teams/$1 | jq -r '"\(.id),\(.organization.id)"')
-teamId=$(echo ${details} | cut -d , -f 1)
-orgId=$(echo ${details} | cut -d , -f 2)
-
-gh api "organizations/${orgId}/team/${teamId}/members" | \
-  jq -r '.[] | .login' | \
-  xargs -I % gh search prs --author=% --created="${start}..${end}" \
-  --json="state,repository,url,title,updatedAt,author" --template '{{range .}}{{tablerow (.author.login | autocolor "green") (hyperlink .url .title) (.repository.name | autocolor "blue") (.state | autocolor "red") (timeago .updatedAt)}}{{end}}
-{{tablerender}}'
-

Notification OCD

-

The second script focuses on managing notifications related to pull requests and issues. I usually find that about one-third of my notifications are for merged PRs, PRs created by bots, or closed Issues. I don’t care about these types of events. With this script, I can mark those notifications as done, which reduces clutter in my GitHub notifications and helps me see important updates. As I mentioned above, one cool feature of the api subcommand is that it allows me to consume all possible pages of a response using the --paginate flag, eliminating the need for a loop + token field dance!

-
#!/bin/bash
-declare -A typeLookup
-typeLookup["PullRequest"]="pull"
-typeLookup["Issue"]="issues"
-
-resp=$(gh api /notifications --paginate | jq -r '.[] | select(.subject.type == "PullRequest" or .subject.type == "Issue") | "\(.repository.full_name),\(.subject.url),\(.id),\(.subject.type)"')
-
-for x in $resp; do
-  name=$(echo "${x}" | cut -d ',' -f 1)
-  id=$(echo "${x}" | cut -d ',' -f 3)
-  number=$(basename $(echo "${x}" | cut -d ',' -f 2))
-  ofType=$(echo "${x}" | cut -d ',' -f 4)
-  urlType=$(echo ${typeLookup["${ofType}"]})
-  isBot="false"
-
-  if [ "${ofType}" == "PullRequest" ]; then
-    isMerged=$(gh pr view --repo "${name}" "${number}" --json closed | jq -r .closed)
-    isBot=$(gh pr view --repo "${name}" "${number}" --json author | jq -r .author.is_bot)
-  fi
-
-  if [ "${ofType}" == "Issue" ]; then
-    isMerged=$(gh issue view --repo "${name}" "${number}" --json closed | jq -r .closed)
-  fi
-
-  if [ "${isMerged}" == "true" ] || [ "${isBot}" == "true" ]; then
-    echo "marking https://github.com/${name}/${urlType}/${number} as done..."
-    gh api -X PATCH "/notifications/threads/${id}"
-  fi
-done
-
- Discuss further in my public inbox - ]]>
-
- - End of an era - https://adamsimpson.net/writing/end-of-an-era/ - - https://adamsimpson.net/writing/end-of-an-era/ - Thu, 15 Jun 2023 14:13:50 -0400 - - <![CDATA[ Today I removed two of my most-used apps on my phone, <a href='https://apolloapp.io/'>Apollo</a> and <a href='https://tapbots.com/tweetbot/'>Tweetbot</a>. It feels like the end of an era. ]]> - - <![CDATA[ -

Today I removed two of my most-used apps on my phone, Apollo and Tweetbot. It feels like the end of an era.

-

Twitter and Reddit were both social websites that are/were terrible without a lot of cultivation and effort, but over the years I had shaped my experience on those services to be pretty good thanks in large part to Apollo and Tweetbot being such powerful tools.

-

Ironically the only social web thing I still use (outside of Instagram) is RSS. I will probably spin up a Mastodon instance here eventually but for now I’ve subscribed to folks via Mastodon’s RSS support and it’s good enough for now.

-

I guess I just wanted to give a shout out to the devs of Apollo and Tweetbot: thank you for making such great apps, I will miss them.

- - Discuss further in my public inbox - ]]>
-
- - Hacking on Grafana with Web Assembly - https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ - - https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ - Fri, 19 Aug 2022 15:10:19 -0400 - - <![CDATA[ Grafana had a hack week this past week and I opted to work on WebAssembly(WASM)-related things. My vague original idea was to see if I could compile the Grafana server for WASM. ]]> - - <![CDATA[ - -

The original inspiration for this idea came from Simon Willison’s work with Datasette Lite. However, compiling Grafana as a WASM binary proved difficult with existing build constraints. After spending some time trying to get that to work I changed course a bit and instead focused on compiling a basic go HTTP server as a WASM module. The new goal being to have a proof of concept that bundled the HTTP server as a WASM binary and intercepted any clicked links on the page and finally passed those links to be resolved by the go server in WASM.

-

I used a Web Worker to interact with the WASM binary. This frees up the main thread of the browser. To put the WASM binary into the worker I loaded the binary and sent a message that contained the binary as a WebAssembly.Module.

-

The Web Worker can then call any go functions that have been exposed via FuncOf. Once the go function returns data, the worker posts that response back to the main thread via another message.

-
let module;
-importScripts("wasm_exec.js")
-go = new Go();
-
-self.onmessage = async (e) => {
-  if (e.data.type === "module") {
-    module = e.data.module;
-    return;
-  }
-
-  if (module) {
-    console.log('Message received: ', e.data.path);
-    const instance = await WebAssembly.instantiate(module, go.importObject);
-    go.run(instance);
-    postMessage(parsePath(e.data.path)); // parsePath is exposed via FuncOf
-  }
-}
-

Sidenote: I wish go could use the same pragma syntax tinygo uses to expose functions instead of the verbose FuncOf. There’s an issue but it has been open since 2018.

-

Obviously, there is no localhost to listen on in a WASM environment. To get around that I created a bare bones ResponseWriter and used that with the Request to run the Handler’s ServeHTTP function which consults the routes that are defined and runs the matching handler code. This allowed me to use a build constraint (setup.go and setup_js.go) and keep my HTTP server functioning normally when run from a terminal but then also worked when run in a WASM context. Here’s what those two files look like:

-

setup

-
//go:build !js
-// +build !js
-
-package main
-
-import (
-	"fmt"
-	"net/http"
-)
-
-func setup() {
-	s := NewServer()
-	err := http.ListenAndServe(":9001", s.mux)
-	if err != nil {
-		fmt.Println("error: ", err)
-	}
-}
-

setup_js

-
package main
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"syscall/js"
-)
-
-type ResponseWriter struct {
-	Body *bytes.Buffer
-}
-
-func (r ResponseWriter) Header() http.Header {
-	return make(http.Header)
-}
-
-func (r ResponseWriter) Write(buf []byte) (int, error) {
-	if r.Body != nil {
-		r.Body.Write(buf)
-	}
-	return len(buf), nil
-}
-
-func (r ResponseWriter) WriteHeader(statusCode int) {}
-
-func createWriter() ResponseWriter {
-	return ResponseWriter{
-		Body: new(bytes.Buffer),
-	}
-}
-
-func parsePath(this js.Value, args []js.Value) interface{} {
-	fmt.Println("args: ", args)
-	server := NewServer()
-	path := args[0].String()
-	req, err := http.NewRequest(http.MethodGet, path, nil)
-
-	if err != nil {
-		fmt.Println("request error: ", err)
-	}
-
-	h, p := server.mux.Handler(req)
-
-	fmt.Println("pattern: ", p)
-
-	w := createWriter()
-
-	h.ServeHTTP(w, req)
-
-	b, err := ioutil.ReadAll(w.Body)
-
-	if err != nil {
-		fmt.Println("ioutil error: ", err)
-	}
-
-	return string(b)
-}
-
-func setup() {
-	js.Global().Set("parsePath", js.FuncOf(parsePath))
-}
-

Conclusions

-

The PoC worked! It’s pretty slick to see a HTTP server running in WASM return back the correct data when a link is clicked. However, in my opinion, WASM continues to be a “solution in search of a problem”. Yes it’s incredibly cool technology but so are the JS engines in Chrome, Firefox, and Safari. The sheer amount of money and engineering time being spent on making JS fast is a race no other technology can win at the moment.

-

That said, Go seems to have done decent work at providing the necessary pieces to make compiling to WASM not awful.

-

Honestly, the thing that surprised and impressed me the most was working with Web Workers. They are seriously useful and seem to “just work”.

- - - - Discuss further in my public inbox - ]]>
-
- - New workstation - https://adamsimpson.net/writing/new-workstation/ - - https://adamsimpson.net/writing/new-workstation/ - Mon, 02 May 2022 18:14:25 +0000 - - <![CDATA[ I detail my new workstation build featuring the Intel i5-12600k. ]]> - - <![CDATA[ -

New job means time for a new workstation.

-

Some history

-

The first computer I ever purchased was the 12" Powerbook G4. Since that Powerbook I’ve always had laptops as my main machines (desktop gaming PC not withstanding). Remote working the last few years has made me realize that the portability of a laptop is largely wasted since I only travel a handful of times a year and yet I live with the downsides of a laptop the rest of the time. So, last year I started thinking about a desktop machine for my primary workstation. A desktop is appealing for a handful of reasons:

-
    -
  • More powerful CPUs
  • -
  • More expansion capabilities
  • -
  • More durable
  • -
-

The options

-

The Mac Studio was recently released to much fanfare and was really intriguing to me. However, when I started considering it I only had about a week to 10 days before my start date at Grafana and I couldn’t wait the quoted 4-6 weeks delivery time for a Mac Studio with 32GB of RAM.

-

I was also pretty unwilling to leave my comfy NixOS install + i3. Michael Stapelberg’s latest post about his new workstation proved timely and convinced me to give the new Intel Alder Lake CPUs a shot.

-

Apple’s M1 family of chips deliver incredible performance per watt but I wasn’t as concered about the power usage given this was a desktop machine not a laptop. I was however focused on at least matching the M1 chips in single-threaded performance since a good chunk of my development work (Node, build tools, etc) are still single-threaded. I ended up with the Intel i5-12600k and I really couldn’t be happier. Here’s the full parts list:

- -

XMP issues

-

I ran into the same memory XMP issues that Michael mentions in his post so I disabled the XMP profile and the system passed the “Coding Horror burn in tests” with flying colors.

-

Cooling

-

I mounted the 140mm fan to the bottom of the case as intake and the CPU cooler is of course positioned as intake as well. Hot air rises out the top of the case quite well. During the prime95 torture test the CPU never got over 78°C and I couldn’t ever hear either fan. I run both fans in the “silent profile” in the BIOS and I use Noctua’s adapters to lower the voltage even more. Now the only fan I could hear during max load was the PSU fan which doesn’t spin at all under low to medium loads but under high load it kicks on. Day to day it’s hardly on so the system is dead quiet most of the time.

-

Case

-

I absolutely love the Cerberus case. It’s Mini-ATX but still super compact and fits on my desk quite well. All the panels are solid metal and the way all the panels pop off is really really nice. I opted for the handle mount on the top and the internal PSU moutning.

-

Linux

-

NixOS installed just fine. I’m runing the 5.17 kernel because Alder Lake needs a newer kernel for it’s graphics and CPU scheduler (coming soon?). I have WiFi and Bluetooh disabled in the BIOS since everything is hard-wired to the machine.

-

Verdict

-

This build has proven quite comfortable over the few weeks I’ve used it. I love that I have 2 free RAM slots if I ever feel the need for more RAM. I also love that I have 3 remaining Nvme slots on the motherboard for additional solid state storage in the future.

- - Discuss further in my public inbox - ]]>
-
- - 👋 Sparkbox - https://adamsimpson.net/writing/goodbye-sparkbox/ - - https://adamsimpson.net/writing/goodbye-sparkbox/ - Fri, 01 Apr 2022 18:20:31 +0000 - - <![CDATA[ I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox. ]]> - - <![CDATA[ -

I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox.

-

Now, I know it can be problematic to think about work like your (extended) family but when you work at the same place through your twenties and early thirties, have 3 different apartments, buy a house, and have two kids it’s impossible not to view that place differently. I can confidently say Sparkbox changed my life. The team there will always have a special place in my heart.

-

deep breath

-

So where to? Well, I’m super stoked to be joining Grafana as a Senior Software Engineer on their Cloud Data team! I’m looking forward to writing more Go, solving new problems, and learning from the stellar folks there.

-

Here we go…

- - Discuss further in my public inbox - ]]>
-
- - Thirty five - https://adamsimpson.net/writing/thirty-five/ - - https://adamsimpson.net/writing/thirty-five/ - Thu, 03 Mar 2022 10:28:44 -0500 - - <![CDATA[ It's been 5 years since I wrote 'Thirty'. So now I have to come up with 35 things as I turned 35 yesterday. ]]> - - <![CDATA[ -

Well crap.

-

It’s been 5 years since I wrote “Thirty”. So now I have to come up with 35 things as I turned 35 yesterday. If anything from Thirty is grossly wrong or really interesting I’ll update it at the same number eh?

-

Let’s go…

-
    -
  1. I still don’t have it figured out, but this isn’t such a shock anymore.
  2. -
  3. Building a house is more scary.
  4. -
  5. Minivans are awesome.
  6. -
  7. Expecting a third kid is not nearly as scary as expecting the first.
  8. -
  9. COVID sucked.
  10. -
  11. Modern medicine is pretty cool actually.
  12. -
  13. More stuff hurts, still just as healthy.
  14. -
  15. Dishwashers aren’t really as scary to repair as they seem (but that doesn’t mean you won’t lose your mind fixing one).
  16. -
  17. The feeling you get as a parent when your kid gets hurt is impossible to describe.
  18. -
  19. Being knocked out from a crazy car accident is also no fun.
  20. -
  21. Carseats are magic.
  22. -
  23. I’ve accepted that the music I liked in 2010 is going to be the music I’ll like forever.
  24. -
  25. Thanks to the internet there is an endless stream of new music that is at home with music from 2010 or even 2000 (Underoath just released a new album for crying out loud).
  26. -
  27. Open source software is incredible.
  28. -
  29. The thrill from in-progress software working for the first time will never get old for me.
  30. -
  31. Feedback loops are important in every area of life not just software.
  32. -
  33. The year of Linux on the desktop is a moving target.
  34. -
  35. RSS will never die.
  36. -
  37. Mechanical keyboards are a refreshing change and I’m not sure why.
  38. -
  39. The Aeropress is still incredible.
  40. -
  41. Computers were a mistake.
  42. -
  43. Computers are a miracle.
  44. -
  45. The Three-Body Problem trilogy continues to knock around in my brain months after finishing it.
  46. -
  47. Watching your child accomplish something for the first time that they’ve been working on is a feeling unlike any other.
  48. -
  49. I’ve realized I learn best by doing, I need to get better at accounting for the bumps along the way.
  50. -
  51. I write things down to remember them later not to look them up later which means most note systems are not worth the trouble for me.
  52. -
  53. Life will be shallow if you only hang out with people like you.
  54. -
  55. Anything is possible on an infinite timescale the trick is figuring out what do with finite time.
  56. -
  57. RIP Rdio.
  58. -
  59. Never pass on an opportunity to twirl your kids around when they’re small. They get big fast.
  60. -
  61. Hanlon’s razor explains most of social media.
  62. -
  63. If you work at a desk all day you owe it to yourself to remove as much Bluetooth from that setup as possible.
  64. -
  65. None of your peers has it all figured out. Ask them “dumb” questions.
  66. -
  67. Properly evaluating risks when your kids are involved is hard.
  68. -
  69. Keep a sweatshirt handy by your bed when your kids are young, getting up at 2am in the winter is cold.
  70. -
-

❤️ you Christi

- - Discuss further in my public inbox - ]]>
-
- - Windows 11 as KVM guest - https://adamsimpson.net/writing/windows-11-as-kvm-guest/ - - https://adamsimpson.net/writing/windows-11-as-kvm-guest/ - Mon, 28 Feb 2022 13:39:37 -0500 - - <![CDATA[ How I work with Windows 11 as a KVM guest on a NixOS host using virt-manager. ]]> - - <![CDATA[ -

Windows 11 famously has new, stricter requirements for installation; a TPM device and Secure Boot. Here’s how I satisfied those requirements with Windows 11 as a KVM guest with NixOS as the host. The following is pulled from my NixOS configuration.nix:

-
libvirtd.qemu = {
-  package = pkgs.qemu_kvm;
-  runAsRoot = true;
-  swtpm.enable = true;
-  ovmf = {
-    enable = true;
-    package = (pkgs.OVMFFull.override {
-      secureBoot = true;
-      tpmSupport = true;
-    });
-  };
-};
-

The most important bit is the pkgs.OVMFFull.override section where you must specify tpmSupport and secureBoot as true.

-

In virt-manager you’ll need to add “new hardware” and select TPM v2.0. Here’s the relevant XML from my config:

-
<tpm model="tpm-crb">
-  <backend type="emulator" version="2.0"/>
-</tpm>
-

With the above settings you should be able to go through the Windows 11 installer and get the machine up and running as a KVM guest.

-

Stretch goal: nested virtualization

-

If you want to use Docker or WSL 2 inside KVM you’ll need to enable “nested virtualization” in virt-manager. I couldn’t figure this out until I found this great answer on superuser.

-

My original CPU config XML looked like this:

-
<cpu mode="host-model" check="partial">
-  <topology sockets="1" dies="1" cores="2" threads="4"/>
-</cpu>
-

The new XML looks like this:

-
<cpu mode="custom" match="exact" check="partial">
-  <model fallback="allow">Skylake-Client-noTSX-IBRS</model>
-  <topology sockets="1" dies="1" cores="2" threads="4"/>
-  <feature policy="disable" name="hypervisor"/>
-  <feature policy="require" name="vmx"/>
-</cpu>
-

With this applied I could install WSL2 and get Docker Desktop for Windows installed and running.

- - Discuss further in my public inbox - ]]>
-
- - A few POSIX shell tips - https://adamsimpson.net/writing/a-few-posix-shell-tips/ - - https://adamsimpson.net/writing/a-few-posix-shell-tips/ - Mon, 19 Jul 2021 14:53:16 -0400 - - <![CDATA[ I wrote down a few of my most used POSIX shell commands and features. ]]> - - <![CDATA[ -

I was recently working on the release build script for sb and decided I should document a few things I find myself looking up just about every time. One of the advantages of the POSIX shell (not bash, zsh, but Bourne shell, usually /bin/sh on most unix-y systems) is that it has a specification however I’m usually frustrated trying to find the information I need.

- -

You can check it out here: https://github.com/sparkbox/sb

- -

I prefer the POSIX shell because it’s the default on most unix-y system. If I have to be sure if the shell is installed on the target system (like bash or zsh) I’d rather just use a higher-level scripting language like node or ruby where the same requirement exists.

-

Arrays

-

Psych! There aren’t any arrays. Bash has arrays but POSIX does not. If I need an array structure I can use a space-separated string (or another delimiter if you’ve set $IFS) as the data structure, e.g. PLATFORMS="arm64-darwin amd64-linux amd64-darwin". Now I can loop over the variable using a for loop:

-
PLATFORMS="arm64-darwin amd64-linux amd64-darwin"
-
-for PLATFORM in ${PLATFORMS}; do
-  # GOOS=FOO GOARCH=BAR go build ...
-done
-

Or I can take the lack of arrays as a signal I should stop writing a shell script and reach for a language that has the concept of arrays to solve my problem.

-

Conditional “flags”

-

I often forget the various flags one can use in a conditional (aka test/if) statement. Here’s the documentation and here are a few of my favorites:

-
    -
  • -n tests if the string is non-zero, e.g.
  • -
-
if [ -n "${UPLOAD_URL}" ]; then
-    upload_file "${PLATFORM}"
-fi
-
    -
  • -z the opposite of -n.
  • -
  • -f tests if the pathname resolves to a file.
  • -
-

Functions and args

-
    -
  • Functions must be declared before they are invoked.
  • -
  • Functions look like:
  • -
-
someFunc() {
-  echo "a func!"
-}
-
    -
  • There is no syntax for functions accepting args instead they are mapped to $n. $@ is all the args.
  • -
-
upload_file() {
-    NAME=$1
-
-    zip "${NAME}.zip" "${NAME}"
-    curl -H "Accept: application/vnd.github.v3+json" \
-         -H "Authorization: Bearer ${GITHUB_TOKEN}" \
-         -H "Content-Type: application/zip" \
-         --data-binary "@${NAME}.zip" \
-         "${UPLOAD_URL}?name=${NAME}.zip"
-}
-
-upload_file "${PLATFORM}"
-

Use shellcheck

-

This is just preference but I really love using shellcheck to avoid any footguns and enforce a consistent style with my shell scripts. I typically invoke it like this: shellcheck -o all script-name.sh.

- - Discuss further in my public inbox - ]]>
-
- - Recently - https://adamsimpson.net/writing/recently-16/ - - https://adamsimpson.net/writing/recently-16/ - Fri, 23 Apr 2021 11:37:19 -0400 - - <![CDATA[ A random assortment of links and miscellaneous updates on things. ]]> - - <![CDATA[ -

I’m stealing the title format of this post from Tom MacWright’s Recently posts.

-

Here’s a random assortment of links and miscellaneous updates on things.

-

autofs

-

autofs is a cool utility that watches a specific directory path and when a program tries to read or write to that path it mounts a filesystem at that location. I’m using this to auto mount my NAS via SMB for mpd. With autofs in place I can run mpd locally (in a “satellite setup”) and have its music_directory point to a path managed by autofs.

-

One thing that was helpful getting the configuration right was testing autofs by running automount -f -v directly which puts it in the foreground and gives verbose output.

-

The two files I configured were auto.master.d/foo.autofs and auto.foo.

-
    -
  • foo.autofs contains one line: /- /etc/auto.foo
  • -
  • auto.foo contains one line as well: /foo -fstype=cifs,rw,credentials=/home/me/.foo-creds ://NAS.IP/foo
  • -
-

mailpreview updates

-

mailpreview-cli is a little program I use multiple times a day to quickly see my unread email without moving from what I’m currently working on and without touching my mouse. I recently noticed it wasn’t grabbing the body of a specific type of email. In the process of fixing that I also added proper unit tests for every format I currently parse through. Yay faster feedback loops!

-

ffmpeg

-

I’ve been a fan of OBS for awhile now. I was recently doing a quick screen recording of my browser window and the browser window wasn’t full-screen so there were black bars around the edges of the recording. I didn’t love that but it’s time to touch the “ffmpeg exists and is awesome” sign again.

-

This superuser post has the answer which consists of two steps:

-
    -
  1. Get the crop parameters of the video from ffmpeg. ffmpeg will detect the black borders and report back the actual content coordinates. -ffmpeg.exe -i '.\some-video.mkv' -vf cropdetect -f null -
  2. -
  3. Re-encode and crop using the crop parameters to trim the borders. -ffmpeg.exe -i '.\some-video.mkv' -vf crop=624:704:332:10 -c:a copy output.mp4
  4. -
  5. Enjoy your pristine video.
  6. -
- - -

Fin

- - Discuss further in my public inbox - ]]>
-
- - A firewall in 8 lines - https://adamsimpson.net/writing/8-line-firewall/ - - https://adamsimpson.net/writing/8-line-firewall/ - Wed, 31 Mar 2021 11:18:24 -0400 - - <![CDATA[ You only need about 8 lines in iptables to have a great home firewall. ]]> - - <![CDATA[ -

Since 2017 my home router has been a plain x86 box running Alpine Linux. I never really think about it anymore. Recently, I was helping a relative set up their own Linux-based router and took the time to appreciate how little config is needed to setup a serviceable home router firewall using iptables. You can see my base rule-sets (port forwarding omitted) below:

-
-P INPUT DROP
--P FORWARD DROP
--P OUTPUT ACCEPT
--A INPUT -i lo -j ACCEPT
--A INPUT -i eth1 -j ACCEPT
--A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
--A FORWARD -i eth1 -o eth0 -j ACCEPT
--A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-

The benefit of running a x86 box with Alpine (or any version of Linux) is that the box will receive a steady stream of security updates and upgraded kernels as Alpine Linux releases new versions. This is a much better situation to be in than relying on OS and security updates from a vendor like TPLink or Linksys.

-

If you have ideas for how to improve the config I listed above or want to chat more about home network stuff, send an email to my public-inbox.

- - Discuss further in my public inbox - ]]>
-
- - How to use Siji font on polybar - https://www.reddit.com/r/Polybar/comments/ht0jnr/guide_how_to_use_the_siji_font_on_polybar/ - - https://adamsimpson.net/writing/how-to-use-siji-font-on-polybar/ - Fri, 06 Nov 2020 11:18:47 -0500 - <![CDATA[ -

Nice guide on Reddit about how to use the Siji font with polybar.

-
-

[..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

-
-

Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

- - 🔗 - Discuss further in my public inbox - ]]>
-
- - On Polybar bitmap fonts and Ubuntu - https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ - - https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ - Fri, 06 Nov 2020 10:15:09 -0500 - - <![CDATA[ Enable bitmap fonts on Ubuntu for an optimal polybar experience. ]]> - - <![CDATA[ -

I use polybar as my status bar in i3 and it’s been going great for months now. However, I was recently grepping through the syslog trying to figure out why a browser crash happened and the log was filled with polybar spam that looked like this: polybar|warn: Dropping unmatched character. So I started picking at solving the warning.

-

Turns out there’s a Github issue that contains the solution which is to enable bitmap fonts which I’ll paste here for posterity:

-
# "Un-disable" bitmap fonts
-sudo rm /etc/fonts/conf.d/70-no-bitmaps.conf
-# Clear the font cache
-sudo fc-cache -f -v
-

Apparently Ubuntu disables bitmap fonts by default but polybar uses bitmap fonts for icon rendering. I also needed to install the sijj icon font family which was painless.

- - Discuss further in my public inbox - ]]>
-
- - Recently - https://adamsimpson.net/writing/recently-44/ - - https://adamsimpson.net/writing/recently-44/ - Tue, 27 Oct 2020 23:30:46 -0400 - - <![CDATA[ I've written a few small tools over the last couple months and I figured it's time I post about them. ]]> - - <![CDATA[ -

I’ve published a few new projects in the last couple of months and I’m behind on announcing them, so I bundled them up together into this post. I’m stealing the title format of this post from Tom MacWright’s Recently posts.

-

One thing to note is that the source code for all these projects is stored on sourcehut. Sourcehut (or sr.ht) bills itself as “the hacker’s forge”. I highly recommend checking it out. It’s also where I host my public inbox.

-

hover-dns

-

Now that I have fiber internet at the house I’ve been hosting one-off services and apps on my own hardware at the house. This is great, however my residential connection is a typical dynamic IP not a static one. Instead of using a service like DynamicDNS I decided to write some Rust (shocker) and leverage the “unofficial” Hover API. The result is: hover-dns.

-

I have hover-dns running in a crontab for a few different domains to keep my domains pointed to the correct IP for my house. While I’m a little uncomfortable with how similar npm and cargo can feel, the trust-dns package is excellent. I was able to quickly read the source code to understand how to setup a Resolver for opendns. Also impressive is that hover-dns ip beats out dig in returning your public IP. I didn’t expect that!

-

podcastfilter

-

Speaking of hosting things at home, podcastfilter.com is one of those things. podcast-filter is a small Go project that allows you to filter a podcast feed by each episode’s description and return a feed of just those episodes that match.

-

mailpreview

-

The recent project I use the most day-to-day is mailpreview-cli. mailpreview-cli is very straight-forward, it accepts a Mail message and returns either the plain text version or the html version of that message. The reason I don’t just pull the Mail message directly is because a Mail message can contain several versions of the message in different encodings (start here if you’re curious: RFC-822). Instead of writing my own parser I grabbed the excellent mailparse crate and wrapped the behavior I wanted around it. On it’s own mailpreview-cli isn’t super fancy but I trigger it from rofi via a shell script which allows me to browse (and then view) all my unread emails right from rofi. Shameless plug: I wrote a short post about getting started with rofi if you’re unfamiliar. mailpreview-cli could be used with Alfred if you’re on a Mac to accomplish the same thing as I’m doing with a shell script and rofi.

-

Fin

- - Discuss further in my public inbox - ]]>
-
- - Four ways to approach Hacktoberfest 2020 - https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ - - https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ - Thu, 01 Oct 2020 10:26:38 -0400 - - <![CDATA[ I came up with a four different approaches for Hacktoberfest this year: The Dependency Scrub, Polygot Achievement, Unknown Lands, and the Bug Doctor. ]]> - - <![CDATA[ -

Hacktoberfest 2020 is here! I can’t believe 2020 is winding down, good riddance!

-

I’ve been talking about Hacktoberfest with my co-worker Bryan and I thought of four different approaches to Hacktoberfest this year that I wanted to share.

- -

Dependency scrub

-

This is probably common everywhere but the Javascript/web communities are filled with npm packages. It’s packages all the way down. I think it would be interesting to approach this month looking for ways to remove third-party code from projects you love and use frequently.

-

Polygot Achievement

-

Try to submit four pull requests in four different languages. As Drew DeVault writes: Hack everything without fear!

-

Unknown lands

-

Similar to the previous one it could be fun to submit PRs against a project you’ve never been in before that’s in a language you don’t know. This could be anything from diving into Wordpress core, to working on some C for some Linux utilities, or even submitting PRs to open source Mac/iOS applications.

-

Bug doctor

-

Go into a project and find the oldest issues and try to resolve them via PR. This is inspired by Richard Schneeman’s video and post where he runs through 11 issues and 2 PRs in a hour and a half.

-

How are you approaching Hacktoberfest this year? My public inbox is open, let me know!

- - Discuss further in my public inbox - ]]>
-
- - Small tech - https://scattered-thoughts.net/writing/small-tech/ - - https://adamsimpson.net/writing/small-tech/ - Fri, 25 Sep 2020 15:53:06 -0400 - <![CDATA[ -

Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

-
    -
  • -

    curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

    -
  • -
  • -

    git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

    -
  • -
  • -

    Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

    -
  • -
  • -

    sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

    -
  • -
- - 🔗 - Discuss further in my public inbox - ]]>
-
- - Indexing My Blog’s Links - https://blog.jim-nielsen.com/2020/indexing-my-blogs-links/ - - https://adamsimpson.net/writing/indexing-my-blogs-links/ - Fri, 25 Sep 2020 15:49:21 -0400 - <![CDATA[ -

Owning your content means you can do interesting things with that data. Jim Nielsen did just that by tweaking his static site generator to see all the outbound links he’s ever posted.

- - 🔗 - Discuss further in my public inbox - ]]>
-
- - Compose key and i3 - https://adamsimpson.net/writing/compose-key-and-i3/ - - https://adamsimpson.net/writing/compose-key-and-i3/ - Fri, 18 Sep 2020 11:28:19 -0400 - - <![CDATA[ Here's how to bind the compose key to caps lock in i3wm. ]]> - - <![CDATA[ -

The compose key on Linux and other systems enables you to enter symbols like ™ that don’t have a dedicated key on most keyboards. GNOME makes this easy to do via Gnome Tweaks. However, using a window manager like i3 means there’s no dedicated GUI for changing the hotkey for compose.

-

This stackexchange answer sent me down the right path of adding the following config to ~/.Xmodmap to bind Caps lock to compose:

-
.keysym 66 = Mode_switch
-clear Lock
-

You can then enable the key map by running:

-
xmodmap ~/.Xmodmap
-

However, that config didn’t work because Mode_switch wasn’t the right name for the compose key (at least under Ubuntu/PopOS 20 for me). The Arch Wiki states that the name for the compose key is actually Multi_key. With this new name I was able to get Caps lock to act as the compose key by updating the config in ~/.Xmodmap to:

-
keycode 66 = Multi_key
-clear Lock
-

The final step is to set that mapping every time i3 runs by putting this inside your i3 config file like so:

-
exec --no-startup-id "xmodmap ~/.Xmodmap"
-
- Discuss further in my public inbox - ]]>
-
- - cycle v0.3.0 released - https://adamsimpson.net/writing/cycle-v030-released/ - - https://adamsimpson.net/writing/cycle-v030-released/ - Fri, 11 Sep 2020 12:04:16 -0400 - - <![CDATA[ Cycle version v0.3.0 is now available which features syntax highlighting via Chroma. ]]> - - <![CDATA[ -

I just released v0.3.0 of cycle.

-

This version uses Chroma for syntax highlighting instead of Pygments. I never got Pygments running correctly in Netlify’s build environment. Chroma requires no dependencies since it’s distributed as a static binary and it’s also faster due to being written in golang.

-

This version also refactors the main function to accept an optional working directory arg. This allows me to build a site via the CL REPL. It also shortens the feedback loop to try out new features.

- - Discuss further in my public inbox - ]]>
-
-
-
diff --git a/themes/cycle/exampleSite/public/sitemap.xml b/themes/cycle/exampleSite/public/sitemap.xml deleted file mode 100644 index ee85efd..0000000 --- a/themes/cycle/exampleSite/public/sitemap.xml +++ /dev/null @@ -1,539 +0,0 @@ - - - - https://adamsimpson.net/ - 2024-05-10T14:07:43-04:00 - - https://adamsimpson.net/writing/nixpkgs-is-a-treasure/ - 2024-05-10T14:07:43-04:00 - - https://adamsimpson.net/post/ - 2024-05-10T14:07:43-04:00 - - https://adamsimpson.net/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/ - 2023-07-25T15:10:24-04:00 - - https://adamsimpson.net/writing/better-scripting-with-gh/ - 2023-07-22T11:49:30-04:00 - - https://adamsimpson.net/writing/end-of-an-era/ - 2023-06-15T14:13:50-04:00 - - https://adamsimpson.net/writing/hacking-on-grafana-with-web-assembly/ - 2022-08-19T15:10:19-04:00 - - https://adamsimpson.net/writing/new-workstation/ - 2022-05-02T18:14:25+00:00 - - https://adamsimpson.net/writing/goodbye-sparkbox/ - 2022-04-01T18:20:31+00:00 - - https://adamsimpson.net/writing/thirty-five/ - 2022-03-03T10:28:44-05:00 - - https://adamsimpson.net/writing/windows-11-as-kvm-guest/ - 2022-02-28T13:39:37-05:00 - - https://adamsimpson.net/writing/a-few-posix-shell-tips/ - 2021-07-19T14:53:16-04:00 - - https://adamsimpson.net/writing/recently-16/ - 2021-04-23T11:37:19-04:00 - - https://adamsimpson.net/writing/8-line-firewall/ - 2021-03-31T11:18:24-04:00 - - https://adamsimpson.net/writing/how-to-use-siji-font-on-polybar/ - 2020-11-06T11:18:47-05:00 - - https://adamsimpson.net/writing/polybar-fonts-and-ubuntu/ - 2020-11-06T10:15:09-05:00 - - https://adamsimpson.net/writing/recently-44/ - 2020-10-27T23:30:46-04:00 - - https://adamsimpson.net/writing/four-ways-to-approach-hacktoberfest-2020/ - 2020-10-01T11:41:44-04:00 - - https://adamsimpson.net/writing/small-tech/ - 2020-09-25T15:53:06-04:00 - - https://adamsimpson.net/writing/indexing-my-blogs-links/ - 2020-09-25T15:49:21-04:00 - - https://adamsimpson.net/writing/compose-key-and-i3/ - 2020-09-18T11:28:19-04:00 - - https://adamsimpson.net/writing/cycle-v030-released/ - 2020-09-11T12:04:16-04:00 - - https://adamsimpson.net/writing/setting-a-default-browser-in-i3/ - 2020-09-11T00:01:05-04:00 - - https://adamsimpson.net/writing/eight-years/ - 2020-09-04T09:25:36-04:00 - - https://adamsimpson.net/writing/zach-beane/ - 2020-09-01T16:34:26-04:00 - - https://adamsimpson.net/writing/openring/ - 2020-08-21T16:09:44-04:00 - - https://adamsimpson.net/writing/a-public-inbox/ - 2020-08-17T23:14:25-04:00 - - https://adamsimpson.net/writing/rust-module-system/ - 2020-07-19T23:52:26-04:00 - - https://adamsimpson.net/writing/nothing-speaks-like-a-demo/ - 2020-07-19T23:46:14-04:00 - - https://adamsimpson.net/writing/a-new-website-for-2020/ - 2020-07-16T13:52:56-04:00 - - https://adamsimpson.net/writing/app_store_moment_of_clarity/ - 2020-07-13T14:10:09-04:00 - - https://adamsimpson.net/writing/goat-counter/ - 2020-07-01T15:49:45-04:00 - - https://adamsimpson.net/writing/is-webp-really-better-than-jpeg/ - 2020-06-30T13:13:04-04:00 - - https://adamsimpson.net/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/ - 2020-06-30T13:09:40-04:00 - - https://adamsimpson.net/writing/on-george-floyd/ - 2020-06-30T11:01:58-04:00 - - https://adamsimpson.net/writing/flatkill/ - 2020-06-15T13:03:27-04:00 - - https://adamsimpson.net/writing/ffmpeg-convert-multiple-files-using-xargs/ - 2020-06-04T14:43:26-04:00 - - https://adamsimpson.net/writing/search-imessage-sql/ - 2020-05-28T21:25:06-04:00 - - https://adamsimpson.net/writing/macos-catalina-slow-by-design/ - 2020-05-28T21:22:03-04:00 - - https://adamsimpson.net/writing/getting-started-with-rofi/ - 2020-05-28T13:35:15-04:00 - - https://adamsimpson.net/writing/what-time-is-it-in-london/ - 2020-05-22T10:44:04-04:00 - - https://adamsimpson.net/writing/psychicpaper/ - 2020-05-18T10:27:38-04:00 - - https://adamsimpson.net/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/ - 2020-05-18T10:20:08-04:00 - - https://adamsimpson.net/writing/second-guessing-the-modern-web/ - 2020-05-13T11:34:19-04:00 - - https://adamsimpson.net/writing/youtube-subscriptions/ - 2020-05-08T11:36:23-04:00 - - https://adamsimpson.net/writing/hiking-the-pacific-crest-trail-in-three-minutes/ - 2020-05-07T10:27:56-04:00 - - https://adamsimpson.net/writing/oscar/ - 2020-04-29T16:21:17-04:00 - - https://adamsimpson.net/writing/seamless-branch-deploys-with-kubernetes/ - 2020-04-27T10:10:46-04:00 - - https://adamsimpson.net/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/ - 2020-03-17T16:59:34-04:00 - - https://adamsimpson.net/writing/atr2100/ - 2020-01-29T12:55:45-05:00 - - https://adamsimpson.net/writing/rust-strings-and-str/ - 2020-07-03T23:20:47-04:00 - - https://adamsimpson.net/writing/tweet-stash/ - 2019-12-12T21:54:49-05:00 - - https://adamsimpson.net/writing/track-redirects-with-curl/ - 2019-10-22T13:25:50-04:00 - - https://adamsimpson.net/writing/the-thing-about-computers/ - 2019-09-21T13:40:51-04:00 - - https://adamsimpson.net/writing/dead-cells-might-be-a-perfect-game/ - 2019-09-20T10:23:59-04:00 - - https://adamsimpson.net/writing/0-14/ - 2019-07-30T10:31:07-04:00 - - https://adamsimpson.net/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/ - 2019-05-05T14:13:02-04:00 - - https://adamsimpson.net/writing/introducing-cycle/ - 2019-04-05T23:05:17-04:00 - - https://adamsimpson.net/writing/ajax-and-rails/ - 2019-01-28T11:25:49-05:00 - - https://adamsimpson.net/writing/blog-rewrite/ - 2018-11-20T23:02:21-05:00 - - https://adamsimpson.net/writing/medium-isnt-permanent/ - 2018-05-21T11:49:15-04:00 - - https://adamsimpson.net/writing/hosting-assets-via-github-pages/ - 2018-05-11T15:41:35-04:00 - - https://adamsimpson.net/writing/ivy-pinboard-popular/ - 2018-04-26T23:16:14-04:00 - - https://adamsimpson.net/writing/emacs-lite/ - 2018-04-19T10:42:41-04:00 - - https://adamsimpson.net/writing/hello-micro-blog/ - 2018-02-01T16:45:31-05:00 - - https://adamsimpson.net/writing/apple-on-batteries-and-performance/ - 2017-12-28T18:11:14-05:00 - - https://adamsimpson.net/writing/git-worktree/ - 2017-12-11T00:00:17-05:00 - - https://adamsimpson.net/writing/messi-is-re-writing-the-record-book/ - 2017-12-02T15:53:22-05:00 - - https://adamsimpson.net/writing/introducing-ivy-feedwrangler/ - 2017-11-16T11:06:20-05:00 - - https://adamsimpson.net/writing/a-hackintosh/ - 2017-09-14T10:11:55-04:00 - - https://adamsimpson.net/writing/on-equifax/ - 2017-09-08T16:31:42-04:00 - - https://adamsimpson.net/writing/before-circles-2017/ - 2017-09-06T11:52:29-04:00 - - https://adamsimpson.net/writing/five-years/ - 2017-09-05T23:00:18-04:00 - - https://adamsimpson.net/writing/on-diminishing-modes-in-emacs/ - 2017-08-17T12:09:25-04:00 - - https://adamsimpson.net/writing/helm-to-ivy/ - 2017-08-15T11:28:18-04:00 - - https://adamsimpson.net/writing/the-era-of-the-screenshot/ - 2017-06-12T22:56:24-04:00 - - https://adamsimpson.net/writing/format-json-in-emacs/ - 2017-05-23T14:11:28-04:00 - - https://adamsimpson.net/writing/diceware/ - 2017-04-19T21:47:54-04:00 - - https://adamsimpson.net/writing/facetime-killer/ - 2017-04-03T09:44:57-04:00 - - https://adamsimpson.net/writing/what-happens-when-you-remove-friction/ - 2017-03-27T13:33:36-04:00 - - https://adamsimpson.net/writing/emacs-tips/ - 2017-11-17T23:41:43-05:00 - - https://adamsimpson.net/writing/be-a-good-video-call-citizen/ - 2017-03-17T11:18:27-04:00 - - https://adamsimpson.net/writing/thirty/ - 2017-03-02T10:32:47-05:00 - - https://adamsimpson.net/writing/lambda-talk/ - 2017-02-23T13:04:21-05:00 - - https://adamsimpson.net/writing/we-all-need-a-team/ - 2016-06-28T13:48:38-04:00 - - https://adamsimpson.net/writing/web-scraper-cookbook/ - 2016-02-20T21:44:55-05:00 - - https://adamsimpson.net/writing/how-do-we-make-the-web-better/ - 2016-01-29T11:12:52-05:00 - - https://adamsimpson.net/writing/command-line-notification/ - 2016-01-16T15:40:26-05:00 - - https://adamsimpson.net/writing/verse-recall/ - 2015-12-23T09:31:02-05:00 - - https://adamsimpson.net/writing/sqlite-tips/ - 2020-09-17T11:53:48-04:00 - - https://adamsimpson.net/writing/on-webpack/ - 2015-12-07T14:05:04-05:00 - - https://adamsimpson.net/writing/migrate-an-existing-build-process-to-npm-scripts/ - 2017-05-23T14:05:10-04:00 - - https://adamsimpson.net/writing/casperjs-node-and-the-raspberry-pi/ - 2015-10-20T10:06:01-04:00 - - https://adamsimpson.net/writing/amp-html-terrible-html/ - 2015-10-08T09:56:38-04:00 - - https://adamsimpson.net/writing/farewell-heroku/ - 2015-10-06T14:00:52-04:00 - - https://adamsimpson.net/writing/parsing-memory-usage-in-htoptop/ - 2015-10-04T09:07:37-04:00 - - https://adamsimpson.net/writing/three-years/ - 2015-09-04T12:17:30-04:00 - - https://adamsimpson.net/writing/what-is-medium/ - 2015-08-27T14:37:02-04:00 - - https://adamsimpson.net/writing/small-things/ - 2015-08-22T16:43:26-04:00 - - https://adamsimpson.net/writing/automating-socks-proxy/ - 2017-02-24T09:41:13-05:00 - - https://adamsimpson.net/writing/the-stream-hasnt-won/ - 2015-07-17T10:37:33-04:00 - - https://adamsimpson.net/writing/microblogging/ - 2015-06-25T13:02:57-04:00 - - https://adamsimpson.net/writing/learning-to-think-in-react/ - 2015-06-24T11:42:13-04:00 - - https://adamsimpson.net/writing/moving-away-from-google/ - 2015-06-01T09:07:54-04:00 - - https://adamsimpson.net/writing/benedict-evans-in-on-fire/ - 2015-05-25T00:54:17-04:00 - - https://adamsimpson.net/writing/web-performance-and-facebooks-instant-articles/ - 2015-05-14T10:45:57-04:00 - - https://adamsimpson.net/writing/google-fi-and-data-only-plans/ - 2015-04-30T22:05:58-04:00 - - https://adamsimpson.net/writing/iphone-checker-with-capybara-and-twilio/ - 2015-04-03T11:53:41-04:00 - - https://adamsimpson.net/writing/vim-ramblings/ - 2015-03-21T19:45:36-04:00 - - https://adamsimpson.net/writing/s3-security-policy/ - 2015-03-21T19:45:36-04:00 - - https://adamsimpson.net/writing/keeping-up/ - 2015-03-21T19:45:36-04:00 - - https://adamsimpson.net/writing/broadcast-channel/ - 2015-03-21T19:45:36-04:00 - - https://adamsimpson.net/writing/moved-to-siteleaf/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/git-commit-template/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/adn-cross-poster/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/ifttt/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/js2coffee-alfred-workflow/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/huffduffer/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/slanted-elements-with-css3/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/rename-utility/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/what-matters/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/andy-budd-on-time/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/ip-address-alfred-extension/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/bash-function-ip-address-to-clipboard/ - 2015-03-24T13:11:31-04:00 - - https://adamsimpson.net/writing/a-few-bash-tips/ - 2017-02-24T09:36:16-05:00 - - https://adamsimpson.net/writing/rands-on-email/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/lyza-gardner-on-laying-down-our-burdens/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/family-first/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/alfred-and-web-development/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/theme-the-chrome-dev-tools/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/moving-tweetbot-beta-to-a-new-mac/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/heroku-and-ssh-keys/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/i-moved-to-hover/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/how-are-you-living/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/a-new-adventure/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/when-the-music-stops/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/tigers-and-social-networks/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/blogs-data-and-social-networks/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/maybe-you-shouldits-not-youmove-on/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/rotten-tomatoes-and-launch-center/ - 2017-02-24T09:38:13-05:00 - - https://adamsimpson.net/writing/working-with-wordpress-offset-and-pagination/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/plaintext-and-markdown-a-primer/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/gists-snippets-and-sublime-text-2/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/kyle-steed-on-rest/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/convince-the-boss/ - 2015-03-24T13:12:39-04:00 - - https://adamsimpson.net/writing/create-passion/ - 2015-03-24T13:12:21-04:00 - - https://adamsimpson.net/writing/using-the-kindle-to-harness-the-web/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/simple-account-set-up/ - 2017-02-24T09:39:40-05:00 - - https://adamsimpson.net/writing/the-future-is-prototyping/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/story/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/guidelines-for-data/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/whats-best-for-the-readers/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/what-its-all-about/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/sparrow-and-the-app-store/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/css-reusability/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/a-little-hydrofoil/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/the-web-is-not-print/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/declining-expectations/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/someone-is-working-harder-than-you/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/just-start-over/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/a-style-guide-guide/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/zen-garden-part-2/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/pretty-git-log/ - 2017-02-24T13:36:58-05:00 - - https://adamsimpson.net/writing/grow-it-dont-build-it/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/evening-edition/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/balancing-devotion/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/the-web-and-my-goal/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/nginx-www-rewrite/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/my-first-bookmarklet/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/the-wordpress-http-api-is-awesome/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/adam-versus-dropbox-and-oauth/ - 2015-03-24T13:08:44-04:00 - - https://adamsimpson.net/writing/the-manhattan-project-time-lapse/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/writing/hello-world/ - 2015-03-21T19:45:37-04:00 - - https://adamsimpson.net/archive/ - - https://adamsimpson.net/categories/ - - https://adamsimpson.net/page/ - - https://adamsimpson.net/page/support/ - - https://adamsimpson.net/tags/ - - https://adamsimpson.net/page/uses/ - - diff --git a/themes/cycle/exampleSite/public/tags/index.html b/themes/cycle/exampleSite/public/tags/index.html deleted file mode 100644 index 7ccbec8..0000000 --- a/themes/cycle/exampleSite/public/tags/index.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - Tags - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
    - -
-
- -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/tags/rss.xml b/themes/cycle/exampleSite/public/tags/rss.xml deleted file mode 100644 index 0ac0c36..0000000 --- a/themes/cycle/exampleSite/public/tags/rss.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - adamsimpson.net Post Feed - https://adamsimpson.net/ - Last 20 posts for adamsimpson.net - Thu, 09 Oct 2025 21:22:39 +0000 - en-us - - diff --git a/themes/cycle/exampleSite/public/writing/0-14/index.html b/themes/cycle/exampleSite/public/writing/0-14/index.html deleted file mode 100644 index 00df181..0000000 --- a/themes/cycle/exampleSite/public/writing/0-14/index.html +++ /dev/null @@ -1,267 +0,0 @@ - - - - - - 0.14 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

0.14

- - -
-

I type this on a Thinkpad t480s that I recently switched to from a lifetime of using Apple machines (literally grew up on Apple computers, shoutout to the Macintosh Classic!). I switched because it was time for a new machine and I didn’t want to be using a faulty keyboard for the next 5 years. Here are my caveats before I continue:

-
    -
  • If I wasn’t buying a laptop I would get an iMac or iMac Pro and all would be well. Apple desktop computers are in a great place right now.
  • -
  • This machine is for my work as a web developer and technical director at Sparkbox. The range of applications I need are largely all cross-platform: 1Password, Dropbox, Slack, Google Calendar, code editor, browser, terminal, email. I miss but don’t need: iMessage, Photos, Safari, Tweetbot, Sequel Pro etc.
  • -
  • I haven’t completely lost my mind, I’m not running Windows 10. I am using System76’s quite nice Pop_OS linux distro.
  • -
  • I got this Thinkpad before the latest (4th?) revision of the Macbook keyboards. I would still make this decision today given the unknown quality of these “fixed” keyboards.
  • -
-

Some of the niceties that come with the switch:

-
    -
  • User upgradeable RAM. The t480s has 1 open SO-DIMM slot and 8GB soldered to the motherboard. This feels like a nice compromise. Of course I threw in a 16GB stick to have 24GB total.
  • -
  • User upgradeable SSD. I can easily swap the stock SSD. A Samsung 970 Pro 512GB SSD that is faster than what Apple ships in the current Macbook Pro is $150 from Amazon.
  • -
  • Ports. The t480s has 2 USB-A ports and 2 USB-C ports. It also has a full size HDMI, SD card slot, and full-size Ethernet.
  • -
  • Of course, a best-in-class keyboard.
  • -
-

Here’s what stinks about it:

-
    -
  • No macOS
  • -
  • Inferior trackpad
  • -
-

The stark difference between the current Macbook Pros and this Thinkpad remind me of John Gruber’s apt comparison between iOS and macOS when the iPad was new on the scene (emphasis mine):

-
-

When I say that iOS has no baggage, that’s not because there is no baggage. It’s because the Mac is there to carry it. […] Mac OS X has an essential role in an iOS world: serving as the platform for complex, resource-intensive tasks.

-

The funny thing is, the best slogan to describe the Mac’s role is the same one it started with 25 years ago:

-

The computer for the rest of us.

-
-

Apple should apply this to hardware as well, let the iPad be the ultrathin device with limited ports. Don’t force that set of compromises on professional laptop users. Like I said above, Apple’s desktops are fantastic. Heck the Mac mini RAM is almost user serviceable. The t480s is not a thin machine compared to a 13" Macbook Pro: it’s 0.73" thick according to Lenovo’s official specs and weighs in at 2.9lbs. The Macbook Pro for comparison is 0.59" thick and weighs in at 3.02lbs. Is 0.14" difference in thinness worth access to the ports, user upgrade-ability, and the longevity of the keyboard? I certainly don’t think so and I’m disappointed Apple continues to demonstrate they care about that 0.14" more than any other single feature.

-

I desperately miss macOS but the Apple laptop hardware has atrophied to such a degree that the software alone isn’t worth it.

-

Update

-

Quite a bit of discussion happened over at lobste.rs. It’s easy to get hung up on which ports should be included but I think looking at Apple’s desktops is instructive: USB-A, SD Card, and USB-C/TB3 are all included (HDMI is nice in my opinion but I can see the argument for dropping it). None of those ports would cause the device to become unbearably thick and would add significant value and convenience.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/8-line-firewall/index.html b/themes/cycle/exampleSite/public/writing/8-line-firewall/index.html deleted file mode 100644 index 00b1d90..0000000 --- a/themes/cycle/exampleSite/public/writing/8-line-firewall/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - A firewall in 8 lines - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A firewall in 8 lines

- - -
-

Since 2017 my home router has been a plain x86 box running Alpine Linux. I never really think about it anymore. Recently, I was helping a relative set up their own Linux-based router and took the time to appreciate how little config is needed to setup a serviceable home router firewall using iptables. You can see my base rule-sets (port forwarding omitted) below:

-
-P INPUT DROP
--P FORWARD DROP
--P OUTPUT ACCEPT
--A INPUT -i lo -j ACCEPT
--A INPUT -i eth1 -j ACCEPT
--A INPUT -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
--A FORWARD -i eth1 -o eth0 -j ACCEPT
--A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-

The benefit of running a x86 box with Alpine (or any version of Linux) is that the box will receive a steady stream of security updates and upgraded kernels as Alpine Linux releases new versions. This is a much better situation to be in than relying on OS and security updates from a vendor like TPLink or Linksys.

-

If you have ideas for how to improve the config I listed above or want to chat more about home network stuff, send an email to my public-inbox.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html b/themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html deleted file mode 100644 index 7683e5c..0000000 --- a/themes/cycle/exampleSite/public/writing/a-few-bash-tips/index.html +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - A few Bash Tips - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A few Bash Tips

- - -
-

Here are a few custom little functions and aliases that I use everyday, these are all pretty straightforward, you can tweak any of these to fit your specific workflow.

-

The Bash Brothers

-

MAMP Virtual Hosts

-

It’s a pain to set up virtual hosts, which is why I wrote a bash script to automate that horrible process. Here is the script, I’ll explain how it works below (or check out the Gist):

-
#!/bin/bash
-RED="\033[0;31m"
-YELLOW="\033[33m"
-REDBG="\033[0;41m"
-WHITE="\033[1;37m"
-NC="\033[0m"</p>
-
-<pre><code>mkdir -p /Applications/MAMP/Library/vhosts;
-mkdir -p /Applications/MAMP/Library/vhosts/domains;
-
-if [ "$1" = "create" ] || [ "$1" = "add" ]; then
-# Ask for document root
-echo -e "${RED}Enter the document root (relative to 'htdocs'):${NC}";
-read documentRoot;
-
-# Ask for domain name
-echo -e "${RED}Enter local domain: (eg. local.com):${NC}";
-read domain;
-
-# Ask for port number
-echo -e "${RED}Enter MAMP Port Nubmer:${NC}";
-read port;
-
-# Add vhost
-touch /Applications/MAMP/Library/vhosts/domains/$domain;
-
-echo "<VirtualHost *:$port>
-DocumentRoot "/Applications/MAMP/htdocs/$documentRoot"
-ServerName $domain
-<Directory "/Applications/MAMP/htdocs/$documentRoot">
-    Options All
-    AllowOverride All
-    Order allow,deny
-    Allow from all
-</Directory>
-</VirtualHost>" >> /Applications/MAMP/Library/vhosts/domains/$domain;
-
-echo "127.0.0.1 $domain" >> /etc/hosts;
-
-# Restart MAMP
-/Applications/MAMP/bin/apache2/bin/apachectl restart;
-
-echo -e "Finished. ${REDBG}${WHITE}$domain:$port${NC} has been copied to your clipboard.";
-echo "$domain:$port" | pbcopy;
-fi
-
-if [ "$1" = "remove" ] || [ "$1" = "delete" ]; then
-echo -e "${RED}Here are the current custom local domains:${NC}"
-for file in /Applications/MAMP/Library/vhosts/domains/*
-do
-  if [ -f "$file" ];then
-    echo -e "${YELLOW}${file##/*/}${NC}"
-  fi
-done
-echo -e "${RED}Enter the site name you wish to remove:${NC}"
-read siteName;
-
-sed -i.bak "/$siteName/d" /etc/hosts;
-rm /Applications/MAMP/Library/vhosts/domains/$siteName;
-
-echo -e "${YELLOW}$siteName removed."
-fi
-

The script is set up to work with each web project being stored in a directory under htdocs in the MAMP folder. If you want to use a different folder structure, simply change the paths in the script to reflect your particular workflow.

-

The script asks for three pieces of info, the domain you want, the directory name, and the MAMP port number. The script creates a new directory called ‘vhosts’ and a sub directory called ‘vhosts/domains’. Each file in ‘domains’ is a single domain, which makes this all easier to manage. The script then modifies your etc/hosts file with the new domain information. Finally, the script restarts MAMP apache and copies the new domain address to your clipboard.

-

The last piece to this puzzle is the function that fires this script off.

-
function vhost {
-  sudo ~/.dotfiles/osx/mamp_vh.sh $1
-}
-

Just specify the path to the script and you are set.

-

Jump to project directory

-

Another pain point is jumping to a specific project directory quickly, and without a lot of path typing. I wrote a function that lists all the folders in my htdocs directory and lets me select the one I want to go to.

-
function ht {
-  local BLUE="\033[0;34m"
-  local RED="\033[0;31m"
-  local WHITE="\033[0;37m"
-  local NC="\033[0m"
-  echo -e "${BLUE}Projects:${WHITE}"
-    for file in /Applications/MAMP/htdocs/*
-    do
-      if [ -d "$file" ];then
-        echo ${file##/*/}
-      fi
-    done
-  echo -e "${RED}Which Project?${NC}"
-  read dir;
-  cd /Applications/MAMP/htdocs/$dir
-}
-

Again, simply change the paths in the script to adapt this to your workflow.

-

Colored History Grep

-

One little alias that I snagged from the numerous dotfile repos on Github is the ‘h’ alias which simply shortcuts the ‘history’ command. I love this little command, but I found myself typing out h | grep keyword to get a list of commands specific to a keyword. I shortened this up and added color highlighting:

-
function hg {
-  history | grep --color=auto $1
-}
-

Simply pass the function the term you are looking for. Remember you can execute previous functions by typing !999 (999 being the number of the command).

-

Keep tweaking and hacking

-

Hopefully these little utilities were useful in someway, feel free to comment or offer advice by reaching out on twitter or adn.

-

Update

-

I forgot to mention that I have two documents, one called “functions” and the other “aliases”, which I source at the top of my .bash_profile like this (You can see all my dotfiles over on Github):

-
. /.dotfiles/bash/functions
-. /.dotfiles/bash/aliases
-

Sourcing these files makes the functions and aliases inside them available on the command line. To use any of the functions or aliases in this post you have to source them to your bash, then you can simply type the alias or function name plus any arguments:

-
vhost create
-hg term
-ht
-

Thanks to Jack McDade for the advice to include some examples.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html b/themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html deleted file mode 100644 index 145d6fe..0000000 --- a/themes/cycle/exampleSite/public/writing/a-few-posix-shell-tips/index.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - A few POSIX shell tips - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A few POSIX shell tips

- - -
-

I was recently working on the release build script for sb and decided I should document a few things I find myself looking up just about every time. One of the advantages of the POSIX shell (not bash, zsh, but Bourne shell, usually /bin/sh on most unix-y systems) is that it has a specification however I’m usually frustrated trying to find the information I need.

- -

You can check it out here: https://github.com/sparkbox/sb

- -

I prefer the POSIX shell because it’s the default on most unix-y system. If I have to be sure if the shell is installed on the target system (like bash or zsh) I’d rather just use a higher-level scripting language like node or ruby where the same requirement exists.

-

Arrays

-

Psych! There aren’t any arrays. Bash has arrays but POSIX does not. If I need an array structure I can use a space-separated string (or another delimiter if you’ve set $IFS) as the data structure, e.g. PLATFORMS="arm64-darwin amd64-linux amd64-darwin". Now I can loop over the variable using a for loop:

-
PLATFORMS="arm64-darwin amd64-linux amd64-darwin"
-
-for PLATFORM in ${PLATFORMS}; do
-  # GOOS=FOO GOARCH=BAR go build ...
-done
-

Or I can take the lack of arrays as a signal I should stop writing a shell script and reach for a language that has the concept of arrays to solve my problem.

-

Conditional “flags”

-

I often forget the various flags one can use in a conditional (aka test/if) statement. Here’s the documentation and here are a few of my favorites:

-
    -
  • -n tests if the string is non-zero, e.g.
  • -
-
if [ -n "${UPLOAD_URL}" ]; then
-    upload_file "${PLATFORM}"
-fi
-
    -
  • -z the opposite of -n.
  • -
  • -f tests if the pathname resolves to a file.
  • -
-

Functions and args

-
    -
  • Functions must be declared before they are invoked.
  • -
  • Functions look like:
  • -
-
someFunc() {
-  echo "a func!"
-}
-
    -
  • There is no syntax for functions accepting args instead they are mapped to $n. $@ is all the args.
  • -
-
upload_file() {
-    NAME=$1
-
-    zip "${NAME}.zip" "${NAME}"
-    curl -H "Accept: application/vnd.github.v3+json" \
-         -H "Authorization: Bearer ${GITHUB_TOKEN}" \
-         -H "Content-Type: application/zip" \
-         --data-binary "@${NAME}.zip" \
-         "${UPLOAD_URL}?name=${NAME}.zip"
-}
-
-upload_file "${PLATFORM}"
-

Use shellcheck

-

This is just preference but I really love using shellcheck to avoid any footguns and enforce a consistent style with my shell scripts. I typically invoke it like this: shellcheck -o all script-name.sh.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html b/themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html deleted file mode 100644 index 851ee36..0000000 --- a/themes/cycle/exampleSite/public/writing/a-fluid-userscript-that-adds-read-it-later-to-twitter/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - A Fluid Userscript that adds Read it Later to Twitter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A Fluid Userscript that adds Read it Later to Twitter

- - -
-

I use and love Craig Mod’s Twitter for Minimalists. It is a great way to experience the Twitter web client without some of the cruft. However, the biggest thing I miss from third party apps like Tweetbot is the ability to send interesting links directly to my Instapaper account with one click.

-

Since Twitter for Minimalists runs inside a Fluid instance I can set custom Userstyles (like Twitter for Minimalists) and Userscripts. I decided to write a Userscript that would parse through every tweet and determine if it had a link and - if it did - append a Send to Instapaper button to the bottom of the tweet. I was able to create the button using Instapaper’s iFrame Button API. You can find the the finished code for the Read it Later Userscript here.

-

Hope you find it useful!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-hackintosh/index.html b/themes/cycle/exampleSite/public/writing/a-hackintosh/index.html deleted file mode 100644 index 5c7810b..0000000 --- a/themes/cycle/exampleSite/public/writing/a-hackintosh/index.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - A Hackintosh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A Hackintosh

- - -
-

Taking the Hackintosh plunge

-

I built a PC (here’s the partslist) in May to replace my Xbox One (yay no more Live fees!). And then last week with support for AMD GPUs in 10.12.6, I took the plunge and turned that PC into a Hackintosh. The process of getting a Hackintosh up and running wasn’t really that much more difficult than setting up Arch Linux. In fact I’d say you could and probably should follow most of the Arch Linux ideals about knowing what and why you’re updating as you maintain a Hackintosh.

-

Here’s a few tips and things I learned along the way. I’d also recommend reading through the tips in this reddit post.

-

Happy Path (Use Clover)

-

The ideal setup is to use Clover to add ktext and modify the config.plist in the /EFI partition. This leaves your actual macos install untouched. Avoid Unibeast and Multibeast, they try do too much and mask complexity. The truly “do-it-yourself” approach is outlined here. I ended up following a guide and using (and then modifying) their pre-made /EFI partition. Speaking of…

-

Find a guide

-

I combined and followed these two guides:

- -

Keep it simple

-

Solve one thing at a time. Google error messages.

-

Use compatible parts

-
    -
  • I’d recommend an Intel KabyLake CPU since it’s the latest and greatest and it means you’ll need a 200 series motherboard which is recommended anyway. AMD CPUs are not really supported.
  • -
  • While my build uses the Pentium G4560 I wouldn’t recommend it as a great Hackintosh CPU. It works, but things would be smoother with an i5 or i7.
  • -
  • AMD GPUs (if you can find one at a decent price, damn you Etherium) have great native support now in 10.12.6, e.g. Metal Support!
  • -
  • Grab a WiFi/Bluetooth card from osxwifi.com, genuine Apple parts which means things just work (I’m content with no Bluetooth and Ethernet for now)
  • -
-

One OS per drive

-

Don’t try to partition a drive and install macos and Windows on it. Keep all operating systems on their own boot drives and then boot into them using Clover.

-

Disable hibernation if you’re on a Pentium

-

You’ll need to set two power management switches:

-

sudo pmset -a hibernatemode 0

-

sudo pmset -a standby 0

-
-

To disable hibernation images completely, ensure hibernatemode standby and autopoweroff are all set to 0. ~ pmset man page

-
-

I didn’t run into issues with autopoweroff.

-

Disable automatic updates.

-

You can still update through the App Store but it’s advised to wait and see if any ktexts or plist changes are needed before updating

-

That’s it. Hopefully this post helps clarify the process to create a Hackintosh of your own.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html b/themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html deleted file mode 100644 index b801cac..0000000 --- a/themes/cycle/exampleSite/public/writing/a-little-hydrofoil/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - A Little Hydrofoil - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A Little Hydrofoil

- - -
-

While taking a short break today, I flipped over to Robin Sloan’s interview on the Setup. Now Mr. Sloan almost broke the Internet a few days ago with his book review in Javascript. In his interview for the Setup he described how he sees himself as a programmer,

-
-

I imagine professional programmers as jumbo jets, capable of cruising smoothly and swiftly at altitude for hours, no internet needed; by contrast, I’m just a little hydrofoil kinda bumping along, held shakily aloft by the ground effect of online documentation, code snippets and tutorial blog posts.

-
-

I totally identify with his analogy, and would wager most “jumbo jets” feel the same way. I think this ties into why I agree so strongly with Alex Sexton’s tweet from earlier this year (hat-tip to Motherfuton for the RT),

-
-

I think being skilled at debugging is probably more important than being skilled at coding.

-
-

Programming is problem-solving, hence my constant dips into Stackoverflow and Google. To extend Mr. Sloan’s analogy a bit more, even Jumbo Jets need maintenance and fuel.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-new-adventure/index.html b/themes/cycle/exampleSite/public/writing/a-new-adventure/index.html deleted file mode 100644 index c745854..0000000 --- a/themes/cycle/exampleSite/public/writing/a-new-adventure/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - A New Adventure - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A New Adventure

- - -
-

Today I started my new job working as a Front-End Developer at Sparkbox! I am thrilled at the opportunity to work with these guys and can’t wait for the adventures and challenges ahead.

-

Onward and upward.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html b/themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html deleted file mode 100644 index 6bf4fb0..0000000 --- a/themes/cycle/exampleSite/public/writing/a-new-website-for-2020/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - A new website for 2020 - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A new website for 2020

- - -
-
-

According to my Cargo.lock file, my website currently depends on 364 crates. So it’s really about standing on the shoulder of a carefully-curated set of giants.

-
-
-

364 may seem like a lot (and in a way, it is), but please reserve your judgement until after you’ve heard about everything it does.

-
-

I /love/ posts like this. Amos goes in deep on the decisions he made while re-writing his website from scratch. It’s a truly awesome post.

-

I’m seriously tempted to copy his SQLite full-text search implementation for this blog, but that’s a decision for another time.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-public-inbox/index.html b/themes/cycle/exampleSite/public/writing/a-public-inbox/index.html deleted file mode 100644 index c0eddb5..0000000 --- a/themes/cycle/exampleSite/public/writing/a-public-inbox/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - A public inbox - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A public inbox

- - -
-

I’ve tried a few blog commenting systems in my day but have never really been happy with any of them. Part of the problem with comment systems is that a discussion forum is not a blog.

-

Recently I’ve noticed a few other folks (Drew, Ethan, Tom, and Jonnie) around the internet turning to email as the solution to have conversations about the things on their respective websites. I liked how Drew’s solution not only leveraged email but mailing lists! The benefits are pretty obvious to me:

-
    -
  • Folks are comfortable composing messages in their email client of choice
  • -
  • A mailing list is public
  • -
  • A mailing list is searchable
  • -
  • A mailing list facilities conversation.
  • -
-

So I’m gonna give it a spin. Here is my public inbox.

-

Of course I’ll always accept direct email at adam@adamsimpson.net.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html b/themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html deleted file mode 100644 index 42ebcba..0000000 --- a/themes/cycle/exampleSite/public/writing/a-style-guide-guide/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - A Style Guide, Guide - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A Style Guide, Guide

- - -
-

Thanks to @behoff for tweeting out Elyse Holladay’s blog post about a guide for style guides.

-

The post is a fantastic read, and is chock full of good information. I then clicked over to see what else Ms. Holladay had written and found her Hello World? post. It really resonated with my own reasons for starting this blog, especially this bit:

-
-

I realized two things have stopped me: the feeling of inadequacy that leads to the fear of not starting, and the need to get it perfect first.

-
-

I struggle with the same mindset. I’ve found the best way to get over it, is to just ship. So, congrats Ms. Holladay on shipping, and congrats on the blog, it’s awesome.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html b/themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html deleted file mode 100644 index ed0551c..0000000 --- a/themes/cycle/exampleSite/public/writing/adam-versus-dropbox-and-oauth/index.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - Adam versus Dropbox and oAuth - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Adam versus Dropbox and oAuth

- - -
-

Frustration post incoming. If you’d like to skip my ranting, watch this breakdancing bear. Otherwise, let’s keep going.

-

Update: I’ve posted an update below.

-

Stuck

-

I’ve never developed anything using Dropbox’s API or oAuth before. I’m assuming I’m making a horrible, noobish mistake somewhere in here. There is no official PHP SDK for Dropbox API. There are a couple libraries floating around, but they looked like overkill for the simple app idea I’m working on.

-

My problem is that when I try to request a token from Dropbox via PHP and cURL I get an ‘Error 4xx’. I’ve looked at the oAuth specs for the proper parameters to send in the header of the request, and right now my request looks like:

-

-[request_header] => POST /1/oauth/request_token HTTP/1.1
-Host: api.dropbox.com
-Accept: <em>/</em>
-Authorization: OAuth oauth_consumer_key="CONSUMERKEY", oauth_nonce="1340748835", oauth_signature_method="PLAINTEXT", oauth_timestamp="1340748835", oauth_version="1.0", oauth_signature="CONSUMERSECRET%26"
-Content-Length: -1
-Content-Type: application/x-www-form-urlencoded
-Expect: 100-continue
-

And this doesn’t yield a token, just ‘Error 4xx’.

-

Yet, when I paste in the full request in the address bar of Chrome:

-

https://api.dropbox.com/1/oauth/request_token?oauth_consumer_key=CONSUMERKEY&oauth_nonce=1340743892&oauth_signature_method=PLAINTEXT&oauth_timestamp=1340743892&oauth_version=1.0&oauth_signature=CONSUMERSECRET%26

-

I get my token back no problem. So I’m assuming something is wrong with the format of my cURL request.

-

The reason I’m using PLAINTEXT as the method is because of this post in the Dropbox forums. And, like I said, just entering in the request directly works fine.

-

Help

-

Any ideas? Let me know on Twitter @a_simpson. I’ll be sure to update this post once I get this problem sorted. So far, the lack of documentation for all this has been frustrating.

-

Update

-

Well I’ve sorted it out after sleeping on it, and breaking it all down again.

-

Turns out the cURL options array I was passing was incorrect. I was declaring CURLOPT_POST => true after several other POST-reliant options such as CURLINFO_HEADER_OUT and CURLOPT_POSTFIELDS. This mix-up was causing the request to error out. In retropect I should have realized that right away, oh well. Once I got the order straightened out, the request went through.

-

However, in my Googling to solve my problem I came across an awesome post from Wez Furlong detailing how to do HTTP requests in PHP without using cURL or any other library. I’ll let you read it, but all I’ll say is I switched to the solution he outlines, and I love it.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html b/themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html deleted file mode 100644 index 177d70f..0000000 --- a/themes/cycle/exampleSite/public/writing/adn-cross-poster/index.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - ADN Cross-poster - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

ADN Cross-poster

- - -
-

Recently I released a App.net to Twitter cross-posting app that runs via a single Heroku worker dyno (which means it’s free, gracias Heroku).

-

IFTTT Issues

-

For awhile I had been using IFTTT to crosspost any posts I made on App.net to Twitter, however there were two things I wasn’t totally thrilled with.

-

First, IFTTT automatically converts any links in your App.net post to bit.ly links, which stinks as I want the links in my intended format and style. The other thing IFTTT did poorly was how it handled posts that were longer than 140 characters. Since App.net posts can be up to 256 characters, sometimes a post will be too long for Twitter, IFTTT would simply chop your post at the 140 character point and be done.

-

Features

-

ADN-Crossposter specifically addresses these two complaints.

-

First, it leaves links alone. The app simply pushes your post text to Twitter.

-

Second, the app checks the character count of the App.net post and if it’s longer than 140 character it trims the post and adds a link to the App.net post, e.g. a read more link.

-

Get the app

-

Clone the app. Add your ADN username to the config.rb file. You can also choose how to handle @replies as well.

-

Twitter Setup

-

Since this is something that deals with Twitter there are a few steps involved in getting it up and running with their API. You will need to set up your own app within the Twitter dev panel. Your Twitter app needs to have read and write access to your Twitter account for this to work. Once you have the app created you will need to copy the four OAuth keys into the config.rb file.

-

You may need to regenerate your keys after changing your app from “Read” to “Read and Write”.

-

Heroku Setup

-

Create a Heroku app via the Heroku dashboard. Go back to your local git repo and add this Heroku app as a git remote.

-

Launch

-

Run git push HEROKU_REMOTE master after committing all the necessary changes to the config.rb file. Heroku will detect what type of app it is automatically. Now set your process or worker dyno to 1 via the Heroku dashboard or the command line, heroku ps:scale clock=1

-

Wrap Up

-

That’s it. Whew. If for some reason the app isn’t working, run heroku logs from the command line to see what the error was. If you still have issues, create an issue on Github with any log message you can.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html b/themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html deleted file mode 100644 index 34c15b5..0000000 --- a/themes/cycle/exampleSite/public/writing/ajax-and-rails/index.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - Ajax and Rails - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Ajax and Rails

- - -
-

This is just a short post to save a few links and document that “Server Javascript Responses” in Rails are still useful in 2018/19.

-

Lifecycle of SJR

-

The basic idea behind Server Javascript Responses (SJR) is diagrammed below:

-

img

-

SJR works like this:

-
    -
  1. -

    A User submits a form that has the Rails attribute remote=true on the form tag which makes the form submission happen via AJAX. See the Rails guide for more information.

    -
  2. -
  3. -

    The server receives the data payload and processes a response.

    -
  4. -
  5. -

    The Response from the server is a blob of JS not JSON that usually comes from a matching name.js.erb template.

    -
  6. -
  7. -

    The User’s browser receives the JS blog and evals the JS to update the page.

    -
  8. -
- -
    -
  1. DHH’s original post
  2. -
  3. Medium post about eschewing fancy front-end frameworks for SJR
  4. -
  5. Ajax calls the Rails way
  6. -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html b/themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html deleted file mode 100644 index 1037892..0000000 --- a/themes/cycle/exampleSite/public/writing/alfred-and-web-development/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - Alfred and Web Development - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Alfred and Web Development

- - -
-

Fellow web developer and all around awesome guy Adam Clark, put together two fantastic screencasts on his blog which demonstrate the power of Alfred and how to enhance common front-end workflows. Inspired by his post, I thought I would start sharing some tips on how I use Alfred throughout the day.

-

I use Alfred 57.4 times a day. It’s awesome, so awesome that it has replaced Spotlight on my Mac. I have two custom searches that relate directly to front-end development, a Mozilla Developer Documentation custom search, and a Can I use custom search. These shortcuts allow me to:

-
    -
  1. Invoke Alfred
  2. -
  3. Type “cani” or “mdn” followed by a space.
  4. -
  5. Type my query, i.e. “background-size”
  6. -
  7. Hit Enter and see the resulting documentation or caniuse page for the query.
  8. -
-

Here are the actual URLs as I set them up in Alfred: https://developer.mozilla.org/en-US/search?q={query} http://caniuse.com/#search={query}

-

This is a simple thing to setup, and it probably only saves a few seconds, but it feels friction-less which is the whole point of using Alfred.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html b/themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html deleted file mode 100644 index 4bea5cf..0000000 --- a/themes/cycle/exampleSite/public/writing/amp-html-terrible-html/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - AMP HTML, Terrible HTML - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

AMP HTML, Terrible HTML

- - -
-

Seriously, how could this possibly go wrong?!

-

AMP HTML is another middle finger to publishers and ad companies everywhere, and in the process it throws the baby out with the bath water. Essentially Google is saying to publishers and ad companies, “You can’t responsibly handle the power the web gives you. So here’s something far more limited. Enjoy.”

-

I agree with the first part, but is the answer developing a subset of HTML/JS/CSS?

-

-

Update

-

This post explores my misgivings in more detail:

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html b/themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html deleted file mode 100644 index 5919db8..0000000 --- a/themes/cycle/exampleSite/public/writing/andy-budd-on-time/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - Andy Budd on Time - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Andy Budd on Time

- - -
-

Fantastic Pastry Box post from Andy Budd, I’ll quote the final thought here, but it’s worth it to read the entire thing

-
-

The best designers and developers rarely have more talent. They simply have more time.

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html b/themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html deleted file mode 100644 index 2ed731e..0000000 --- a/themes/cycle/exampleSite/public/writing/app_store_moment_of_clarity/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - A Moment of Clarity Regarding the Raison d’Etre for the App Store - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

A Moment of Clarity Regarding the Raison d’Etre for the App Store

- - -
-
-

I’d like to see all the vim, vigor, and vigilance Apple applies to making sure no app on the App Store is making a dime without Apple getting three cents applied instead to making sure there aren’t any scams or ripoffs, and that popular apps support good-citizen-of-the-platform features within a reasonable amount of time after those features are introduced in the OS. I don’t know exactly how long “reasonable” is, but five fucking years for split-screen support ain’t it.

-
-

I’ve been thinking the same thing ever since the Hey app rejection right before WWDC. The App Store is supposed to be a place to get software that has been vetted by Apple but there seems to be a growing disconnect between what users imagine that vetting is and what Apple is doing.

-

I want to believe this tweet by Ben Evans is the goal of the App Store:

- -

If we can trust the apps that come out of the App Store:

-
    -
  • why is the US considering banning TikTok because of its rampant data collection?
  • -
  • why do we need a new notification in iOS 14 when apps query the clipboard?
  • -
  • why do we need a microphone/camera indicator at the system level?
  • -
-

Maybe I was naive and alone in my assumption that Apple would root this stuff out during the review process. If they’re not rooting this out then what is the point of the review process at all?

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html b/themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html deleted file mode 100644 index cf374c7..0000000 --- a/themes/cycle/exampleSite/public/writing/apple-on-batteries-and-performance/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - Apple on batteries and performance - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Apple on batteries and performance

- - -
-

Apple released a statement on the battery and performance issues.

-
-

Apple is reducing the price of an out-of-warranty iPhone battery replacement by $50 — from $79 to $29 — for anyone with an iPhone 6 or later whose battery needs to be replaced, starting in late January and available worldwide through December 2018. Details will be provided soon on apple.com.

-
-

This is the penalty for not being clear with users. How and why did Apple make this so opaque? It continues to baffle me.

-
-

Early in 2018, we will issue an iOS software update with new features that give users more visibility into the health of their iPhone’s battery, so they can see for themselves if its condition is affecting performance

-
-

This is what should have been in iOS when the processor management feature was released.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/atr2100/index.html b/themes/cycle/exampleSite/public/writing/atr2100/index.html deleted file mode 100644 index 02288f1..0000000 --- a/themes/cycle/exampleSite/public/writing/atr2100/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - ATR2100 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

ATR2100

- - -
-

I recently purchased the ATR2100 mic to use for work calls and maybe some podcasting in the future. I stumbled upon the ATR2100 via Marco Arment who has a great roundup of good podcasting mics that I highly recommend if you want to explore mics. I ended up picking up an Amazon bundle that included a Knox boom arm, Knox pop filter, and the ATR2100 for around $90. I don’t see it on the site anymore but you could cobble together the same bundle pretty easily.

-

Requirements

-

These were my requirements for upgrading from the built-in mic on my laptop/webcam:

-

Sound good with little effort

-

Obvious but important. I didn’t want to have to fiddle with things to achieve better sound. I also didn’t want to invest in a DAC or other ancillary equipment.

-

Reduce background noise

-

My office at home is in the basement right below my 3 year-old daughter’s room. Kids make noises from time to time and I wanted a mic that would not pick those up.

-

Be under $100

-

I didn’t have the budget to go get a premium mic.

-

Verdict

-

I’ve used the mic for some gaming and Zoom calls and in both cases I’ve gotten several comments that my voice sounds “radio quality” and “really clear”. I have zero complaints with the mic and I can’t recommend it enough. I will note that this type of mic requires you to be about 2-6 inches away for optimal volume and quality. This is the cost of not picking up those background noises I mentioned above in my requirements. Windows 10, Linux (Pop_OS), and macOS all recognized the mic without any drivers or needing any configuration. If you’re looking to upgrade your audio on a budget look no further than the ATR2100.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html b/themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html deleted file mode 100644 index ae64e03..0000000 --- a/themes/cycle/exampleSite/public/writing/automating-socks-proxy/index.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - Automating SOCKS proxy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Automating SOCKS proxy

- - -
-

I’ve used a SOCKS proxy while on public WiFi ever since reading Paul Stamatiou’s article years ago. I recently took the time to automate the setup process.

-

Paul’s article provides a good overview of what the heck a SOCKS proxy is and why it’s beneficial, so I won’t focus on any of that here. Just know that setting up a SOCKS proxy on a Mac is a multi-step process. This process led me to create two bash functions; one to start it and another to shut it down.

-
function tunnel_off {
-  PID="$(ps aux | grep $1 | grep -v grep | awk '{print $2}')";
-  kill ${PID} && networksetup -setsocksfirewallproxystate Wi-Fi off;
-}
-
-function tunnel {
-  ssh -D 8080 -f -q -N $1 && networksetup -setsocksfirewallproxystate Wi-Fi on
-}
-
-

I do need to pass the ssh server name (configured in ~/.ssh/config) I want to use, e.g. tunnel vpn.

-

The only setup is to manually configure which port I want to use for the SOCKS proxy, I set that in System Preferences under Network:

-

The best part is the networksetup -setsocksfirewallproxystate command. This command makes the whole thing go by toggling the proxy on and off.

-

For extra credit, I use the fantastic TextBar utility to monitor if the ssh connection is active and display the lightning emoji in my menu bar if it is. I now know when the proxy is running or not by glancing up at the menubar.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/balancing-devotion/index.html b/themes/cycle/exampleSite/public/writing/balancing-devotion/index.html deleted file mode 100644 index b208101..0000000 --- a/themes/cycle/exampleSite/public/writing/balancing-devotion/index.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - Balancing Devotion - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Balancing Devotion

- - -
-

After watching Indie Game: The Movie I couldn’t help but think of the Robert Louis Stevenson quote that Shawn Blanc used a few weeks ago:

-
-

Perpetual devotion to what a man calls his business, is only to be sustained by perpetual neglect of many other things.

-
-

In the movie, the game designers and developers pour their lives into creating these games. At one point in the movie, the creator of Fez said he would literally kill himself if he were unable to finish and release it. Thankfully, he released Fez in 2012 to wide acclaim. Despite his success, his quote still bothers me. Suicide over a game?! I don’t get it.

-

Matthew Smith of Zaarly, recently wrote for the Pastry Box Project:

-
-

Turn off your phone when you get home. Off. Don’t just put it on the counter. Turn it off for a few hours at least each day. Why? So that you’re not always available to others. Be available to yourself. Be available to your family. Then at 8am when you turn your phone back on, you can be fully available and totally present.

-
-

Matthew is talking about disconnecting from the interewbs in order to recharge, and be a better son/father/daughter/wife/mother/roommate/friend/neighbor/whatever. I struggle with disconnecting, while I don’t have the same intensity as suicide over a game, it’s the same kind of devotion, and I know how easily it creeps in.

-

This all makes me wonder if it is possible to create something truly extraordinary without causing everything else to wither? In one of the most recent entries on The Pastry Box, Molly Holzschlag tries to answer this question.

-
-

Here’s some advice from the heart: There is nothing wrong with giving your life to an ideal. I have done it, and the rewards are rich— friends from all over the world, respect from my peers, to have traveled much of the earth and been made welcome upon it—that is the miraculous part of giving your work your all, it comes back. Just don’t let what happened to me happen to you—the work, the ideal takes over too young and for too long, and you could easily end up childless or without family, with little or no life structure or real measure of how to reconcile this elusive balance.

-
-

She acknowledges that to achieve something extraordinary you have to devote yourself to it. Her solution is to not devote yourself for so long that you are left with nothing. That’s the trick.

-

I think there has to be a better way than planning to “wake up” before your 30s are gone. As I was writing this post yesterday, Jack McDade posted a short note that was exactly what I was trying to say. He wrote:

-
-

So how do you “switch off”? It’s not hard when you have perspective. You just switch off. Boy does it feel great.

-
-

Hes got it. There isn’t a secret way to achieve both a great product and a healthy life outside of it. I believe it’s possible to do both, not keeping them in balance is just much easier. Keeping that balance is a constant struggle, it’s a fight, it’s learning how to say “no” at the right times, it’s turning your phone off when you get home. Hell, merely going home at 5 or 6 helps the balance.

-

To keep it all in balance, you just have to do it.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html b/themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html deleted file mode 100644 index e18c1f3..0000000 --- a/themes/cycle/exampleSite/public/writing/bash-function-ip-address-to-clipboard/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - Bash Function - IP Address to Clipboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Bash Function - IP Address to Clipboard

- - -
-

I have to admit, I am addicted to customizing my bash experience. Yesterday, I came up with a little, one-off function that smooths over a point of friction in my workflow – working with my internal IP address.

-

During any project, I am often testing in virtual machines. On my development machine I have my host file hacked to manage all the dev URLs. The friction point is constantly having to look up my IP address to test in VMs, or on other devices. This bash function simply parses out my IP address from the results of ‘ifconfig’ and copies that IP address to my clipboard. Now, instead of jumping into the Network pane to see my IP, or reading through ifconfig myself, I can simply type “ip”, and jump back to my VM and paste in the address. The function also displays the IP address on the command line ready for easy typing into a mobile device.

-
function ip {
-  IP=$(ifconfig | grep 'inet 1' | cut -c 6- | awk 'NR==2 {print $1}')
-  echo $IP
-  echo $IP | pbcopy
-}
-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html b/themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html deleted file mode 100644 index ed95bfd..0000000 --- a/themes/cycle/exampleSite/public/writing/be-a-good-video-call-citizen/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - Be a good video call citizen - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Be a good video call citizen

- - -
-

Ah the video call. Usually fraught with 5 minutes of “Can you hear me now?”, distorted faces, or your two children in the background. I’ve been in my fair share of video calls and I thought I’d share a few tricks that help limit my contributions to the chaos.

-

Be a few minutes early.

-

If you’re there early you can get any hiccups (technical or otherwise) out of the way before the meeting actually starts. No fancy technical trick here.

-

Keep your workspace neat

-

Again, not a technical solution but a practical one. Limit the distractions you may present by having a tidy workspace. Pay special attention to what’s behind you before you get on a call. Everyone’s been laughing at poor Professor Kelly recently but notice that he clearly spent some time before the call trying to make his background look good.

-

Use a cough button (aka push-to-talk)

-

I love the Shush app. It works at the system level to mute or unmute your microphone and binds that action to a hotkey. Shush is fantastic because you don’t need to remember where each video service stashes its mute button. The ability to quickly toggle mute is a super power that goes a long way towards minimizing any distractions you may create while on the call.

-

There you have it, my top three tips for video calls. Do you have any other tips? Let me know about them on twitter and I’ll list them below.

-

Replies

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/before-circles-2017/index.html b/themes/cycle/exampleSite/public/writing/before-circles-2017/index.html deleted file mode 100644 index 06d77b8..0000000 --- a/themes/cycle/exampleSite/public/writing/before-circles-2017/index.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - Before Circles 2017 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Before Circles 2017

- - -
-

I’m currently sitting on an airplane headed to Grapevine, Texas for Circles Conf. Circles Conf is a design conference that I’ve kept an eye on for the last couple years. I specifically chose this conference because it wasn’t a development conference. As a frontend developer, I think it’s important to be well-rounded in all aspects of the frontend and that includes design. I feel like the last couple years I’ve invested deeply in Javascript and all the incredible ways frontend code is changing. However, I think it’s time to work out a different set of muscles. So, I’m headed to a design conference as a frontend developer and I don’t see a single talk about “Slack bots with Node” (or something about “Serverless and React”) on the schedule and I’m super pumped.

-

Expectations

-

I thought I’d list out a few of the talks I’m looking forward to and what I hope to come away with. I think the entire lineup looks great but there are a few TBA slots with no title so I have no idea what to think about those. I’m hoping to review this post after the conference and use it as a kind of guide to digest everything that happened.

-

Panels

-

I have no idea what to expect from the scheduled Panels. There is one each day maybe this will be some solid Q/A or good round-table discussion?

-

Dan Rubin

-

I’m excited to hear Dan Rubin. I’ve followed Dan on Twitter and Instagram for some time but I’ve never heard him speak.

-

Ash Huang

-

I’ve never heard of Ash until I saw the speaker line-up, but she’s seems like a prolific writer and deep thinker. Her talk is called “Design was supposed to be The Answer” and I can’t wait to hear it. I also think there is a talk called “Javascript was supposed to be The Answer” just waiting to be written.

-

Jay Argaet

-

I’m a fan of Hillsong’s music along with their branding and art direction. I’m curious to hear what Jay has to say about “Unlocking Creativity”.

-

Annette Neu

-

The topic for Annette’s talk resonates with me. I often feel unsure how to begin on a problem that has lots of uncertainty surrounding it. I’m confident this will apply to all creative disciplines (e.g. development as well as design).

-

Here we go

-

So there you have it. My scant expectations on what I’m looking forward to at Circles Conf. If you’re attending Circles don’t hesitate to say hi (or hit me up on twitter) and get a swanky Sparkbox business card!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html b/themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html deleted file mode 100644 index 11de1a9..0000000 --- a/themes/cycle/exampleSite/public/writing/benedict-evans-in-on-fire/index.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - Benedict Evans is on fire - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Benedict Evans is on fire

- - -
-

I’ve been behind my pinboard unread queue for a few days and consequently have been missing the truth pouring out of Benedict Evans.

-

His last three pieces are right on the money regarding mobile, and the web versus native apps.

-

Starting with Mobile First, he says:

-
-

[…]the smartphone itself is an internet platform in a way that a PC was not. On a PC the web browser was the internet platform, but on a smartphone it’s the entire device and the browser is turned from ’the internet’ to one icon, just a phone calls turned from the purpose of the device to just one icon.

-
-

Then in Apps versus the web he finishes the piece by saying:

-
-

In either of these cases - whether you have an app and a website or just a website, you should presume that your customers will engage with you only on mobile.

-
-

And finally his last piece The future is mobile and apps, except that it isn’t he writes:

-
-

So the mobile experience needs to be complete. That might, paradoxically, mean that your total experience might need to be edited, to fit, but it’s dangerous to pick a subset of your offer and put just that on mobile - it might be your only touch point. Conversely, one could argue that in some cases it’s the desktop experience that should be a subset of the mobile one.

-
-

Complete

-

The mobile experience needs to be complete, and that experience can be just a website, or just an app, or both. Regardless it needs to be complete. Complete is the operative word that binds these thoughts together. As we saw last week, complete includes performance, especially performance on mobile.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html b/themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html deleted file mode 100644 index c9b5dae..0000000 --- a/themes/cycle/exampleSite/public/writing/better-scripting-with-gh/index.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - Better scripting with gh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Better scripting with gh

- - -
-

I’ve become a big fan of the gh CLI tool from Github. It has eliminated the need for me to manage developer tokens for my scripts. Instead of using curl with a Github token and the Github API, I can simply use gh. What’s even better is that in more advanced situations where there isn’t a valid subcommand for what I want to script, I can use the gh api escape hatch to do curl-style HTTP requests to the API without messing with authentication or even pagination. Here are two recent scripts I wrote that highlight the power and convenience of gh.

-

PR Kudos

-

I created this script to help me give better kudos to folks in our retro meeting. When I provide a Github team name as an argument, it displays all PRs from members of that team. What I really like is that it only shows PRs from the last two weeks, which gives me a nice overview of recent activity.

-
#!/bin/bash
-
-start=$(date -d "2 weeks ago" +%Y-%m-%d)
-end=$(date +%Y-%m-%d)
-
-details=$(gh api /orgs/grafana/teams/$1 | jq -r '"\(.id),\(.organization.id)"')
-teamId=$(echo ${details} | cut -d , -f 1)
-orgId=$(echo ${details} | cut -d , -f 2)
-
-gh api "organizations/${orgId}/team/${teamId}/members" | \
-  jq -r '.[] | .login' | \
-  xargs -I % gh search prs --author=% --created="${start}..${end}" \
-  --json="state,repository,url,title,updatedAt,author" --template '{{range .}}{{tablerow (.author.login | autocolor "green") (hyperlink .url .title) (.repository.name | autocolor "blue") (.state | autocolor "red") (timeago .updatedAt)}}{{end}}
-{{tablerender}}'
-

Notification OCD

-

The second script focuses on managing notifications related to pull requests and issues. I usually find that about one-third of my notifications are for merged PRs, PRs created by bots, or closed Issues. I don’t care about these types of events. With this script, I can mark those notifications as done, which reduces clutter in my GitHub notifications and helps me see important updates. As I mentioned above, one cool feature of the api subcommand is that it allows me to consume all possible pages of a response using the --paginate flag, eliminating the need for a loop + token field dance!

-
#!/bin/bash
-declare -A typeLookup
-typeLookup["PullRequest"]="pull"
-typeLookup["Issue"]="issues"
-
-resp=$(gh api /notifications --paginate | jq -r '.[] | select(.subject.type == "PullRequest" or .subject.type == "Issue") | "\(.repository.full_name),\(.subject.url),\(.id),\(.subject.type)"')
-
-for x in $resp; do
-  name=$(echo "${x}" | cut -d ',' -f 1)
-  id=$(echo "${x}" | cut -d ',' -f 3)
-  number=$(basename $(echo "${x}" | cut -d ',' -f 2))
-  ofType=$(echo "${x}" | cut -d ',' -f 4)
-  urlType=$(echo ${typeLookup["${ofType}"]})
-  isBot="false"
-
-  if [ "${ofType}" == "PullRequest" ]; then
-    isMerged=$(gh pr view --repo "${name}" "${number}" --json closed | jq -r .closed)
-    isBot=$(gh pr view --repo "${name}" "${number}" --json author | jq -r .author.is_bot)
-  fi
-
-  if [ "${ofType}" == "Issue" ]; then
-    isMerged=$(gh issue view --repo "${name}" "${number}" --json closed | jq -r .closed)
-  fi
-
-  if [ "${isMerged}" == "true" ] || [ "${isBot}" == "true" ]; then
-    echo "marking https://github.com/${name}/${urlType}/${number} as done..."
-    gh api -X PATCH "/notifications/threads/${id}"
-  fi
-done
-
-
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/blog-rewrite/index.html b/themes/cycle/exampleSite/public/writing/blog-rewrite/index.html deleted file mode 100644 index 422bdfb..0000000 --- a/themes/cycle/exampleSite/public/writing/blog-rewrite/index.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Blog rewrite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Blog rewrite

- - -
-

I haven’t posted here recently. That’s largely because I did the classic “Time to rewrite the blog, I’ll post when it’s done” thing. Well it’s not done, but I messed up by not sharing my thought process and reasoning for the re-write. So, I’m trying to rectify that now with some scant and scattered sentences.

-

Current setup

-

The blog is currently built using a custom Node app that lives inside a few AWS lambda functions.

-

To begin with I created my own auth system (insert eyeroll emoji I know) which works like this:

-

Image depicting the AWS Lambda system that provides authentication for my blog.

-

Once the user is authenticated they can create posts which looks like this:

-

Image depicting the various stages of the AWS Lambda system that creates posts.

-

Benefits

-

The benefits of my current setup are:

-
    -
  1. Entirely static.
  2. -
  3. No server to maintain.
  4. -
  5. Provides ability to post from my phone using the /admin interface in the browser.
  6. -
-

Drawbacks

-

The things pushing me to consider a re-write, are:

-
    -
  1. Local development is hard. The site generation is very tightly coupled to Lambda. There is no local server option for /admin.
  2. -
  3. Because of its disorganized nature it’s getting harder to maintain and add features (high microservices :wave:).
  4. -
  5. Fully reliant on AWS stack (Lambda, DynamoDB, Cognito, S3, CloudFront, Certificates, Route53).
  6. -
-

Where do I want to go?

-

I’m thinking of moving towards what I call “The Jekyll model”: an engine to build the site. I could then combine that engine with the following functionality to fill in the gaps:

-
    -
  1. Mobile publishing via SFTP of markdown files to a VPS/home server.
  2. -
  3. Use a file system watcher to trigger new builds when a new post is uploaded/changed.
  4. -
  5. Built site is uploaded to Netlify, S3, or Github pages. Keep it static.
  6. -
-

Going this route addresses all the Drawbacks but introduces a server to maintain. I’m OK with that change if I can iterate on design changes quicker than I can now, did I mention how painful that is currently? The one aspect of this I don’t have solved completely is post metadata (remember currently I’m using SQLite as my DB). I’m not a huge fan of the front-matter + markdown file approach because I’d rather have my data in a more standard data structure, e.g. a JSON file per post or something. If I go with a JSON file per post then I need to create something to generate that file upon post creation or modification. The other option is to keep using SQLite I guess.

-

Image outlining how a potential new system would work for the blog.

-

The Engine

-

The above should work. I just need something that consumes markdown and can match my existing URL scheme. I’ve ping-ponged back and forth between the following options:

-
    -
  • -

    Common Lisp

    -

    I initially thought I would build out the engine myself in Common Lisp (to get more experience in CL). Part of the draw of Common Lisp was that I could create an executable and send that to the server and not have to install a bunch of dependencies just to get it to run. However the lack of a markdown library that supports code-fencing (which I use extensively) has killed the idea (and my spirit).

    -
  • -
  • -

    Jekyll/Hugo/Gatsby

    -

    I toyed with just using Jekyll/Hugo but I would have to convert every post to MD + front matter. That sounded like a pain. I’ve also thought about using GatsbyJS but that introduces a ton of new tech that my site doesn’t need.

    -
  • -
  • -

    Node

    -

    I don’t really want to do Node again because:

    -
      -
    1. I’ve done a lot of Node recently
    2. -
    3. Requires installing dependencies and language runtime on server.
    4. -
    -
  • -
  • -

    Emacs

    -

    This one is the craziest idea I’ve had. Use an Emacs docker container + org-mode + some command line magic to have Emacs with org-mode be responsible for publishing the HTML for my site.

    -
  • -
  • -

    Rust

    -

    I’m currently considering upping my fledgling Rust game and writing my engine in Rust. I can then create a binary and ship that to a server. And yes, before anyone asks I already checked and there are several solid looking markdown crates (libraries).

    -
  • -
-

Now what?

-

I have no idea where this leaves me. This post has been a thinking/documentation exercise for me more than a post. I think I’ll keep exploring the Rust option and see where that leads me.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html b/themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html deleted file mode 100644 index ddd71c3..0000000 --- a/themes/cycle/exampleSite/public/writing/blogs-data-and-social-networks/index.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - Blogs, data, and social networks - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Blogs, data, and social networks

- - -
-

Anil Dash wrote a piece last week advocating for a transition from “page-centric” publishing platforms to “stream-centric”. He points to services such as Twitter, Facebook, and even Tumblr as examples for why stream-based publishing platforms are the future. His observation that the only reason the “old page model” is still around is because of advertising is spot-on and well said.

-

However, Dash misses on one big point in his post, he writes:

-
-

So: Start publishing streams. Start moving your content management system towards a future where it outputs content to simple APIs, which are consumed by stream-based apps that are either HTML5 in the browser and/or native clients on mobile devices.

-
-

These APIs already exist, we call them RSS. We don’t need a ton of VC money, and developers and designers to solve this problem; it’s already solved. What we need are those designers and developers to start creating tools that work on top of the existing RSS/Atom layer.

-

After reading Dash’s article, I stumbled across Scott Hanselman’s post on blogging. He starts off with a bang, and I’ll just post it here,

-
-

You are not blogging enough. You are pouring your words into increasingly closed and often walled gardens. You are giving control - and sometimes ownership - of your content to social media companies that will SURELY fail. These companies are profoundly overvalued, don’t care about permalinks, don’t make your content portable, and have terms of service that are so complex and obtuse that there are entire websites dedicate to explaining them.

-
-

Interesting uh? This blog right here is mine; I own the content, the URL, the design, everything. I have structured it so that each item has a permanent link for people to save, retweet, share, whatever. I don’t have to worry about this great service I use being bought by someone else and killed off as a “talent acquisition”. I still use Twitter of course, and I have an app.net account, but the “important” pieces of data, flow from this blog to those streams.

-

Scott ends his post by asking a simple question:

-
-

You want control? Buy a domain and blog there.

-
-

He’s right. Start blogging, and start re-thinking how that blog looks and functions. Mr. Dash is right too, streams are the better way to go, the beauty of it is that blogs can easily be streams. I know I have a couple ideas that I want to experiment with right here in the coming months.

-

So get to it, start a blog. Make something, stop whining, and enjoy the incredible era we live in.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html b/themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html deleted file mode 100644 index eed83c5..0000000 --- a/themes/cycle/exampleSite/public/writing/britain-goes-coal-free-as-renewables-edge-out-fossil-fuels/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Britain goes coal free as renewables edge out fossil fuels - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Britain goes coal free as renewables edge out fossil fuels

- - -
-
-

Britain is about to pass a significant landmark - at midnight on Wednesday it will have gone two full months without burning coal to generate power.

-
-
-

A decade ago about 40% of the country’s electricity came from coal; coronavirus is part of the story, but far from all.

-
-

This is fascinating. The UK has been aggressively investing in renewable energy sources for years and it appears all that investment is starting to catch up with demand.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/broadcast-channel/index.html b/themes/cycle/exampleSite/public/writing/broadcast-channel/index.html deleted file mode 100644 index 13edb9f..0000000 --- a/themes/cycle/exampleSite/public/writing/broadcast-channel/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Broadcast channel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html b/themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html deleted file mode 100644 index 172dd64..0000000 --- a/themes/cycle/exampleSite/public/writing/casperjs-node-and-the-raspberry-pi/index.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - CasperJs, Node, and the Raspberry Pi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

CasperJs, Node, and the Raspberry Pi

- - -
-

So I’ve been working on a pet project today, getting my Raspberry Pi to be a dedicated screen-scraping machine.

-

I’m still in the middle of getting things working, so I’ll be updating this post as I figure more stuff out. This post is intended to be a log for myself and hopefully a helpful resource for others.

-

Boot Image

-

I’m using the Raspbian Jessie image provided by Raspberry Pi. To create and backup my SD card images I’m using the excellent ApplePi Baker app. It provides a GUI wrapper around some gnarly command line tools to flash images to the Raspberry Pi SD card.

-

Installing Node

-

This post by Conall Laverty shows exactly how to get node and npm up and running on a Pi. I tried using the apt-get manager like I do with a VPS and the Pi wasn’t liking it.

-

Installing CasperJS and Phantom

-

Another helpful post by Alexander Bilz shows how to get casperjs and a specialized version of phantomjs working on the Pi.

-

I’ve run into issues with the 1.9.8 version of phantom compared to the 2.0 version on my laptop. Finding a compiled binary of 2.0 has proven to be quite difficult. So I’m on hold for now until I can get a 2.0 version running.

-

Troubleshooting

-

Since I’m using my Pi headless, I’m configuring everything over ssh. Sometimes this just doesn’t work well. I’ve found VNC to be a nice solution in those cases. This post has simple instructions for getting a VNC server up and running on your Pi. I use Chicken VNC as the client on my Mac to connect to the Pi’s server.

-

Speed

-

The Pi is slow. Really slow. I’ve found adding some casper.waits to my code have helped iron out some random errors.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/command-line-notification/index.html b/themes/cycle/exampleSite/public/writing/command-line-notification/index.html deleted file mode 100644 index c9d4efc..0000000 --- a/themes/cycle/exampleSite/public/writing/command-line-notification/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Command line notification - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Command line notification

- - -
-

This week I wrote a bash function that curls the SendGrid API and sends a Boxcar notification. This is useful to chain to the end of long-running commands, e.g. transcoding a video. When the command finishes I get a push notification on my phone.

-

If you’re unfamiliar with the various ways to chain commands together in bash, here’s a cheatsheet. One thing I didn’t know is that you can combine the various operators like long-running command || alert "failure!" && alert "success!".

-

Happy scripting.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html b/themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html deleted file mode 100644 index 9c15430..0000000 --- a/themes/cycle/exampleSite/public/writing/compose-key-and-i3/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - Compose key and i3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Compose key and i3

- - -
-

The compose key on Linux and other systems enables you to enter symbols like ™ that don’t have a dedicated key on most keyboards. GNOME makes this easy to do via Gnome Tweaks. However, using a window manager like i3 means there’s no dedicated GUI for changing the hotkey for compose.

-

This stackexchange answer sent me down the right path of adding the following config to ~/.Xmodmap to bind Caps lock to compose:

-
.keysym 66 = Mode_switch
-clear Lock
-

You can then enable the key map by running:

-
xmodmap ~/.Xmodmap
-

However, that config didn’t work because Mode_switch wasn’t the right name for the compose key (at least under Ubuntu/PopOS 20 for me). The Arch Wiki states that the name for the compose key is actually Multi_key. With this new name I was able to get Caps lock to act as the compose key by updating the config in ~/.Xmodmap to:

-
keycode 66 = Multi_key
-clear Lock
-

The final step is to set that mapping every time i3 runs by putting this inside your i3 config file like so:

-
exec --no-startup-id "xmodmap ~/.Xmodmap"
-
-
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html b/themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html deleted file mode 100644 index 9a6d18a..0000000 --- a/themes/cycle/exampleSite/public/writing/confessions-marcus-hutchins-hacker-who-saved-the-internet/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The Confessions of Marcus Hutchins, the Hacker Who Saved the Internet

- - -
-
-

Janet Hutchins had the day off from her job as a nurse at a local hospital. She had been in town catching up with friends and had just gotten home and started making dinner. So she had only the slightest sense of the crisis that her colleagues had been dealing with across the NHS. That’s when her son came upstairs and told her, a little uncertainly, that he seemed to have stopped the worst malware attack the world had ever seen.

-
-
-

“Well done, sweetheart,” Janet Hutchins said. Then she went back to chopping onions.

-
-

It’s hard to pick my favorite section from this article about Marcus Hutchins — the hacker who stopped the WannaCry malware attack.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/convince-the-boss/index.html b/themes/cycle/exampleSite/public/writing/convince-the-boss/index.html deleted file mode 100644 index 1c4de90..0000000 --- a/themes/cycle/exampleSite/public/writing/convince-the-boss/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - Convince the Boss - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Convince the Boss

- - -
-

Speaking of cultivation and passion, Jeremy Keith wrote up a great post on how to convince one’s boss or client to adopt new web standards or methods.

-
-

I do sometimes wonder whether we use the big bad client or the big bad boss as a crutch. “Oh, I’d love to try out this technique, but the client/boss would never go for it. Something something IE6.” Maybe we’re not giving them enough credit. Given the right argument, they might just listen to reason.

-
-

Go work on getting the right arguments for your specific client or boss, go cultivate a metric-ton of data to overwhelm whoever is holding back progress. No one is going to reach out and whack your boss or client with a “Web Standards Genius” stick for you, do the whacking yourself (figuratively, I do not endorse or condone violence against one’s superiors, peers, or underlings). If after all that effort you’re still not getting anywhere, then follow Mr. Keith’s other piece of advice:

-
-

Another tactic that I’ve used in the past is to simply not ask for permission, but go ahead and use the new technologies and techniques anyway.

-
-

Go do.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/create-passion/index.html b/themes/cycle/exampleSite/public/writing/create-passion/index.html deleted file mode 100644 index 5eea455..0000000 --- a/themes/cycle/exampleSite/public/writing/create-passion/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Create Passion - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Create Passion

- - -
-

I’m slowly working my way through the latest edition of The Manual Vol. #3. I just finished Tiffani Jones Brown’s excellent essay on Practicing Passion. This quote really stuck with me,

-
-

Instead of asking “what will make me feel passion?” we should ask, “how can I make passion happen?” The answer is to cultivate a way of living and working that makes passion more likely.

-
-

I love this, it doesn’t leave room for me to have any excuses. Cultivation takes effort, perseverance, hard work, and purpose. Time to get to work, the passion will show up if I do.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/css-reusability/index.html b/themes/cycle/exampleSite/public/writing/css-reusability/index.html deleted file mode 100644 index 25d7878..0000000 --- a/themes/cycle/exampleSite/public/writing/css-reusability/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - CSS Reusability - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

CSS Reusability

- - -
-

Chris Coyier posted a great question over at CSS-Tricks.

-
-

You’ve probably coded up something like that, right? How many times? A lot? Did you do it from scratch each time?

-
-

I’ll be honest, aside from the usual normalise.css I don’t re-use much CSS. Unlike PHP or JS, where I re-use a lot of code.

-

Chris continues on in the comment thread,

-
-

If a developer needs a login function for a website, do they write it from scratch? I bet very rarely. They use an existing project (e.g. a CMS like WordPress) or a modular component to a framework (e.g. a Rails gem). What makes back-end so code much more reusable?

-
-

Chris has a great point. I know the obvious answer is that CSS deals with layout and design, which is wildly different from project to project. Yet, I think he’s on to something, I need to be more efficient with the code I write. I can be more efficient by starting to think about CSS in a more modular way, what little re-usable objects or chunks can I carry from project to project?

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html b/themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html deleted file mode 100644 index 14d30f3..0000000 --- a/themes/cycle/exampleSite/public/writing/cycle-v030-released/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - cycle v0.3.0 released - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

cycle v0.3.0 released

- - -
-

I just released v0.3.0 of cycle.

-

This version uses Chroma for syntax highlighting instead of Pygments. I never got Pygments running correctly in Netlify’s build environment. Chroma requires no dependencies since it’s distributed as a static binary and it’s also faster due to being written in golang.

-

This version also refactors the main function to accept an optional working directory arg. This allows me to build a site via the CL REPL. It also shortens the feedback loop to try out new features.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html b/themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html deleted file mode 100644 index 668313c..0000000 --- a/themes/cycle/exampleSite/public/writing/dead-cells-might-be-a-perfect-game/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - Dead Cells might be a perfect game - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Dead Cells might be a perfect game

- - -
-

Dead Cells is an incredible single-player fighting platformer (not sure the proper term for it). It only took a few minutes before I felt like a total badass running around squashing baddies. However, that feeling is tempered by the fact that this game is quite fiendishly difficult.

-

It’s available on Steam for Mac, Linux, and Windows. It’s also available on most consoles, including the Switch, and recently iOS.

-

I was so impressed with this game I went hunting around for information on the creators of the game, Motion Twin. I found this documentary on Youtube about the studio and the game which is quite good:

- - - -

There’s also this video which highlights some of the smart ways the developers made the game feel better to players:

- -

If you’re looking for a new game or something different I highly recommend checking out Dead Cells.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/declining-expectations/index.html b/themes/cycle/exampleSite/public/writing/declining-expectations/index.html deleted file mode 100644 index df6d261..0000000 --- a/themes/cycle/exampleSite/public/writing/declining-expectations/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Declining Expectations - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Declining Expectations

- - -
-

Matthew Butterick’s talk at TYPO Berlin is a fantastic read.

-
-

And that’s really what I mean tonight by declining expectations. This idea of what happens when we defer to technology, instead of standing on its shoulders. What happens when we choose convenience over quality. Eventually, we’re going to forget what quality was like.

-
-

Chilling and inspiring.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/diceware/index.html b/themes/cycle/exampleSite/public/writing/diceware/index.html deleted file mode 100644 index 0952e80..0000000 --- a/themes/cycle/exampleSite/public/writing/diceware/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - Diceware - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Diceware

- - -
-

Glenn Fleishman (@GlennF) recently linked to a method for generating passphrases called Diceware.

-
-

@craigmod Switch to diceware-style ones, if you haven’t. It’s so goddamn much easier, even with 2x the characters of a random one.

-

— Glenn Fleishman (@GlennF) March 24, 2017

-
-

Being a fan of dice (d20 for life) I thought this was super cool and worth sharing.

-

The basic premise is (to quote Wikipedia):

-
-

Diceware is a method for creating passphrases, passwords, and other cryptographic variables using ordinary dice as a hardware random number generator. For each word in the passphrase, five rolls of the dice are required. The numbers from 1 to 6 that come up in the rolls are assembled as a five-digit number, e.g. 43146. That number is then used to look up a word in a word list. In the English list 43146 corresponds to munch. By generating several words in sequence, a lengthy passphrase can be constructed.

-
-

I dig this, it’s an analog solution to a digital problem. The incredible folks at the EFF have a couple wordlists to get you started. Happy rolling! 🎲

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/eight-years/index.html b/themes/cycle/exampleSite/public/writing/eight-years/index.html deleted file mode 100644 index b3bb921..0000000 --- a/themes/cycle/exampleSite/public/writing/eight-years/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - Eight years - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Eight years

- - -
-

Eight years ago I started working at Sparkbox. Here are some of things that have happened since I started:

-
    -
  • The Cubs won a World Series.
  • -
  • Facebook released a small Javascript library called React.
  • -
  • The iPhone 5 was unveiled the week after I started.
  • -
-

Time flies when you’re having fun.

-

Thank you Sparkbox team for giving me an opportunity to work with ya’ll and for making me a better developer and person. Let’s keep it rolling!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/emacs-lite/index.html b/themes/cycle/exampleSite/public/writing/emacs-lite/index.html deleted file mode 100644 index b8876d9..0000000 --- a/themes/cycle/exampleSite/public/writing/emacs-lite/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - Emacs lite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Emacs lite

- - -
-

I really dig Emacs. I think it’s a one-of-kind computing experience. However, it’s defaults are pretty rough and some of my favorites aspects of Emacs are third party packages.

-

I wondered if I could cram the “awesome Emacs” experience into 200 lines of configuration or less. Turns out I could. I only included what I consider (as someone who writes JS most days) “essential”. I didn’t re-bind any keys except for M-x and that has the same function with an upgraded interface. I didn’t include evil-mode (Vim emulation) either, introducing Emacs and Vim keybinds to someone is a suicide mission.

-

To use this config copy and paste the config snippet into one of three config file locations (sooooo Emacs):

-
-

Emacs looks for your init file using the filenames ~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el

-
-

Then boot up Emacs (I’m assuming you already have it installed), there will be a bit of waiting the first time as packages are installed for you.

-

If you run into issues, hit me up via email, github issue, twitter, micro.blog etc. There’s also a reddit thread with some helpful discussion from the awesome /r/emacs community.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/emacs-tips/index.html b/themes/cycle/exampleSite/public/writing/emacs-tips/index.html deleted file mode 100644 index f312f05..0000000 --- a/themes/cycle/exampleSite/public/writing/emacs-tips/index.html +++ /dev/null @@ -1,268 +0,0 @@ - - - - - - Emacs tips - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Emacs tips

- - -
-

evil-mode (vim for emacs) is good but not perfect. There will be occasions where you will get dropped into regular ‘ole emacs mode for some feature or plugin. The trick is to not panic remember a few basic movement keys that will get through in 90% of cases.

-
    -
  1. C-n and C-p (C stands for the ctrl key) go down and up by line respectively.
  2. -
  3. M-f (M stands for the alt key) and M-b will go forwards and backwards by word respectively.
  4. -
  5. C-g is the universal emacs key for “STOP WHATEVER YOU’RE DOING”.
  6. -
-

There are a few other random things to keep in mind that will make life easier.

-
    -
  1. M-x (remember, M stands for the alt key) allows you to execute just about any function, e.g. kill-buffer.
  2. -
  3. F1 f will bring up documentation for any loaded function.
  4. -
  5. F1 v will bring up documentation for any variable.
  6. -
  7. F1 k will allow you to type a keybind and see what it’s bound to.
  8. -
-

Scripting tips

-

A few helpful built-in functions to know to start making your own functions.

-
    -
  1. -

    nth is a built-in which lets you pull a specific item from a list by it’s index like so: (nth 1 '("red", "blue")). Returns "blue".

    -
  2. -
  3. -

    split-string is another built-in that splits a string given a separator and returns the results in a list. (split-string "foo-bar" "-"). Returns ("foo" "bar")

    -
  4. -
  5. -

    concat also a built-in, combines strings. (concat "hello" "world"). Returns "helloworld".

    -
  6. -
  7. -

    null also a built-in. Return t if OBJECT is nil, and return nil otherwise. (null OBJECT).

    -
  8. -
-

I’ll add to this post as I think of things that helped me out when I first started using emacs. You can also check out my emacs config in my dotfiles if you want to see how I have everything setup.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/end-of-an-era/index.html b/themes/cycle/exampleSite/public/writing/end-of-an-era/index.html deleted file mode 100644 index 3e12a55..0000000 --- a/themes/cycle/exampleSite/public/writing/end-of-an-era/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - End of an era - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

End of an era

- - -
-

Today I removed two of my most-used apps on my phone, Apollo and Tweetbot. It feels like the end of an era.

-

Twitter and Reddit were both social websites that are/were terrible without a lot of cultivation and effort, but over the years I had shaped my experience on those services to be pretty good thanks in large part to Apollo and Tweetbot being such powerful tools.

-

Ironically the only social web thing I still use (outside of Instagram) is RSS. I will probably spin up a Mastodon instance here eventually but for now I’ve subscribed to folks via Mastodon’s RSS support and it’s good enough for now.

-

I guess I just wanted to give a shout out to the devs of Apollo and Tweetbot: thank you for making such great apps, I will miss them.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/evening-edition/index.html b/themes/cycle/exampleSite/public/writing/evening-edition/index.html deleted file mode 100644 index 721c9a7..0000000 --- a/themes/cycle/exampleSite/public/writing/evening-edition/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - Evening Edition - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/facetime-killer/index.html b/themes/cycle/exampleSite/public/writing/facetime-killer/index.html deleted file mode 100644 index 6f65b59..0000000 --- a/themes/cycle/exampleSite/public/writing/facetime-killer/index.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - Facetime Killer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Facetime Killer

- - -
-

TLDR: I made an app, VDCAssistant-Killer, to restart the process that manages the Facetime camera on your Mac.

-

Anyone who uses a Cinema Display with their Macbook has undoubtedly noticed that occasionally the Cinema Display Facetime camera will not be available for use in Hangouts/Zoom/Facetime call. The only fix was to restart the machine which usually made me late (and is a terrible solution in 2017).

-

Since I’m on video calls quite a bit this quickly started to drive me batty. I jumped into a google deep dive and found out the culprit was the process that manages the Facetime cameras on a Mac, VDCAssistant.

- -

This command worked fine for anyone comfortable with the command line, but what about folks who would rather have a GUI to do this? So I made VDCAssistant-Killer a menubar app that executes the exact shell command to restart the VDCAssistant process for you. You shouldn’t have to restart the computer or even the video call program, the assistant should automatically restart and make all connected cameras available to you immediately.

-

A few other notes:

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/family-first/index.html b/themes/cycle/exampleSite/public/writing/family-first/index.html deleted file mode 100644 index a5209f3..0000000 --- a/themes/cycle/exampleSite/public/writing/family-first/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Family First - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Family First

- - -
-

Chris Bowler jots down some fantastic advice in his latest post (emphasis mine).

-
-

But my purpose here is to simply encourage those with families. Please do not spend your time endlessly comparing your accomplishments or progress with those who have no family. Your setting yourself up for guilt at best, and resenting your family at worst.

-
-

I do not have any kids yet but I think this advice applies to everyone, especially those working on the web. I’ve been slowly learning that I cannot continue to compare myself to other people in my industry - it’s counterproductive.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/farewell-heroku/index.html b/themes/cycle/exampleSite/public/writing/farewell-heroku/index.html deleted file mode 100644 index c07a022..0000000 --- a/themes/cycle/exampleSite/public/writing/farewell-heroku/index.html +++ /dev/null @@ -1,269 +0,0 @@ - - - - - - Farewell Heroku - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Farewell Heroku

- - -
-

I’ve migrated my apps off Heroku and won’t be using the service for personal apps going forward. Why? Let me back up a bit and explain what was so great about Heroku.

-

Haiku? Ha-who?

-

Heroku is a “hosting as a service” company. They try to take away the pain of deploying and managing web applications. They actually do this quite well, it’s a great service. The “secret sauce” that made Heroku so good was it’s free pricing tier. The free tier essentially allowed a single web or a single “worker” process to run 24/7. There was enough processing power to run apps or processes for a small number of users, perfect for apps like my six plus checker or youtuberss app.

- -

If apps grew popular enough they would hit processing limits and I could go in and scale the app up to meet demand. Scaling an app also meant that I was no longer in the free tier and would begin paying Heroku for the additional resources. It really was an ideal setup (from my perspective as a developer).

-

Sadness

-

Sadly, Heroku announced a few months ago a pretty big shift in their pricing. The free tier would no longer run 24/7 as a single process:

-
-

Every app using free dynos can include not just a free web, but also one free worker, and free usage of heroku run and Heroku Scheduler. Free dynos can run up to eighteen hours a day, but have to “sleep” for at least the remaining six. That’s eighteen hours each of serving traffic, running a background worker, and scheduled processes

-
-

I totally get they are trying to offer more of their platform in “demo mode” but I think it’s the wrong move. To be clear, I’m not griping about a free lunch going away. I’m griping because the new pricing:

-
    -
  1. Is harder to understand and manage. Seriously, I’m supposed to monitor my app in 18 hour increments?
  2. -
  3. Doesn’t incentivize developers to try out new apps that could potentially become paying applications.
  4. -
-

Re: #2, The very impressive emojitracker was built on Heroku’s platform. Matthew Rothenberg, the project’s developer, recounts how Heroku let him easily scale to meet demand:

-
-

I did this manually. That first evening I needed a break from intense computer usage all day, so I actually spent the evening in a bar across the street from my apartment with some friends, having a drink while passively monitoring these charts on some iPhones sitting on the table. Whenever it looked like something was spiking, I used the Nezumi Heroku client to scale up instances from my phone directly. I didn’t even have to put down my drink!

-
-

This is awesome. It illustrates the ideal scenario: no money up front to try something out and a natural path to scaling it up if it takes off. Simple, it was.

-

Where to now?

-

I tweeted yesterday:

- -

I’ve now finished moving my node apps over to Chunkhost. With Chunkhost I get 1GB of RAM for under $5/month by paying yearly and via bitcoin (I use Coinbase to purchase and manage Bitcoins). In comparison, Digital Ocean offers 512MB of RAM for $5/month. With the extra overhead from Chunkhost, I can easily host multiple apps on the same box. Plus, I’ve found that the two node apps I have running are both only using ~50MB of RAM!

-

Sysadmin

-

Yes, with Chunkhost I have to play as sysadmin and keep the VPS running. However I’m in total agreement with this quote from Marco Arment:

-
-

Modern Linux server administration is much easier than you think. If you can write a halfway decent app, you can manage a Linux VPS in your sleep.

-
-

He’s exactly right, managing a VPS isn’t beyond the abilities of anyone who can write an app and put it on Heroku. I’ve found Ansible + Bitbucket private repos + PM2 a great deployment and management combo; one that I’ll write more about later. It took some effort to set up, but now I can launch new apps in minutes.

-

Heroku’s new pricing has forced me to branch out and figure out how to host, manage, and deploy my apps. Perhaps the pricing change wasn’t all bad after all.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html b/themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html deleted file mode 100644 index 0105678..0000000 --- a/themes/cycle/exampleSite/public/writing/ffmpeg-convert-multiple-files-using-xargs/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - FFMPEG: Convert multiple files using xargs - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

FFMPEG: Convert multiple files using xargs

- - -
-

I stumbled upon this post (Google cache link) when I was trying to process multiple files via xargs.

-
-

ls *.webm | xargs -I % ffmpeg -i % %.m4a

-
-
-

The key part of this one-liner is xargs -i %. This means that each line of STDIN passed to xargs is put into a variable and can be referenced as %. Hence, the following text which specifies ffmpeg -i x.webm x.m4a to make it convert.

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/five-years/index.html b/themes/cycle/exampleSite/public/writing/five-years/index.html deleted file mode 100644 index 6c09413..0000000 --- a/themes/cycle/exampleSite/public/writing/five-years/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Five years - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Five years

- - -
-

Five years

-

Today is my five year anniversary at Sparkbox! Five years is a long time, especially working on the internet, and I’ve loved every stinking minute of it.

-

To my fellow Sparkboxers: thank you for making Sparkbox such an incredible place to work. Here’s to the next five!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/flatkill/index.html b/themes/cycle/exampleSite/public/writing/flatkill/index.html deleted file mode 100644 index d02ffea..0000000 --- a/themes/cycle/exampleSite/public/writing/flatkill/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - flatkill - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

flatkill

- - -
-
-

And it’s not only about these security problems. Running KDE apps in fakepak? Forget about desktop integration (not even font size). Need to input Chinese/Japanese/Korean characters? Forget about that too - fcitx has been broken since flatpak 1.0, never fixed since.

-
-
-

The way we package and distribute desktop applications on Linux surely needs to be rethinked, sadly flatpak is introducing more problems than it is solving.

-
-

Flatpak is an emerging alternative way to install applications on Linux that is apparently rife with security and usability issues. This is a bummer because there’s lots of room in this space for improvement. The lack of multi-lingual input is especially egregious.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html b/themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html deleted file mode 100644 index 7696bd8..0000000 --- a/themes/cycle/exampleSite/public/writing/format-json-in-emacs/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - Format JSON in emacs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Format JSON in emacs

- - -
-

I wrote an elisp function to yank JSON off my clipboard, prettify it, and then return it to my clipboard ready to be pasted wherever.

-
(defun simpson-pretty-json()
-  "ideal for getting pretty JSON from JSON that is copied from a XHR request"
-  (interactive)
-  (with-temp-buffer
-    (clipboard-yank)
-    (json-pretty-print-buffer)
-    (kill-new (buffer-string))
-  )
-)
-
-
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html b/themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html deleted file mode 100644 index 54f5b3c..0000000 --- a/themes/cycle/exampleSite/public/writing/four-ways-to-approach-hacktoberfest-2020/index.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - Four ways to approach Hacktoberfest 2020 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Four ways to approach Hacktoberfest 2020

- - -
-

Hacktoberfest 2020 is here! I can’t believe 2020 is winding down, good riddance!

-

I’ve been talking about Hacktoberfest with my co-worker Bryan and I thought of four different approaches to Hacktoberfest this year that I wanted to share.

- -

Dependency scrub

-

This is probably common everywhere but the Javascript/web communities are filled with npm packages. It’s packages all the way down. I think it would be interesting to approach this month looking for ways to remove third-party code from projects you love and use frequently.

-

Polygot Achievement

-

Try to submit four pull requests in four different languages. As Drew DeVault writes: Hack everything without fear!

-

Unknown lands

-

Similar to the previous one it could be fun to submit PRs against a project you’ve never been in before that’s in a language you don’t know. This could be anything from diving into Wordpress core, to working on some C for some Linux utilities, or even submitting PRs to open source Mac/iOS applications.

-

Bug doctor

-

Go into a project and find the oldest issues and try to resolve them via PR. This is inspired by Richard Schneeman’s video and post where he runs through 11 issues and 2 PRs in a hour and a half.

-

How are you approaching Hacktoberfest this year? My public inbox is open, let me know!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html b/themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html deleted file mode 100644 index 3deb406..0000000 --- a/themes/cycle/exampleSite/public/writing/getting-started-with-rofi/index.html +++ /dev/null @@ -1,282 +0,0 @@ - - - - - - Getting started with Rofi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Getting started with Rofi

- - -
-

Rofi is a Linux app that is a:

-
-

[..] window switcher, application launcher and dmenu replacement

-
-

I’ve been using Rofi for about a year but didn’t really understand how to write my own scripts for it until recently.

-

dmenu? Huh?

-

A key to my lack of apprecaition for Rofi’s feature set was that I didn’t understand why it billed itself as a “dmenu replacement”. What the heck is dmenu?

-
-

dmenu is a fast and lightweight dynamic menu for X. It reads arbitrary text from stdin, and creates a menu with one item for each line. The user can then select an item, through the arrow keys or typing a part of the name, and the line is printed to stdout. (emphasis mine)

-
-

Essentially dmenu lets you create and present your own menu and then act once a menu item is selected by the user. One of my favorite applications of all time is Alfred, the infinitely customizable launcher utility for macOS. The best part about Alfred was Workflows which (like dmenu) allow you to create custom menus and actions as part of the main launcher interface. How do we create a menu though?

-

STDIN STDOUT

-

dmenu will display whatever comes in on STDIN as the menu, e.g. echo "foo\nbar" | dmenu" (if you have a Linux install available install dmenu and give that command a try). Each new line in STDIN becomes a new line in the dmenu menu. The previous command creates a menu with two options: foo and bar. Once the user hits enter on a menu item the value of the selected item gets sent to STDOUT. That’s it. dmenu reads in from STDIN and prints out selections to STDOUT. dmenu is super handy to add to workflows and scripts to give them a bit of UI. You can squeeze dmenu anywhere you need feedback from the user, e.g.: echo "Hello $(echo 'World\nPeople' | dmenu)". This prints a hello world message after the users chooses “World” or “People” from dmenu.

-

Rofi + dmenu

-

Rofi adds dmenu capability plus lots of other things like selecting open windows, running ssh commands etc. To enable dmenu mode in Rofi pass it as an option -dmenu. Let’s port our previous example code snippet to Rofi: echo "foo\nbar" | rofi -dmenu. Easy enough! With the dmenu option Rofi becomes just as useful as Alfred and makes me think Alfred should gain a command line option to pop open Alfred from within scripts like dmenu or Rofi.

-

My first script

-

The motivation to write this post came a couple weeks ago when I wrote my first real Rofi script. I use Pop_OS! as my Linux distribution of choice for work and the defaults are really good. However when I want to change my audio output (headphones or external speakers) I’ve grown annoyed by having to manually mouse up to the menubar and select the desired output. I set out to write a Rofi script to handle changing the audio output. On Linux you can control everything related to the audio system via the pactl utility. The pieces of data I needed for my script were:

-
    -
  • A list of all available outputs to generate my Rofi menu
  • -
  • A way to change to the selected output
  • -
-

pactl list sinks displays all active “sinks” or available outputs (“Sinks” is the Linux audio system term for outputs). We can customize this a bit further wih pactl list short sinks which will cram relevant sink information into one line each instead of multiple lines per sink. This makes parsing the output much easier.

-

Now that I had a list of available speakers/headphones on the system I needed to change to that output. This turned out to be a two step process because of how the audio system works:

-
    -
  1. pactl move-sink-input INPUT SINK moves anything currently playing to the specified speaker/headphone.
  2. -
  3. pactl set-default-sink SINK sets the specified speaker/headphones as the default output going forward, e.g. launching a video call or playing a video.
  4. -
-

To accomplish #1 I needed to get the currently playing input which can be done via: pactl list sink-inputs. Again we can specify short to get the relevant information on a single line: pactl list short sink-inputs.

-

The finished script looks like this:

-
#!/bin/bash
-
-source="$(pactl list short sinks | cut -f 2 | rofi -dpi 1 -dmenu -p "Change audio:")";
-inputs="$(pactl list sink-inputs short | cut -f 1)";
-
-for input in $inputs; do
-  pactl move-sink-input "$input" "$source";
-done
-
-pactl set-default-sink "$source";
-

Upon invoking the script, Rofi presents me with a menu that contains all the available outputs. Once I select one the audio changes instantly.

- -

Conclusion

-

I find Rofi so useful that I have a system-wide hotkey that invokes Rofi as a general launcher like this: rofi -combi-modi run,window,drun -show combi -modi combi -dpi 1. The flags I’m using are documented under “Combi settings” in the Rofi manpage.

-

Rofi transforms otherwise vanilla shell scripts into poweful transient workflows that allow me to control aspects of my machine without leaving whatever I’m currently working on. It’s become an essential part of my toolbox.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html b/themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html deleted file mode 100644 index 13e1375..0000000 --- a/themes/cycle/exampleSite/public/writing/gists-snippets-and-sublime-text-2/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - Gists, Snippets, and Sublime Text 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Gists, Snippets, and Sublime Text 2

- - -
-

I’ve been using Sublime Text 2 for a little under a year I guess, but I’ve only recently started customizing the hell out of it largely thanks to the Fetch plugin. Today I had the thought of setting up Fetch to download and insert the raw code of a Github Gist.

-

Gists are great for a couple reasons. One is that they are version controlled, it’s easy to track any changes right from the gist. Another great thing is that Gists are independent of Sublime, and more importantly my local computer, this makes them easier to share and backup. The only drawback from normal snippets I can see is that I can’t set up tab triggers, and hot keys.

-

So today I created three Worpress specific gists, and set up Fetch in Sublime Text 2 to pull them down. These are pretty basic snippets, but they are ones that I use a lot and don’t want to think about.

-

I just started messing around with this stuff today, so I’d love any comments regarding snippets or how you set up any kind of automation in Sublime Text 2. Reply to @a_simpson with your comments.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/git-commit-template/index.html b/themes/cycle/exampleSite/public/writing/git-commit-template/index.html deleted file mode 100644 index ff2a9f6..0000000 --- a/themes/cycle/exampleSite/public/writing/git-commit-template/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - Git Commit Template - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Git Commit Template

- - -
-

TL;DR how do I do this?

-

At work we’ve been moving toward standardized Git commit messages. By following the pattern, it’s very easy to see what type of code is in a specific commit.

-

We use Sprint.ly and Github. Both of these services can perform actions based on what is in a commit message. Github can close or reference an issue if I type closes #144 at the end of my commit. Sprint.ly can pull a commit message into a specific ticket in much the same way.

-

The problem with all this, is remembering to actually do it in the heat of the moment, when I’m buried in code and trying to push stuff out the door. That’s why I put together a Git commit message template. All my template does is list the various flags and an example of how to reference a Sprint.ly ticket, but it shows this in my editor every time I commit. It’s been incredibly useful.

-

Add your own template

-
    -
  1. Create a file to hold your template, e.g. git-commit-template.txt. Put in whatever you want to remember, just be sure to keep everything commented out (via #) or it will be in the actual message.
  2. -
  3. Run git config --global commit.template /path/to/git-commit-template.txt or edit ~/.gitconfig and add template = /path/to/.gitmessage.txt under the [commit] block.
  4. -
  5. Done.
  6. -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/git-worktree/index.html b/themes/cycle/exampleSite/public/writing/git-worktree/index.html deleted file mode 100644 index f198976..0000000 --- a/themes/cycle/exampleSite/public/writing/git-worktree/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - Git worktree - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Git worktree

- - -
-

I was happily (I had just started obviously) browsing Twitter today when I saw this tweet from the esteemed Wilfred Hughes:

- -

Huh? What is git-worktree? A quick Google landed me on the documentation for git-worktree. The ;TLDR of git-worktree is that it breaks time and space and lets a user check out multiple branches at the same time. No more stash-checkout-stash-pop dance between branches and fixes! The example in the documentation is really really good (except for the boss part, that’s usually played by my short-attention span).

-

Magit

-

After reading the documentation, my next thought was “Does magit support this?” Yep, since last year! Let me take this moment to rave like a maniac, magit is amazing and everyone should be using it as their primary git client (irregardless of Emacs usage for text-editing). As the documentation explains, to get worktree information in the standard magit status buffer the magit-status-sections-hook needs to be updated like so:

-

(add-hook 'magit-status-sections-hook 'magit-insert-worktrees).

-

The actions for creating or checking out a worktree are (hiding) in the branches (b) popup. I don’t know why I’ve never noticed them until now!

-

git-worktree is another example of git not standing still. It’s exceptional (even under-appreciated) software that continues to improve and that’s something that doesn’t get enough praise and attention.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/goat-counter/index.html b/themes/cycle/exampleSite/public/writing/goat-counter/index.html deleted file mode 100644 index 773848f..0000000 --- a/themes/cycle/exampleSite/public/writing/goat-counter/index.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - GoatCounter web analytics - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

GoatCounter web analytics

- - -
-
-

What seems to be lacking is a “middle ground” that offers useful statistics to answer business questions, without becoming a specialized marketing tool requiring in-depth training to use effectively. Furthermore, some tools have privacy issues (especially Google Analytics). I saw there was space for a new service and ended up putting my original idea in the freezer and writing GoatCounter.

-
-

I agree 100% with this assessment and I’m excited about Goatcounter. I setup a free instance of Goatcounter for this site as a way to kick the tires on it. So far, I’m enjoying that it’s privacy respecting and doesn’t drag down page performance.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html b/themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html deleted file mode 100644 index 91ef61c..0000000 --- a/themes/cycle/exampleSite/public/writing/goodbye-sparkbox/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - 👋 Sparkbox - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

👋 Sparkbox

- - -
-

I can’t believe I’m writing this but after 9 and a half years today is my last day at Sparkbox.

-

Now, I know it can be problematic to think about work like your (extended) family but when you work at the same place through your twenties and early thirties, have 3 different apartments, buy a house, and have two kids it’s impossible not to view that place differently. I can confidently say Sparkbox changed my life. The team there will always have a special place in my heart.

-

deep breath

-

So where to? Well, I’m super stoked to be joining Grafana as a Senior Software Engineer on their Cloud Data team! I’m looking forward to writing more Go, solving new problems, and learning from the stellar folks there.

-

Here we go…

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html b/themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html deleted file mode 100644 index c9f4432..0000000 --- a/themes/cycle/exampleSite/public/writing/google-fi-and-data-only-plans/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - Google Fi and data only plans - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Google Fi and data only plans

- - -
-

Last week, Google began selling wireless cellular service via a new program, Google Fi, which utilizes Sprint and T-Mobile for coverage. Fi’s pricing model is refreshingly straight-forward (following the example of T-Mobile and Ting); every plan is $20 with data billed at $10/Gb on top of that. @benthompson and @jamesallworth discussed the various aspects of Fi on a recent episode of their podcast, Exponent. At one point, James asked (I’m paraphrasing here) why the base of the Fi plan includes voice/sms. Why doesn’t Google just offer data? James went on to say that he always thought if anyone were to offer a data-only plan, it would be Google. What he didn’t know was this: there is already a fantastic data-only plan in America, and it’s on T-Mobile.

-

Data only-ish

-

On T-Mobile’s prepaid site, the company heavily advertises its main pre-paid price tiers: $40, $50, and $60. However, a quick scroll down the page will reveal two additional plans. The first one is talk and text only, with no data included. The second is the best kept secret in wireless. This second plan is $30/month for 100 minutes, unlimited SMS, and 5GB of LTE data (throttled after 5GB). 100 minutes is nothing, so this plan is essentially just data. There’s no catch - the LTE isn’t throttled at all, and the plan includes free international texting from the US. It even qualifies for Music Freedom, which doesn’t count music streaming against your 5GB LTE allowance. You can add hotspot tethering for $15/month, and this can be added and removed as you need it.

-

What are minutes for?

-

My wife and I have been on this plan for almost a year now. It’s perfect. We use FaceTime Audio if we need to call each other or anyone else that has an iOS device. We use the Vonage mobile app (any VOIP service would work) when we need to make a normal call and don’t want to use our 100 minutes. Both Vonage and FaceTime Audio use data, not voice minutes, exactly the scenario James outlined on Exponent.

-

Caveats

-

The only downside to this plan I have found is that T-Mobile’s coverage is still behind AT&T’s and Verizon’s, though it’s much closer now than it has ever been. 2015 has seen T-Mobile continue to build out its LTE reach, and it’s impressive. Living in Columbus, OH, one of the first cities to get Wideband LTE, I see speedtest results as high as 70mbps down.

-

If Google Fi isn’t as radical as you’d like, I would recommend giving this T-Mobile plan a try. It’s $30 (plus the cost of a SIM card) to give it a shot. The one “catch” is that it’s only for phones (or SIMs) activated in Walmart or online, but it’s easy enough to order a SIM card and give it a try.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html b/themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html deleted file mode 100644 index 57128bc..0000000 --- a/themes/cycle/exampleSite/public/writing/grow-it-dont-build-it/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Grow it, don't build it - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Grow it, don't build it

- - -
-

John Graham-Cumming wrote up a fantastic list of things he’s learned about programming. There all great. Yet, I really resonated with #6. So. True.

-
-

It’s easier to grow software than build it […] When you create a massive architecture from the start you (a) get it wrong and (b) have created a Byzantine maze that you’ll find hard to change. If, on the other hand, you work from small pieces that communicate with each other, refactoring will be easier when you realize you got it wrong from the start.

-
-

Hat-tip to Jonathan Christopher for the article link.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html b/themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html deleted file mode 100644 index ab6163a..0000000 --- a/themes/cycle/exampleSite/public/writing/guidelines-for-data/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - Guidelines for Data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Guidelines for Data

- - -
-

The wonderful Contents Magazine released a special report entitled Data Protection. In that report they outlined three principles for Data Protection. All three principles are fantastic, but number two really stood out to me.

-
-

No upload without download. Build in export capabilities from day one.

-
-

That seems pretty straightforward, but I started thinking of this in the context of the sites I build for clients. Our platform of choice at my company is Wordpress which has a capable Import/Export tool available.

-

Is this enough? Do my clients know about it? Is the XML it exports good enough that clients can migrate platforms in a couple years? A quick bit of searching uncovered the Export to Text plugin, which allows Wordpress users to export their data as plain txt files. This certainly seems better than XML, but again will my clients know how to use it if they want to leave? Should Wordpress have more robust export options built in?

-

I don’t have any answers right now, but I think it’s important that I do.

-

Do you have a solid solution for this type of situation? Let me know @a_simpson.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html b/themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html deleted file mode 100644 index c9ea5fb..0000000 --- a/themes/cycle/exampleSite/public/writing/hacking-on-grafana-with-web-assembly/index.html +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - Hacking on Grafana with Web Assembly - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Hacking on Grafana with Web Assembly

- - -
- -

The original inspiration for this idea came from Simon Willison’s work with Datasette Lite. However, compiling Grafana as a WASM binary proved difficult with existing build constraints. After spending some time trying to get that to work I changed course a bit and instead focused on compiling a basic go HTTP server as a WASM module. The new goal being to have a proof of concept that bundled the HTTP server as a WASM binary and intercepted any clicked links on the page and finally passed those links to be resolved by the go server in WASM.

-

I used a Web Worker to interact with the WASM binary. This frees up the main thread of the browser. To put the WASM binary into the worker I loaded the binary and sent a message that contained the binary as a WebAssembly.Module.

-

The Web Worker can then call any go functions that have been exposed via FuncOf. Once the go function returns data, the worker posts that response back to the main thread via another message.

-
let module;
-importScripts("wasm_exec.js")
-go = new Go();
-
-self.onmessage = async (e) => {
-  if (e.data.type === "module") {
-    module = e.data.module;
-    return;
-  }
-
-  if (module) {
-    console.log('Message received: ', e.data.path);
-    const instance = await WebAssembly.instantiate(module, go.importObject);
-    go.run(instance);
-    postMessage(parsePath(e.data.path)); // parsePath is exposed via FuncOf
-  }
-}
-

Sidenote: I wish go could use the same pragma syntax tinygo uses to expose functions instead of the verbose FuncOf. There’s an issue but it has been open since 2018.

-

Obviously, there is no localhost to listen on in a WASM environment. To get around that I created a bare bones ResponseWriter and used that with the Request to run the Handler’s ServeHTTP function which consults the routes that are defined and runs the matching handler code. This allowed me to use a build constraint (setup.go and setup_js.go) and keep my HTTP server functioning normally when run from a terminal but then also worked when run in a WASM context. Here’s what those two files look like:

-

setup

-
//go:build !js
-// +build !js
-
-package main
-
-import (
-	"fmt"
-	"net/http"
-)
-
-func setup() {
-	s := NewServer()
-	err := http.ListenAndServe(":9001", s.mux)
-	if err != nil {
-		fmt.Println("error: ", err)
-	}
-}
-

setup_js

-
package main
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"syscall/js"
-)
-
-type ResponseWriter struct {
-	Body *bytes.Buffer
-}
-
-func (r ResponseWriter) Header() http.Header {
-	return make(http.Header)
-}
-
-func (r ResponseWriter) Write(buf []byte) (int, error) {
-	if r.Body != nil {
-		r.Body.Write(buf)
-	}
-	return len(buf), nil
-}
-
-func (r ResponseWriter) WriteHeader(statusCode int) {}
-
-func createWriter() ResponseWriter {
-	return ResponseWriter{
-		Body: new(bytes.Buffer),
-	}
-}
-
-func parsePath(this js.Value, args []js.Value) interface{} {
-	fmt.Println("args: ", args)
-	server := NewServer()
-	path := args[0].String()
-	req, err := http.NewRequest(http.MethodGet, path, nil)
-
-	if err != nil {
-		fmt.Println("request error: ", err)
-	}
-
-	h, p := server.mux.Handler(req)
-
-	fmt.Println("pattern: ", p)
-
-	w := createWriter()
-
-	h.ServeHTTP(w, req)
-
-	b, err := ioutil.ReadAll(w.Body)
-
-	if err != nil {
-		fmt.Println("ioutil error: ", err)
-	}
-
-	return string(b)
-}
-
-func setup() {
-	js.Global().Set("parsePath", js.FuncOf(parsePath))
-}
-

Conclusions

-

The PoC worked! It’s pretty slick to see a HTTP server running in WASM return back the correct data when a link is clicked. However, in my opinion, WASM continues to be a “solution in search of a problem”. Yes it’s incredibly cool technology but so are the JS engines in Chrome, Firefox, and Safari. The sheer amount of money and engineering time being spent on making JS fast is a race no other technology can win at the moment.

-

That said, Go seems to have done decent work at providing the necessary pieces to make compiling to WASM not awful.

-

Honestly, the thing that surprised and impressed me the most was working with Web Workers. They are seriously useful and seem to “just work”.

- - - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html b/themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html deleted file mode 100644 index 3e6fb61..0000000 --- a/themes/cycle/exampleSite/public/writing/hello-micro-blog/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - Hello micro.blog - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Hello micro.blog

- - -
-

👋 micro.blog

-

I’ve started posting my normal blog feed and a new micro feed to https://micro.blog/simpson. My motivation for integrating with micro.blog is that it feels like the right approach for the “open web”.

-

It did take me awhile to understand the core concepts of micro.blog. The description on the iOS App Store is illuminating:

-

Instead of trying to be a full social network, Micro.blog is a thin layer that glues the open web together, making it more useful. Micro.blog adds discovery and conversations on top of previously unconnected blog posts.

-

Brent Simmons (of inessential.com) had a good post today summarizing what makes micro.blog different from app.net or other social networks:

-
-

And so everyone who follows me on Micro.blog sees my blog posts, and I see theirs. Simple.

-

And anyone who wants to could just read my blog in an RSS reader instead. All good, all open.

-
-

Micro.blog is simply a layer on top of existing RSS/JSON feeds; its simplicity echoes the simplicity of podcasting.

-

So hop on board! Follow me over at micro.blog/simpson or subscribe directly to my new micro feed.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/hello-world/index.html b/themes/cycle/exampleSite/public/writing/hello-world/index.html deleted file mode 100644 index 111ed0e..0000000 --- a/themes/cycle/exampleSite/public/writing/hello-world/index.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - Hello World - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Hello World

- - -
-

I’m proud, nervous, and a little surprised that adamsimpson.net is finally live! It has been a long time in the making, and I’m relieved to have it up. Now the fun begins.

-

A Little About Me

-

To sum me up, I’ll bust out the ‘ol bullet points.

-
    -
  • I work for a small web shop, based in Pennsylvania (though I live in Ohio) and do anything from front-end development and design to “social media” and copy-writing.
  • -
  • I am twenty-five years old and married to the greatest gal there is.
  • -
  • I graduated from college with a degree in English Lit (the web is made of words, so this works, right? right?).
  • -
  • I love: the interwebs, design, development, David Foster Wallace, C.S. Lewis, Don DeLillo, and Jimmy Eat World.
  • -
  • I dislike: most vegetables, Windows (not the ones in buildings), Jane Austen, bad drivers, and when the blinds in our apartment are open at night, it just skeeves me out.
  • -
-

About This Site

-

Still here uh? Brave. Very brave. You have leveled up +1 in patience.

-

Anyway, my vision for this site is a place where I can share the things I’m learning as I do my job, so lots of nerdy posts about front-end development stuff, design stuff, and writing stuff. I’ll probably also throw in observations on the latest tech gadgetry. I may also do more general posts regarding general creative work or whatever else strikes my fancy.

-

Technical Bits

-

This site is powered by Jekyll, a static-site generator. Jekyll is fantastic for a number of reasons, but I love it because I give it text files, and it gives me my site.

-

I’ve modified my Jekyll install a bit. I added Steven Romej’s permalink changes to stop Jekyll from creating ‘post-name-as-a-folder->index.html’ to ‘post-name-as-a-file.html’. I also adopted the pagination changes from Dane Harrigan’s fork.

-

Jekyll is running on top of a Linode 512 running Unbuntu and Nginx. I added one line to my Nginx conf file to support better permalinks thanks to this great post. I just used the one line, try_files $uri.html $uri/ 404.html;.

-

My posting process is simple and straightforward, all I need is Dropbox and a text editor. Usually this means I am using iA Writer, which happily melds the two requirements (and works on my iPhone, iPad, or Mac). I simply write a post and save it in my posts folder in Dropbox. Dropbox takes care of syncing it to the Linode which has Dropbox and a shared copy of my site folder. When a new post is synced up, Jekyll builds my site with the new data and it’s done, the post is live.

-

Now I owe Ted Kulp and Tyler Hall a beer for their posts that got me going with this Dropbox to Jekyll setup. I followed Mr. Kulp’s idea and had incron fire a little bash script when a new post came in from Dropbox.

-

The other obvious benefit to having my site in Dropbox is that my site is automatically backed up.

-

Hardware

-

And now, the infamous, what-do-I-use-at-my-desk section.

-

Well, I currently use a 15" MacBook Pro circa 2009. I connect it to an old 20" Dell LCD at my desk, and also use a Apple Wireless Keyboard, and Magic Mouse.

-

I also have an iPhone 4, iPad 2, and a Kindle.

-

Overall, I’m happy with my current setup, though I do plan on picking up an SSD + 8GB of RAM in the near future.

-

Software

-

As I already mentioned, I use iA Writer to write this site, and also for any writing needs for work. I also use Simplenote & NValt for quick thoughts and to-do lists on the go.

-

I use Fireworks and Photoshop for any design related work. I use a combination of Transmit and Sublime Text 2 for my FTPing and coding needs. Terminal is usually open for Git, or server tomfoolery.

-

Finally, for my browsers I use Safari & Chrome Canary for browsing and development respectively.

-

The End

-

I hope this wall of text isn’t too intimidating and that you learned a little bit about me and what makes this site tick. Just a word of warning, the look and feel of this site may change from time to time. I love to tinker, so consider it a constant work in progress. Thanks for reading.

-

Stick around and enjoy the ride with me!

-

-Adam

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html b/themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html deleted file mode 100644 index dcf4439..0000000 --- a/themes/cycle/exampleSite/public/writing/helm-to-ivy/index.html +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - From helm to ivy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

From helm to ivy

- - -
-

I started playing around with Ivy earlier today. I was motivated in part by reading through the author’s blog, oremacs. I also love his swiper plugin and figured I had to give Ivy a try.

-

Background

-

For the record I discovered Helm about 20 minutes into my initial foray into emacs. I ❤ Helm. I support the project on Patreon. It’s great. I’m all about mastering my tools though and to do that I need to at least try other tools. Enter my attempt to switch to Ivy.

-

Progress

-

This post isn’t meant to be a finished product. I’m going to try and circle back occasionally as I use Ivy for the next couple days. A few notes on my experience so far:

-
    -
  • I somehow had an old version of Ivy installed and when I went to install counsel I was getting weird errors. Deleting Ivy from my elpa directory manually cleared things up.
  • -
  • Wow, by default, Ivy feels much more sparse than Helm. The first thing I had to do was figure out the “buffers list” implementation and change my C-= binding from helm to ivy. It’s definitely more spartan, but I don’t think its a negative necessarily just a change.
  • -
  • Ivy is just a completion package, by itself it doesn’t do a ton. That’s why it comes with counsel and swiper these are the primary interfaces to the good stuff, e.g. counsel-ag searches your project with Silver Searcher.
  • -
  • Previews are incredible! Thanks to this comment on reddit. With the C-M-n and C-M-p commands you cycle through any matches and you see the entire file in the buffer. Imagine searching for a keyword in a project and then getting to see all the glorious context as you pick through the matches without having to open every single file!
  • -
  • Not sure how to completely prevent a package from loading. I don’t want helm to load while I play with Ivy. The :disabled: keyword in use-package doesn’t really prevent it from being loaded, it just prevents the use-package form from being executed. I ended up relying on git and removed the lines from my .emacs and I rm -rf the helm package directories. I looked at this again after sleeping on it. I defined two variables simpson-evil and simpson-helm and I check those values in my config to set up configurations depending on which packages is available. Easy enough.
  • -
  • I had a epiphany about how use-package works. use-package will auto load any package that has a :bind, :mode, :command, or :init keyword. If all you have is :config that package won’t load itself. However adding :defer 1 will load that package once emacs is idle for a second and then fire off the :config body. So far so good. :disabled comes into play even if you have a :after keyword because if you have :after combined with any of the “auto load” keywords above the package will try to do stuff.
  • -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html b/themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html deleted file mode 100644 index cc2faec..0000000 --- a/themes/cycle/exampleSite/public/writing/heroku-and-ssh-keys/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Heroku and SSH Keys - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Heroku and SSH Keys

- - -
-

Heroku rocks. I’ve been using it to host this blog (for free, mind you) for the last couple months. However, I’ve run into a problem where Heroku refuses to authorize a git push heroku by declaring Permission denied (publickey). After messing around deleting, creating, and re-adding SSH keys, I found these two posts that solved the problem for me. Apparently Heroku fails if you point it to any kind of custom SSH key. Simply add Heroku to your SSH config file and specify the key to use, problem solved.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html b/themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html deleted file mode 100644 index 7514a66..0000000 --- a/themes/cycle/exampleSite/public/writing/hiking-the-pacific-crest-trail-in-three-minutes/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Hiking the Pacific Crest Trail in Three Minutes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html b/themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html deleted file mode 100644 index aaeba3e..0000000 --- a/themes/cycle/exampleSite/public/writing/hosting-assets-via-github-pages/index.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - Hosting assets via Github Pages - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Hosting assets via Github Pages

- - -
-

Screenshots in README.mds are really helpful to quickly demonstrate what your open source project does. Hosting those can be surprisingly difficult. There are a couple options:

-

The Problem

-
    -
  1. Upload the image to a image hosting service and then reference the direct URL in the README.md.
  2. -
  3. Check the image into the repo and reference its raw URL in the README.md.
  4. -
-

Both of these have their downsides. The first option means that your image is tied to the uptime of the image hosting service. If the service is down your image is now 404. Option two means you have the image mixed in with your source files which stinks from an organizational perspective.

-

The Solution

-

The solution is fairly obvious but took me awhile to realize it: use Github pages by pushing assets to the gh-pages branch.

-

Hosting assets via Github pages means I don’t have to worry about the image hosting service uptime since Github is hosting both the README.md and the asset now. I also don’t have to worry about those assets cluttering my source directories because Github pages uses a specific branch gh-pages and those assets only show up when that branch is checked out.

-

Here’s a quick walk-through of how to push an image to Github pages (assuming there isn’t a gh-pages branch yet).

-
    -
  1. Create a gh-pages branch off of master (usually).
  2. -
  3. Add the image to the repo via git add /path/to/image.
  4. -
  5. Stage, commit, and push the branch to Github.
  6. -
  7. Go to Github and head to your project settings to grab the Github pages URL. Append the asset name to the end of it and check if you can view the image in your browser.
  8. -
  9. Go back to the command line and checkout master.
  10. -
  11. Add the image to the README.md and check it in.
  12. -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/how-are-you-living/index.html b/themes/cycle/exampleSite/public/writing/how-are-you-living/index.html deleted file mode 100644 index dab266a..0000000 --- a/themes/cycle/exampleSite/public/writing/how-are-you-living/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - How are you living - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

How are you living

- - -
-

One of my favorite writers, Shawn Blanc recently published a short piece entitled, Most People. I highly encourage everyone to head over and read the entire essay. However, because I love the ending so much, I had to share it here as it is truly fantastic:

-
-

Here’s a metric that can help you determine if you’re on track for reaching your goals: are you spending your time, money, and attention differently than most people?

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html b/themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html deleted file mode 100644 index 5495694..0000000 --- a/themes/cycle/exampleSite/public/writing/how-do-we-make-the-web-better/index.html +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - How do we make the Web better - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

How do we make the Web better

- - -
-

The introductory post for The Shift started with this statement about Twitter (emphasis mine):

-
-

Twitter has become a dumping ground for ill-thought-out opinions. Removing the barriers to publishing seems like a great way to encourage people to be a part of discussions they might not otherwise. Unfortunately, for all its possibilities, the platform can actually discourage well-thought-out conversation.

-
-

Ben is completely right, but I find the complaint framed around having a conversation especially apt. I’ve been reading Reclaiming Conversation: The Power of Talk in a Digital Age by Sherry Turkle and she makes the same assertion regarding social media and how it warps our understanding of the very nature of conversation. She writes that:

-
-

As we ramp up the volume and velocity of our online connections, we want immediate answers. In order to get them, we ask simpler questions; we dumb down our communications, even on the most important matters.

-
-

This is profound and terrifying. We’ve traded deeper conversations for shallow ones, as a culture we are preferring quantity over quality.

-

We’ve got to go deeper

-

So, how do we make the Web better? Simple, go deeper and have more meaningful conversations. Done. We can all go home, thanks for reading everyone.

-

Not so fast. The question within the question is how do we (internet workers) have more meaningful conversations in order to make the Web better? I don’t have the answer, but I have a few ideas:

-
    -
  1. -

    Pick better places or platforms for these conversations. Twitter, Reddit, and Hacker News seem to have proven they are not the correct venue.

    -
  2. -
  3. -

    Come with truckloads of empathy.

    -
  4. -
  5. -

    Disconnect

    -
  6. -
-

Platforms

-

I don’t want to get all hippie-dippie, but writing on a blog (with comments disabled) seems like a promising alternative to social media. This is why I think the Shift is such a great idea. Blogs require work to write and work to read. That work or friction is closer to the work of an actual conversation. It’s easier to blast out a snarky tweet, or rip someone apart in a comment thread. So let’s start writing on blogs more and reacting to half-thoughts on Twitter less.

-

Empathy

-

People always talk about empathy. It comes up everywhere, but in practice empathy is not very sexy. The dictionary definition of empathy from Merriam-Webster is:

-
-

the action of understanding, being aware of, being sensitive to, and vicariously experiencing the feelings, thoughts, and experience of another of either the past or present without having the feelings, thoughts, and experience fully communicated in an objectively explicit manner; also : the capacity for this

-
-

Empathy is making the mental effort to think from another perspective. Empathy is having patience as someone struggles through formulating a thought. Empathy is time. We need this so badly in our conversations around the Web. We can’t even begin to make the Web better if we’re not going to take the time to consider other opinions or ideas.

-

Disconnect

-

Turkle highlights another side of conversation that is fading, solitude. She writes that:

-
-

of the rewards of solitude is an increased capacity for self-reflection—the conversations we have with ourselves in the hope of greater insight about who we are and want to be. Professionally, what is our vocation? Personally, what gives us purpose and meaning? Can we forgive our transgressions and those of others? In self-reflection, we come to understand ourselves better and we nurture our capacity for relationship.

-
-

To make the Web better we may need to step back and disconnect to better understand the world and how the Web fits in it. Instead of listening to podcast after podcast in our commutes, what if we spent 20 minutes just thinking in silence? Could we even bear it? We won’t have those ideas to make the Web better without this “lonely thinking”.

-

The future

-

The Shift is a great opportunity to start formulating some of these ideas. I’m excited to see the writings and thoughts that emerge from this experiment. At its core the Web is conversations and relationships. To make it better we need to have better conversations which will enrich our relationships which will ultimately improve the Web.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html b/themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html deleted file mode 100644 index 1c66b89..0000000 --- a/themes/cycle/exampleSite/public/writing/how-to-use-siji-font-on-polybar/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - How to use Siji font on polybar - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

How to use Siji font on polybar

- - -
-

Nice guide on Reddit about how to use the Siji font with polybar.

-
-

[..] install the siji font, and then run "view.sh" in the terminal. If you get an error, try to launch the install.sh again. You’ll get a list of all the glyphs available, select the one you want [..] to use and then look where it says “Character 0x00e002” or something like that.

-
-

Of note is that you’ll end up with weird looking glyphs but siji will interpret it correctly. This is because Siji maps character codes to different icons than other fonts do.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/huffduffer/index.html b/themes/cycle/exampleSite/public/writing/huffduffer/index.html deleted file mode 100644 index c90fc7e..0000000 --- a/themes/cycle/exampleSite/public/writing/huffduffer/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Huffduffer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Huffduffer

- - -
-

I have quite the commute to Sparkbox, as such I listen to a lot of podcasts (usually via Instacast on my iPhone).

-

My one pain point with this setup was when someone would recommend a specific episode of a podcast I didn’t subscribe to. In order for me to listen to that episode, I would have to either download the MP3 and send it over to my phone via iTunes, stream it via Safari on my phone, or subscribe to the whole podcast in Instacast. None of those options are very convenient.

-

Enter Huffduffer. Huffduffer is simple genius, I don’t know why I didn’t use it sooner! Once you sign up for a Huffduffer account, you get your own Huffduffer feed URL. Subscribe to that feed and you’re done. Now, when someone recommends a podcast episode, simply visit the episode page and click your Huffduffer bookmarklet to “huffduff” the episode. Your podcast app will receive the new episode via your Huffduffer feed subscription, sweet eh?

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html b/themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html deleted file mode 100644 index 390a42b..0000000 --- a/themes/cycle/exampleSite/public/writing/i-moved-to-hover/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - I moved to Hover - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

I moved to Hover

- - -
-

In case you didn’t hear, Anonymous broke GoDaddy today. I figured now would be as good a time as any to explain why I moved away from GoDaddy a few weeks ago.

-

I chose Hover to be my GoDaddy replacement. I’ve never hosted anything through GoDaddy (I’m not a crazy person), but I did manage all my domain names through them. Hover and GoDaddy could not be more different, GoDaddy’s interface is comedically awful, Hover’s interface is relatively simple and light - two words you never, ever hear about GoDaddy’s administrative panels. I figure that 90% of using a DNS service is spent in front of their admin interface, it counts to have a good one.

-

I would highly recommend switching from GoDaddy to Hover, or Namecheap, or DNS Simple, the point is to switch away from GoDaddy not really where you switch to. So take the leap, and stop feeling sad inside when you hear another joke about GoDaddy.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/ifttt/index.html b/themes/cycle/exampleSite/public/writing/ifttt/index.html deleted file mode 100644 index 7f8a116..0000000 --- a/themes/cycle/exampleSite/public/writing/ifttt/index.html +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - IFTTT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

IFTTT

- - -
-

I love IFTTT. IFTTT is one of those awesome services that I desperately wished had a business plan.

-

Here are a few of my favorite IFTTT recipes.

-

App.net to Twitter

-

A few weeks ago I made the decision to give ADN another try, largely because ADN offers a RSS feed of my posts, something Twitter thought was too complicated. So I decided to funnel my original posts through ADN and then post them to Twitter. IFTTT facilities all of this with ease.

-

Get the App.net to Twitter recipe

-

Post to App.net from Day One

-

I love Day One, however it doesn’t support posting to ADN. I set up an IFTTT recipe that works off an email from Day One and posts it ADN. This recipe also gets bonus points for working in conjunction with the above ADN To Twitter Recipe.

-

Get the post to ADN via Email recipe

-

Camera Roll to Flickr

-

This recipe is only possible through the new, delightful IFTTT iOS app. Whenever a new photo is taken, IFTTT uploads the photo to my Flickr account. This recipe serves the second purpose of offloading my Camera Roll backups from iCloud to Flickr.

-

Get the Camera Roll to Flickr recipe

-

Feature Request

-

I do wish IFTTT had one additional feature, Feed actions. I would love to have a personal feed, ala Huffduffer, into which IFTTT would dump any data from the various IFTTT triggers. A Feed action would technically allow basic looping when combined with the Feed trigger, which would be super useful and interesting.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html b/themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html deleted file mode 100644 index 20baf94..0000000 --- a/themes/cycle/exampleSite/public/writing/indexing-my-blogs-links/index.html +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - Indexing My Blog’s Links - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/introducing-cycle/index.html b/themes/cycle/exampleSite/public/writing/introducing-cycle/index.html deleted file mode 100644 index fec5e63..0000000 --- a/themes/cycle/exampleSite/public/writing/introducing-cycle/index.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - Introducing Cycle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Introducing Cycle

- - -
-

Cycle is a half-baked static site-generator that I wrote to publish this here interweb page. Cycle is not really ready for anyone else to use but me at this point. However I wanted to outline my rationale for the various design decisions that inform how Cycle works today.

-

Language choice

-

I wrote in my previous post announcing my re-write that I was considering Rust or Common Lisp because those languages allowed me to build a stand alone binary of my site builder. I got some feedback on Twitter that Common Lisp would actually be a good choice:

- -

I ended up going with Common Lisp and I really enjoyed the experience. Common Lisp has the best REPL I’ve ever used in any language. It’s wonderful to use. Having a good REPL is a key component of not only creating new features but also fixing bugs. Once I had chosen the language it was time to figure out how I wanted my program to consume and build my site.

-

Mimic Jekyll…to a point

-

I spent some time understanding how Jekyll works to figure out which parts I wanted to emulate and which parts I wanted to leave behind or solve differently.

-

JSON > YAML

-

Jekyll relies heavily on YAML for data files and inside every post. The decision to include it in every post has always bugged me about Jekyll so I wondered what a static site generator would look like if it used JSON instead of YAML. In my implementation every post is represented as a Markdown file and data for that post is represented as a separate JSON file. The directory structure looks like this:

-
./
-├── README.md
-├── posts
-│   ├── a-few-bash-tips.json
-│   ├── a-few-bash-tips.md
-
-

While this increases the amount of files needed to build the site, I find keeping the Markdown files as “vanilla” as possible worth the trade-off.

-

The Good Parts

-

I copied Jekyll’s directory and file structure pretty closely. The site is built from these source files into a directory called site that holds the entire site. Here’s a breakdown of the required directories and files:

-
    -
  • public: anything in public is copied over verbatim to site. This is the place to put assets like images, third-party JS etc.
  • -
  • posts: contains posts that are processed through templates and dropped into site. Cycle processes all the posts into a data structure that is then available globally inside Cycle for any other part of the build process to use.
  • -
  • templates: hold the various templates for pages and posts as well as templates for RSS and Sitemap.
  • -
  • pages: holds files that are either .mustache files or .md files. If a page file is a .md file then it gets processed with a generic templates/page.mustache template. The only supported .mustache file at the moment is the archive.mustache file which is passed the entire post data object to generate paginated archive pages.
  • -
  • site.css is a file in the root of the project. Any CSS in this file is inlined into the <head> of the built site.
  • -
-

Easy to add new features and fix bugs

-

Another aspect I was hoping to solve with this re-write was to make it easier to add new features and fix bugs as they come up. Common Lisp’s previously mentioned REPL helps in this area. Slime is an Emacs extension that integrates Common Lisp’s REPL into Emacs along other functionality like debugger support. Having the ability to set breakpoints and execute portions of my program at will right inside my editor helps identify bugs. The expressiveness of Lisp also helps in ramping up on code that I wrote months ago. I’ve been using Cycle for a few months now and I’ve enjoyed that I don’t feel overwhelmed when I have to look back at the code.

-

Building binaries in Travis

-

One last thing about Common Lisp and it’s stand-alone binaries. I got Travis CI hooked up and building macOS and Linux versions of cycle without too much struggle. Now whenever I tag a new release Travis builds the binaries and attaches them to the Release in Github. Automating this build and release work has made the actual hosting and building of the site pretty painless.

-

Netlify

-

I switched from AWS S3 to Netlify not because S3 was inadequate in anyway but more because I wanted an excuse to play with Netlify’s features. I ended up writing a Makefile that Netlify can execute to download the latest version of Cycle and then build the site. Netlify is configured to run make cycle && make when a new post is pushed to the repo.

-

Some Common Lisp helper functions

-

Over the course of getting a working version of Cycle out the door I wrote a few helper functions that remove some friction in some common tasks.

-

String concat

-

The concatenate function in Common Lisp is a general purpose function that works over strings as well as lists and other data types. It’s typically used like this: (concatenate 'string "hello" "world"). Notice that concatenate requires that the type of the values to be specified. I didn’t like this so I wrote this:

-
(defun concat (&rest strings)
-  "Wrapper around the more cumbersome concatenate form."
-  (let (result)
-    (dolist (x strings)
-      (setf result (concatenate 'string result x)))
-    result))
-

concat takes any number of strings and uses the dolist macro to call concatenate on them. It’s used like this: (concat "hello" "world"). Much better in my opinion.

-

Write to file

-

Cycle writes a lot of files. That’s pretty much it’s main jam. I realized I was writing the same boilerplate to write files all over the place so I wrote a wrapper function:

-
(defun write-file (contents file)
-  "Write CONTENTS to FILE."
-  (with-open-file (stream file
-                      :direction :output
-                      :if-exists :supersede)
-    (write-sequence contents stream)))
-

Now I can write a file like this: (write-file "Hello world" "./hello-world").

-

String splitting

-

The last helper function I want to show is my wrapper around the UIOP:split-string function. Much like the concat function this mainly avoids extra typing:

-
(defun split-string (string sep)
-  "Wrapper around uiop:split-string to avoid keyword typing."
-  (uiop:split-string string :separator sep))
-

Now I can split a string like this: (split-string "Hello World" " "). Much easier.

-

Never done

-

While I may be using Cycle to publish this very site it’s not done and I don’t think it ever will be. That’s the beauty of software and specifically software written for an audience of me. I will always have new ideas and things I want to fix and Common Lisp provides some fairly unique and fun ways to keep iterating.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html b/themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html deleted file mode 100644 index 8c2b7b4..0000000 --- a/themes/cycle/exampleSite/public/writing/introducing-ivy-feedwrangler/index.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - Introducing ivy-feedwrangler - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Introducing ivy-feedwrangler

- - -
-

It’s not secret that I’ve become quite the Emacs fan over the past couple years. One of my favorite things about Emacs is the Ivy package (and counsel and swiper of course). In exploring what Ivy was capable of I had the idea to write a small package that used Ivy as the interface for my RSS service of choice, Feedwrangler. You can check out the repository here and install the package via melpa.

-

What is Ivy?

-

Ivy is, according to it’s Github repo, a “a generic completion mechanism for Emacs.” Quite simply Ivy is an interface for quickly working with lists of data whether that be:

- -

Ivy-feedwrangler

-

Ivy makes manipulating and filtering lists super quick and easy. In fact, I’d say it’s the quickest way to work with this kind of data. Working with my RSS feed is now lightning fast. Here are a few features of ivy-feedwrangler:

-
    -
  • Mark individual posts as read or mark all as read
  • -
  • View text posts inside a buffer in Emacs, this supports inline images!
  • -
  • Quickly filter through unread items since Ivy can handle regex out of the box
  • -
  • Uses authinfo to handle authentication which uses GPG to encrypt credentials.
  • -
-

The other big perk to using ivy-feedwrangler is that, unlike elfeed (the package for RSS in Emacs), it interacts directly with the Feedwrangler API! That means I can read things in Emacs and that state is synced correctly to my phone and vice-versa.

-

So, if you have a Feedwrangler account, give ivy-feedwrangler a try and let me know what you think!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html b/themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html deleted file mode 100644 index 2651391..0000000 --- a/themes/cycle/exampleSite/public/writing/ip-address-alfred-extension/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - IP Address Alfred Extension - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

IP Address Alfred Extension

- - -
-

I have to admit, I am addicted to customizing my bash experience. Yesterday, I came up with a little, one-off function that smooths over a point of friction in my workflow – working with my internal IP address.

-

During any project, I am often testing in virtual machines. On my development machine I have my host file hacked to manage all the dev URLs. The friction point is constantly having to look up my IP address to test in VMs, or on other devices. This bash function simply parses out my IP address from the results of ‘ifconfig’ and copies that IP address to my clipboard. Now, instead of jumping into the Network pane to see my IP, or reading through ifconfig myself, I can simply type “ip”, and jump back to my VM and paste in the address. The function also displays the IP address on the command line ready for easy typing into a mobile device.

-

function ip { IP=$(ifconfig | grep 'inet 1' | cut -c 6- | awk 'NR==2 {print $1}') echo $IP echo $IP | pbcopy }

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html b/themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html deleted file mode 100644 index 93836e3..0000000 --- a/themes/cycle/exampleSite/public/writing/iphone-checker-with-capybara-and-twilio/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - iPhone checker with Capybara and Twilio - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

iPhone checker with Capybara and Twilio

- - -
-

I got my gigantic iPhone 6+ last weekend, and not via the online Apple Store where my order had been sitting for a couple weeks and wasn’t going to ship until Nov. 5th. Instead I got a friendly text message the minute the phone was available at my local Apple Store. With a few great tools it was incredibly easy to set this system up.

-

TL;DR: I set up a small Heroku app that uses Capybara to check Apple’s website for availability and sends a text to my phone using the Twilio service.

-

The entire process was pretty simple once I figured out a few Heroku oddities. The app hinges on the fact that Apple provides a “Check Availability” link during the ordering process. This link pops open a modal that take your zip code and checks nearby Apple stores for your product.

-

All I had to tell Capybara to do was visit the URL, click the check availability button, and enter my zip code. After that I loop through the store list and check the status message. If the phone is available I send myself a text with the store name, phone model, and link.

-

The toughest part of this project was figuring out how to tell Heroku where the Phantomjs executable was located. Capybara uses Phantomjs behind the scenes and without it the whole thing wouldn’t work. I initially tried to use the Phantomjs build pack but a weird thing with Heroku is that declaring a build pack seemingly removes the path for the Ruby executable. I then discovered the awesome multi build pack tool. Once I created my .buildpack document I just had to tell Heroku to load the Phantomjs build pack and the Ruby build pack like this:

-
https://github.com/stomita/heroku-buildpack-phantomjs.git  https://github.com/heroku/heroku-buildpack-ruby
-

The last piece of the app uses clockwork to kick off the scrape every 10 minutes. Clockwork is incredibly easy to setup and use. Specify the command in the Procfile and Heroku will understand exactly what to do.

-

The code for the project can be found over at Github. Reach out on Twitter or file an issue if you have any questions.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html b/themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html deleted file mode 100644 index a05f83d..0000000 --- a/themes/cycle/exampleSite/public/writing/is-webp-really-better-than-jpeg/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Is WebP really better than JPEG? - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Is WebP really better than JPEG?

- - -
-
-

If you have used tools like Google’s PageSpeed Insights, you probably have run into a suggestion to use “next-gen image formats”, namely Google’s WebP image format. Google claims that their WebP format is 25 – 34% smaller than JPEG at equivalent quality.

-
-
-

In any case, when converting images to WebP, check that they are actually smaller than the JPEG equivalent. There’s no need to serve larger images to your users than needed.

-
-

Great analysis of the WebP image format and a good reminder to not blindly follow what various auditing tools are reporting. Test and verify in addition to implementing the various suggested improvements.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html b/themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html deleted file mode 100644 index de735fd..0000000 --- a/themes/cycle/exampleSite/public/writing/ivy-pinboard-popular/index.html +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - Pinboard popular page in Emacs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Pinboard popular page in Emacs

- - -
-

Ok, this one is still piping hot in my *scratch* buffer so remember that before you criticize the rough edges. I’ve long wanted to quickly filter through the popular links page on pinboard.in without jumping over to a browser. Ideally this page would have an RSS feed or API end point but alas it has neither. I love pulling things into Emacs (yay for text-based interfaces!); so I set out to pull these links into Emacs and display them via Ivy.

-

Feel free to skip ahead and checkout the repo if you’re so inclined.

-

Steps

-

I curled the page down and pasted the HTML into a buffer in Emacs so I could start pulling things apart. My first attempt was to use the excellent elquery library but that was choking on the DOM structure and I never could quite pin down where (sorry Adam, I need to post an issue about that!). My next attempt was to use a more “manual” scripting approach. Since Emacs possesses so many ways to manipulate buffer text I was sure there could be a programmatic way to do this (without doing a bunch of regexing which I’m terrible at and even more so in Emacs). The basic series of steps boiled down to this:

-
    -
  • Use the new-to-me keep-lines function to trim everything out of the buffer except the popular links. I used the classname of the links (bookmark_title) to identify them.
  • -
  • Use loop-for-each-line to well loop over each line. Inside this loop I would need to pull out the href and the title of each anchor link.
  • -
  • I used re-search-forward to move from target to target to figure out the point boundaries for my href and my link text.
  • -
-

I ended up breaking this functionality out into it’s own function since I used it more than once and it was cumbersome to type it all out.

-
    (defun re-capture-between(re-start re-end)
-      "Return the string between two regexes."
-      (let (start end)
-        (setq start (re-search-forward re-start))
-        (setq end (re-search-forward re-end))
-        (buffer-substring-no-properties start end)))
-
    -
  • The final step was dumping the href and the link text into a plist and push that into a larger collection I could pass onto ivy-read to generate my interface.
  • -
-

Coding string

-

One gotcha I ran into is that my titles would occasionally contain odd character sequences like \302. Turns out those are punctuation and various text symbols. The solution is to run the title through decode-coding-string for 'utf-8 to generate the proper characters.

-

❤ Emacs

-

Emacs is so powerful for this type of text manipulation because you can interactively work each step of a program out in an actual buffer and then put those steps together into a function. Each potential solution I thought of was quickly trialed via M: and frequent looks at documentation. Hopefully this has been a helpful look into how I approach solving problems in Emacs. Thanks for reading!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html b/themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html deleted file mode 100644 index 3427376..0000000 --- a/themes/cycle/exampleSite/public/writing/js2coffee-alfred-workflow/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - JS2Coffee Alfred Workflow - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/just-start-over/index.html b/themes/cycle/exampleSite/public/writing/just-start-over/index.html deleted file mode 100644 index 92f520e..0000000 --- a/themes/cycle/exampleSite/public/writing/just-start-over/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - Just Start Over - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Just Start Over

- - -
-

I love when designers write about their experience and process in designing a product.

-

Recently, Sebastiaan De With wrote a post about his experience designing the doubleTwist Alarm Clock, an Android Clock app made by doubleTwist. I found myself nodding my head at this paragraph in his write up:

-
-

During the process, I threw away a ton of designs and simply started over. I also touched on this being an important part of the design process in the interview I gave on design.org: when you feel like what you’re working on really needs a little bit extra, you have to realize that — even though you spent so much time on them — your designs are just pixels, and you can probably simply do better. Throw it out. Kill your baby. Start over. It’s made this app what it is today.

-
-

Starting over is a skill, and it’s something I need to get better at.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/keeping-up/index.html b/themes/cycle/exampleSite/public/writing/keeping-up/index.html deleted file mode 100644 index c13f076..0000000 --- a/themes/cycle/exampleSite/public/writing/keeping-up/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - Keeping up - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Keeping up

- - -
-

Thanks to this tweet by Adam Clark and this post by Brian Rinadli I’ve been thinking about how I keep up with changes in the web development world.

-

Brian writes in his article that

-
-

One of the biggest difficulties front-end developers face can be deciding what is worth paying attention to and what isn’t. If you follow social media, Hacker News, EchoJS or even a handful of blogs, it can be hard to decipher the tools or frameworks that are deserving of investigation versus those that maybe just aren’t there yet.

-
-

I agree; there’s good signal in those streams. However, it’s incresingly difficult to parse the good stuff from the link bait. Brian shares a great list of email newsletters that aim to help cull the noise into manageable chunks of information. I subscribe to Web Design Weekly and Web Development Reading List. I probably only click on 3-4 links in each one, but this approach has worked really well for me for quite some time.

-

Adam expressed another angle to this issue:

- -

Personally, I gave up trying to read my entire feed a while ago; it isn’t feasible. I also try to be selective about how many folks I follow. The harsh reality is that eventually you won’t be able to keep up. I recommend News.Me which emails you the top couple links that were shared in your twitter feed the previous day.

-

I also highly recommend Pinboard’s popular page. While not specifically related to web development, I always find a good link or two perusing it every few days.

-

These tools allow me to relax. Keeping up with the web industry is tough, but this approach nicely limits my twitter check-ins to once or twice a day during the week.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html b/themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html deleted file mode 100644 index 634d779..0000000 --- a/themes/cycle/exampleSite/public/writing/kyle-steed-on-rest/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Kyle Steed on rest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Kyle Steed on rest

- - -
-

Inspiring article by Mr. Kyle Steed, do yourself a favor and take a few minutes and read it.

-
-

Resting isn’t being lazy. Resting is the promise we receive by faith to believe what the Father has spoken and trusting Him to provide all the while continuing to live and work and love.

-
-

I found this quote especially important given my recent string of posts on working hard. Life is all about balance, which is hard.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/lambda-talk/index.html b/themes/cycle/exampleSite/public/writing/lambda-talk/index.html deleted file mode 100644 index cda871c..0000000 --- a/themes/cycle/exampleSite/public/writing/lambda-talk/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - Lambda Talk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html b/themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html deleted file mode 100644 index 108ed1a..0000000 --- a/themes/cycle/exampleSite/public/writing/learning-to-think-in-react/index.html +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - Learning to think in React - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Learning to think in React

- - -
-

Some of you may have noticed that this blog has been going through some renovations. I’ve spent the last couple months moving off Siteleaf and towards a hosted WordPress install. My ultimate goal is to use Wordpress strictly for managing content and to attach a separate front-end written in React.js. While not completely finished, I’m at the point where all pieces are functional enough that I feel comfortable to begin sharing what I’ve learned through the process.

-

React

-

At the moment, React is definitely the cool kid on the Javascript framework block, which history tells us is a perilous and passing position. Regardless, I’ve been intrigued by its philosophy and decisions for a while. Love Facebook or hate them, you can’t deny they have a fantastic engineering team solving some of the hardest problems on the web. My interest in React stems from the fact that that, instead of setting out to solve all the problems of building a web app, it aims to solve just one: the complexity of building user-interfaces. Facebook explains how React makes building UIs easier in a perfect introductory post (which I’ve gone back to many times) that walks through building up a frontend from scratch. Because React is focused on the user interface, it isn’t a very large API to learn. This focus encourages you to use any other tooling, frameworks, or libraries for other aspects of your app.

-

Isomorphic

-

React’s other big draw for me is that it easily enables an isomorphic structure for your web application, which simply means that the same code can render HTML pages on the server and render HTML in the browser. React accomplishes this via two render methods: render and renderToString. render is the default method that inserts the React HTML into a DOM node, and renderToString does what it says on the tin by passing the HTML out as a string.

-

The biggest challenge has been learning to think “isomorphically.” Thankfully, there are several fantastic articles that walk through how to structure and reason about an isomorphic app. Nicolas Hery has a fantastic overview of what an isomorphic app structure can and should look like; I still have this one open in my browser, as I refer to it constantly. I was inspired by James Long’s excellent post on moving his blog to React. Additionally, Charlie Marsh’s post helped me get off the ground when it comes to writing an isomorphic app with React.

-

Data flow

-

Having an isomorphic app means data flow in the app is going to change, and I definitely bent my brain trying to figure out a reasonable approach. The aforementioned Hery article does a great job of outlining one possible solution. Facebook of course has its Flux architecture as the “preferred” approach, but I opted for a simpler approach more akin to James’ flow. Essentially, I defined a static function called fetchData anywhere I needed to request data. I then called this function on the router level.

-

React-router

-

Speaking of the router, I’m using the awesome and delightful React-router. React-router is a fantastic example of how to maintain an open-source project. This post announcing changes to its API reveal the depth of thinking and intentionality of React-router’s authors. I’ve poured over the docs and issues in the course of this project and have been impressed with it constantly.

-

I’m using React-router to handle routes on the server and the client (yay, isomorphic!) with React’s render and renderToString methods. This means that I have a server-routes.js file and a client-routes.js file, which are the only two files that aren’t shared between the client and the server. I’m using a vanilla Express server to kickoff the server portion of the blog. React-router simply plugs in as middleware to handle serving up the application. On the client, I have React-router using the History APIs to navigate, which greatly increases the perceived performance of the site.

-

Promises

-

This was my first experience working with Promises in Javascript. I don’t know how I could have done this project without them - I’d probably still be untangling all the callbacks. Luckily, the brilliant minds behind CujoJS have not only a great promises library, but also a rest library that returns promises. Moreover, both libraries work in the browser and on the server. The pattern I followed for my data fetching looks like this:

-
var promises = state.routes.filter(function (route) {
-  return route.handler.fetchData;
-}).reduce(function (promises, route) {
-  promises[route.name] = route.handler.fetchData(state.params);
-  return promises;
-}, {});
-
-resolveHash(promises).then(function (data) {
-  React.render(<Handler data={data}/>, container);
-});
-
-

Sidenote: For a fantastic primer on .map, .reduce, and .filter, check out Elijah Manor’s post.

-

These functions go in react-router’s run callback. The state.routes object contains the matching route components, so you can filter over them and get all the necessary fetchData functions. We massage this object of functions into a key:value structure to use with the resolveHash method that ships with whenjs. resolveHash will call all the fetchData methods, and once all data has been fetched it calls back to React to render with the new data. This is all possible because, thanks to rest, every fetchData method returns a promise. Here is an example of what a fetchData function looks like:

-
fetchData: function(pageNumber) {
-  var fetchPosts = rest(url).then(function(response) {
-    var postInfo = {
-    };
-    return postInfo;
-  });
-  return fetchPosts;
-}
-
-

Going Forward

-

I think that covers the React portion for now. I’ve pulled the React portion out of my private repo and published it on Github, feel free to browse around. I hope to outline other interesting pieces of the blog, including the WordPress side of things, soon. Feel free to ping me on twitter with any questions.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html b/themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html deleted file mode 100644 index ce18f1c..0000000 --- a/themes/cycle/exampleSite/public/writing/lessons-learned-from-integrating-openai-into-a-grafana-data-source/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Lessons learned from integrating OpenAI into a Grafana data source - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html b/themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html deleted file mode 100644 index 1b59969..0000000 --- a/themes/cycle/exampleSite/public/writing/lyza-gardner-on-laying-down-our-burdens/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - Lyza Gardner on Laying Down our Burdens - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Lyza Gardner on Laying Down our Burdens

- - -
-
-

Part of being successful on the pan-device web is relinquishing control of things we never had control of in the first place. Some of this you have probably heard. Web design processes are being re-imagined with an emphasis on adaptation and a rejection of pixel-perfect mockups. Content is increasingly given a position of centrality, and design flows around it.

-
-

Just go read the whole thing.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html b/themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html deleted file mode 100644 index 524cac1..0000000 --- a/themes/cycle/exampleSite/public/writing/macos-catalina-slow-by-design/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - macOS 10.15: Slow by Design - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

macOS 10.15: Slow by Design

- - -
-

A few days ago Allan Odgaard wrote up the reasons for the frequent slowdowns he’s experiencing in macOS Catalina and it’s shocking:

-
-

Apple has introduced notarization, setting aside the inconvenience this brings to us developers, it also results in a degraded user experience, as the first time a user runs a new executable, Apple delays execution while waiting for a reply from their server. This check for me takes close to a second.

-
-
-

This is not just for files downloaded from the internet, nor is it only when you launch them via Finder, this is everything. So even if you write a one line shell script and run it in a terminal, you will get a delay!

-
-
-

I am writing this post to call attention to what I consider a serious design problem with Apple’s most recent OS where it appears that low-level system API such as exec and getxattr now do synchronous network activity before returning to the caller.

-
-

Marco Arment hit the nail on the head with his tweet summary of the post:

-
-

The macOS security team needs to ask themselves hard questions about their implementation choices when very smart people are disabling huge parts of their OS security layer just to get reasonable performance from common tasks.

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html b/themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html deleted file mode 100644 index ee434f5..0000000 --- a/themes/cycle/exampleSite/public/writing/maybe-you-shouldits-not-youmove-on/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - Maybe you should…it's not you…move on. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Maybe you should…it's not you…move on.

- - -
-

Twitter’s recent API changes and announcements seem to be purposefully obtuse. I don’t know why they can’t just make an announcement telling third-party, client developers to “kick rocks” and turn off the API? It would be easier, their brand probably wouldn’t suffer as much. Maybe they think that any publicity is good publicity? Or maybe Twitter has been incompetent from the start (the fail whale was fun right?), and we forget how they really didn’t contribute any meaningful features or innovations to their own platform, users did.

-

Don’t get me wrong, I’m not ganging up on Twitter (wouldn’t want to hurt a companies feelings right?) or anything. I’m not upset with Twitter for changing how their platform works, it is their platform after all. I’m just amazed at the lack of clear, direct communication.

-

So, here is a list of other writers who have attempted to unravel what Twitter’s recent announcements actually mean. Enjoy.

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html b/themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html deleted file mode 100644 index 0b24bbc..0000000 --- a/themes/cycle/exampleSite/public/writing/medium-isnt-permanent/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - Medium isn't a permanent fixture on the Internet - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Medium isn't a permanent fixture on the Internet

- - -
-

Owen Williams just realized Medium isn’t a permanent fixture on the Internet:

-
-

It’s not difficult to imagine an acquisition on the horizon (by who, one would wonder) or some other sort of exit. It doesn’t feel like Medium has a strategy, living on borrowed time and money; what happens if this beautiful, simple central store of content just disappears?

-
-

No offense to Owen but this has been Medium’s problem from day one. If you’re writing on the Internet and you aren’t hosting (owning) your content you’re work will disappear; it’s just a matter of time.

-

Owning your content is why micro.blog is so interesting to me. Owning your content is why RSS is never going away. Owning your content is why things like Wordpress, Moveable Type, and the JAM stack are much better choices than yet another online service.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html b/themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html deleted file mode 100644 index 0bf76f8..0000000 --- a/themes/cycle/exampleSite/public/writing/messi-is-re-writing-the-record-book/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - Messi is re-writing the record book - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Messi is re-writing the record book

- - -
-

In a fantastic video the YouTube channel MagicalMessi documents all the various records that Messi has broken during his illustrious career. It’s a fantastic video. Messi is one of a kind and we’ll never see someone like him again.

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/microblogging/index.html b/themes/cycle/exampleSite/public/writing/microblogging/index.html deleted file mode 100644 index 4c39a3b..0000000 --- a/themes/cycle/exampleSite/public/writing/microblogging/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - Microblogging - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Microblogging

- - -
-

Manton Reece recently shared his microblogging setup with WordPress. I have a similar system that was inspired by Jeremy Keith’s example. Like Manton, I had to figure out the quickest way to create a new post. I eventually settled on SMS-to-post thanks (once again) to Twilio. SMS-to-post lets me text my Twilio number which sends the text to WordPress where it becomes a new “note”. Publishing that “note” to Twitter is just a matter of hooking into the WordPress publish_post action and sending the post to Twitter via its API.

-

Here are a few other implementation notes:

-
    -
  • I created a custom post type in WordPress called “Notes”.
  • -
  • The post status API makes this entire process smooth.
  • -
  • SMS-to-post has a few gotchas, the biggest one is that SMS with emoji are limited to 70 characters.
  • -
  • I don’t have an RSS feed for my Notes…yet
  • -
  • I save the tweet ID of every post that gets posted to Twitter. I use that ID to pull in the favorite and retweet counts and display them next to each “note” in the WordPress dashboard.
  • -
  • Twilio needs an endpoint to POST incoming texts to WordPress. Creating custom endpoints is trivial thanks to this great guide. I also recommend the rewrite rules inspector plugin for working with rewrite rules.
  • -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html b/themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html deleted file mode 100644 index a671f93..0000000 --- a/themes/cycle/exampleSite/public/writing/migrate-an-existing-build-process-to-npm-scripts/index.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - Migrate an existing build process to npm scripts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Migrate an existing build process to npm scripts

- - -
-

Last week I gave a short introduction to using npm as a build tool at GemCity JS.

- -

Rewrite?

-

There were a few questions about how to start using npm as a build tool on an existing project. The short answer is: start abstracting tasks behind npm scripts. This weekend I migrated this blog to my new favorite host and ended up replacing a grunt task with a npm task. Here’s how it went down.

-

Pick a task

-

I was using two plugins, grunt-usemin and grunt-rev, to “fingerprint” or rev my asset files. It barely worked (only some files were properly rev’d and inserted) and it was awkward. Usemin requires specific HTML comments so that it knows what files to replace. I finally decided to write my own rev task.

-

The old

-

For reference here is my old Grunt config:

-
 rev:
-  files:
-    src: ["public/js/browser.js", "public/css/base.css"]
-
-  usemin:
-    html: 'server/app.hbs'
-    options:
-    assetsDirs: 'public/'
-
-  useminPrepare:
-    html: ['server/app-tmp.hbs']`
-

These tasks were run in this order during deployment: rev, useminPrepare, usemin.

-

The plan

-

I stared off by jotting down the flow and transformations required for revving my assets. I came up with this list:

-
    -
  1. Compile assets (sass, babel)
  2. -
  3. Rev them (this is just magic right?)
  4. -
  5. Overwrite non-rev’d paths in app.hbs.
  6. -
-

That list was terribly shortsighted. Here’s how it actually turned out:

-
    -
  1. Compile assets
  2. -
  3. Generate rev filename for each asset
  4. -
  5. Write new asset file with rev’d filename for each asset.
  6. -
  7. Create (force if necessary) app.hbs from app-tmp.hbs (-tmp for template)
  8. -
  9. Read app.hbs as a string.
  10. -
  11. Replace non-rev’d paths with rev’d paths in app.hbs using String.replace().
  12. -
-

Seem like this might be more code and trouble than it’s worth? Not at all.

-

The new task

-

Since we’re going to replace a grunt task with a npm script task, lets use ES6 goodness. I installed babel which lets me execute scripts using babel-node instead of node. I then created a new directory called tasks/ and named my new task file, tasks/rev.js. I also installed the super awesome rev-file package to handle the reving.

-

The code turns out to be fairly succicent:

-
import rev from "rev-file";
-import path from "path";
-import fs from "fs-extra";
-
-const projectPath= path.dirname(__dirname);
-const tmp = `${projectPath}/server/app-tmp.hbs`;
-const app = `${projectPath}/server/app.hbs`;
-
-fs.copySync(tmp, app, {'clobber': true});
-
-const assets = [
-  `${projectPath}/public/css/base.css`,
-  `${projectPath}/public/js/browser.js`
-];
-
-assets.forEach((f) => {
-  const revPath = rev.sync(f);
-  fs.copySync(f, revPath);
-  const appString = fs.readFileSync(app, 'utf8');
-  fs.writeFileSync(app, appString.replace( path.basename(f), path.basename(revPath) ));
-});
-

Wrap it up

-

Now I have a task. How do I integrate this into my existing Grunt process? npm scripts to the rescue. I created a new script entry in my package.json like this:

-

-"scripts": {
-  "start": "node ./bin/www",
-  "rev": "babel-node tasks/rev.js"
-}
-

npm scripts can be called directly using npm run, npm run rev in this case. The final step is to modify my Gruntfile to run the rev command using the handy grunt shell plugin:

-

-  shell:
-    rev:
-      command: "npm run rev"
-

And that’s all I had to do. Now I can continue to replace pieces of my build system with npm scripts without having to do a big re-write. Using npm as a build tool also illustrates the simplicity of some of these tasks. It’s much easier to maintain a 20 line task than to keep multiple plugins up to date.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html b/themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html deleted file mode 100644 index b9350fe..0000000 --- a/themes/cycle/exampleSite/public/writing/moved-to-siteleaf/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - Moved to Siteleaf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Moved to Siteleaf

- - -
-

I’ve moved this blog from Jekyll on Heroku to Siteleaf on S3. I did this for a couple reasons:

-
    -
  1. Siteleaf gives me more control without having to be on my computer. The ability to post from my phone is the secret sauce in my opinion.
  2. -
  3. Siteleaf is just an API. I was able to easily convert my Jekyll posts to Siteleaf with a simple Ruby script. I can just as easily switch to another platform in the future.
  4. -
-

I’m excited by the move, I also took the opportunity to freshen the design up around here too. Hopefully you’ll see more posts, more regularly.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html b/themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html deleted file mode 100644 index 75750cc..0000000 --- a/themes/cycle/exampleSite/public/writing/moving-away-from-google/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - Moving away from Google - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Moving away from Google

- - -
-

Marco and Gruber shared last week that they both use DuckDuckGo and Fastmail(referral link) instead of Google search and Gmail. Since I just started using both services, here are a few of my thoughts on them.

-

I previously had Google Apps set up for my domain email (adam@adamsimpson.net). By far the best thing I can say about Fastmail is that I haven’t noticed anything different since switching. Fastmail’s spam protection, speed, and reliability all seem on par with Google’s and I appreciate the superior incentives of Fastmail when it comes to privacy.

-

It’s the same story with DuckDuckGo, I haven’t noticed a drop-off in the quality of the search results. One of my favorite features is the ability to send search queries as POST requests instead of GET requests. I love this because it prevents my history from getting polluted with DuckDuckGo pages that have terms in the URL; a little thing for sure, but one I appreciate.

-

I was skeptical about how happy I would be with things outside of Google’s ecosystem, but I’ve been pleasantly surprised. Fastmail and DuckDuckGo offer a great alternative to Google’s apps.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html b/themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html deleted file mode 100644 index d117f7d..0000000 --- a/themes/cycle/exampleSite/public/writing/moving-tweetbot-beta-to-a-new-mac/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Moving Tweetbot Beta to a new Mac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Moving Tweetbot Beta to a new Mac

- - -
-

Tweetbot for Mac entered Beta a few weeks ago, and also cut off new users from trying out the Beta to comply with new API changes from Twitter.

-

I love Tweetbot, and the Mac client is no exception. However I ran into a snag when I tried to set up the Tweetbot Beta on my new MacBook Air. The app kept redirecting me to the Tweetbot Beta blog post. Now to be fair, I think if I had used the Migration Assistant built into OS X I wouldn’t have run into this issue. However I had already decided to “start fresh” on this new machine and only bring things over from my old MacBook Pro when needed. After spending a couple minutes Googling around for a solution, I gave up and reverted to my trusty, stand-by Twitterific.

-

After a couple days of this I got the bug again to see if I could get Tweetbot Beta up and running on my new machine. New comments on the Tweetbot Beta blog post revealed the solution. Check out these two answers, Tweetbot Beta is now happily running on my new MacBook Air. To move Tweetbot Beta to a new machine copy the Tweetbot Keychain item, Application Support folder, and Container folder to your new Mac and you should be good to go.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html b/themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html deleted file mode 100644 index 3bd9b7e..0000000 --- a/themes/cycle/exampleSite/public/writing/my-first-bookmarklet/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - My First Bookmarklet - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

My First Bookmarklet

- - -
-

Update

-

ESPN has wisely fixed this workaround as of 08/10. I’ll leave the rest of the post up for posterity though.

-

Original Post

-

It all started when I was doing my daily sports news catch-up, and clicked on a link that lead me to an ESPN Insider article, only without the Insider paywall. I clicked on another Insider article and hit the paywall. I wondered if the Insider paywall simply checked the URL scheme, and didn’t have any session or cookie security.

-

I compared the two links and noticed some minor differences, I decided to match the paywalled link to the structure of the non-paywalled link and it worked! Now, I’m assuming ESPN knows this is one way around their Insider paywall, most paywalls seem to have holes (see NYT, WSJ, etc.).

-

Anyway, like any good geek, I went ahead and made my first ever bookmarklet to automate the URL matching. The code is below.

-

javascript:(function(){ var pathArray = window.location.href; var newValue = pathArray.split('&action='); var firstUrl = newValue[0]+newValue[1]+newValue[1]; var secondUrl = firstUrl.split('login&'); var finalUrl = firstUrl+'login%26'+secondUrl[2]; function readInsider() { windowObjectReference = window.open(finalUrl, "_blank"); } readInsider(); })();

-

You may have to hit the bookmarklet more than once for it to work. Despite the hacky nature of the code and skittish performance, the success of my quick little project has me thinking of how I can BOOKMARKLET ALL THE THINGS!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/new-workstation/index.html b/themes/cycle/exampleSite/public/writing/new-workstation/index.html deleted file mode 100644 index d5b32e7..0000000 --- a/themes/cycle/exampleSite/public/writing/new-workstation/index.html +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - New workstation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

New workstation

- - -
-

New job means time for a new workstation.

-

Some history

-

The first computer I ever purchased was the 12" Powerbook G4. Since that Powerbook I’ve always had laptops as my main machines (desktop gaming PC not withstanding). Remote working the last few years has made me realize that the portability of a laptop is largely wasted since I only travel a handful of times a year and yet I live with the downsides of a laptop the rest of the time. So, last year I started thinking about a desktop machine for my primary workstation. A desktop is appealing for a handful of reasons:

-
    -
  • More powerful CPUs
  • -
  • More expansion capabilities
  • -
  • More durable
  • -
-

The options

-

The Mac Studio was recently released to much fanfare and was really intriguing to me. However, when I started considering it I only had about a week to 10 days before my start date at Grafana and I couldn’t wait the quoted 4-6 weeks delivery time for a Mac Studio with 32GB of RAM.

-

I was also pretty unwilling to leave my comfy NixOS install + i3. Michael Stapelberg’s latest post about his new workstation proved timely and convinced me to give the new Intel Alder Lake CPUs a shot.

-

Apple’s M1 family of chips deliver incredible performance per watt but I wasn’t as concered about the power usage given this was a desktop machine not a laptop. I was however focused on at least matching the M1 chips in single-threaded performance since a good chunk of my development work (Node, build tools, etc) are still single-threaded. I ended up with the Intel i5-12600k and I really couldn’t be happier. Here’s the full parts list:

- -

XMP issues

-

I ran into the same memory XMP issues that Michael mentions in his post so I disabled the XMP profile and the system passed the “Coding Horror burn in tests” with flying colors.

-

Cooling

-

I mounted the 140mm fan to the bottom of the case as intake and the CPU cooler is of course positioned as intake as well. Hot air rises out the top of the case quite well. During the prime95 torture test the CPU never got over 78°C and I couldn’t ever hear either fan. I run both fans in the “silent profile” in the BIOS and I use Noctua’s adapters to lower the voltage even more. Now the only fan I could hear during max load was the PSU fan which doesn’t spin at all under low to medium loads but under high load it kicks on. Day to day it’s hardly on so the system is dead quiet most of the time.

-

Case

-

I absolutely love the Cerberus case. It’s Mini-ATX but still super compact and fits on my desk quite well. All the panels are solid metal and the way all the panels pop off is really really nice. I opted for the handle mount on the top and the internal PSU moutning.

-

Linux

-

NixOS installed just fine. I’m runing the 5.17 kernel because Alder Lake needs a newer kernel for it’s graphics and CPU scheduler (coming soon?). I have WiFi and Bluetooh disabled in the BIOS since everything is hard-wired to the machine.

-

Verdict

-

This build has proven quite comfortable over the few weeks I’ve used it. I love that I have 2 free RAM slots if I ever feel the need for more RAM. I also love that I have 3 remaining Nvme slots on the motherboard for additional solid state storage in the future.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html b/themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html deleted file mode 100644 index 630e266..0000000 --- a/themes/cycle/exampleSite/public/writing/nginx-www-rewrite/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - Nginx www rewrite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Nginx www rewrite

- - -
-

Quick tip for rewriting www.example.com to example.com or vice versa in Nginx.

-

My conf file originally looked like:

-

server { server_name www.example.com example.com; }

-

I had to create another server block, and move all the conf information to the new block. In my case I was rewriting www to non-www.

-

server { server_name www.example.com; //rewrite here; } server { server_name http://example.com; //all the server stuff goes in this block; }

-

Update

-

Instead of mucking around with rewriting, I should have just used return, like so:

-

server { server_name www.example.com; return 301 http://example.org$request_uri; }

-

The lesson is, always check out the official docs before Google.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html b/themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html deleted file mode 100644 index f5c9e68..0000000 --- a/themes/cycle/exampleSite/public/writing/nixpkgs-is-a-treasure/index.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - nixpkgs is a treasure - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

nixpkgs is a treasure

- - -
-

Nix and NixOS continue to be the best way to manage and build software that I’ve found. Every project has a shell.nix file in the root where I can define the specific software needed to work on that project along with any necessary environment variables or $PATH modifications. I ran into an issue this week though where I needed an “old” version of Go (1.20) but the version had already been removed from nixpkgs. How can I pull in an “unlisted” version into my shell.nix?

-

It’s actually pretty straightforward, utilize fetchTarball to pull in nixpkgs based on a commit where the version was present sometime in the past. You can mix that import in with regular/“current” packages with no issue like so:

-
{ pkgs ? import <nixpkgs> {} }:
-
-let oldGo = import (builtins.fetchTarball {
-    url = "https://github.com/NixOS/nixpkgs/archive/33c51330782cb486764eb598d5907b43dc87b4c2.tar.gz";
-    sha256 = "sha256:0nflmpfp3pk704vhlvlgh5vgwl8qciqi18mcpl32k79qjziwmih8";
-    }) {};
-in 
-
-pkgs.mkShell {
-  buildInputs = [
-    oldGo.go_1_20
-    pkgs.gopls
-    pkgs.nodejs_18
-  ];
-  
-  hardeningDisable = [ "fortify" ];
-
-  shellHook = ''
-    mkdir -p .go .npm
-    export GOPATH=$PWD/.go
-    export NODE_PATH=$PWD/.npm
-    export NPM_CONFIG_PREFIX=$NODE_PATH
-    export PATH=$PWD/.yarn/sdks/typescript/bin:$PWD/.go/bin:$PATH:$NODE_PATH/bin
-  '';
-}
-

Notice I can reference the “nixpkgs” tarball/snapshot, oldGo, and pull in the version of Go I need?! nixpkgs is such a treasure trove of software, it’s absolutely incredible!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html b/themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html deleted file mode 100644 index 147f636..0000000 --- a/themes/cycle/exampleSite/public/writing/nothing-speaks-like-a-demo/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Nothing speaks like a demo - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Nothing speaks like a demo

- - -
-

Great post from my friend and co-worker Bryan Braun on the value of demoing.

-
-

It didn’t matter that his demos weren’t fully built, or available for anyone to use. We simply needed to see it, in order to understand.

-
-

I find this is true for any kind of project: hobby or professional. Feedback — that elusive crucial ingredient to a good product — tends to arrive when someone else can see/hear/touch/examine what you’re working on.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html b/themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html deleted file mode 100644 index c47c07a..0000000 --- a/themes/cycle/exampleSite/public/writing/on-diminishing-modes-in-emacs/index.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - On diminishing modes in emacs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

On diminishing modes in emacs

- - -
-

“Diminishing modes” in Emacs is a popular topic. It took me a while to understand the basic (and simple) rules around how to customize the display of the various mode names.

-

What are modes

-

Modes in Emacs come in two flavors, major and minor modes. The Emacs manual explains modes like this:

-
-

Emacs contains many editing modes that alter its basic behavior in useful ways.

-
-

Major modes:

-
-

[…] provide specialized facilities for working on a particular file type […] Major modes are mutually exclusive; each buffer has one and only one major mode at any time.

-
-

Minor modes are:

-
-

[…] optional features which you can turn on or off, not necessarily specific to a type of file or buffer. […] Minor modes are independent of one another, and of the selected major mode.

-
-

Customize the mode line

-

Modes are great, yet they fill up the mode line. I only really want to know about a handful of minor modes and the major mode. On top of that I don’t like how some modes name themselves (e.g. all caps, too long, etc.). Changing the display or completely hiding a mode is different for major and minor modes.

-

Changing minor mode names

-

Minor mode names are stored in a list variable called minor-mode-alist. You can customize that directly or use the fantastic package diminish as a wrapper around that functionality, like so:

-

(diminish 'flyspell "spell")

-

Changing major mode names

-

Major mode names are not stored in a simple list variable. Yet, fear not! In reading the source of the diminish package, I stumbled across this comment:

-
-

To diminish a major mode, (setq mode-name “whatever”) in the mode hook.

-
-

The variable mode-name couldn’t be correct could it? Yes, yes it is. Here’s an example of changing the mode name for the default elisp-mode:

-

(add-hook 'emacs-lisp-mode-hook (λ () (setq mode-name "λ")))

-

Now you have all the tools at your disposal to change every mode’s name in your mode line.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/on-equifax/index.html b/themes/cycle/exampleSite/public/writing/on-equifax/index.html deleted file mode 100644 index 4b84760..0000000 --- a/themes/cycle/exampleSite/public/writing/on-equifax/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - On Equifax - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

On Equifax

- - -
-
-

In the end, the truth of the Equifax breach—who was affected, and how, and what the company will do to help, and what the terms of such assistance entail—might not be the most important lesson from this incident. More than anything, it suggests that a corner has been turned in corporate consumer data responsibility. Like severe weather, breaches have become so frequent and severe that they can begin receding from prominence. No matter their grievous effects, Equifax’s response suggests that fatalism might replace responsibility, planning, and foresight. This is just what happens now.

-
-

I don’t do many link posts but Ian Bogost sums up my feelings perfectly about the Equifax breach.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/on-george-floyd/index.html b/themes/cycle/exampleSite/public/writing/on-george-floyd/index.html deleted file mode 100644 index 49192b4..0000000 --- a/themes/cycle/exampleSite/public/writing/on-george-floyd/index.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - On George Floyd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

On George Floyd

- - -
-

I haven’t written anything here about George Floyd’s murder. I still don’t have a cogent response but here’s what I’ve been mulling over:

-
    -
  • America has a problem when year after year the very institution put in place to serve folks in our communities ends up killing and harassing them and even goes out of its way to target Black people in those communities.
  • -
  • Like everything in America today the response to Floyd’s murder has become politicized. We all need to make the effort to move past our collective politics and biases and grapple with what changes need to be made both personally and collectively.
  • -
-

I’ve collected three links that have stuck with me over the last handful of weeks.

-

Unsurprisingly Dave Chappelle’s 8:46 special on George Floyd is insightful, gripping, and poignant.

- -

Around the 5:40 mark he breaks down the problem:

-
-

What are you signifying — that you can kneel on a man’s neck for eight minutes and 46 seconds and feel like you wouldn’t get the wrath of God? That’s what is happening right now. It’s not for a single cop. It’s for all of it. Fucking all of it.

-
-

Elsewhere, McSweeney’s, in typical fashion, cast the issue in a new light:

-
-

This initiative, also known as Skynet, was created by Cyberdyne Systems for the Department of Defense as a way to keep Americans safe. Critics have said that spending half of our country’s GDP on developing an army of state-of-the-art cyborgs with advanced weapons systems and an AI specifically trained to neutralize threats was a bad idea. And while the recent killings might seem to confirm that, we feel that, despite a few stumbles here and there, this program has still been an overwhelming success.

-
-

Finally, Chris Rock has this great segment about “bad apples”.

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/on-webpack/index.html b/themes/cycle/exampleSite/public/writing/on-webpack/index.html deleted file mode 100644 index 65c76e6..0000000 --- a/themes/cycle/exampleSite/public/writing/on-webpack/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - On Webpack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/openring/index.html b/themes/cycle/exampleSite/public/writing/openring/index.html deleted file mode 100644 index 53695a0..0000000 --- a/themes/cycle/exampleSite/public/writing/openring/index.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - Openring - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Openring

- - -
-

I’ve added Drew DeVault’s openring project to the blog. openring is a nice utility (written in Golang) that parses RSS feeds and generates an HTML template file to include on your website. I love things that utilize RSS feeds and things that make indie sites better and openring does both! Thanks to Drew for the tool.

-

It was pretty easy to integrate into my build system. I added a new Makefile task that looks like this:

-
openring.mustache:
-	./bin/openring \
-	-s https://drewdevault.com/feed.xml \
-	-s https://fasterthanli.me/index.xml \
-	-s https://endler.dev/rss.xml \
-	-s https://inessential.com/xml/rss.xml \
-	-s https://www.bryanbraun.com/rss.xml \
-	< openring.html \
-	> ./templates/partials/openring.mustache
-

I then added this new task as a dependency on my build/generate step and I was done.

-

You can view my template file here.

-

I also added the openring binary directly to the repo. It’s not pretty but it beats compiling the binary every time my site deploys (Note: I do pull down a new cycle binary every time the site deploys but I can control that flow whereas I can’t control where openring builds.)

-

For now I’m only displaying my openring on the home page of the blog but if folks think it would be useful on other pages (like this post page) shoot me a message in my public inbox (link below).

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/oscar/index.html b/themes/cycle/exampleSite/public/writing/oscar/index.html deleted file mode 100644 index 663bb96..0000000 --- a/themes/cycle/exampleSite/public/writing/oscar/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Introducing oscar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Introducing oscar

- - -
-

I’ve been working on a small command-line utility written in Rust called oscar. oscar polls the pbskids.org API for new episodes of any PBS show. If it finds an episode it hasn’t seen before it downloads the episode to the specified directory.

-

I run oscar via the cron scheduler on my home server and over the past few months it’s been largely invisible and maintenance-free. Whenever new episodes show up, oscar downloads them and my 3 year-old can stream it on any of the devices in the house via Plex or Infuse.

-

To get started I recommend pulling down the latest release from Github (if it’s not broken) or building locally via cargo build --release. To view the available shows run oscar list. Once you have found a show tell oscar to find episodes by invoking it with the --show-slug option and the destination directory option like: oscar --show-slug SHOW_SLUG --output /path/to/video/folder.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html b/themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html deleted file mode 100644 index 7f0292f..0000000 --- a/themes/cycle/exampleSite/public/writing/parsing-memory-usage-in-htoptop/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Parsing memory usage in htop/top - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Parsing memory usage in htop/top

- - -
-

I’ve been trying to figure out how much memory a node app is using on my VPS, and output from top or htop is fairly overwhelming. In searching around I found Mugurel Sumanariu’s post clearly explaining each column related to memory usage.

-

The column I should be paying attention to is RES, which

-
-

[..] stands for the resident size, which is an accurate representation of how much actual physical memory a process is consuming. (This also corresponds directly to the %MEM column.)

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html b/themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html deleted file mode 100644 index bd4fa86..0000000 --- a/themes/cycle/exampleSite/public/writing/plaintext-and-markdown-a-primer/index.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - Plaintext and Markdown - A Primer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Plaintext and Markdown - A Primer

- - -
-

My little sister is headed for her freshmen year of college, and so of course she asked me the classic question, “Should I get Word or Pages for my Mac?”. I told her to get Pages and call it good, but inside I wanted to tell her go get a copy of Byword, iA Writer, Write Room, or any of the other fabulous text editors on the Mac and iOS. I didn’t say any of these things, but I did decide to write it all down.

-

Plaintext

-

Plaintext is all the little .txt files TextEdit saves (but only if you’re in Plaintext mode, naturally). A Plaintext file is the most basic kind of text document. The format is literally just text, there is no formatting aside from basic paragraphs and indents, and no compatibility requirements. None. Read it again. No. Compatibility. Requirements. Last year David Sparks wrote up a fantastic article for Macworld explaining the benefits of Plaintext, he wrote (emphasis mine):

-
-

Although modern word processing programs can do some amazing things—adding charts, tables, and images, applying sophisticated formatting—there’s one thing they can’t do: Guarantee that the words I write today will be readable ten years from now.

-

That’s just one of the reasons I prefer to work in plain text: It’s timeless. My grandchildren will be able to read a text file I create today, long after anybody can remember what the heck a .docx file is.

-
-

Plaintext will last (at least much longer than .doc will), you can count on it. If you need to apply some arcane formatting for a research paper, fire up a copy of Pages or Word and copy and paste your text in. Keep the plaintext file around though, let the actual text live on in those .txt files.

-

Markdown

-

The jelly to Plaintext’s peanut butter is Markdown by John Gruber. Markdown extends Plaintext by adding basic formatting such as headings, unordered and order lists, block quotes, and italics and bolding. Markdown allows you to add inline images, external and internal hyperlinks, and even tables, without compromising the integrity of your Plaintext documents.

-

Every post on this blog is written in Markdown. The blog engine, Jekyll, interprets the Markdown and spits out the appropriate HTML. If I ever wanted to switch to another blog engine, I have a bunch of simple plaintext files that are very portable.

-

If you want to see Markdown in action, or want to practice with the syntax, head over to Markdownr by the indefatigable Mr. Sam Soffes. Markdownr lets you input Markdown on the left side and instantly see the formatted text on the right side. Check it out.

-

If you want the Markdownr experience on your desktop, check out Brett Terpstra’s app Marked.

-

A Few Bullet Points

-

Other benefits of Plaintext and Markdown are:

-
    -
  • Easy for modern Operating Systems to index and search
  • -
  • Simple to backup
  • -
  • Simple to move
  • -
  • Easy to edit on any device
  • -
  • Format agnostic.
  • -
-

Plaintext and Markdown make a great pair, they are unrestricted by compatibility, specific software, or corporate governance. I’ve moved all my text-related work to plaintext and Markdown and it has added a lightness to working with text that is just perfect.

-

Give Markdown + Plaintext a shot, there is literally no barrier to entry. Hopefully you will realize that getting out of heavy word processors like Word or Pages frees up your text, mind, and words.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html b/themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html deleted file mode 100644 index 21f4a7e..0000000 --- a/themes/cycle/exampleSite/public/writing/polybar-fonts-and-ubuntu/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - On Polybar bitmap fonts and Ubuntu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

On Polybar bitmap fonts and Ubuntu

- - -
-

I use polybar as my status bar in i3 and it’s been going great for months now. However, I was recently grepping through the syslog trying to figure out why a browser crash happened and the log was filled with polybar spam that looked like this: polybar|warn: Dropping unmatched character. So I started picking at solving the warning.

-

Turns out there’s a Github issue that contains the solution which is to enable bitmap fonts which I’ll paste here for posterity:

-
# "Un-disable" bitmap fonts
-sudo rm /etc/fonts/conf.d/70-no-bitmaps.conf
-# Clear the font cache
-sudo fc-cache -f -v
-

Apparently Ubuntu disables bitmap fonts by default but polybar uses bitmap fonts for icon rendering. I also needed to install the sijj icon font family which was painless.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/pretty-git-log/index.html b/themes/cycle/exampleSite/public/writing/pretty-git-log/index.html deleted file mode 100644 index 93c4dde..0000000 --- a/themes/cycle/exampleSite/public/writing/pretty-git-log/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - Pretty Git log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/psychicpaper/index.html b/themes/cycle/exampleSite/public/writing/psychicpaper/index.html deleted file mode 100644 index b3ecc08..0000000 --- a/themes/cycle/exampleSite/public/writing/psychicpaper/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - Psychic Paper - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Psychic Paper

- - -
-
-

RIP my very first 0day and absolute best sandbox escape ever:

-
-
<key>application-identifier</key>
-<string>...</string>
-<!---><!-->
-<key>platform-application</key>
-<true/>
-<key>com .apple.private.security.no-container</key>
-<true/>
-<key>task_for_pid-allow</key>
-<true/>
-<!-- -->
-

Tweet that demonstrates a recent zero-day (now patched) in iOS. This serves as your annual reminder that parsing xml-like things is a fraught activity.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/rands-on-email/index.html b/themes/cycle/exampleSite/public/writing/rands-on-email/index.html deleted file mode 100644 index 10eea13..0000000 --- a/themes/cycle/exampleSite/public/writing/rands-on-email/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Rands on Email - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Rands on Email

- - -
-

Michael Lopp delivers a great piece on dealing with Email. I especially loved this quote:

-
-

Email is imprecise. It is easy to misinterpret. Email is a digital force of nature. It’s not going anywhere, but email, while convenient and sometimes efficient, is dehumanizing.

-
-

Do yourself a favor and read the whole thing.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/recently-16/index.html b/themes/cycle/exampleSite/public/writing/recently-16/index.html deleted file mode 100644 index a108d1b..0000000 --- a/themes/cycle/exampleSite/public/writing/recently-16/index.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - Recently - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Recently

- - -
-

I’m stealing the title format of this post from Tom MacWright’s Recently posts.

-

Here’s a random assortment of links and miscellaneous updates on things.

-

autofs

-

autofs is a cool utility that watches a specific directory path and when a program tries to read or write to that path it mounts a filesystem at that location. I’m using this to auto mount my NAS via SMB for mpd. With autofs in place I can run mpd locally (in a “satellite setup”) and have its music_directory point to a path managed by autofs.

-

One thing that was helpful getting the configuration right was testing autofs by running automount -f -v directly which puts it in the foreground and gives verbose output.

-

The two files I configured were auto.master.d/foo.autofs and auto.foo.

-
    -
  • foo.autofs contains one line: /- /etc/auto.foo
  • -
  • auto.foo contains one line as well: /foo -fstype=cifs,rw,credentials=/home/me/.foo-creds ://NAS.IP/foo
  • -
-

mailpreview updates

-

mailpreview-cli is a little program I use multiple times a day to quickly see my unread email without moving from what I’m currently working on and without touching my mouse. I recently noticed it wasn’t grabbing the body of a specific type of email. In the process of fixing that I also added proper unit tests for every format I currently parse through. Yay faster feedback loops!

-

ffmpeg

-

I’ve been a fan of OBS for awhile now. I was recently doing a quick screen recording of my browser window and the browser window wasn’t full-screen so there were black bars around the edges of the recording. I didn’t love that but it’s time to touch the “ffmpeg exists and is awesome” sign again.

-

This superuser post has the answer which consists of two steps:

-
    -
  1. Get the crop parameters of the video from ffmpeg. ffmpeg will detect the black borders and report back the actual content coordinates. -ffmpeg.exe -i '.\some-video.mkv' -vf cropdetect -f null -
  2. -
  3. Re-encode and crop using the crop parameters to trim the borders. -ffmpeg.exe -i '.\some-video.mkv' -vf crop=624:704:332:10 -c:a copy output.mp4
  4. -
  5. Enjoy your pristine video.
  6. -
- - -

Fin

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/recently-44/index.html b/themes/cycle/exampleSite/public/writing/recently-44/index.html deleted file mode 100644 index fc7f342..0000000 --- a/themes/cycle/exampleSite/public/writing/recently-44/index.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - Recently - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Recently

- - -
-

I’ve published a few new projects in the last couple of months and I’m behind on announcing them, so I bundled them up together into this post. I’m stealing the title format of this post from Tom MacWright’s Recently posts.

-

One thing to note is that the source code for all these projects is stored on sourcehut. Sourcehut (or sr.ht) bills itself as “the hacker’s forge”. I highly recommend checking it out. It’s also where I host my public inbox.

-

hover-dns

-

Now that I have fiber internet at the house I’ve been hosting one-off services and apps on my own hardware at the house. This is great, however my residential connection is a typical dynamic IP not a static one. Instead of using a service like DynamicDNS I decided to write some Rust (shocker) and leverage the “unofficial” Hover API. The result is: hover-dns.

-

I have hover-dns running in a crontab for a few different domains to keep my domains pointed to the correct IP for my house. While I’m a little uncomfortable with how similar npm and cargo can feel, the trust-dns package is excellent. I was able to quickly read the source code to understand how to setup a Resolver for opendns. Also impressive is that hover-dns ip beats out dig in returning your public IP. I didn’t expect that!

-

podcastfilter

-

Speaking of hosting things at home, podcastfilter.com is one of those things. podcast-filter is a small Go project that allows you to filter a podcast feed by each episode’s description and return a feed of just those episodes that match.

-

mailpreview

-

The recent project I use the most day-to-day is mailpreview-cli. mailpreview-cli is very straight-forward, it accepts a Mail message and returns either the plain text version or the html version of that message. The reason I don’t just pull the Mail message directly is because a Mail message can contain several versions of the message in different encodings (start here if you’re curious: RFC-822). Instead of writing my own parser I grabbed the excellent mailparse crate and wrapped the behavior I wanted around it. On it’s own mailpreview-cli isn’t super fancy but I trigger it from rofi via a shell script which allows me to browse (and then view) all my unread emails right from rofi. Shameless plug: I wrote a short post about getting started with rofi if you’re unfamiliar. mailpreview-cli could be used with Alfred if you’re on a Mac to accomplish the same thing as I’m doing with a shell script and rofi.

-

Fin

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/rename-utility/index.html b/themes/cycle/exampleSite/public/writing/rename-utility/index.html deleted file mode 100644 index d694805..0000000 --- a/themes/cycle/exampleSite/public/writing/rename-utility/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - Rename utility - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Rename utility

- - -
-

I often find myself needing to rename batches of files. I find myself doing this when I have a set of images that are named image-2x.png, and I duplicate them for 1x assests. I tried Automator to see if I could whip up a quick service that would remove the ‘-2x’ from my 1x assests. I couldn’t figure it out in 5 minutes, so I gave up (par for the course with these types of things). I then googled around a bit and turned up several tutorials using awk, sed, or some other custom function. None of that sounded very fun or easy; I then stumbled upon rename.

-

Rename is a standard Unix utility that simply renames files given a pattern to search for and something (or nothing) to replace the pattern with. It supports standard things like globbing, and even supports testing your query to see the results! A basic command looks like this: rename 's/2x copy//g' *.jpg Simple and perfect. In this case rename is going to strip out ‘2x copy’ from any files that have that pattern and replace it with nothing, hence the double slashes at the end. That’s all there is to it. Hopefully this helps someone else who just wants to rename a batch of files.

-

To get rename on a Mac, just brew it, brew install rename.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html b/themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html deleted file mode 100644 index 7f2d277..0000000 --- a/themes/cycle/exampleSite/public/writing/rotten-tomatoes-and-launch-center/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - Rotten Tomatoes and Launch Center - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Rotten Tomatoes and Launch Center

- - -
-

I appreciate Rotten Tomatoes, I don’t always agree with the ratings, but I like how they can add to an argument or conversation about a movie.

-

I hate the Rotten Tomatoes experience on an iPhone. It starts with this horrible app pop-up: Rotten Tomatoes Nag

-

Then it nags you to add the site to your homescreen, my home screen is meticulously planned out and I don’t have the room for non-apps, so Rotten Tomatoes can go kick rocks.

-

A month or so ago I decided to do something about these things that bug me about Rotten Tomatoes. I spent an hour or two poking around the API and cobbled together Diet Rotten Tomatoes. It’s a quick, lightweight way to get a movie’s ratings, a full-size movie poster (click the thumbnail), and a link to the movie on Rotten Tomatoes.

-

I also added a way to search using Alfred or Launch Center Pro. Simple append your search term to the URL like #die hard and it’ll fire off a search as the page loads.

-

Hopefully you find it useful.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/rust-module-system/index.html b/themes/cycle/exampleSite/public/writing/rust-module-system/index.html deleted file mode 100644 index a8fea95..0000000 --- a/themes/cycle/exampleSite/public/writing/rust-module-system/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Clear explanation of Rust’s module system - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Clear explanation of Rust’s module system

- - -
-

This is a great explanation of Rust’s module system. I wish I had this clear of a picture when I was using modules for the first time in creating oscar.

-

The big takeaway and deviation from npm is this:

-
-

We need to explicitly build the module tree in Rust, there’s no implicit mapping to file system.

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html b/themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html deleted file mode 100644 index 8dbaa8c..0000000 --- a/themes/cycle/exampleSite/public/writing/rust-strings-and-str/index.html +++ /dev/null @@ -1,321 +0,0 @@ - - - - - - Understanding Rust Strings and str inside structs. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Understanding Rust Strings and str inside structs.

- - -
-

Rust is a challenging language to work in coming from a more dynamic language like Javascript or Ruby. Here’s a short breakdown of a compiler error message that stumped me for a bit.

-

Background

-

First, some background about Rust. Rust is a strongly-typed language, which means variables and return values from functions usually require a type annotation that looks like this:

-
let favorite_number: u32 = 12;
-

The type annotation on the variable favorite_number is u32. This should look familiar to anyone who has used a strongly typed language before.

-

A struct in Rust is a way for the user to define any data type. Here’s an example:

-
struct Config {
-  name: String,
-  id: u32
-}
-

Here is how we would approximate this in Javascript:

-
const config = {
-  name: "Adam",
-  id: 4
-}
-

Notice how, in Javascript, we use an Object named config to hold some config for our application. In Rust, we create a struct called Config and define the various fields we need. Rust is strongly typed, so even the fields in the Config struct are type-annotated. Let’s move to where I got tripped up.

-

Stumped

-

I created a Vector (a mutable Array data structure) that contained a couple of instances of a struct. It looked something like this:

-
struct Example {
-    id: String
-}
-
-fn main() {
-    let example: Vec<Example> = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}];
-    println!("{:?}", example);
-}
-

So far, so good. However, I now wanted to map over the collection and create a new collection that just contained the id. Here’s what I tried and what failed:

-
struct Example {
-    id: String
-}
-
-fn main() {
-    let example: Vec<Example> = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}];
-    let map_fail: Vec<String> = example.iter().map(|item| item.id).collect();
-    println!("{:?}", map_fail);
-}
-

Rust playground

-

Understanding the problem

-

What’s happening here? Well, the compiler message is instructive:

-
  error[E0507]: cannot move out of `item.id` which is behind a shared reference
-    --> src/main.rs:10:59
-      |
-  10 |     let map_fail: Vec<String> = example.iter().map(|item| item.id).collect();
-      |                                                           ^^^^^^^ move occurs because `item.id` has type `std::string::String`, which does not implement the `Copy` trait
-
-  error: aborting due to previous error
-
-  For more information about this error, try `rustc --explain E0507`.
-

In Rust there is no Garbage collection (automatic memory management). Instead, Rust requires you, the programmer, to indicate to the Rust compiler what variables have ownership over the value they represent. If that ownership moves in an invalid way, Rust will throw a compile error to prevent a memory error at runtime. The benefit in not having Garbage Collection is two-fold:

-
    -
  1. Faster code without a GC process.
  2. -
  3. Whole classes of bugs are impossible due to Rust’s ownership rules.
  4. -
-

In our error case, mapping over our vector moves the data stored at id to a new Vector. This shift to a new Vector means Rust can no longer guarantee the safety of that portion of memory. Let’s look at the documentation around this error code from the compiler.

-

The explainer page for this error gives us three options:

-
-
    -
  1. Try to avoid moving the variable.
  2. -
  3. Somehow reclaim the ownership.
  4. -
  5. Implement the Copy trait on the type.
  6. -
-
-

#3 sounded like too much for this specific case. #2 also seemed like the wrong approach because I didn’t want to change the ownership, I just wanted a copy or reference to it. #1 was the right answer, but how do I avoid moving the variable?

-

The Solution

-

This is where it’s important to understand the two basic types for strings in Rust, String and str. The doc page for String states (I added the underlines for emphasis):

-
-

The String type is the most common string type that has ownership over the contents of the string. It has a close relationship with its borrowed counterpart, the primitive str.

-
-

Aha, so we’re dealing with a String here, and it sounds like we need a str. A quick glance at the String doc page again reveals just the function we need: as_str. as_str gives us a reference called a slice to the value of a String. Armed with this new knowledge, here’s the solution to this compiler error:

-
struct Example {
-    id: String
-}
-
-fn main() {
-    let example: Vec<Example> = vec![Example{id: "one".to_string()}, Example{id: "two".to_string()}];
-    println!("{:?}", example);
-
-    let map_str: Vec<&str> = example.iter().map(|item| item.id.as_str()).collect();
-    println!("{:?}", map_str);
-}
-

Rust playground

-

Fin

-

Rust has proven challenging to learn, but I think the journey and difficulty is worth it. Ownership, the type-system, and the excellent performance continue to impress me. I hope this post encourages folks to give Rust a try! I’m happy to answer any questions via the comments or twitter or wherever else.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/s3-security-policy/index.html b/themes/cycle/exampleSite/public/writing/s3-security-policy/index.html deleted file mode 100644 index 87512fb..0000000 --- a/themes/cycle/exampleSite/public/writing/s3-security-policy/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - S3 Security Policy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

S3 Security Policy

- - -
-

I love S3, I use it with Arq, I use it to host this site, backup configs on VPSs, and to transfer random files that are too big for e-mail.

-

As my S3 usage has grown I’ve started creating seperate AMI users for each task, e.g. a siteleaf user for this blog. It wasn’t until tonight that I took the time to craft a better security policy for some of these users.

-

I struggled finding good policy examples until I stumbled across this one over on the AWS Security blog. I highly recommend reading it all the way through.

-

Here’s the basic policy I came up with. This policy restricts access to a single bucket, and allows access via the AWS cli.

-

Note: I had to move the policy to a gist as prismjs was having a hard time with it.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html b/themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html deleted file mode 100644 index 9f01763..0000000 --- a/themes/cycle/exampleSite/public/writing/seamless-branch-deploys-with-kubernetes/index.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - Seamless branch deploys with Kubernetes - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Seamless branch deploys with Kubernetes

- - -
-

A trait of good software is the ability to quickly see and verify changes:

-
-

The result is what’s in-use today for HEY: a system that (almost) immediately deploys any branch to a branch-specific endpoint that you can access right away to test your changes without having to use the claims system or talk to anyone else (along with an independent job processing fleet and Redis instance to support the environment).

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html b/themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html deleted file mode 100644 index cc4b4d5..0000000 --- a/themes/cycle/exampleSite/public/writing/search-imessage-sql/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Using SQL to Look Through All of Your iMessage Text Messages - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Using SQL to Look Through All of Your iMessage Text Messages

- - -
-
-

If you use iMessage on your Mac, you can access the SQLite database where all of your messages are stored. With a little setup, you can use SQL’s raw power to look through your old messages.

-
-

via Simon Willison

-

In this post Dan Kelch walks through how to access the SQLite database that backs iMessage on a Mac. He also shares a few helpful SQL snippets to demonstrate how powerful using SQL on your text messages can be.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html b/themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html deleted file mode 100644 index f20f1b9..0000000 --- a/themes/cycle/exampleSite/public/writing/second-guessing-the-modern-web/index.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - Second-guessing the modern web - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Second-guessing the modern web

- - -
-
-

The low performance parts don’t need to be React. Listing pages, static pages, blogs - these things are increasingly built in React, but the benefits they accrue are extremely narrow. A lot of the optimizations that are cropping up in these corners, things like bundle splitting, server-side rendering, and prerendering, are triangulating, essentially, what we had before the rise of React.

-
-

This isn’t really about React but more about the over-engineering of large swaths of page-types and sites that used to “just work”. I love React and it’s been a giant leap forward for creating complex UIs on the web, that doesn’t mean it’s right for every situation.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html b/themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html deleted file mode 100644 index 03d2881..0000000 --- a/themes/cycle/exampleSite/public/writing/setting-a-default-browser-in-i3/index.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - Setting a default browser in i3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Setting a default browser in i3

- - -
-

The problem

-

I’ve been using the excellent qutebrowser for a few weeks now and I really enjoy it’s minimal approach to web browsing. I still reach for Firefox or Chrome for web development purposes but qutebrowser shines as a daily driver. An issue I ran into is I didn’t know how to set qutebrowser as my default web browser when using i3wm (or any tiling window manager really).

-

The Solution

-

Here’s the solution if you don’t care about the process of figuring it out:

-
xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop
-

The Yak

-

Thankfully there’s an issue on the qutebrowser repo where folks discussed this very thing. Let’s pull the solution apart to gain some understanding of the systems at play here.

-

The first part of the solution in the issue thread is:

-
ls /usr/share/applications/ | grep qutebrowser
-

which lists all the files in /usr/share/applications and then greps that list for entries that contain the word qutebrowser. The Arch Wiki entry on “Desktop entries” explains what the files inside /usr/share/applications are and why that directory is important.

-
-

Desktop entries for applications, or .desktop files, are generally a combination of meta information resources and a shortcut of an application. These files usually reside in /usr/share/applications/ or /usr/local/share/applications/ for applications installed system-wide, or ~/.local/share/applications/ for user-specific applications.

-
-

So by looking for qutebrowser in /usr/share/applications we’re looking for its .desktop file which is important for the next step.

-

Looking at the next part of the solution involves running a program called xdg-settings. What is that? The man page declares that xdg-settings is used to “get various settings from the desktop environment”. OK, so it’s a tool to get (and apparently set?) desktop environment settings. This seems like the right thing. Let’s keep reading the man page.

-

Further on in the man page we find an example on how to set Chrome as the default web browser: xdg-settings set default-web-browser google-chrome.desktop. Notice the .desktop file at the end of the command? XDG uses that file name to figure out which app to use for certain file and link types like text/html or x-scheme-handler/http. Back to our specific case, we need the full name of the desktop file to pass to xdg-settings which is org.qutebrowser.qutebrowser.desktop. With this information we can change the default browser to qutebrowser by running:

-
xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop
-

This tells the desktop environment to launch whatever process is defined in that .desktop file for “browser things”.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html b/themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html deleted file mode 100644 index 44ba322..0000000 --- a/themes/cycle/exampleSite/public/writing/simple-account-set-up/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - Simple Account Set-up - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Simple Account Set-up

- - -
-

I recently received my invite to Simple, a new banking service that has taken the design and development communities by storm with the promise of intelligently designed banking apps and interfaces. Now, I’m still waiting for my card to come, so I can’t comment on the service itself. But, during the account set-up process, I was struck by how “right” it all felt, I took some screenshots as I went through to share.

-

Once you fill in your personal info and are approved for an account, you are taken to a page to set up a username and passphrase. Yes, you read that correctly, not a password, a passphrase. Simple claims a passphrase is easier to remember and improves the security of the account.

-

Once your passphrase and username are set up, Simple moves you to the next stage of the process, as pictured below: download the simple app

-

I elected to have a SMS sent to my iPhone to download the Simple app, sure enough in a few seconds there it was. I left the browser window open and proceeded to install the app which had me pick a 4 digit PIN as part of its setup.

-

Once I selected my PIN, the app presented the various user agreements and banking terms with a signature box to sign with my finger. After signing the box and poking around the app a bit more, I looked up at my computer screen and saw that the Simple page had changed to this: signature complete

-

Slick! The app had sent my signature to the page! In doing so, Simple infused a little bit of magic into a typically mundane sign-up process. The other key point of this process is that it ensures the focal point of the service, the Simple app, is set up and ready to go on every customer’s phone.

-

I’m excited to get my Simple card and start using the service, I hope every other bank in the world is paying attention, these little details matter!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html b/themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html deleted file mode 100644 index 4962ea4..0000000 --- a/themes/cycle/exampleSite/public/writing/slanted-elements-with-css3/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Slanted Elements with CSS3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/small-tech/index.html b/themes/cycle/exampleSite/public/writing/small-tech/index.html deleted file mode 100644 index 4b88b5d..0000000 --- a/themes/cycle/exampleSite/public/writing/small-tech/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - Small tech - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Small tech

- - -
-

Jamie Brandon has a nice post about “small tech”: tech that isn’t backed by a big corporation like Microsoft or Apple but still has an out-sized impact. I love the post and I thought I would add a few additional products to the list.

-
    -
  • -

    curl is open-source and has thousands of contributors but is still primarily designed and managed by @bagder (Daniel Stenberg). If you ever do anything with http for any kind of development mastering curl is worth the time investment.

    -
  • -
  • -

    git is the premier version control system on the planet. It started out as a side-project to manage Linux kernel development.

    -
  • -
  • -

    Alpine Linux is a Linux distribution that is maintained by a small group of folks and yet is the first choice for most folks when creating Docker images.

    -
  • -
  • -

    sr.ht does not have the type of scale or impact that the others items on this list have but I think it could some day. sr.ht is version control host, issue tracker, mailing list tool, and CI toolbox. It competes directly with Github, Gitlab, and Bitbucket. However, sr.ht is run by one person—Drew DeVault—and is 100% open-source.

    -
  • -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/small-things/index.html b/themes/cycle/exampleSite/public/writing/small-things/index.html deleted file mode 100644 index 5e1f249..0000000 --- a/themes/cycle/exampleSite/public/writing/small-things/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - Small things - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Small things

- - -
-

Recently I’ve come to love MicroJS. I love that I can find tiny, specific libraries that do one thing, and do it well. I think my affection for MicroJS is fueled by my current fascination, React. React bills itself as:

-
-

A Javascript library for building user interfaces.

-
-

I think this focus on building user interfaces pushes me to seek out complimentary tools that focus on solving singular problems. React’s narrowly-defined API and reliance on Javascript’s primitives leaves lots of space for me to cobble together the stack that best solves the current problem(s).

-

As I’ve thought about this more, I’ve realized just how powerful a framework’s aspirations can be. They trickle in and bend my perspective when I use them. It is a small thing that developers, myself included, often overlook.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html b/themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html deleted file mode 100644 index 52d8fb4..0000000 --- a/themes/cycle/exampleSite/public/writing/solving-busybox-crond-hanging-on-alpine-linux-boot/index.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - Solving busybox crond hanging on Alpine Linux boot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Solving busybox crond hanging on Alpine Linux boot

- - -
-

I recently clean installed Alpine Linux 3.9.3 on my home router (more to come on that in a future post) and ran into a weird bug. Once I successfully installed Alpine and rebooted, the system would start and then hang for over a half hour(!) with the message “Starting busybox crond…”. I tried downgrading to 3.8.0 without any luck. I did some quick Googling and didn’t find anything about busybox crond hanging.

-

Stumped I headed over to the #alpine-linux IRC and posted my situation there. A friendly user suggested it might have something to do with “entropy changes” and to switch the daemons in question to use /dev/urandom. I didn’t feel like switching the daemons was going to be a good long-term solution but I was intrigued by the entropy angle. I looked it up and stumbled upon this reply to a bug thread about “Startup hangs (aports: sshd?)”:

-
-
-

Hello.

-

After upgrading to [edge] i see a possibly endless hang upon -startup, which seems to be caused by PRNG init.

-
-

Try add random.trust_cpu=1 as boot option.

-

See: -https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.19.y&id=39a8883a2b989d1d21bd8dd99f5557f0c5e89694

-

and: -https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.19.y&id=9b25436662d5fb4c66eb527ead53cab15f596ee0

-

-nc

-
-

Interesting. Entropy and boot time are related. Remember I had installed Alpine on a router: a headless PC without any I/O other than two Ethernet NICs and a SSD. Not much there for Linux to generate entropy with, especially since the default was to not trust my CPU.

-

I searched for entropy on the excellent Alpine wiki and found this page. This lead me to Haveged. Haveged is a service that generates additional entropy. I stared it up, enabled it to run at boot, and I no longer had any hang time at boot!

-

I later found this bug report that outlined my problem exactly. Turns out I was too focused on the crond aspect of my boot problem and not the general delay in booting. Oh well, TIL.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html b/themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html deleted file mode 100644 index f9f6dd9..0000000 --- a/themes/cycle/exampleSite/public/writing/someone-is-working-harder-than-you/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - Someone is working harder than you - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Someone is working harder than you

- - -
-

When I was in junior high I attended a basketball camp. The camp moto for the week went something like: “There’s always more one can do, always someone working harder than you”.

-

At the time I thought this meant Michael Jordan was working harder than me (he was!), but that I was right up there cause I was at camp, duh!

-

Scott Berkun wrote a few days ago:

-
-

Few people in history that we call creatives today read books or took courses on creativity. Instead they apprenticed with masters in a craft and worked with them. They did the grunt work until they had the skills needed to do more sophisticated work. They learned how to develop ideas and deliver finished work by working. There is no other way.

-
-

Go work.

-

As the youths say, ’nough said.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html b/themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html deleted file mode 100644 index 3e63548..0000000 --- a/themes/cycle/exampleSite/public/writing/sparrow-and-the-app-store/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Sparrow and the App Store - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Sparrow and the App Store

- - -
-

David Barnard writes up his take on why Sparrow sold out. I found the end of his post fascinating:

-
-

The age of selling software to users at a fixed, one-time price is coming to an end. It’s just not sustainable at the absurdly low prices users have come to expect. Sure, independent developers may scrap it out one app at a time, and some may even do quite well and be the exception to the rule, but I don’t think Sparrow would have sold-out if the team — and their investors — believed they could build a substantially profitable company on their own. The gold rush is well and truly over.

-
-

We are witnessing so many changes on the web and in the mobile industry. Software pricing and sustainability is just another item on a long list of things that are evolving.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/sqlite-tips/index.html b/themes/cycle/exampleSite/public/writing/sqlite-tips/index.html deleted file mode 100644 index baa083c..0000000 --- a/themes/cycle/exampleSite/public/writing/sqlite-tips/index.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - SQLite Tips - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

SQLite Tips

- - -
-

I’ve been playing around with SQLite recently and I’ve stumbled across a few things I want to remember, so I’m putting them here.

-
    -
  1. -

    The SQLite CLI is pretty darn good. Just remember to read in the SQLite DB file first, e.g. .open /path/to/file. After that, any SQLite command is valid. Specific CLI commands are prefixed with a period.

    -
  2. -
  3. -

    Set the the .mode to line to visually grep the results.

    -
  4. -
  5. -

    To see the rowid include it specifically in SELECT statements on the CLI, e.g. SELECT rowid,* from table.

    -
  6. -
  7. -

    Delete an entry by rowid like this, DELETE FROM table WHERE rowid=7;

    -
  8. -
  9. -

    When structuring a database, create a unique ID for each row like so: create table foo (id INTEGER AUTO_INCREMENT PRIMARY KEY UNIQUE NOT NULL, other_column TEXT).

    -
  10. -
  11. -

    View all tables via .tables.

    -
  12. -
  13. -

    View schema for a table via .schema TABLENAME.

    -
  14. -
-

That’s all I got for now. I’ll drop more tips in this post as I come across them.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/story/index.html b/themes/cycle/exampleSite/public/writing/story/index.html deleted file mode 100644 index 5cdd349..0000000 --- a/themes/cycle/exampleSite/public/writing/story/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - Story - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Story

- - -
-
-

Before a technologist writes a line of code, or a marketer writes a line of copy, or a designer creates a single wireframe or design, you have to establish the story that your product is going to tell.

-
-

-UX Mag

-

Story is essential for many things, beyond just products. Stories are how we as humans define our memories and explain our world.

-

A product without a good story - a story that explains where something came from and where it is going - inspires apathy and disinterest.

-

Stories not only affect the consumer and the success of the product, they also affect the people working on the product. If you are feeling “disinterested” or “unmotivated” in your work, examine the story behind your work or product.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html b/themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html deleted file mode 100644 index 197188b..0000000 --- a/themes/cycle/exampleSite/public/writing/the-era-of-the-screenshot/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - The era of the screenshot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The era of the screenshot

- - -
-

From Benedict Evan’s weekly newsletter on the new screenshot features in iOS11:

-
-

Finally, screenshots. It’s pretty clear that smartphone screenshots are the new PDF - a universal data exchange format.

-
-

:facepalm: We really couldn’t have picked a worse data exchange format.

-

-1000 internets everybody.

-
    -
  • How do those with vision handicaps parse the data in a screenshot?
  • -
  • How do machines reliably parse screenshot information?
  • -
-

-100 more internets after I’ve thought about it some more.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html b/themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html deleted file mode 100644 index 7649a76..0000000 --- a/themes/cycle/exampleSite/public/writing/the-future-is-prototyping/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - The Future is Prototyping - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The Future is Prototyping

- - -
-

First off, you need to read this entire post, Try and Try Again – Why Prototyping Matters over at Big Spaceship. It’s fantastic, awesome, informative, funny, and best of all correct! I’ll be posting more on my personal experience with this topic eventually, but for now here is my favorite quote from the post,

-
-

If action speaks louder than words, then prototyping must be doing the death-metal guttural scream right in speculation’s ear. Instead of spending time discussing possibilities, we can spend time actually making something work. The earlier you get to the trying, the better you can inform the design – from font choices and colors to advanced interaction and mental models.

-
-

Go read the whole thing.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html b/themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html deleted file mode 100644 index 549f9fc..0000000 --- a/themes/cycle/exampleSite/public/writing/the-manhattan-project-time-lapse/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - The Manhattan Project Time-Lapse - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html b/themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html deleted file mode 100644 index d2c7417..0000000 --- a/themes/cycle/exampleSite/public/writing/the-stream-hasnt-won/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - The Stream hasn't won - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The Stream hasn't won

- - -
-

Hossein Derakhshan wrote a fascinating piece over on Medium that speaks about the web and his relation to it before and after his time in an Iranian prison. He outlines how the web as he knew it has disappeared and been replaced by “The Stream”, or social media. His post is beautifully written and I highly recommend reading it. However, I disagree with some of his conclusions:

-
-

I miss when people took time to be exposed to different opinions, and bothered to read more than a paragraph or 140 characters. I miss the days when I could write something on my own blog, publish on my own domain, without taking an equal time to promote it on numerous social networks; when nobody cared about likes and reshares.

-
-

Nothing in this statement has gone away! The rise of social networks does not mean “the blog” or “the web” is in decline. “The Stream” hasn’t won, I’m not convinced there’s even a fight.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html b/themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html deleted file mode 100644 index 9ba73b7..0000000 --- a/themes/cycle/exampleSite/public/writing/the-thing-about-computers/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - The thing about computers - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The thing about computers

- - -
-
-

Maybe because I lived through this — maybe because I’m a certain age — I believe that that freedom to use my computer exactly how I want to, to make it do any crazy thing I can think of — is the thing about computers.

-
-

Brent Simmons

-

I literally cannot agree with this more strongly! It’s been open in a tab on my phone since Brent published it and I can’t stop thinking about it.

-

I think there’s a line somewhere where convenience and ease-of-use meets this freedom to do anything computing ideal. I think I will always bend toward the freedom side over convenience when it comes to my personal computers. Conversely, I think I bend towards the convenience side over freedom when it comes to my phone. I’m not sure why that is.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html b/themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html deleted file mode 100644 index 4668c3d..0000000 --- a/themes/cycle/exampleSite/public/writing/the-web-and-my-goal/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - The web, and my goal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The web, and my goal

- - -
-

The Pastry Box Project is a fantastic collaboration that is updated once every day with entries regarding the web, development, best practices, or life.

-

Today, Bruce Lawson wrote:

-
-

[…]So the next time you hit upon a clever technique, blog about it. Or if you write some code that could be useful to someone else, put it on Github. Put something back into the community.

-
-

That is my motivation for starting this blog. I glean so much information from fellow web workers that I thought it was high-time I began giving back.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html b/themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html deleted file mode 100644 index fc11e48..0000000 --- a/themes/cycle/exampleSite/public/writing/the-web-is-not-print/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - The Web is Not Print - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The Web is Not Print

- - -
-

Zeldman’s notes from Luke Wroblewski’s talk, “Mobile to the Future” at Austin, AEA.

-
-

Likewise, we still have ingrained print characteristics impacting how we think about web and mobile. (Page/canvas, grid layouts, typography, graphical ads.) As many people will tell you — but not many people practice — the web is not print.

-
-

It’s exciting to be working on the web when some of these “print ideas” are starting to give way as the web matures.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html b/themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html deleted file mode 100644 index 2387d74..0000000 --- a/themes/cycle/exampleSite/public/writing/the-wordpress-http-api-is-awesome/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - The Wordpress HTTP API is Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

The Wordpress HTTP API is Awesome

- - -
-

The title says it all. I completely forgot about the Wordpress HTTP API until today, when I was working with HTTP requests in a plugin. I stumbled upon the wp_remote_post function and it immediately replaced my custom HTTP function.

-

Hidden Gem

-

One of the hidden gems in the wp_remote_post function is in the optional arguments you can pass along, specifically the “blocking” option. This option allows you to block script execution while it waits for the response or allows the script to continue on. So simple!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html b/themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html deleted file mode 100644 index 48ac485..0000000 --- a/themes/cycle/exampleSite/public/writing/theme-the-chrome-dev-tools/index.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - Theme the Chrome Dev Tools - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Theme the Chrome Dev Tools

- - -
-

Let me start by explaining that the Chrome Developer Tools are incredible, and that I consider them essential to doing my job. What I did not know about these awesome tools is that they are essentially a web app; an app that I can tweak, change, and even inspect with itself.

-

Last week, I stumbled across this post by Mr. Clarke where he explains how to theme the Dev Tools using a single CSS file. This blew my mind and led to a fury of Googling for different themes. I eventually found the exact same theme I use in Sublime, only for the Dev Tools. The Tomorrow Theme for Chrome by Ben Truyman was almost perfect, I made a few slight modifications to it and posted my own gist here.

-

Some of you may be wondering, “Wait, how did you make modifications? Guesswork?”. Nope. Paul Irish explains in this thread how to inspect the Dev Tools…using the Dev Tools! With this little hint, you can easily tweak or completely theme the Chrome Dev Tools.

-

I hope this post was helpful to someone who was unaware of all this functionality a mere stylesheet away.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/thirty-five/index.html b/themes/cycle/exampleSite/public/writing/thirty-five/index.html deleted file mode 100644 index cd85ee9..0000000 --- a/themes/cycle/exampleSite/public/writing/thirty-five/index.html +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - Thirty five - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Thirty five

- - -
-

Well crap.

-

It’s been 5 years since I wrote “Thirty”. So now I have to come up with 35 things as I turned 35 yesterday. If anything from Thirty is grossly wrong or really interesting I’ll update it at the same number eh?

-

Let’s go…

-
    -
  1. I still don’t have it figured out, but this isn’t such a shock anymore.
  2. -
  3. Building a house is more scary.
  4. -
  5. Minivans are awesome.
  6. -
  7. Expecting a third kid is not nearly as scary as expecting the first.
  8. -
  9. COVID sucked.
  10. -
  11. Modern medicine is pretty cool actually.
  12. -
  13. More stuff hurts, still just as healthy.
  14. -
  15. Dishwashers aren’t really as scary to repair as they seem (but that doesn’t mean you won’t lose your mind fixing one).
  16. -
  17. The feeling you get as a parent when your kid gets hurt is impossible to describe.
  18. -
  19. Being knocked out from a crazy car accident is also no fun.
  20. -
  21. Carseats are magic.
  22. -
  23. I’ve accepted that the music I liked in 2010 is going to be the music I’ll like forever.
  24. -
  25. Thanks to the internet there is an endless stream of new music that is at home with music from 2010 or even 2000 (Underoath just released a new album for crying out loud).
  26. -
  27. Open source software is incredible.
  28. -
  29. The thrill from in-progress software working for the first time will never get old for me.
  30. -
  31. Feedback loops are important in every area of life not just software.
  32. -
  33. The year of Linux on the desktop is a moving target.
  34. -
  35. RSS will never die.
  36. -
  37. Mechanical keyboards are a refreshing change and I’m not sure why.
  38. -
  39. The Aeropress is still incredible.
  40. -
  41. Computers were a mistake.
  42. -
  43. Computers are a miracle.
  44. -
  45. The Three-Body Problem trilogy continues to knock around in my brain months after finishing it.
  46. -
  47. Watching your child accomplish something for the first time that they’ve been working on is a feeling unlike any other.
  48. -
  49. I’ve realized I learn best by doing, I need to get better at accounting for the bumps along the way.
  50. -
  51. I write things down to remember them later not to look them up later which means most note systems are not worth the trouble for me.
  52. -
  53. Life will be shallow if you only hang out with people like you.
  54. -
  55. Anything is possible on an infinite timescale the trick is figuring out what do with finite time.
  56. -
  57. RIP Rdio.
  58. -
  59. Never pass on an opportunity to twirl your kids around when they’re small. They get big fast.
  60. -
  61. Hanlon’s razor explains most of social media.
  62. -
  63. If you work at a desk all day you owe it to yourself to remove as much Bluetooth from that setup as possible.
  64. -
  65. None of your peers has it all figured out. Ask them “dumb” questions.
  66. -
  67. Properly evaluating risks when your kids are involved is hard.
  68. -
  69. Keep a sweatshirt handy by your bed when your kids are young, getting up at 2am in the winter is cold.
  70. -
-

❤️ you Christi

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/thirty/index.html b/themes/cycle/exampleSite/public/writing/thirty/index.html deleted file mode 100644 index 0ac1721..0000000 --- a/themes/cycle/exampleSite/public/writing/thirty/index.html +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Thirty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Thirty

- - -
-

Today I turn 30. For the last couple birthdays I’ve wanted to do a “X things I’ve learned” post like the incomparable Mr. Noah Stokes but I kept forgetting. Not this year! This past year has been exceptionally full. In my mind, turning 30 has always been a milestone. Turns out (spoilers!) the day is just a that, a marker; all the exciting stuff is ahead and behind. I’m so thankful I get to navigate it all with a great partner in crime/life/adventure, my wife Christi 😍.

-

Without further ado, I present to you my list of 30 things I’ve learned in the past year (or so).

-
    -
  1. You won’t have it figured out by the time you turn 30.
  2. -
  3. Buying a house is scary.
  4. -
  5. Buying a house is amazing.
  6. -
  7. Expecting a kid is scary.
  8. -
  9. Expecting a kid is amazing.
  10. -
  11. Problems in software are usually never software problems.
  12. -
  13. When something hurts sometimes your not dying, it just hurts.
  14. -
  15. You can take your dryer apart and put it back together and it will be ok.
  16. -
  17. Vim is better inside emacs.
  18. -
  19. Passing out is no fun.
  20. -
  21. JavaScript is everywhere, get used to it.
  22. -
  23. We all need a team
  24. -
  25. The command line will never die.
  26. -
  27. Drywall molleys are amazing.
  28. -
  29. You can’t keep water out, you can only redirect it.
  30. -
  31. Remembering what is Real™ is vital.
  32. -
  33. Relationships are a #1 priority. I forget this too often.
  34. -
  35. Nothing beats pen and paper.
  36. -
  37. Physical fitness involves way more sleeping and eating well than pumping iron.
  38. -
  39. There is no better coffee maker than the Aeropress.
  40. -
  41. Setting aside time for reading and writing is difficult.
  42. -
  43. I need to spend more time reading and writing.
  44. -
  45. Two opposing things can both be True at the same time. Dealing with that is adulthood.
  46. -
  47. I will always enjoy the Fast and the Furious franchise.
  48. -
  49. LeBron is under-rated.
  50. -
  51. Never give up, even when your down 3-1.
  52. -
  53. No one makes it on their own.
  54. -
  55. I need to read more novels.
  56. -
  57. I still miss Rdio.
  58. -
  59. Read a little C.S. Lewis every morning (start here). It’s good for you.
  60. -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html b/themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html deleted file mode 100644 index d6e1fd6..0000000 --- a/themes/cycle/exampleSite/public/writing/three-easy-tuneups-to-fix-video-calls-while-working-from-home/index.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - Three easy tuneups to fix video calls while working from home - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Three easy tuneups to fix video calls while working from home

- - -
-

Thanks to the COVID-19 virus (aka the coronavirus) lots of folks are experiencing the joys and existential terror of working from home. There’s many things to tackle when optimizing a work from home setup like:

-
    -
  • Proper workspace ergonomics
  • -
  • Proper lighting for video calls
  • -
  • Proper audio for video/audio calls
  • -
  • Picking up the dirty laundry/toys/pizza boxes that are visible in the background on video calls
  • -
-

These are all important but pale in comparison to this one: tuning your network for peak performance in video calls and remote screen sharing.

-

Three problems

-

There is usually some combination of the following three problems going on when Zoom pops up the dreaded “Your connection is unstable”:

-
    -
  1. Your internet speed is too slow
  2. -
  3. You’re Wifi signal is bad
  4. -
  5. Your router/modem from the ISP is suffering from bufferbloat.
  6. -
-

Speed

-

The first one is easy to fix: speed. Zoom lists their bandwidth requirements and the highest requirement is 3.0 Mbps (up/down) which is for sending 1080p video. For consumer broadband that is nothing, heck for DSL that’s nothing. However, it’s the first and easiest thing to check: do you have 3.0 Mbps+? Head over to fast.com and run a speed test.

-

Wifi

-

The second one, wifi signal strength, is more difficult to nail down. I check two things: the connection bit rate and the connection frequency. Bit rate will tell you the speed of the connection; it should be above 3 Mbps (honestly it should be above 100 Mbps if you have ac wifi). I also always choose to connect to the 5Ghz band if I can. 2.4Ghz suffers from interference much more so than 5Ghz and that interference will result in an unstable connection. An easy check to see if your Wifi is causing the problem, connect directly to the router with an Ethernet cord if you have one. If the problems goes away, it’s the wifi if not keep reading. To view connection and bitrate on a Mac: Option + click on the WiFi icon and you’ll be able to see the bit rate and connection frequency. On Linux iwconfig in the terminal will print the relevant info.

-

Bufferbloat

-

A very long explanation (and solution) of bufferbloat can be found here. The gist of it is that most routers/modems are (mis-)configured out of the box to prioritize speed over everything else. The software will stuff as many packets as it can and then once it’s full things start getting laggy. To see if you are suffering from bufferbloat head over to fast.com again and click on the “Show more info” button after the test. You want the difference between “loaded” and “unloaded” to be as small as possible. If you see a difference over 100, e.g. 25 unloaded and 150 loaded, you are probably suffering from bufferbloat.

-

-

The solution here is to poke around in your modem/router admin interface and look for something like “QoS” or “Codel” settings. QoS stands for Quality of Service and it typically allows you to either setup device prioritization or better yet implement fq_codel. The beauty of fq_codel is that it’s pretty transparent to everyone on the network. Kiddos can stream Frozen 2 until their eyes bleed and your Zoom will never stutter. Device prioritization QoS works but other devices on the network feel the squeeze.

-

If you’re modem/router doesn’t have QoS settings then it’s time to look into buying some new equipment (or yes flash your existing router with OpenWRT but that’s outside the scope of this post). If you already have your own router/wifi, that is separate from your modem, then I’d recommend picking up a Ubiquiti EdgeRouter X and placing that between your modem and your existing router/wifi. The EdgeRouter X has built-in support for fq_codel as a QoS setting. Adding QoS at any point in the chain between your computer and the public internet will fix bufferbloat as the traffic only needs to be shaped once.

-

-

Addressing the three primary culprits for unstable connections should dramatically improve your conference call experience. Please reach out if you have questions or I was incorrect about anything. I’ll try to respond as quickly as I can.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/three-years/index.html b/themes/cycle/exampleSite/public/writing/three-years/index.html deleted file mode 100644 index 9875413..0000000 --- a/themes/cycle/exampleSite/public/writing/three-years/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - Three years - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html b/themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html deleted file mode 100644 index 1e1a964..0000000 --- a/themes/cycle/exampleSite/public/writing/tigers-and-social-networks/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - Tigers and Social Networks - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Tigers and Social Networks

- - -
-

Charlie Pratt published a post today giving his take on current happenings with both Twitter and Facebook. One company that has a history of ignoring any outside feedback, and one that he leaves out of his post, is Apple. While not a social network (R.I.P. Ping), Apple still sells multiple products to a massive, global consumer base. The difference between Apple and Twitbook is that Apple makes money from their consumers, something Twitter and Facebook are currently trying to put together.

-

Mr. Pratt goes on to observe:

-
-

As we watch Facebook and Twitter peak, one can’t help but notice that they suddenly seem incredibly vulnerable to the whim of the crowd. Crowds are finicky[…]

-
-

This only happens when you try to turn your consumer base, your crowd, into the product your selling.

-

Tigers don’t like being sold, feeling captive, or turned into anything other than tigers.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html b/themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html deleted file mode 100644 index 982903f..0000000 --- a/themes/cycle/exampleSite/public/writing/track-redirects-with-curl/index.html +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Track redirects with curl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Track redirects with curl

- - -
-

I was recently debugging some .htaccess redirects and wanted to know two things:

-
    -
  1. How was my URL changing as it went through the redirects?
  2. -
  3. How many redirects occurred?
  4. -
-

I quickly got fed up with testing in the browser because of 301/302 redirect caching issues. With my limited curl knowledge I knew I could dump headers and that would show me the redirect code and the URL but figuring out how many hops occurred was frustrating.

-

I searched around and found this very helpful post by Chris Latta. The curl command from the post introduced me to the fact that curl has basic templating support! I read through man curl and noticed there were other built-in variables besides url_effective, like num_redirects! This was exactly what I wanted. Below is what I eventually ended up with:

-
curl -LSs -D - -o /dev/null -w 'Final URL: %{url_effective} \nNumber of Redirects: %{num_redirects} '
-

I added this to my dotfiles as an alias called redirects, here is a sample of what the output looks like:

-
❯ redirects "http://adamsimpson.net/uses"
-HTTP/1.1 301 Moved Permanently
-Cache-Control: public, max-age=0, must-revalidate
-Content-Length: 44
-Content-Type: text/plain
-Date: Tue, 22 Oct 2019 17:39:10 GMT
-Location: https://adamsimpson.net/uses
-Age: 0
-Connection: keep-alive
-Server: Netlify
-X-NF-Request-ID: de179b0f-db8b-401a-97ad-7ce523020763-108626
-
-HTTP/2 200
-cache-control: public, max-age=0, must-revalidate
-content-type: text/html; charset=UTF-8
-date: Tue, 22 Oct 2019 17:39:10 GMT
-etag: "3f4bb560fd31e7328aedc7bc08a9c541-ssl"
-strict-transport-security: max-age=31536000
-age: 0
-server: Netlify
-x-nf-request-id: de179b0f-db8b-401a-97ad-7ce523020763-108794
-
-Final URL: https://adamsimpson.net/uses
-Number of Redirects: 1 %
-

curl might be one of the most important tools I have at my disposal for working with HTTP requests and I feel like I’ve only begun to scratch the surface of what it can do.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/tweet-stash/index.html b/themes/cycle/exampleSite/public/writing/tweet-stash/index.html deleted file mode 100644 index bc5c99e..0000000 --- a/themes/cycle/exampleSite/public/writing/tweet-stash/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - Tweet stash - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Tweet stash

- - -
-

Two tweets that I’ve had stuck in my tabs for awhile and decided to stash them here.

-

Dismal laptops

-

The first one is a tweet from Dave Nanian, creator of SuperDuper, which paints a good picture of how bad Apple laptops had gotten from 2016-2019.

- -

Talk show entrances

-

This next tweet is hysterical. It’s a clip of Nic Cage being hyped in the 90s when he’s introduced to on a talk show in England. The thread is worth reading as you’ll also see Chris Farley’s Letterman entrance which is even more incredible.

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html b/themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html deleted file mode 100644 index 2dbd2b4..0000000 --- a/themes/cycle/exampleSite/public/writing/using-the-kindle-to-harness-the-web/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Using the Kindle to harness the Web - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Using the Kindle to harness the Web

- - -
-

Currently, I have the cheapest Kindle you can buy and I love it. I love it for reasons entirely different from my iPad. I love this Kindle cause it’s super cheap and durable, and I never worry about its battery life or wether it’s getting smashed in a bag when I travel.

-

I also love this Kindle for reading. I set up my Instapaper account to send me a digest of my Unread list every weekend, perfect for traveling, the pool, or even the beach – you know, places the iPad shouldn’t and can’t go. The Kindle feature in Instapaper got me excited about other possibilities for reading web stuffs on my Kindle.

-

The first thing I stumbled upon shortly after setting up my Instapaper to Kindle connection was Readlists. Readlists are brought to you by the same folks behind Readability. Readlists allows you to cobble together a list of articles from all over the web that they then compile into a Kindle digest. Rad!

-

After I discovered Readlists, I started finding several fantastic guides or books on JavaScript and Javascript best practices. Prominent members of the developer community are releasing these materials for free via Github or personal sites. I wanted to convert these excellent resources into documents on my Kindle. It was then that I discovered another fantastic resource from the Readability folks.

-

Readability released a simple bookmarklet that takes whatever page you’re viewing in your browser and sends it to your Kindle. Problem solved! I now have a couple Kindle “books” that are sourced from the web, how awesome is that? Try it out for yourself and start utilizing the incredible resources out there.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/verse-recall/index.html b/themes/cycle/exampleSite/public/writing/verse-recall/index.html deleted file mode 100644 index a883487..0000000 --- a/themes/cycle/exampleSite/public/writing/verse-recall/index.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - Verse Recall - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Verse Recall

- - -
-

Whew, time to share something with the world I haven’t really talked about online at all, my first and only (so far) iOS app. I did manage to find this tweet celebrating the launch (thanks to Twitter’s advanced search):

- -

Verse Recall was a Christmas gift to my Dad in 2013. He got a TestFlight beta, and it actually shipped in March. I’m pretty proud of it. The app was simple. It let you look up a Bible verse, save it locally to the device and schedule a local notification with the text of the verse. The goal was to help memorize verses.

-

When I started I didn’t know Obj-C (no Swift at the time), had never used Xcode, and had no real clue where to start. Despite all that I shipped it and I’m proud of the 30-odd copies I sold ($0.99 big money!). I never would have made it without these awesome tools:

- -

A few days ago I let my Apple Developer account “expire” therefore removing Verse Recall from the App Store. I’ve gone back and forth the last couple months on wether to renew again. There’s more I’d like to do with it, bugs I’d like to fix and features I’d like to add (like maybe port it to React Native?!), but I never spent the time to do those things for whatever reason. It works fine for now and my Dad still uses it so I’m content. If and when it breaks with an iOS update, I’ll either update it and side-load the fix onto my Dad’s phone or we’ll let it die.

-

This morning I moved the current state of the project from my private Bitbucket repo to Github. I wanted to share the entire project history because the commits are hilarious to read (they range from rage to despair and back again), but I foolishly committed API keys and the like that were too difficult to clean out of Git’s history. I doubt the code will be that useful to anyone at this point, but I like having it out there so I can point to it as a thing I did.

-

So ends Verse Recall, I’m proud of it and I learned a ton making it. In my mind it was a raging success.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/vim-ramblings/index.html b/themes/cycle/exampleSite/public/writing/vim-ramblings/index.html deleted file mode 100644 index 01df647..0000000 --- a/themes/cycle/exampleSite/public/writing/vim-ramblings/index.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - Vim Ramblings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Vim Ramblings

- - -
-

So, in the past 6 months I’ve switched from Sublime Text to Vim.

-

And just like that I’ve fulfilled Harry Robert’s tweet:

- -

Whelp. Anyway, onwards and upwards I guess.

-

Speaking of Harry, if your looking to get started with Vim, checkout his awesome guide that he wrote to save me the trouble of writing one myself!

-

Earlier tonight I was perusing the interwebs (shocker right?) and wound up on Wynn Netherland’s archives, because he’s an awesome dude and wicked smart. I came across a few really good Vim posts that I thought I’d highlight here:

- -

I totally agree with the anti-patterns and vimrc posts. I also need to try the relative numbers approach.

-

To finish up this hode-podge of links and rambling, my buddy @seanwashington recently pointed me to vimawesome, and holy crap it’s awesome, I highly recommend checking out the awesome plugins on that site.

-

Anyway, back to your regularly scheduled internets.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html b/themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html deleted file mode 100644 index 4c87f00..0000000 --- a/themes/cycle/exampleSite/public/writing/we-all-need-a-team/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - We all need a team - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

We all need a team

- - -
-

Bill Simmons’ latest piece on Pat Riley is full of great Riley stories. One particular moment where Riley talks to Kevin Garnett really resonated with me (italics mine):

-
-

It happened to everyone. You won’t truly know how outstanding you are, Riley promised him, until you’re surrounded by elite teammates who make you better. He told stories about Magic’s Lakers teams, how special they were, how many battles they fought, how those postseasons bonded them for life. There was a higher level of basketball. It was out there. You wouldn’t understand until you’ve experienced it. And until you’ve lost it, too.

-
-

We all need a team. On the right team we can go higher and be better than we ever thought we could.

-

To put it another way, we can only go so far alone.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html b/themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html deleted file mode 100644 index f4c5b02..0000000 --- a/themes/cycle/exampleSite/public/writing/web-performance-and-facebooks-instant-articles/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - Web performance and Facebook's Instant Articles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Web performance and Facebook's Instant Articles

- - -
-

John Gruber wrote down his initial thoughts on Facebook’s Instant Articles. This portion regarding performance stood out:

-
-

I’m intrigued by the emphasis on speed. Not only is native mobile code winning for app development, but with things like Instant Articles, native is making the browser-based web look like a relic even just for publishing articles. If I’m right about that, it might pose a problem even for my overwhelmingly-text work at Daring Fireball. Daring Fireball pages load fast, but the pages I link to often don’t. I worry that the inherent slowness of the web and ill-considered trend toward over-produced web design is going to start hurting traffic to DF.

-
-

Maybe I can’t see past my web developer bias, but I don’t believe this is a death knell for the “open web.” I think this is a wake-up call; there is no reason that Instant Articles should have such a speed advantage over a webpage.

-

Crafting a high-performing web experience for mobile is not easy, but it’s not so impossibly hard that Instant Articles is the only solution. With Instant Articles, Facebook is saving publishers from themselves - notice the lack of advertising, over-the-top branding, or massive image slideshows. Instant Articles isn’t faster because native beats the web. It’s faster because disciplined, curated content wins over content shoved between 1MB of advertisements.

-
-

Update:

- - -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html b/themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html deleted file mode 100644 index 8e0054a..0000000 --- a/themes/cycle/exampleSite/public/writing/web-scraper-cookbook/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - Web scraper cookbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Web scraper cookbook

- - -
-

I’ve been on a web scraping tear lately. So, I thought I’d compile what I’ve learned and put together a repo as a howto/cookbook/guide thing. So, here it is: introducing the Node web scraper cookbook.

-

I hope it’s useful. It’s nice to have this stuff written down just for my own sake. If you find it useful, awful, or confusing feel free to create an issue on the repo and I’ll try to update things.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html b/themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html deleted file mode 100644 index 67035eb..0000000 --- a/themes/cycle/exampleSite/public/writing/what-happens-when-you-remove-friction/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - What happens when you remove friction - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

What happens when you remove friction

- - -
-

When you remove friction from a process or task, all the factors change. This seems obvious, but it’s fundamental to understanding the world as it currently is. Polygon has a post up about the rash of “Youtuber burnouts” lately. The conclusion of the article stuck out to me (emphasis mine):

-
-

YouTube has a speed and quantity problem, and it affects all aspects of the business. If you are a content creator, take a little time with controversial stuff. It really is fun to make things, but irreverent, boundary-breaking stuff is high-risk/high-reward. Don’t just spit it out: run things by friends and people not in the business. Test the tone before you go live. Sleep on it.

-
-

Youtube is entertainment without traditional support mechanisms (i.e. friction). It’s relentless and there are no structures in place to push back at all. I think this lack of friction is at the root of the majority of problems in tech. Things move quickly and because of that speed safeguards and checks haven’t been instantiated yet. Not everything that pushes back is bad, that push-back can be life-saving.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/what-is-medium/index.html b/themes/cycle/exampleSite/public/writing/what-is-medium/index.html deleted file mode 100644 index 5299c31..0000000 --- a/themes/cycle/exampleSite/public/writing/what-is-medium/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - What is Medium? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

What is Medium?

- - -
-

Manton Reece in a post about Medium wondered:

-
-

Is it a blogging tool? Sort of. Is it a social network? Not exactly.

-
-

I’ve found Medium incredibly useful for browsing a community’s current thoughts and ideas. For instance, I love browsing the React tag on Medium. It’s filled with various posts about build tools, upcoming libraries, and thought pieces that I would never have found via RSS or Twitter.

- -

Regardless of what Medium intends to be, they at least seem to have stumbled upon something interesting with tags (from my perspective). I’m curious to see how Medium continues to evolve.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/what-its-all-about/index.html b/themes/cycle/exampleSite/public/writing/what-its-all-about/index.html deleted file mode 100644 index 988f88d..0000000 --- a/themes/cycle/exampleSite/public/writing/what-its-all-about/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - What it's all about - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

What it's all about

- - -
-

Wordpress Pro, and all around Nice Guy, Jonathan Christopher posted one of his many asides. This little snippet stuck out to me so much, I decided to post what is essentially an aside about an aside. Blogging has no rules right? Cool.

-

Jonathan wrote this about writing code,

-
-

The real joy comes from struggling to figure something out for way longer than you thought it would take and then actually seeing it work. That’s what it’s all about!

-
-

Spot on.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/what-matters/index.html b/themes/cycle/exampleSite/public/writing/what-matters/index.html deleted file mode 100644 index bf5f3cf..0000000 --- a/themes/cycle/exampleSite/public/writing/what-matters/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - What Matters - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

What Matters

- - -
-

A post from David Heinemeier Hansson over at 37 Signals on settling into your work for the long term. This is something I’ve been thinking about lately, largely because I’ve found a place at Sparkbox that is such a fantastic place to work.

-

David provides two solid reasons for why it’s worth it to stay put at an organization for both the employee and the employeer. This one stuck out to me the most.

-
-

[Focus] on the residue of knowledge and practices carried over from game to game is far more important than worrying about the output of any one game.

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html b/themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html deleted file mode 100644 index a8e3933..0000000 --- a/themes/cycle/exampleSite/public/writing/what-time-is-it-in-london/index.html +++ /dev/null @@ -1,237 +0,0 @@ - - - - - - What Time Is It in London? - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

What Time Is It in London?

- - -
-
-

Nilay Patel asked this of Siri on his Apple Watch. After too long of a wait, he got the correct answer — for London Canada. I tried on my iPhone and got the same result. Stupid and slow is heck of a combination.

-
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html b/themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html deleted file mode 100644 index 976739a..0000000 --- a/themes/cycle/exampleSite/public/writing/whats-best-for-the-readers/index.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - What's best for the readers - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

What's best for the readers

- - -
-

So good, it doesn’t need an intro.

-
-

For the same reason, we don’t show crappy display ads and we make all our revenue from social advertising that users love and share. We never launched one of those “frictionless sharing” apps on Facebook that automatically shares the stories you click because those apps are super annoying. We don’t post deceptive, manipulative headlines that trick people into reading a story. We don’t focus on SEO or gaming search engines or filling our pages with millions of keywords and tags that only a robot will read. We avoid anything that is bad for our readers and can only be justified by short term business interests. Instead, we focus on publishing content our readers love so much they think it is worth sharing. It sounds simple but it’s hard to do and it is the metric that aligns our company with our readers. In the long term is good for readers and good for business.

-
-

This excerpt is from Chris Dixon’s post where he published Jonah Peretti’s letter to employees and investors of Buzzfeed.

-

You should read all of it.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html b/themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html deleted file mode 100644 index 3d5ac21..0000000 --- a/themes/cycle/exampleSite/public/writing/when-the-music-stops/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - When the Music Stops - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

When the Music Stops

- - -
-

Dave Winer wrote a great post last week; he describes what happens when a piece of web software (i.e. Tumblr, Wordpress, etc) disappears. I decided to link to his post because I think it relates to my own Plaintext and Blogs, Data, and Social Networks posts. Ultimately we are each responsible for our own data, or as Winer writes:

-
-

I’m writing this […] to the users to wise up and also to stop being such children. If you feel there’s value in your writing, then treat it like it has value. If you depend on strangers to pay your rent, you have to know that isn’t going to work, long-term.

-
-

Start owning.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html b/themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html deleted file mode 100644 index 0460f0a..0000000 --- a/themes/cycle/exampleSite/public/writing/windows-11-as-kvm-guest/index.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - Windows 11 as KVM guest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Windows 11 as KVM guest

- - -
-

Windows 11 famously has new, stricter requirements for installation; a TPM device and Secure Boot. Here’s how I satisfied those requirements with Windows 11 as a KVM guest with NixOS as the host. The following is pulled from my NixOS configuration.nix:

-
libvirtd.qemu = {
-  package = pkgs.qemu_kvm;
-  runAsRoot = true;
-  swtpm.enable = true;
-  ovmf = {
-    enable = true;
-    package = (pkgs.OVMFFull.override {
-      secureBoot = true;
-      tpmSupport = true;
-    });
-  };
-};
-

The most important bit is the pkgs.OVMFFull.override section where you must specify tpmSupport and secureBoot as true.

-

In virt-manager you’ll need to add “new hardware” and select TPM v2.0. Here’s the relevant XML from my config:

-
<tpm model="tpm-crb">
-  <backend type="emulator" version="2.0"/>
-</tpm>
-

With the above settings you should be able to go through the Windows 11 installer and get the machine up and running as a KVM guest.

-

Stretch goal: nested virtualization

-

If you want to use Docker or WSL 2 inside KVM you’ll need to enable “nested virtualization” in virt-manager. I couldn’t figure this out until I found this great answer on superuser.

-

My original CPU config XML looked like this:

-
<cpu mode="host-model" check="partial">
-  <topology sockets="1" dies="1" cores="2" threads="4"/>
-</cpu>
-

The new XML looks like this:

-
<cpu mode="custom" match="exact" check="partial">
-  <model fallback="allow">Skylake-Client-noTSX-IBRS</model>
-  <topology sockets="1" dies="1" cores="2" threads="4"/>
-  <feature policy="disable" name="hypervisor"/>
-  <feature policy="require" name="vmx"/>
-</cpu>
-

With this applied I could install WSL2 and get Docker Desktop for Windows installed and running.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html b/themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html deleted file mode 100644 index ea77de8..0000000 --- a/themes/cycle/exampleSite/public/writing/working-with-wordpress-offset-and-pagination/index.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - Working with Wordpress, offset and pagination - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Working with Wordpress, offset and pagination

- - -
-

Yesterday I was working on a project (that will hopefully be released soon) that displays the most recent post differently than the rest of the posts on the page. This project also calls for pagination-like behavior on the second set of posts, while the feature post (most recent post) should be static and have no pagination.

-

I initially tried to use the offset parameter for the second post query to remove the most recent post from that loop. This however didn’t seem to work with the pagination.

-

Turns out Wordpress’ offset and pagination features collide, as the note says (always read those little notes!),

-
-

Note: Setting offset parameter will ignore the paged parameter.

-
-

I think the pagination feature uses offset internally which is why an explicit offset breaks the pagination.

-

Anyway, after hunting around a bit to see if anyone had a quick fix for this, I stumbled upon a post which had a quite complex question and an equally complex answer. Yet, it confirmed what I thought I’d have to do.

-

I simplified the solution quite a bit for my particular scenario, here is my code (note I am using verbose variable names here to help clarify):

-
$number_of_feature_posts = 1;
-$number_of_secondary_posts = 3;
-$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
-$how_many_secondary_posts_past = ($number_of_secondary_posts * ($paged - 1));
-$off = $number_of_feature_posts + (($paged > 1) ? $how_many_secondary_posts_past : 0);
-
-

I then used a simple WP_Query loop for the first loop, the featured (most recent) post, and then just used the normal query_posts with the additional arguments from the above snippet, for the second loop

-

-query_posts( "posts_per_page=$number_of_secondary_posts&offset=$off&showposts=$number_of_secondary_posts" );
-

This basically keeps the offset dynamic and relative to the page we are on. Hope you find it useful.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html b/themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html deleted file mode 100644 index 64bb8d7..0000000 --- a/themes/cycle/exampleSite/public/writing/youtube-subscriptions/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - youtube-subscriptions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

youtube-subscriptions

- - -
-

I’ve been using youtube-subscriptions for a few months now and I really enjoy it. It’s described as a:

-
-

terminal client to browse youtube subscriptions

-
-

It’s great to quickly see any new videos right in the terminal and videos play via mpv or vlc!

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/zach-beane/index.html b/themes/cycle/exampleSite/public/writing/zach-beane/index.html deleted file mode 100644 index 88c6b43..0000000 --- a/themes/cycle/exampleSite/public/writing/zach-beane/index.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - Uses This / Zach Beane - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Uses This / Zach Beane

- - -
-

A great interview with the creator of Quicklisp, Zach Beane. I enjoy two things about this interview:

-
    -
  1. The inclusion of outdoor/farming tools in the list of tools.
  2. -
  3. Zach’s conservative approach to languages and software tools.
  4. -
- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - - diff --git a/themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html b/themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html deleted file mode 100644 index 5229231..0000000 --- a/themes/cycle/exampleSite/public/writing/zen-garden-part-2/index.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - Zen Garden Part 2? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
-
- -

Zen Garden Part 2?

- - -
-

Remember the glorious days of the CSS Zen Garden before all of this CSS3 @font-face crazyness and @media resizing insanity?

-

I do, and probably most web designers and developers do to. Rick Monro definitely does, and he wrote yesterday that we need to create another CSS Garden, this time for Responsive Web Design (RWD).

-

Now, I think that’s a great idea, the more RWD resources, the better in my opinion. Of course we already have the RWD Book, which is a must read for any web designer or developer. And Trent Walton, Brad Frost, Mark Boulton, and Jordan Moore are all chronicling their experiences and solutions with Responsive Web Design as they use it in the real world. Hell, Brad Frost even has an e-mail newsletter dedicated entirely to RWD, so it’s not like resources on RWD don’t exist. I think Mr. Monro knows this, but he’s seeking a resource that mimics the Zen Garden and goes beyond the Mediaqueri.es gallery approach. Again, I think this is a great idea.

-

Yet, I take issue with how he frames the need for a RWD Garden. His claims make it sound like a “RWD Garden” is needed to finish the argument that RWD is the next advancement in our practice. In my opinion and the opinion of many in our industry, Responsive Web Design is the future, period. We’re past the convincing point with RWD, the web is changing.

-

I want to note that Responsive Web Design is not only concerned with fluid-width design. RWD incorporates other principles for developing sites, such as sites that are responsive to: mobile-sized screens, low bandwidth situations, and HD / Retina graphics. The entire package, this package called Responsive Web Design, is what is pushing the web forward. If all we are concerned with is narrow and wide views then Mr. Monro is quite right when he says:

-
-

Designers and developers are the only people I know who sit and accordion their browser window to see how a site will respond. We’re too in love with technique because we know that somewhere, another designer or developer is going to think it’s cool. And folks, when it gets to the point when we are designing for other designers, that should ring some pretty loud alarm bells

-
-

I think as a community we are still figuring out what this Responsive Web Design thing is, what it looks like, how we design for it, where Photoshop fits (does it?!), etc. We’ve had years to figure out how to design with and for CSS, we’re only just getting started with RWD. It’s an exciting time to be working on the web, yet Mr. Monro thinks there is too much “pressure” to use RWD:

-
-

The overwhelmingly positive spin accompanying a responsive site launch creates a subtle (but tangible) pressure on conscientious designers to ‘step up’ and deliver RWD on their own projects. Which would be fine, but the inference that RWD is desirable at any cost.

-
-

Of course, I’m not advocating an eyes-closed acceptance of Responsive Web Design for every client project. Tables are still used on the web, mostly in emails now, but there not gone; the same holds true for a site designed without applying RWD. However, “Positive spin” implies that we’re all trying to cover up something bad, which isn’t true. Any “spin” or “pressure” is simply the same encouragement as when moving from tables to CSS, that this is the right way to go. That “pressure” is what makes this industry so incredible. The web thrives on action, learning, pushing, and experimenting.

-

We shouldn’t slow down because the web is changing and things are all new and scary again. New and scary does not mean we’re going in the wrong direction. We are headed in the right direction, and that is why I fully support the creation of as many additional resources as possible to educate each other, as well as push RWD further.

- -
- Have a comment? Send an email to my public inbox. Please follow proper mail etiquette. -
-
-
-
- -
- -
- - -
-

Built with ♻ Cycle, Tachyons, and Emacs in the Midwest.

-
- - - -