DEV Community

Cover image for An artisan-style boilerplate generator for the VirtusLab Scala stack
AranaDeDoros
AranaDeDoros

Posted on

An artisan-style boilerplate generator for the VirtusLab Scala stack

The problem: Scala has a steep first mile

If you come from Laravel, Rails or Django, you're used to a command that gives you a model, a route and something that runs in a few seconds. In Scala, getting to that point means choosing an HTTP library, a JSON library, an endpoint description format, wiring everything together and keeping it compiling.

The VirtusLab stack (Tapir, Sttp, Jsoniter) is a great, modern way to write Scala. But for a beginner, or for anyone who just wants to experiment, the setup can be what makes them quit before writing a single line of business logic.

That's why I started Sprout.

What is Sprout?

Sprout is an opinionated boilerplate generator for the VirtusLab Scala stack. It's inspired by Laravel's artisan: you describe what you want, and it generates the repetitive parts for you.

It's aimed at greenfield projects that don't have models or routing yet. It's experimental, and I'm building it in the open.

The stack:

  • Scala 3.9
  • Tapir for endpoint definitions
  • Sttp as the HTTP client
  • Jsoniter for JSON serialization
  • SnakeYAML for loading and parsing specs

The idea: describe it in YAML, get the code

You put your schemas in src/main/resources/schemas/. Each file describes a model and, optionally, its endpoints:

name: User
modelDef:
  - name: id
    valueType: Long
  - name: name
    valueType: String
endpoints:
  - path: users
    method: post
    request: User
    response: User
Enter fullscreen mode Exit fullscreen mode

You can leave out either modelDef or endpoints. Sprout reads what's there and decides what to generate based on the flags you pass.

Two commands

new

Creates a model or a router.

sprout new:model User --with-router
Enter fullscreen mode Exit fullscreen mode

This generates a case class under sprout/models and, because of --with-router (or -wr), a simple router too.

sprout new:router User --api --model
Enter fullscreen mode Exit fullscreen mode

With --api you get RESTful endpoints, and --model tells Sprout to look for an existing User model under sprout/models to base them on.

Everything is generated into a sprout package, so it doesn't collide with your existing code.

forage

sprout forage
Enter fullscreen mode Exit fullscreen mode

Once you have generated files, forage walks through your schemas folder, produces the declared definitions and bootstraps all routes into a Server.scala, wiring routes and endpoints together.

Why I think this matters for beginners

  • Seeing a working shape early. Reading a generated Tapir endpoint next to the YAML that produced it is a decent way to learn how the pieces fit.
  • Less decision fatigue. The stack is opinionated on purpose. You don't need to compare five libraries before writing your first route.
  • A path to modern Scala. Instead of starting from older tutorials, you begin with Scala 3 and a current, typed stack.
  • A familiar workflow. If you've used artisan, rails generate or similar tools, the commands will feel natural.

Limitations (being honest)

  • Sprout overwrites by default. I recommend keeping generated files in sprout/ separate from your own models and endpoint logic. That also keeps wiring and business logic apart, which is a good habit anyway.
  • It's a work in progress, so expect breaking changes.

What's next

I'd like to keep making it friendlier: better error messages and safer generation, and support for more of the ecosystem.

If you're new to Scala, or you're curious about the VirtusLab stack, I'd love for you to try it and tell me where it gets confusing. Issues, ideas and PRs are welcome.

👉 Repo: https://github.com/AranaDeDoros/Sprout

Peace out.

Top comments (0)