Skip to content
Dylan San GabrielDylan
Get in touch

GET /api/work

Projects, written up properly.

Each one says what the problem was, what was non-obvious about the approach, and what came out of it, in the same places every time, so you can compare them.

The internal ERP that runs a dental supply company

Live · 2026 · sole engineer · 13 daily users

The company sold on six websites using six different tools that never agreed. I built the one system that runs it all, about 500 orders a day.One system for orders, inventory, repricing, shipping, service and books across six sales channels, built from scratch, about 500 orders a day.

Read the project

The ERP's warehouse map: a floor plan of the main building with named rooms and 147 numbered storage locations, a building switcher, a layout editor and a printable map.

Running a dozen AI coding sessions on one repo

Live · 2026 · sole engineer

I use AI helpers to write much of the code, like a chef running a fast kitchen. This is the system of rules and checks that keeps the plates right.How I use AI coding agents at scale without vibe-coding, auto-loading rules, hooks that block the dangerous operations, and review triggered by consequence.

Read the project

A second brain where the agent does the filing

Live · 2026 · solo · personal tooling

A filing cabinet for my own notes, mail and messages that an AI assistant maintains for me. It proposes what needs doing next; I approve it. Everything stays on my Mac.A plain-markdown vault an AI librarian keeps for me — 738,000 messages indexed locally, nothing filed without my approval, no cloud.

Read the project

Split the check from a photo

In progress · 2026 · solo · side project

Photograph the dinner receipt, say who ate what, and it tells everyone what they owe. It checks its own answer against the receipt's printed total and won't show a split that doesn't match.Photograph a receipt, tap who had what, get the split. Runs on your phone with no server, and refuses to show a split that doesn't add up.

Read the project

The splitter after reading the example receipt. On the left, the receipt it was pointed at and, below it, what each person owes: You $28.86, Friend $40.40, summing to the printed $69.26. On the right, the green "Adds up" verdict and the five line items with a name tapped onto each.

Testing an ERP by hand, then automating a cloud app

Archived · 2024 · contributor · team of 10

Ten of us taught robots to re-test a business app every night, after testing it by hand first, which is how we found the bugs the robots would've missed.Two sprints on the CYDEO SDET program — fourteen user stories tested by hand against an ERP, then a Cucumber and Selenium suite against a cloud app.

Read the project

Galaxy Defense

Archived · 2020 · solo

A game I built in high school using drag-and-drop coding blocks. It has a shop, upgrades, a boss, and a teleport ability, all made without the normal tools programmers use to keep code organised.A space shooter built in block code in high school. 790 lines, an economy, and a boss fight, with no arrays or classes available.

Read the project

Galaxy Defense running: the player's ship at the bottom, two green aliens descending, three green bunkers, and the lives, points, bombs and FTL readouts.

Shotcall

Live · 2026 · solo

Like Wordle, but with a bouncing ball. One puzzle a day: work out which pocket it ends up in. Guess wrong and it shows you one more bounce.A daily puzzle. A ball bounces three times and drops into a pocket; you guess which one. Every miss shows you one more bounce.

Read the project

A solved Shotcall board. The ball's real path is chalked in white from the top rail, off the right rail, the bottom rail and the underside of a wooden block, into pocket L; the player's own amber line, drawn freehand, tracks it bank for bank and dies on the bottom rail beside K. Four pockets are crossed out, fourteen are lettered A to P on the green cloth.

This Portfolio

Live · 2026 · solo

This website. It has two voices, plain English and engineer, and a whole second mode where the portfolio becomes a help desk. Also it can run games.A content site that can also run games, built so the writing stays easy and the demos stay cheap.

Read the project

GET/api/work

Parameters

Request

curl "https://portfolio.dylansg0318.workers.dev/api/work"
source: src/content/projects/*

Response200 OK · 7.8 KB

{
  "category": "all",
  "count": 8,
  "items": [
    {
      "id": "internal-erp",
      "title": "The internal ERP that runs a dental supply company",
      "status": "live",
      "year": 2026,
      "category": "work",
      "role": "sole engineer · 13 daily users",
      "summary": "One system for orders, inventory, repricing, shipping, service and books across six sales channels, built from scratch, about 500 orders a day.",
      "summary_plain": "The company sold on six websites using six different tools that never agreed. I built the one system that runs it all, about 500 orders a day.",
      "stack": [
        "TypeScript",
        "Node.js",
        "Express",
        "React",
        "PostgreSQL",
        "Railway",
        "GitHub Actions",
        "Docker"
      ],
      "metrics": {
        "orders_day": "~520",
        "products": "32K",
        "sales_channels": "6",
        "daily_users": "13",
        "orders_ingested": "300K+",
        "price_changes_logged": "138K+",
        "automated_tests": "2,721",
        "scheduled_jobs": "180"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp"
    },
    {
      "id": "agent-fleet",
      "title": "Running a dozen AI coding sessions on one repo",
      "status": "live",
      "year": 2026,
      "category": "work",
      "role": "sole engineer",
      "summary": "How I use AI coding agents at scale without vibe-coding, auto-loading rules, hooks that block the dangerous operations, and review triggered by consequence.",
      "summary_plain": "I use AI helpers to write much of the code, like a chef running a fast kitchen. This is the system of rules and checks that keeps the plates right.",
      "stack": [
        "Claude Code",
        "Node.js",
        "Git hooks",
        "GitHub Actions",
        "Jest",
        "Markdown"
      ],
      "metrics": {
        "commits_in_6_months": "14K",
        "parallel_sessions": "10+",
        "operating_docs": "300+",
        "models_cross_reviewing": "2"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/agent-fleet"
    },
    {
      "id": "second-brain",
      "title": "A second brain where the agent does the filing",
      "status": "live",
      "year": 2026,
      "category": "tool",
      "role": "solo · personal tooling",
      "summary": "A plain-markdown vault an AI librarian keeps for me — 738,000 messages indexed locally, nothing filed without my approval, no cloud.",
      "summary_plain": "A filing cabinet for my own notes, mail and messages that an AI assistant maintains for me. It proposes what needs doing next; I approve it. Everything stays on my Mac.",
      "stack": [
        "Claude Code",
        "Node.js",
        "SQLite",
        "FTS5",
        "Astro",
        "Markdown",
        "Obsidian"
      ],
      "metrics": {
        "messages_indexed_locally": "738K",
        "text_hidden_in_a_binary_blob": "88%",
        "notes_filed_without_approval": "0",
        "leaks_a_careful_scrub_missed": "3"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/second-brain"
    },
    {
      "id": "receipt-splitter",
      "title": "Split the check from a photo",
      "status": "wip",
      "year": 2026,
      "category": "tool",
      "role": "solo · side project",
      "summary": "Photograph a receipt, tap who had what, get the split. Runs on your phone with no server, and refuses to show a split that doesn't add up.",
      "summary_plain": "Photograph the dinner receipt, say who ate what, and it tells everyone what they owe. It checks its own answer against the receipt's printed total and won't show a split that doesn't match.",
      "stack": [
        "TypeScript",
        "Preact",
        "Tesseract.js",
        "Vite"
      ],
      "metrics": {
        "network_calls_after_load": "0",
        "wrong_splits_on_real_receipts": "0",
        "money_arithmetic": "integer cents"
      },
      "links": {
        "source": "https://github.com/Dylansg318/SplitApp",
        "play": "https://portfolio.dylansg0318.workers.dev/play/receipt-splitter"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/receipt-splitter"
    },
    {
      "id": "erp-test-automation",
      "title": "Testing an ERP by hand, then automating a cloud app",
      "status": "archived",
      "year": 2024,
      "category": "work",
      "role": "contributor · team of 10",
      "summary": "Two sprints on the CYDEO SDET program — fourteen user stories tested by hand against an ERP, then a Cucumber and Selenium suite against a cloud app.",
      "summary_plain": "Ten of us taught robots to re-test a business app every night, after testing it by hand first, which is how we found the bugs the robots would've missed.",
      "stack": [
        "Java",
        "Selenium",
        "Cucumber",
        "Gherkin",
        "REST Assured",
        "JUnit",
        "Maven",
        "Jenkins",
        "Jira"
      ],
      "links": {
        "source": "https://github.com/drwekilowa/B34_G11_Sprint_2CloudAuto"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/erp-test-automation"
    },
    {
      "id": "galaxy-defense",
      "title": "Galaxy Defense",
      "status": "archived",
      "year": 2020,
      "category": "game",
      "role": "solo",
      "summary": "A space shooter built in block code in high school. 790 lines, an economy, and a boss fight, with no arrays or classes available.",
      "summary_plain": "A game I built in high school using drag-and-drop coding blocks. It has a shop, upgrades, a boss, and a teleport ability, all made without the normal tools programmers use to keep code organised.",
      "stack": [
        "JavaScript",
        "Code.org Game Lab",
        "Blockly",
        "Canvas"
      ],
      "metrics": {
        "lines_of_generated_js": "790",
        "sprites_placed_by_hand": "17",
        "arrays_available": "0"
      },
      "links": {
        "play": "https://portfolio.dylansg0318.workers.dev/play/galaxy-defense"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/galaxy-defense"
    },
    {
      "id": "shotcall",
      "title": "Shotcall",
      "status": "live",
      "year": 2026,
      "category": "game",
      "role": "solo",
      "summary": "A daily puzzle. A ball bounces three times and drops into a pocket; you guess which one. Every miss shows you one more bounce.",
      "summary_plain": "Like Wordle, but with a bouncing ball. One puzzle a day: work out which pocket it ends up in. Guess wrong and it shows you one more bounce.",
      "stack": [
        "TypeScript",
        "Astro",
        "SVG",
        "Node"
      ],
      "metrics": {
        "board_shapes_searched": "170,356",
        "boards_that_survive": "1,037",
        "ball_positions_verified": "1.55M"
      },
      "links": {
        "play": "https://portfolio.dylansg0318.workers.dev/play/shotcall"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/shotcall"
    },
    {
      "id": "portfolio-site",
      "title": "This Portfolio",
      "status": "live",
      "year": 2026,
      "category": "tool",
      "role": "solo",
      "summary": "A content site that can also run games, built so the writing stays easy and the demos stay cheap.",
      "summary_plain": "This website. It has two voices, plain English and engineer, and a whole second mode where the portfolio becomes a help desk. Also it can run games.",
      "stack": [
        "Astro",
        "TypeScript",
        "Tailwind",
        "Cloudflare Workers",
        "MDX"
      ],
      "metrics": {
        "js_on_a_write_up": "0 KB",
        "hosting": "$0/mo",
        "demo_lanes": "2"
      },
      "links": {
        "source": "https://github.com/Dylansg318/Portfolio"
      },
      "page": "https://portfolio.dylansg0318.workers.dev/projects/portfolio-site"
    }
  ],
  "page": "https://portfolio.dylansg0318.workers.dev/projects"
}

Live: this is the answer from this site’s API, not a mock. Send re-runs the request with your parameters; if the answer names a page, it opens.

Inside the ERP

Six parts of the ERP with write-ups of their own. They are not separate projects — they are the pieces that made the whole thing work.

  • Repricing every minute without a race to the bottom

    Prices used to be a spreadsheet someone updated every morning. Now a robot checks every product once a minute, and knows better than to start a price war.Replaced a morning pricing spreadsheet with an engine that reprices every minute, with cooldowns, floors, and a rule to never chase the lowest price.

  • Six channels, one product master

    Six websites, each with its own version of the truth about our 32,000 products. One catalog, owned by people, that none of them is allowed to overwrite.Order intake and listing sync for six channels, with the identity rules that keep 49,000 marketplace listings from ever overwriting the product catalog.

  • Counting what sells, not what exists

    A nightly job decides which products are worth counting and reordering. It had been calling nearly everything important, which is the same as calling nothing important.A nightly classifier ranked all 27,215 products and made 1,979 of them class A. Ranking only what sells turned a fake Pareto into a real one.

  • Printing labels when the printer can lie about it

    Every box needs a label and a slip, printed on machines in a warehouse nobody logs into. This is what prints them, checks they came out, and repairs itself when an update goes bad.A thermal-label pipeline and a self-updating Windows print fleet — predicted widths, verified feeds, and an update that rolls itself back.

  • Keeping the books and the app in agreement

    The sales system and the accounting books have to agree to the penny. This is the connection that keeps them agreeing, and the logbook that ended the false alarms.A two-way QuickBooks Desktop integration over the Web Connector, plus a claims ledger so a finance discrepancy is refuted once, not rediscovered monthly.

  • The toolbox, extracted

    The system itself must stay private, but the useful parts don't have to. Nine pieces pulled out and scrubbed clean — real warehouse code, public and readable.Nine self-contained pieces of the ERP, lifted out and sanitized — barcode parsing, thermal-print layout, a self-updating device agent, invoice parsers.

GET/api/work/{id}

Parameters

Request

curl "https://portfolio.dylansg0318.workers.dev/api/work/internal-erp?fields=subsystems"
source: src/content/projects/{id}

Response200 OK · 2.3 KB · Open /projects/internal-erp

{
  "subsystems": [
    {
      "id": "internal-erp/repricing",
      "title": "Repricing every minute without a race to the bottom",
      "summary": "Replaced a morning pricing spreadsheet with an engine that reprices every minute, with cooldowns, floors, and a rule to never chase the lowest price.",
      "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp/repricing"
    },
    {
      "id": "internal-erp/channel-sync",
      "title": "Six channels, one product master",
      "summary": "Order intake and listing sync for six channels, with the identity rules that keep 49,000 marketplace listings from ever overwriting the product catalog.",
      "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp/channel-sync"
    },
    {
      "id": "internal-erp/inventory",
      "title": "Counting what sells, not what exists",
      "summary": "A nightly classifier ranked all 27,215 products and made 1,979 of them class A. Ranking only what sells turned a fake Pareto into a real one.",
      "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp/inventory"
    },
    {
      "id": "internal-erp/printing",
      "title": "Printing labels when the printer can lie about it",
      "summary": "A thermal-label pipeline and a self-updating Windows print fleet — predicted widths, verified feeds, and an update that rolls itself back.",
      "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp/printing"
    },
    {
      "id": "internal-erp/quickbooks",
      "title": "Keeping the books and the app in agreement",
      "summary": "A two-way QuickBooks Desktop integration over the Web Connector, plus a claims ledger so a finance discrepancy is refuted once, not rediscovered monthly.",
      "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp/quickbooks"
    },
    {
      "id": "internal-erp/toolbox",
      "title": "The toolbox, extracted",
      "summary": "Nine self-contained pieces of the ERP, lifted out and sanitized — barcode parsing, thermal-print layout, a self-updating device agent, invoice parsers.",
      "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp/toolbox"
    }
  ],
  "page": "https://portfolio.dylansg0318.workers.dev/projects/internal-erp"
}

Live: this is the answer from this site’s API, not a mock. Send re-runs the request with your parameters; if the answer names a page, it opens.