This is a submission for the GitHub Finish-Up-A-Thon Challenge
How 21 commits, 230 files, and 40k lines transformed a forgotten DSL into production-ready software - with GitHub Copilot as my pair programmer.
What I Built
JSSON is a human-friendly configuration language that transpiles to JSON, YAML, TOML, and TypeScript. Think of it as HJSON on steroids — featuring variables, templates, ranges, maps, conditionals, reusable presets, built-in validators ([@]uuid, [@]email, [@]datetime - ignore the brackets), and full schema support.
// A JSSON source file
@preset "server-defaults" {
port = 8080
host = "localhost"
timeout = 30
}
users [
template { id, role }
map (u) = {
id = u.id
role = u.role
active = true
}
1..100, "admin"
101..1000, "user"
]
A single file like the one above can generate 1,000 user objects across four different formats instantly.
The project was my own creation, but I had completely abandoned it for 5 months. It was stuck in that "it works, but don't look at the source" phase: monolithic 800-line files, interface{} everywhere, zero integration tests, no linters, and manual build scripts.
So I did what any sane developer would do: I rolled up my sleeves, called GitHub Copilot to my side, and spent two intense days refactoring everything.
Demo
Here is JSSON in action. You can run these commands yourself using the examples provided in the repository.
Transpiling to JSON
# Build the binary
make build
# Transpile a basic example
./bin/jsson -i examples/basics/01-hello-world.jsson
Multiple Output Formats
# YAML, TOML, and TypeScript support
./bin/jsson -i examples/basics/03-objects.jsson -f yaml
./bin/jsson -i examples/basics/03-objects.jsson -f toml
./bin/jsson -i examples/basics/03-objects.jsson -f typescript
Advanced Features: Ranges & Formatting
# Expand ranges
./bin/jsson -i examples/basics/05-ranges.jsson
# Format your JSSON files (The new 'jsson fmt' command!)
./bin/jsson fmt examples/real-world/apiconfig.jsson
The Comeback Story: From Chaos to Clarity
When I picked up the project again, it was a mess of monolithic files:
| File | Lines |
|---|---|
parser.go |
837 |
evaluator.go |
355 |
main.go |
631 |
validate.go |
384 |
lexer.go |
392 |
The entire AST was built on interface{}, meaning the compiler couldn't help me. If a node was the wrong type, I'd only find out through a runtime panic.
The Refactoring Journey
1. The Great Linting War (2,062 Issues!)
This was where GitHub Copilot truly shone. The project had zero linters. When I finally configured golangci-lint, it flagged 2,062 issues.
With Copilot's help, we used golangci-lint run --fix intelligently to resolve 1,527 issues automatically (wsl, nlreturn, wrapcheck, etc.). I then manually fixed the remaining 535 issues with Copilot suggesting the corrections. Today, the project has 0 lint issues.
2. Typed AST - Goodbye interface{}
I replaced the fragile if-else type assertion chains with a proper Node interface and type switches. This eliminated 100% of runtime type assertions in the hot path. Even the LSP (Language Server) became stable and warning-free.
3. Surgical Slicing
I broke down those massive files into cohesive modules. The 837-line parser became 4 focused files. The evaluator became 5 specialized modules. Now, no core file exceeds 200 lines.
4. E2E Testing with Golden Files
I implemented 136 "golden files" as a safety net. Every time I refactored a core component, I could run go test -tags=e2e -update to verify that the output remained identical. This gave me the confidence to perform aggressive architectural changes without fear.
The Numbers (Before vs. After)
| Metric | Before | After |
|---|---|---|
| Test Suites | Unit only | Unit + 136 E2E Goldens + Stdin/Fmt tests |
| Release Pipeline | Manual scripts | Makefile + GoReleaser (Automated) |
| Action Pinning | Moving tags (@v4) |
Commit SHAs (Secure) |
| AST Typing | interface{} |
Concrete Node types |
| Max File Size | 837 lines | < 200 lines |
| Formatter | None |
jsson fmt with -w and -check
|
21 commits, 230 files modified, ~40k lines of changes, and zero regressions.
My Experience with GitHub Copilot
Using AI for this level of refactoring changed my perspective on "Pair Programming." I expected hallucinations given the complexity of a custom DSL, but GitHub Copilot proved to be a reliable partner.
It didn't "know" my architecture, but it understood my intent. I would provide the context — a file diff or a goal like "refactor this using a type switch" - and it would handle the mechanical parts: splitting files, updating imports, and renaming symbols across the workspace.
What would have taken weeks manually took only two days. This allowed me to focus on high-level design decisions while Copilot handled the "grunt work" of moving code around.
The result is a project I am finally proud to share. JSSON v0.1 is now stable, maintainable, and ready for the community.
- Repository: github.com/jsson-lang/jsson
- The Big Refactor PR: PR #4




Top comments (0)