Quick Start
Full App
Move from the one-file app into the conventional GoLazy application layout.
Start from the generated layout
lazy new creates a conventional app:
app/
controllers/
public/
services/
views/
cmd/app/
init/
test/
The split is intentionally small. cmd/app starts the process, init wires the
app together, and app holds the behavior that serves requests.
Keep main thin
The executable should only start the application:
func main() {
if err := appinit.App().ListenAndServe(); err != nil {
log.Fatal(err)
}
}
That keeps tests able to construct the full handler without opening a network listener.
Wire the app once
init/app.go composes the app:
func App() *lazyapp.App {
return lazyapp.New(lazyapp.Config{
Name: "sample_app",
Drawer: Draw,
Public: app.Public,
Views: app.Views,
Context: Context,
})
}
The app owns dependencies, routes, embedded views, and public files. The framework owns dispatch, rendering, asset registration, and route binding.
Put routes in one place
init/routes.go draws the route table:
func Draw(router *lazyroutes.Scope) {
router.Get("/", home.New, (*home.HomeController).Index)
router.Resources(postcontroller.New)
}
Controllers stay under app/controllers, views stay under app/views, and
services stay under app/services.
Keep public outputs embeddable
Generated assets are committed under app/public:
app/public/styles.css
app/public/assets/importmap.json
app/public/assets/lazyshaft/
Run the asset commands before tests and builds when those inputs change:
lazy tailwind
lazy js
go test ./...
Continue with Application Structure for the full directory map.