Skip to content

Instantly share code, notes, and snippets.

View dantman's full-sized avatar

Daniel Friesen dantman

View GitHub Profile
@dantman
dantman / README.md
Last active October 2, 2026 11:24
How-to quickly setup an ephemeral "Self-Hosted" PostHog instance to test API client implementations against

How-to quickly setup an ephemeral "Self-Hosted" PostHog instance to test API client implementations against

I was writing an application that connected to customer PostHog accounts via the PostHog API and wanted to make sure it still worked for self-hosted PostHog users. But it's pretty hard to find any of those, much less ones where I can ask for an API key with Query permission, so I needed to host it myself.

Now I didn't actually want to go and setup any VPS to run this on. I use serverless platforms like Vercel and Convex for the things I write so I don't have access to any VPS-like environment that would be easy to run a series of Docker containers in without much work. So the natural thing I wanted to reach to was a Devcontainer and a temporary localhost tunnel. _No paying for a temporary VPS, Docker just runs on my machine. It all lives inside of a devcontainer so it doesn't polute my local environment, I can easily interact with it t

@dantman
dantman / curl-jq-api-tips.md
Created September 30, 2026 11:16
Tips for making JSON API calls with curl and jq: pretty-printing and paging responses, sending JSON POSTs with --json @-, embedding text like SQL queries with jq -Rs, and a jqless pager function.

Lately I've been making a LOT of API calls with curl, mostly to PostHog's API, and picked up some tricks along the way.

Let's start by trying this:

curl --no-progress-meter --dump-header=% https://xkcd.com/info.0.json | jq .

When APIs return JSON a lot of them don't pretty-print it. Pipe it into jq ., install it if you don't have it, and you'll get the JSON back with both pretty-printing and syntax highlighting.

@dantman
dantman / isNonNullable.ts
Created September 13, 2026 00:34
isNonNullable utility, allows you to simply write .filter(isNonNullable) on an array to exclude null/undefined and get the correct array type as a result.
/**
* Type guard to check if a value is non-nullable.
*
* This is useful for filtering out null and undefined values from arrays.
* Unlike Boolean this will only filter out null and undefined values and the type of the value will be narrowed accordingly.
*
* @param value The value to check.
* @returns True if the value is not null or undefined, false otherwise.
*
* @example If condition
@dantman
dantman / gist:555b1e2d53591d412545e9cafeae7114
Created September 6, 2026 01:30
Pasteable bash one-shot to temporarily add `./pinact` to a project (e.g. one in a devcontainer) you want to pin GitHub actions in
(
set -e
version="$(gh release view --repo suzuki-shunsuke/pinact --json tagName -q .tagName)"
asset="$(echo "pinact_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')".tar.gz)"
gh release download -R suzuki-shunsuke/pinact "$version" -p "$asset"
gh attestation verify "$asset" \
-R suzuki-shunsuke/pinact \
--signer-workflow suzuki-shunsuke/go-release-workflow/.github/workflows/release.yaml
tar -xzf "$asset" -C . "pinact"
chmod +x ./pinact
@dantman
dantman / header.ts
Created August 31, 2026 22:09
An experimental mini-library for getting an array of the user's language preferences from Accepts-Language/navigator.languages in a way that works without hydration errors and updates when preferences change
import { normalizeLanguageCode } from "./normalize";
/**
* A regexp to separate language tags from their optional q-factor weight in the Accept-Language header.
*/
const DIRECTIVE_REGEX = /^([^;]+)(?:;\s*q\s*=\s*(\d(?:\.\d+)?|\.\d+)\s*)?$/i;
/**
* Represents a single language directive from the Accept-Language header, including its position, normalized language code, and quality factor.
* e.g. "en;q=0.5" as the first word in the header would result in `{ headerIndex: 0, languageCode: "en", q: 0.5 }`.
@dantman
dantman / README.md
Last active September 3, 2026 23:50
Reusable "definedForm" boilerplate

📝 React + Zod + React Hook Form Boilerplate

A reusable pattern for building type-safe, validated forms in React using:

  • react-hook-form: For ergonomic form state management.
  • zod: For schema-based validation and type inference.
  • TypeScript: For full type safety throughout your forms.

Features

  • defineForm(schema): Generates a custom hook for your form, automatically wiring up Zod validation and type inference.
{
"name": "typefabric-management-app",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "typefabric-management-app",
"version": "0.1.0",
"dependencies": {
@dantman
dantman / copilot-instructions.md
Created June 4, 2025 14:05
Prompt to automate Drizzle migration process

An AI agent should attempt to run cli commands on behalf of the user when they are needed.

Before running any command as a terminal command, the AI agent should check if there is a relevant MCP (Machine Command Protocol) command available in the project. If there is, it should use that instead of running a terminal command directly.

Check type safety using the npm run typecheck task instead of tsc directly.

Drizzle

The database schema can be found in schema.ts. For timestamp and date column types use { mode: "date" } to give the column the Date type.

@dantman
dantman / WorkspaceSetup.prompt.md
Created May 30, 2025 17:44
Daniel's preferred workspace setup as a prompt
mode agent

We are in the folder for a new project. Your job is to set up the workspace according to my usual preferences. Here are the requirements:

Add the following scripts to package.json

{
	"scripts": {
@dantman
dantman / nvm-manage.sh
Created April 20, 2025 20:48
A Bash script that automatically manages Node.js versions with NVM, keeping specified versions updated and removing unused ones.
#!/bin/bash
# Authored by: Kagi Assistant
# https://kagi.com/assistant/6995ca12-6df0-4f88-9d91-848e993a2870
# Source NVM to make it available to the script
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
# Check if NVM is available
if ! command -v nvm &> /dev/null; then