Spectra, day one
I bootstrapped Spectra on a Thursday morning. By midnight it was reading real Laravel routes. The first commit that mattered was not the one that mattered.
I bootstrapped Spectra at 9am on a Thursday. By midnight it was scanning real Laravel routes off a real project on my disk.
That was 2026-05-08. The first commit in the repo bootstrapped the Wails template. The second commit that day shipped the scanner. Nine days later there was a beta build with auto-updates and billing wired in. The story of how Spectra started is mostly the story of one rule I gave myself on day one.
The decision
I had spent the previous month complaining about Postman in private and shipping nothing about it. Complaining is free. So I stopped, opened a terminal, and ran wails init.
The stack was not a hype call. I picked Go because the product needs to shell out to PHP and parse its output without fighting a language runtime. I picked Wails because Electron carries 200MB of Chromium I do not want shipping to a Laravel developer’s MacBook. I picked React because the UI is going to be busy and I am not interested in rewriting form state management for fun. None of those choices are clever. They are the boring choices that survive contact with the second month.
The first commit was a template. That is normal. What was not normal was the rule attached to it.
Day one had to ship the scanner
The rule: if Spectra cannot read a real Laravel project on the day it was bootstrapped, it is vapor. Not vapor next week. Vapor now. The thing that distinguishes an API client that knows your framework from yet another HTTP request runner is the scanner. Everything else is paint. If I shipped the paint first I would never come back to the engine.
So the second commit on 2026-05-08 shipped a real Laravel route scanner, persisted to SQLite. It calls php artisan route:list --json against a project path the user picks, parses the output, and writes endpoints to a local database.
// internal/drivers/laravel/route_list.go
cmd := exec.CommandContext(ctx, phpPath, "artisan", "route:list", "--json")
cmd.Dir = projectPath
cmd.Env = enrichedEnv()
That is the whole idea. There is no clever inference. The framework already publishes its own routes. Spectra reads what is already there.
By the end of that Thursday the scanner had landed, API-only filtering had landed, and a universal HTTP request runner with a workspace base URL was wired in. One day, three commits that proved the loop: pick a Laravel project, see its routes, fire a request. The thing was alive.
It was ugly. The UI was a stub. There was no auth detection, no schema inference, no exporter, no nothing. But it was alive in the only way that mattered: it told the truth about a real codebase the moment you pointed it at one. Every feature after that was a feature on top of a working system. None of them were features on top of a promise.
The closer
The first commit that mattered was not the bootstrap. It was the one that proved the framework would talk back. If you are starting a product, find your version of route:list --json on day one. The rest is paint.