I’m excited to share the first release of Neon (v0.1.0), a personal project that grew out of my desire to simplify how I build REST APIs in Go. I’ve always loved Go’s standard library, and with the recent enhancements to http.ServeMux in Go 1.22, I saw an opportunity to create a lightweight, zero-dependency framework that felt both powerful and distinctly “Go.”

The “Why” Behind Neon

I built Neon to solve a problem I kept running into: writing the same boilerplate for every new API. I wanted a way to define routes, middleware, and API versions declaratively, without pulling in heavy external dependencies. My goal was to create something that leverages the power of the standard library while reducing repetitive code.

Sticking with the Standard Library

A core principle for Neon was to have zero external dependencies. By building on top of Go 1.22’s improved http.ServeMux, I could keep the framework lean and secure. This means smaller binaries, faster builds, and no supply chain risks—just pure Go.

It also means that Neon plays nicely with the rest of the Go ecosystem. For example, extracting path parameters is as simple as calling r.PathValue("id").

type UserService struct {
    neon.Module `base:"/users" v:"1"`
    getUser     neon.Get `url:"/{id}"`
    getUserPosts neon.Get `url:"/{id}/posts/{postId}"`
}

func (s UserService) GetUser(w http.ResponseWriter, r *http.Request) {
    userID := r.PathValue("id") // Standard Go 1.22+ feature
    w.Write([]byte(fmt.Sprintf("User: %s", userID)))
}

What I’ve Built So Far

Here are some of the key features I’ve implemented in this first version:

1. Declarative API Structure with Struct Tags

This is my favorite part. You can define your entire API structure—routes, methods, middleware, and versions—using simple struct tags. It keeps the configuration right next to the code that uses it.

type BlogService struct {
    neon.Module `base:"/blog" v:"2" middleware:"auth,logging"`
    
    // GET /blog/v2/posts
    listPosts   neon.Get    `url:"/posts"`
    
    // POST /blog/v2/posts
    createPost  neon.Post   `url:"/posts" middleware:"admin"`
    
    // GET /blog/v2/posts/{id}
    getPost     neon.Get    `url:"/posts/{id}"`
    
    // PUT /blog/v2/posts/{id}
    updatePost  neon.Put    `url:"/posts/{id}" middleware:"owner"`
    
    // DELETE /blog/v2/posts/{id}
    deletePost  neon.Delete `url:"/posts/{id}" middleware:"admin"`
}

2. A Flexible Middleware System

I wanted middleware to be flexible, so I designed a three-level system:

  • Global: Applied to every request.
  • Service-level: Applied to all endpoints within a service.
  • Endpoint-specific: Applied only to a single handler.
// Global middleware
app := neon.New()
app.Use(loggingMiddleware, corsMiddleware)

// Service-level middleware
type APIService struct {
    neon.Module `base:"/api" v:"1" middleware:"auth,rateLimit"`
    // All endpoints here will use auth and rateLimit middleware
}

// Endpoint-specific middleware
type AdminService struct {
    neon.Module `base:"/admin" v:"1"`
    dashboard   neon.Get `url:"/dashboard" middleware:"admin,audit"`
    // The dashboard gets extra admin and audit middleware
}

3. Clean and Powerful Routing

Because it’s built on the new http.ServeMux, Neon gets a lot of powerful routing features for free, like clean path parameter extraction, proper handling of HTTP methods, and support for API versioning.

This is just the beginning, but I’m really happy with how it’s turned out. It’s been a great learning experience and has already made my personal projects much more fun to build.

If you’re interested in checking it out, you can find the source code and more examples on GitHub. I’d love to hear any feedback or ideas you might have!

4. Good Developer Experience

  • 100% test coverage - I’m pretty thorough with testing
  • Clear documentation - Tried to make it easy to understand
  • Integration tests - Real-world usage scenarios
  • Simple configuration - Sensible defaults

Performance & Design

I designed Neon with performance and simplicity in mind:

  • Minimal overhead - Keep request handling fast
  • Memory conscious - Avoid unnecessary allocations
  • Thread-safe - Safe for concurrent use
  • Well-tested - Comprehensive test suite

Contributing

This is an open-source project and I’d love contributions! Here’s how you can help:

If You Want to Use It

  • Try it out in a side project
  • Report bugs if you find any
  • Share feedback - what works, what doesn’t
  • Star the repo if you like it

If You Want to Contribute Code

  • Check the issues - I’ll add some “good first issue” labels soon
  • Improve docs - The README could definitely use more detail
  • Add examples - Would love to see interesting use cases
  • Write tests - More coverage is always good

I’m still working on detailed contributing guidelines, but feel free to open an issue or PR if you’re interested!

Resources

Quick Start

go get -u github.com/sri-shubham/[email protected]

Documentation

More examples and detailed documentation coming soon!

Thanks

Thanks to the Go team for the great improvements in Go 1.22 that made this possible, and to anyone who tries out Neon and provides feedback!

Try It Out

Want to give Neon a quick try? Here’s a simple example:

# Create a new project
mkdir my-api && cd my-api
go mod init my-api

# Install Neon
go get -u github.com/sri-shubham/[email protected]

# Create main.go
cat << 'EOF' > main.go
package main

import (
    "fmt"
    "net/http"
    "github.com/sri-shubham/neon"
)

type UserService struct {
    neon.Module `base:"/users" v:"1"`
    getUser     neon.Get `url:"/{id}"`
}

func (s UserService) GetUser(w http.ResponseWriter, r *http.Request) {
    userID := r.PathValue("id")
    w.Write([]byte(fmt.Sprintf("Hello, %s!", userID)))
}

func main() {
    app := neon.New()
    app.AddService(&UserService{})
    
    if err := app.Run(); err != nil {
        panic(err)
    }
}
EOF

# Run your API
go run main.go

# Test it (in another terminal)
curl http://localhost:8080/users/alice
# Returns: Hello, alice!

That’s it! You’ve got a working API with path parameters and proper routing.

Feedback Welcome

This is a personal project that I’m sharing because I think others might find it useful. If you try it out, I’d love to hear your thoughts - good or bad! You can:

  • Open issues on GitHub for bugs or feature requests
  • Start discussions for questions or ideas
  • Send me a message if you build something cool with it

Thanks for reading, and happy coding! 🙂


If you like Neon, consider starring it on GitHub to help others discover it.