Project Layout
A common mistake when starting a new service is either:
- Not thinking about structure at all
- Or over-engineering structure before understanding the problem
Plumego encourages a third approach:
Start with a small, explicit layout that can evolve naturally.
This document introduces a minimal but disciplined project structure for Plumego applications.
The Minimal Recommended Layout
After creating a minimal server, your project can start with the following structure:
plumego-demo/
βββ go.mod
βββ main.go
βββ internal/
βββ app/
βββ app.go
This is enough to support:
- A clear entry point
- Application wiring
- Future growth without refactoring
Why This Layout Works
This layout intentionally separates:
- Process entry (
main.go) - Application construction (
internal/app) - Future domain and infrastructure code
It avoids:
- Premature layering
- Overly generic folder names
- Framework-specific leakage into business code
main.go: The Process Boundary
Your main.go should remain small.
Its responsibilities are limited to:
- Bootstrapping configuration
- Creating the application
- Starting the server
- Handling process-level concerns
Example:
package main
import "example.com/plumego-demo/internal/app"
func main() {
app.Run()
}
The goal is for main.go to remain boring.
internal/app: Application Wiring
The internal/app package is responsible for:
- Creating the Plumego application
- Registering routes
- Attaching middleware
- Returning a runnable server
Example internal/app/app.go:
package app
import (
"net/http"
"github.com/spcent/plumego"
)
func Run() {
app := plumego.New()
app.GET("/", func(ctx *plumego.Context) {
ctx.String(http.StatusOK, "Hello, Plumego")
})
if err := app.Run(":8080"); err != nil {
panic(err)
}
}
This keeps Plumego usage contained and visible.
Why internal/ Matters
Using Goβs internal/ directory:
- Prevents accidental imports from other modules
- Clearly signals application-private code
- Enforces architectural boundaries at the compiler level
This aligns well with Plumegoβs emphasis on explicit boundaries.
What Not to Add Yet
At this stage, avoid introducing:
pkg/directoriesservice/,controller/,handler/splits- Complex configuration systems
- Dependency injection frameworks
These structures make sense only after real complexity appears.
Growing the Layout Gradually
As your application grows, the structure can evolve naturally.
A common next step:
internal/
βββ app/
βββ http/
β βββ handler/
β βββ middleware/
βββ domain/
But do not start here unless you need to.
Plumego does not require a fixed layout β
it encourages layouts that reflect real boundaries.
Layout Principles to Keep in Mind
Regardless of structure, Plumego encourages:
- Framework code at the edges
- Domain logic isolated from HTTP
- Explicit wiring over auto-discovery
- Fewer, clearer directories over many vague ones
These principles matter more than any specific tree.
Common Anti-Patterns
Avoid the following early on:
- Copying a βstandard layoutβ without understanding it
- Mirroring framework internals in your project
- Creating directories for concepts you do not yet have
- Mixing domain logic into handlers
Structure should follow understanding, not templates.
Summary
A good Plumego project layout is:
- Small at the beginning
- Explicit in responsibility
- Easy to evolve
- Resistant to accidental complexity
Start simple.
Let structure emerge from real needs.
Next
Now that you have:
- A running server
- A minimal project layout
The next step is to understand how requests move through the system.
Continue with:
β Concepts / Request Lifecycle
Or, if you prefer to complete the Getting Started flow:
β Getting Started / First Request