GitHub Activity
Portfolio
Selected projects I’ve built. Each one has a writeup over on the blog if you want the longer story.
Projects
JDExtractor
A local-first job search CRM that lives entirely on your machine. JDExtractor ships as a single Go binary that doubles as a CLI and a web server, with a Svelte 5 + Vite frontend embedded into the executable via //go:embed. It captures job descriptions, keeps them organized in a structured filesystem layout, and uses an LLM (DeepSeek or Kimi) to tailor your resume and cover letter to each posting without sending your search history to a third-party service.
Notable design choices:
- Zero Go module dependencies. The entire backend is
go 1.25stdlib only. No SDKs, no router framework, no retry library. Hand-rolled HTTP client with exponential backoff, hand-rolled CSRF middleware, hand-rolled LLM client. - Filesystem as the database. Every job application is a folder named
YYYY-MM-DD-{rand}-{role-slug}containingmeta.json,resume.txt, and an optionalcover.txt. Backups aretar. Migrations don’t exist. - No headless browsers. URL fetching goes through
r.jina.aito handle JS-heavy SPAs without bundling Chromium. - PII sanitization before any data leaves the machine. Emails and phone numbers are redacted before the prompt is sent.
- Networking CRM built in: track contacts, log conversations, and generate AI follow-up messages with suggested timing and channel.
Go · Svelte 5 · Vite · DeepSeek · embedded web server · local-first
dilates-education.com
A Pilates-focused learning management system (internally named “Dimalates”) architected and built for MKA Cloud Studio, my consultancy. It hosts courses, lessons, and student enrollments, runs live chat between instructors and students, and supports multiple studios on a single deployment with proper data isolation.
Notable architectural choices:
- Phoenix LiveView 1.1 on top of the Ash Framework 3.x. Three Ash domains (
Accounts,Content,Learning), each with declarative resources, actions, validations, and policies. The web layer never callsAsh.read!/2directly; everything goes through domain code interfaces. - Multi-tenancy via Ash’s attribute strategy with a
tenant_idcolumn on every tenant-aware resource. The framework refuses to execute unscoped queries, so cross-tenant data leaks are impossible at the framework level. - AshAuthentication with both password (with email confirmation) and Google OAuth, including a custom
CreateOAuthUserAccountchange that provisions the user, account, and tenant attachment in a single transaction. - Authorization at the resource level. Every resource has a
policiesblock. There is zero auth logic in LiveViews or controllers. The framework checks every action against the active actor and tenant. - Full OpenTelemetry instrumentation across Phoenix, Bandit, Ecto, and Ash, with errors going to Sentry. Linked traces let me jump from a slow request straight to the offending Ash action and Ecto query.
- Tailwind + daisyUI only. No custom CSS, no inline styles. Deployed to Fly.io.
Elixir · Phoenix LiveView · Ash Framework · PostgreSQL · AshAuthentication · OpenTelemetry · Fly.io