Project Portfolio

Click any tile to view technical details and screenshots. Then try each site live for yourself!

Church Management Platform

Public

Multi-tenant SaaS with white-label branding, comprehensive REST API, granular RBAC, Stripe/PayPal payments, Twilio SMS, thermal printer kiosk check-in, and a React Native mobile app.

ASP.NET Core React / React Native PostgreSQL Stripe Twilio EF Core

Texas Hold'em Poker

Public

Go (Golang) backend with goroutine-per-table game engine, WebSocket real-time play, 3-strategy AI bots with aggro tracking, and crypto/rand provably fair shuffle.

Go WebSocket Expo / React Native PostgreSQL Redis crypto/rand

VPS Monitor

Public

Dual-auth monitoring dashboard — API-key ingestion from bash watchdog, JWT dashboard access, cooldown-based alerting, and time-series visualization.

ASP.NET Core React Recharts PostgreSQL Bash / cron

Mandelbrot Set Viewer

Public

GPU-accelerated Mandelbrot fractal viewer in the browser. Rust + WebGPU with custom double-float WGSL arithmetic to extend zoom precision past native f32 limits.

Rust wgpu WebAssembly WebGPU WGSL

OHPM Website

Public

Static React site replacing WordPress — self-hosted newsletter system with AWS Lambda, SES, S3, API Gateway, and PostgreSQL replacing Mailchimp. 1.2 GB self-hosted media with hashed-asset cache busting.

React TypeScript AWS Lambda AWS SES PostgreSQL Tailwind CSS

Bible Memory

Public

First-letter memorization algorithm with server-side web scraping, print-optimized dual-page layout, and cross-project API consumption.

ASP.NET Core React AngleSharp Tailwind CSS

OHPM Financials

Private

Subset-sum bank reconciliation engine replacing Excel + Access — multi-source import (bank, PayPal API, ADP), fuzzy name matching, and seasonal board reporting.

ASP.NET Core React PostgreSQL PayPal API ClosedXML

Church Management Platform

Try it live API Docs Public

Multi-tenant church management platform replacing legacy systems like Planning Center and Church Community Builder. A unified system that consolidates people, families, groups, events, check-ins, services/worship planning, giving/donations, communications, and user accounts into a single interface — simpler than Planning Center's fragmented per-module apps. Isolated per-client databases deliver a more responsive experience than Church Community Builder's shared-infrastructure model. White-label branding system allows per-church customization of name, logo, colors, and contact info with zero code changes.

Includes 3 interactive demo accounts (Member, Staff, Admin) with guided walkthrough guides so users can test-drive the full platform with role-appropriate permissions.

ASP.NET Core 9.0 React 19 TypeScript Vite React Native (Expo SDK 54) PostgreSQL EF Core Stripe Payment Intents PayPal Orders v2 Twilio SMS Gmail SMTP Mailchimp API JWT Auth Google OAuth Apple Sign-In Nginx systemd

Architecture & Data

  • Comprehensive REST API covering auth, people, families, events, groups, check-ins, giving, services, forms, reports, and 3rd-party integrations
  • Granular RBAC: 12 roles, 48 permissions across 10 modules with [RequireModule] attribute-based backend gating
  • JSONB archival system — 71% data reduction (61,927 checkins into 105 JSONB rows) with event-date-based retention and VACUUM FULL post-archival via weekly cron
  • Two-tier audit framework — Tier 1: automatic field-level change tracking via EF Core SaveChangesInterceptor on 11 entities. Tier 2: explicit admin action logging with IP address capture
  • 12-feature modular flag system (7 included + 5 add-on) with [RequireModule] backend gating, ModuleRoute frontend gating, and 5-minute TTL cache
  • VPS firewall rules deny all inbound traffic except HTTP/HTTPS, SSH, and database — all other ports blocked

Payments & Communications

  • Stripe (one-time + recurring subscriptions via Payment Intents API) & PayPal (Orders v2) with cover-fees calculation (2.9%+$0.30 card, 0.8% ACH capped at $5)
  • Twilio SMS — phone verification, toll-free messaging, SMS-to-Give webhook with keyword triggers ("CONNECT"/"HI"/"HELLO")
  • HMAC-signed visitor Connection Cards — self-validating tokens (Base64Url + HMAC-SHA256) with 24-hour expiry, fuzzy email matching via Levenshtein distance with 20+ domain typo corrections
  • Email broadcasts via Gmail SMTP, Mailchimp audience sync integration

Integrations & Mobile

  • Bidirectional Planning Center sync — IAsyncEnumerable pagination with SemaphoreSlim rate limiting, HMAC-SHA256 webhook verification, remote_id bidirectional lookup
  • React Native mobile app (iOS App Store + Android) — giving, check-in, small groups, watch sermons (YouTube), church info, biometric auth, multi-church selector, encrypted JWT via expo-secure-store
  • Thermal printer integration — 4"x2" ZD421 labels (child, parent pickup, volunteer) with shared family security codes and auto-print on kiosk check-in
  • Hierarchical group-based event auto-resolution — walks parent_group_id ancestor chain so children in nested groups auto-match department-level events
  • Service plan builder with song library, chord charts with transposition, team scheduling, volunteer blockouts, and digital Music Stand module
  • Two-tier profanity filter as global action filter — evasion-resistant regex with gap-matching, leetspeak detection, and 70+ word whitelist
Church Management Platform admin dashboard showing module cards for kiosk, events, people, services, forms, and more

Texas Hold'em Poker

Try it live API Docs Public

Real-time multiplayer Texas Hold'em with 9-seat tables and AI opponents. The Go backend runs the entire game engine as a single goroutine per table with a full state machine (WAITING → PRE_FLOP → FLOP → TURN → RIVER → SHOWDOWN → HAND_OVER). The frontend is a React Native (Expo) app with Skia canvas rendering on mobile, View-based web overrides, and forced landscape rotation on mobile. Load-tested at 240 hands/sec with full PostgreSQL persistence. Supports 1,000+ concurrent tables (9,000+ players) per backend host. Horizontally scalable — add hosts behind a load balancer for linear throughput gains, using Go's lightweight goroutine-per-table model, WebSocket multiplexing, and async persistence.

Three bot AI strategies (Passive, Aggressive, Balanced) with position-aware play, pot odds calculation, bluff-catching (15-30% hero-call rate for pair+), and an aggro tracker that boosts bluff-catch probability by up to +15% against players who raise >40% of actions. The shuffle uses crypto/rand Fisher-Yates with rejection sampling — verifiably fair via 10K-hand chi-squared statistical tests (from the lobby, click "RNG Stats" top-right to see live card frequency and hand distribution data, or see screenshots below).

Go 1.23 goroutines WebSocket crypto/rand React Native (Expo) TypeScript Zustand React Native Skia PostgreSQL Redis JWT Auth Docker Nginx systemd

Game Engine

  • Single goroutine per table — all game mutations serialized on one goroutine; bots use the same action channel as humans
  • Full state machine: WAITING → STARTING → PRE_FLOP → FLOP → TURN → RIVER → SHOWDOWN → HAND_OVER
  • Side pot engine with correct all-in splitting — no spurious pots when bets are equal
  • crypto/rand Fisher-Yates shuffle with rejection sampling — chi-squared validated across 10K hands
  • Hand history persistence — hands, hand_players, hand_actions tables with retroactive evaluation for folded players
  • 15-second auto-fold timer with pre-action queue bypass

Bot AI

  • Three strategies: Passive (calls, folds to pressure), Aggressive (raises frequently, ~15% bluff rate), Balanced (position-aware, pot odds)
  • AggroTracker — per-human raise frequency tracking; >40% raise rate (min 5 samples) triggers +15% bluff-catch boost
  • Calibrated postFlopStrength rank map: HighCard=0.05 through RoyalFlush=1.0 with facingPressure fold thresholds
  • Dynamic bot lifecycle — batch refill (15-50 hand lifespan), humans kick bots, 10s refill delay to prevent race conditions

Frontend & UX

  • Forced landscape rotation on mobile via CSS transform + useLandscapeDimensions hook
  • Pre-action system — FOLD, CHECK, CALL ANY queueable during opponent turns, auto-fired with 300ms delay
  • Expo web static export with cache-busting post-export scripts and service worker kill-switch
  • Auto-auth (silent guest registration) + auto-sit + fixed shareable table IDs (/table/1, /table/micro, /table/high)
  • Fully functional on mobile phone browsers — forced landscape rotation and adaptive geometry ensure playable UI on any screen size
  • RNG stats dashboard — card frequency heat maps and hand rank distribution charts read directly from PostgreSQL
  • VPS firewall rules deny all inbound traffic except HTTP/HTTPS, SSH, and database — all other ports blocked

OHPM Website

Visit site API Docs Public

Static React site for Only Hope Prison Ministries (501(c)(3) nonprofit), replacing a legacy WordPress site and Mailchimp email service with a fully self-hosted stack. The newsletter system uses AWS Lambda, SES, S3, and API Gateway — deployed via SAM/CloudFormation — to handle subscriber management, double opt-in confirmation, and batch email delivery to ~1,000 subscribers at a fraction of Mailchimp's cost. An admin-only TipTap WYSIWYG editor enables composing, previewing, and sending branded HTML newsletters with inline image uploads to S3. All content — PDFs, MP3s, images, JSON data — is self-hosted (~1.2 GB) on shared hosting with no external CMS. Cache busting uses Vite hashed asset filenames with no-cache on index.html, ensuring users always get the latest version without hard refreshes.

React 19 TypeScript Vite 7 Tailwind CSS 4 React Router 7 Apache / .htaccess SiteGround AWS Lambda AWS SES AWS S3 AWS API Gateway AWS SAM / CloudFormation AWS IAM PostgreSQL TipTap Editor Node.js 20

Self-Hosted Newsletter System (Mailchimp Replacement)

  • AWS SES email delivery — domain-verified with DKIM authentication, SPF/DMARC DNS records, production-approved sending (50,000 emails/day, 14/sec rate limit). Replaced Mailchimp at ~$20/month with SES at $0.10 per 1,000 emails
  • 5 AWS Lambda functions (Node.js 20.x, ES modules) — subscribe (double opt-in with UUID confirmation tokens), confirm, unsubscribe, send-newsletter (batch sending with 14/sec rate limiting), and upload-image (base64 to S3 with MIME validation)
  • AWS SAM / CloudFormation — entire serverless stack defined as infrastructure-as-code in template.yaml. Single-command deploy with parameter overrides for secrets. Configures API Gateway, Lambda functions, IAM roles, and environment variables
  • AWS API Gateway — RESTful HTTP endpoints with CORS restricted to production domain only. Bearer token authentication on admin endpoints (send, upload)
  • AWS S3 — newsletter image storage with public-read bucket policy scoped to images/* prefix. Timestamp-based filenames prevent collisions. Admin uploads via Lambda proxy
  • AWS IAM — dedicated service user with scoped S3 and SES permissions. Temporary elevated permissions during SAM deploy, then reduced to least-privilege
  • PostgreSQL subscriber databasesubscribers table with UUID tokens, confirmation status, and timestamps. 994 subscribers imported from Mailchimp export (Excel) via Python script with duplicate detection. Lambda functions connect directly to PostgreSQL on VPS, secured by VPS firewall rules that deny all inbound traffic except database
  • CAN-SPAM compliant email template — branded HTML email wrapper with navy header, scripture quote, content body, donation CTA, physical mailing address, and personalized per-subscriber unsubscribe links
  • TipTap WYSIWYG newsletter editor — admin-only React page with rich text editing (headings, bold, italic, lists, blockquotes, links), inline image upload to S3, edit/preview toggle, test-send to single address, and batch-send to all confirmed subscribers
  • Subscribe form component — reusable React component on home page and newsletters page. Handles loading/success/error states with inline feedback. Confirmation and unsubscribe status messages via URL query parameters
  • Newsletter archive migration — Python script scraped 47 Mailchimp campaign HTML files, stripped tracking pixels and chrome. Archive pages render via iframe with CSS clipping to hide Mailchimp navigation bar

Static Site

  • JSON-driven content architecture — 6 data files decouple content from code, enabling updates without redeploys
  • ~1.2 GB self-hosted media served directly (no CDN), with SiteGround Nginx proxy cache + PURGE on deploy
  • Tiered .htaccess cache headers: no-cache for HTML, 1-year hashed assets, 1-week PDFs, 1-year MP3s
  • ErrorBoundary with auto-recovery — detects chunk loading failures, performs one hard refresh, prevents infinite loops via sessionStorage flag
  • Embedded media player — YouTube embed conversion with timestamp parsing, inline MP3 playback, video lightbox modal
  • Non-profit payment strategy — Stripe Payment Links (zero backend), ACH at 0.5% capped $5, Zelle zero-fee option
  • Photo slideshow with lightbox navigation, keyboard controls, image preloading
  • Responsive fluid typography with CSS clamp() and mobile-first sticky nav with scroll lock handling
  • Hashed asset cache busting — Vite generates unique filenames per build, users always get latest without Ctrl+Shift+R
  • Smart data sorting — pinned items (no date) first, then reverse-chronological dated items
  • Fully functional on mobile phone browsers — responsive design with mobile hamburger nav and touch-optimized media playback

OHPM Financials

Private
This application manages real financial data for a nonprofit organization and is not publicly accessible.

Full-stack financial reconciliation platform for a nonprofit prison ministry, replacing a decades-old Excel + Access workflow. Handles hundreds of donors and payee records, 15 years of historical data (2011–2026), and significant annual transaction volume with automated bank reconciliation, donor tracking, expense management, and board-level financial reporting. Three role-based views serve distinct user needs:

Role-Based Access

  • Donor — View personal giving history, print end-of-year tax giving statements, and update contact information via Google OAuth login
  • Viewer — Read-only access to donations, expenses, ledger (checkbook), and people data. Month-over-month and year-over-year financial trend reporting with interactive charts
  • Admin — Full write access including auto-import from PayPal REST API, copy/paste bank data for automatic record creation and reconciliation, person merge, expense management, and bulk donor statement mailing
ASP.NET Core 9.0 React 19 TypeScript Vite PostgreSQL EF Core ClosedXML PayPal REST API JWT Auth Google OAuth Gmail SMTP

Reconciliation Engine

  • Subset-sum matching algorithm with multiple strategies (by amount, by fee formula, by net amount) for penny-perfect multi-transfer PayPal batch matching
  • 7-tier hierarchical name matching — alias lookup, exact match, fuzzy partial first/last, middle initial/nickname handling, and per-donor pattern scoring
  • Bank web paste parser with type inference — classifies Credit, Debit Card, Zelle, ACH, Check from pasted bank data using keyword + fallback regex
  • PayPal batch grouping by bank transfer events (not UTC dates) with estimated bank posting dates (+1 business day) and cross-day date correction
  • Auto-reconciliation with 3-level confidence — exact/alias person match creates DB records tagged [auto-reconcile] with green AUTO badge
  • Bank check duplicate prevention during reconciliation pass

Reporting & Analysis

  • Excel export via ClosedXML: 10-sheet Ledger, 6-year Board Report, Checkbook Register, 990 Filing Data Export — matching original OHPM format exactly
  • Board financial report with 3-year seasonal estimation — actual monthly weights replace linear extrapolation, with growth caps and ADP 3-pay-period anomaly handling
  • Interleaved checkbook register — PostgreSQL ledger view merges donations and expenses chronologically with running balance from starting balance
  • Per-donor historical pattern scoring — day-of-month statistical distributions (mean, stddev, z-score) across 3 years with ACH ±2 day / check ±5 day tolerance bands
  • ADP payroll PDF parser with biweekly 3-pay-period detection, employer liability separation, and medical withholding income netting
  • Fiscal year awareness throughout — every report endpoint accepts ?fiscalYear=N, 6-year range (actuals + estimate + projection)

Operations

  • Gmail SMTP bulk mailing of annual donor giving statements with 2-second throttle, BCC tracking, and resume-capable statement_sends table
  • 15-year historical data migration from Access VBA & Excel sources, dozens of legacy payees consolidated into unified people table
  • Person merge UI with field-level override and duplicate detection — atomically reassigns all donations/expenses/users to target
  • Multi-category vendor detection with auto-created "Pending" expense for inline breakdown that atomically replaces placeholder on submit
  • Fully functional on mobile phone browsers — responsive top nav with hamburger menu and touch-friendly data entry
  • VPS firewall rules deny all inbound traffic except HTTP/HTTPS, SSH, and database — all other ports blocked

VPS Monitor

Try it live API Docs Public

Self-hosted monitoring dashboard providing real-time visibility into .NET and Go services running across production VPS infrastructure. Replaces manual log-file inspection with a web UI featuring live status cards, historical time-series charts, a paginated event log, and configurable email alerting with cooldown-based deduplication.

Uses a dual-authentication pattern: hashed API keys for script-based metric ingestion, and JWT tokens for interactive dashboard access. A bash watchdog script periodically POSTs system and per-service metrics — all calls are fire-and-forget so monitoring never breaks if the dashboard is unavailable.

A separate HTTP health-check script curls each service's actual endpoint. If a service is unresponsive, it auto-restarts with graduated retry and escalation, logging recovery events to the dashboard.

The public page shows live service status. Additional monitoring functionality — time-series charts, event logs, alert configuration, and system metrics — is available behind a secure login.

ASP.NET Core 9.0 React 19 TypeScript Vite Tailwind CSS 4 PostgreSQL EF Core Recharts JWT + API Key Auth Bash / cron Nginx Linux
  • Clean Architecture (Core, Infrastructure, Shared, API layers) with DI throughout
  • Dual auth: hashed API keys for ingestion, JWT for dashboard — isolated auth paths per use case
  • Cooldown-based alert deduplication — AlertConfig tracks LastFiredAt per event type with configurable cooldown windows to prevent alert spam
  • Auto-triggered alerts on service restarts, down detection, and high CPU steal
  • Gmail SMTP email delivery to managed recipient lists
  • Bash watchdog collects system metrics (CPU, memory, swap, load, steal) and per-service stats (CPU, RSS, PID) via fire-and-forget POST
  • HTTP health checks — curls each service endpoint, auto-restarts unresponsive services with graduated retry and escalation
  • Self-monitoring: included in its own watchdog and nightly recycle rotation
  • Composite indexed columns with descending order for efficient time-range queries — (server_id, recorded_at DESC)
  • EF Core bulk update via ExecuteUpdateAsync() for non-materialized operations
  • Multi-server ready with unique API keys per VPS and aggregate dashboard view
  • Fully functional on mobile phone browsers — responsive dashboard with touch-friendly charts and status cards
  • VPS firewall rules deny all inbound traffic except HTTP/HTTPS, SSH, and database — all other ports blocked

Bible Memory

Try it live Public

Web application that generates printable first-letter memorization sheets for any Bible chapter. Each word is reduced to its initial letter (with punctuation, quotes, and footnote markers preserved), producing a two-sided document: memorization format on front, full text on back. Content is fetched and parsed from a public Bible website via server-side AngleSharp HTML scraping with dynamic book abbreviation detection via regex on CSS classes.

The first-letter algorithm was ported from an original Go implementation to TypeScript with exact parity — handling edge cases like apostrophe-words ("Peter's" → "P's"), leading quotes/parentheses, footnote markers ([a]), and Unicode normalization (curly quotes/dashes to ASCII). The API is designed for cross-project consumption with CORS configured for reuse by other apps.

ASP.NET Core 9.0 React 19 TypeScript Vite Tailwind CSS 4 AngleSharp Nginx
  • First-letter memorization algorithm with full edge-case handling: apostrophes, footnotes, leading quotes, Unicode normalization
  • Server-side web scraping via AngleSharp with dynamic book abbreviation detection and robust footnote/cross-reference removal
  • 10 Bible versions (CSB, ESV, LEB, LSB, NASB, NIV, NKJV, NLT, NRSV, RSV) with per-book chapter count validation
  • Print-optimized dual-page layout — Aptos Serif 11pt, 60pt row heights, light blue (#BDD7EE) every 5th verse, matching original Excel formatting
  • Special Psalm 119 acrostic heading support with verse association and section breaks
  • In-memory caching with 24-hour TTL and typed response models
  • Reusable public API endpoints with CORS for cross-project consumption
  • Print CSS with page breaks, print-color-adjust: exact for background colors, and hidden UI controls
  • VPS firewall rules deny all inbound traffic except HTTP/HTTPS and SSH — all other ports blocked

Mandelbrot Set Viewer

Try it live Math write-up Public

Real-time GPU-rendered Mandelbrot set explorer running in the browser via WebAssembly and WebGPU. The same Rust codebase compiles to both web (WASM + WebGPU) and a native desktop binary — platform differences are gated with #[cfg(target_arch = "wasm32")]. The fragment shader iterates the Mandelbrot recurrence per pixel using software double-float (DF) arithmetic in WGSL, extending the usable zoom range from native f32's ~1e-5 floor down to roughly ~1e-14 before pixelation sets in.

Smooth iteration coloring uses the standard log(log|z|) continuous-escape trick fed into a cosine palette. Zoom-to-cursor math holds the complex-plane point under the mouse fixed across zoom changes. A linked write-up details the math (DF split, two-sum, Dekker product, smooth iteration, fullscreen-triangle rendering) for anyone wanting to replicate the technique.

Rust wgpu winit 0.30 WebAssembly WebGPU WGSL wasm-bindgen trunk Nginx Let's Encrypt

Rendering

  • Fragment-shader Mandelbrot iteration per pixel — fullscreen triangle generated procedurally from vertex_index, no vertex buffer
  • Double-float (DF) arithmetic in WGSL — each f64 split into (hi, lo) f32 pair, shader uses Dekker two_prod, two_sum, and DF add/sub/mul to push usable zoom from ~1e-5 to ~1e-14
  • Smooth iteration coloring via log(log|z|) continuous-escape with cosine palette — tunable banding frequency and per-channel hue offsets
  • 32-byte uniforms struct laid out for WGSL 16-byte alignment without explicit padding
  • WebGPU only — no WebGL2 fallback; capability check banner shown if navigator.gpu is missing

Architecture

  • Single Rust codebase compiles to both wasm32-unknown-unknown (web) and native desktop — platform splits via #[cfg(target_arch = "wasm32")]
  • Async GPU init on web uses wasm_bindgen_futures::spawn_local + EventLoopProxy<UserEvent> to hand initialized state back through the event loop (browser main thread can't block on a future)
  • Native desktop build uses pollster::block_on for synchronous GPU init — same source, two startup paths
  • Canvas sized by CSS, not Rust — winit reads viewport via WindowAttributesExtWebSys and emits resize events on viewport change
  • Release profile: lto = "fat", codegen-units = 1, plus trunk's data-wasm-opt="z" for size-optimized WASM

Controls & Deployment

  • Drag to pan, scroll to zoom (point under cursor stays fixed), R to reset, [ / ] to halve / double iteration cap
  • Trunk static-builds to dist/ and rsync-deploys to Hostinger VPS; Nginx serves with application/wasm MIME and Cache-Control: public, max-age=31536000, immutable on hashed assets
  • Let's Encrypt TLS via certbot's nginx plugin with auto-renewal via system certbot.timer
  • Fully functional on mobile phone browsers with WebGPU support — canvas auto-fits viewport via CSS
Mandelbrot set viewer rendered in the browser via WebGPU, deep zoom showing self-similar fractal detail