Skip to content

Instantly share code, notes, and snippets.

View danawoodman's full-sized avatar
👨‍🔬
Hacking away...

Dana Woodman danawoodman

👨‍🔬
Hacking away...
View GitHub Profile
@danawoodman
danawoodman / Rust-like "results" for TypeScript projects.md
Last active August 20, 2025 19:19
Rust-like "results" for TypeScript projects

Rust-like "results" for TypeScript projects

Handling errors in JavaScript/TypeScript kinda sucks. throwing breaks the control flow, is not "discoverable" (e.g. impossible to really know what will happen in error states), and it is generally more tricky to get well typed error responses.

Taking inspiration from Rust's Result type, we can implement something similar in TypeScript with a minimal amount of code and no dependencies. It's not as robust as Rust's of course, but it has been very useful for me on a variety of large projects.

Implementation

Save the following TypeScript in your project and import it to use the various result utils:

@danawoodman
danawoodman / Get bun.lock files to work with Cloudflare Workers CI.md
Last active August 27, 2025 20:09
Get bun.lock files to work with Cloudflare Workers CI

Get bun.lock files to work with Cloudflare Workers CI

As of the time of this writing, Cloudflare Workers CI does not work with the newer text-based bun.lock file and instead requires a bun.lockb file to build your app via their CI system.

This usually manifests itself with the following error when trying to deploy your apps using a bun.lock file:

13:48:54.691	Initializing build environment...
13:49:02.821	Success: Finished initializing build environment
13:49:03.776	Cloning repository...
@danawoodman
danawoodman / ESP32 Controlled Low-Voltage Path Lights.md
Last active February 5, 2025 03:18
ESP32 Controlled Low-Voltage Path Lights

ESP32 Controlled Low-Voltage Path Lights

Using an ESP32-C3 connected to HomeAssistant via ESPHome, control 12v yard path lights including configuring automations to turn lights on/off at sunset/sunrise and dimming.

This short guide will show you how to use HomeAssistant, and the ESPHome app for it, to control LED dimming. In this case I'm using this for low voltage yard path lights, but could be used for anything.

If you have HomeKit integrated with HomeAssistant than you can also control/dim your LEDs from your iPhone!

Parts

@danawoodman
danawoodman / Svelte action to auto-grow a textarea.md
Created January 14, 2025 19:44
Svelte action to auto-grow a textarea

Svelte action to auto-grow a textarea

A Svelte action that whena applied to a textaarea supports automatically growing or shrinking as content is added or removed.

Implementation

src/lib/actions/autogrow.ts:

export function autogrow(node: HTMLElement) {
@danawoodman
danawoodman / Deploying CloudFlare Workers via CloudFlare Pages in a Turborepo monorepo.md
Last active August 9, 2025 20:07
Deploying CloudFlare Workers via CloudFlare Pages in a Turborepo monorepo

Deploying Cloudflare Workers via Cloudflare Pages in a Turborepo monorepo

Whew, what a mouthful.

Cloudflare Workers is an excellent platform for deploying a variety of applications but it has some limitations compared to Cloudflare's other product, Pages.

Pages gives you git integration which gives you auto-deploying via git push as well as pull request preview deployment links so you can test out features before pushing to production.

However, it's not super clear how to deploy a bare worker to Cloudflare Pages as Pages is more tailored right now for apps (SvelteKit, Astro, Next, etc), that is why I wrote up this little guide.

@danawoodman
danawoodman / Release golang apps using Github Actions.md
Last active February 7, 2024 07:00
Create a Go app release for every git version tag using Github Actions

Release golang apps using Github Actions

Want to release a new binary on Github for every new git tag (e.g. v1.2.7)? Here is a simple Github Actions yaml config file that should get you started.

This script will automatically checkout your code, setup the correct version of go as defined in your go.mod file and build your go binary (in this case using a Makefile default target), then upload it to a new Github Release.

# .github/workflows/release.yml
name: Build and release Go Project
@danawoodman
danawoodman / Raspberry Pi web page kiosk mode.md
Last active February 7, 2024 05:22
How to setup a Raspberry Pi to start up a web page in kiosk mode

Start a web page in kiosk mode on a Raspberry Pi

Install dependencies

Start by installing chromium and unclutter which will hide the cursor on the screen:

sudo apt install -y -no-install-recommends chromium-browser unclutter
@danawoodman
danawoodman / Setup a system service for the RaspberryPi.md
Last active February 7, 2024 00:02
Setup a system service for the RaspberryPi

Setup a system service for the RaspberryPi

If you want to run your own app on a Debian system, like a RaspberryPi, you'll need to build the binary for the given device then setup systemd to run the binary.

Given you have an app called myapp, first create a service file to run your app, say at myapp.service on your local system:

[Unit]
Description=Some description here...
After=network.target
@danawoodman
danawoodman / Serving embedded static files with Echo (Golang).md
Last active August 7, 2024 11:23
Serving embedded static files with Echo (Golang)

Serving embedded static files with Echo (Golang)

For a project I'm working on, I need to ship a single server binary with all static files embedded and use that for the frontend of the server. The backend has a variety of routes which the frontend calls.

The frontend is a SvelteKit static app built to ./frontend/build. Here is the Echo configuration to get these files serving at the root of the web server:

@danawoodman
danawoodman / How to allow the file picker AND camera capture on Android.md
Last active August 16, 2025 21:01
How to allow the file picker AND camera capture on Android

Allow photo album AND the camera

On Android devices, if you want to create a file input that prompts the user to either choose an image from their photo album or take a picture with their camera, you'll need this basically undocumented capture attribute added to your input's accept property:

<input type="file" accept="image/*;capture=camera" />