Skip to content

Instantly share code, notes, and snippets.

View metruzanca's full-sized avatar
☕

Sam Zanca metruzanca

☕
View GitHub Profile
@metruzanca
metruzanca / PITCH.md
Last active October 25, 2026 20:41
gothic: a fullstack Go framework that compiles templ-like components to Go and JavaScript

gothic

One language. Server-rendered HTML. Surgical client-side DOM updates. No JavaScript tax.

The gap

HTMX made server-driven UI mainstream again. You render HTML on the server, swap fragments, and skip most of the SPA stack.

Then the interface needs a counter, a dropdown, a form that updates state without a round trip, or a progress indicator driven by a request. HTMX stops short. You reach for JavaScript, then Alpine.js, then a build chain, and suddenly the "one language" server app has a second language and a second toolchain.

@metruzanca
metruzanca / README.md
Created September 4, 2026 18:28
Drag and drop with Bubble Tea: mouse events, drag state machine, hit-testing, and a runnable demo (no kanban)

Drag and drop with Bubble Tea

A minimal, reusable recipe for click-and-drag interactions with Bubble Tea using mouse events. This is the generic mechanism (grab → move → release) — you can bolt it onto a kanban board, a list reorder, a file palette, a table, whatever.

The companion file main.go is a runnable demo: drag colored boxes around a workspace and drop them on a "recycle" bin to delete them.

@metruzanca
metruzanca / GPUI_GUIDE.md
Created August 19, 2026 01:24
GPUI Guide and Best Practices
@metruzanca
metruzanca / leaflet-catppuccin-macchiato.user.css
Created July 4, 2026 04:27
Catppuccin Macchiato userstyle for Leaflet (stylus)
/* ==UserStyle==
@name Catppuccin Macchiato - Leaflet
@namespace catppuccin.macchiato.leaflet
@version 1.0.0
@description A soothing dark theme for Leaflet based on Catppuccin Macchiato
@author Catppuccin
@preprocessor default
==/UserStyle== */
@-moz-document domain("leaflet.pub") {
@metruzanca
metruzanca / atproto-appview-guide.md
Last active July 1, 2026 17:39
Language-Agnostic ATProto AppView Implementation Guide

Language-Agnostic ATProto AppView Implementation Guide

1. Core Concepts

An ATProto appview is a service that:

  • Has its own DID — the appview is an identity on the network. It owns the lexicon schemas and publishes them from its repo.
  • Defines a lexicon — your data schema published as ATProto records in the appview's own repo
  • Authenticates via OAuth — users grant your app permission to write to their repos
  • Writes records to users' PDSes via com.atproto.repo.createRecord
  • Reads records via com.atproto.repo.listRecords / getRecord

Why Solid over React

Both render JSX. The difference: Solid is fine-grained reactivity, so a state change updates only the DOM nodes that read it and not a component tree, not a virtual DOM, not a diff.

1. No virtual DOM

React maintains a vDOM and diffs it on every update. Solid compiles JSX into direct, precise DOM updates. A signal change touches only the nodes that read it. No diffing, no reconciliation, no key props, no "list virtualization because the diff is expensive."

2. No re-renders

type Modifiers = {
ctrl?: boolean;
shift?: boolean;
};
type HotkeyDetails = { key: string } & Modifiers;
const hotkeyName = ({ key, ctrl, shift }: HotkeyDetails) =>
`hotkey:${ctrl || ""}+${shift || ""}+${key}`;
@metruzanca
metruzanca / truncateMiddle.test.ts
Last active July 30, 2024 19:06
Didn't end up using this in the end, didn't wanna delete it outright.
import { truncateMiddle } from '.';
describe('utils', () => {
// ...pretty exaustive for a string utility, I know...
describe('truncateMiddle', () => {
const testStrings = [
'0x3172635bc846d0c68afce1738d048520dcfafed2d55d1866a5ed5a40d5ea66c7', // 66 chars
'0000000000000000000000000000000000000000000000', // 46 chars
'00000000000000000000000000000000000000000000000', // 47 chars
];
@metruzanca
metruzanca / solid.userscript.js
Last active July 17, 2025 20:13
The poor man's SolidJS implemented in 40 lines
const $ = document.querySelector.bind(document),
$$ = document.querySelectorAll.bind(document),
h = (name, props) => Object.assign(document.createElement(name), props);
const context = []
const getCurrentObserver = () => context[context.length - 1]
function createEffect(fn, name) {
const execute = () => {
context.push(execute)
@metruzanca
metruzanca / signal.ts
Created December 14, 2023 21:56
Basic signal implementation from a Ryan Carnianto Talk
const context: Function[] = []
function getCurrentObserver() {
return context[context.length - 1]
}
function createEffect(fn: Function, name: string) {
const execute = () => {
context.push(execute)
try {