llm4s.g8: a developer experience boost for LLM4S SDK (issue #94) for Scala devs
π― Background
llm4s: Github repo
In the rapidly evolving landscape of software development, where artificial intelligence and language models are reshaping how we build applications, the LLM4S SDK stands out as a powerful toolkit for Scala developers eager to harness the potential of large language models. However, as with many sophisticated tools, the initial onboarding experience can often feel like navigating a labyrinth without a map. This was precisely the challenge highlighted in Issue #94 on the llm4s GitHub repo :
“Using LLM4S code generation requires understanding internal prompts and usage patterns that may not be intuitive for new users. The goal is to improve usability and ergonomics so that Scala developers can easily leverage the power of LLM4S.”
This candid observation resonated deeply with the community and the core development team. While the SDK itself was robust and feature-rich, the friction in getting started was a significant barrier to adoption. It was clear that to unlock the true potential of LLM4S, we needed to transform the onboarding process from a daunting hurdle into a smooth, enjoyable journey.
This blog post chronicles that transformation. Itβs a story of turning complexity into clarity, of converting friction into flow, and of crafting not just code, but a developer experience that empowers and inspires. At the heart of this story lies Giter8, a Scala-based templating tool that enables rapid project scaffolding. By leveraging Giter8, we set out to create a starter template-llm4s.g8-that would serve as a beacon for new users, guiding them effortlessly into the world of LLM4S.
Why does developer experience matter?
Before diving into the nuts and bolts, it’s worth reflecting on why developer experience (DX) is more than just a buzzword. A stellar DX can be the difference between a tool that’s loved and widely adopted, and one that languishes in obscurity. It’s about reducing cognitive load, eliminating guesswork, and enabling developers to focus on what truly matters: building innovative solutions.
For LLM4S, which sits at the intersection of AI and Scala development, this means providing clear, idiomatic examples, seamless integration with existing workflows, and a project structure that βjust worksβ out of the box. The llm4s.g8 template was conceived as a direct response to these needs-a carefully crafted starter kit that embodies best practices, modern tooling, and a touch of developer empathy.
π Building the llm4s.g8 template
Embarking on the creation of the llm4s.g8 template was no mere checkbox exercise. It was a journey marked by iterative refinement, thoughtful design decisions, and a relentless focus on real-world developer workflows. The process unfolded like a narrative of discovery, challenge, and eventual triumph.
The initial spark: Identifying core pain points
The first step was to understand the pain points that new users faced. Through community discussions, issue threads, and direct feedback, several recurring themes emerged:
- Opaque internal prompts: The SDKβs prompt engineering capabilities were powerful but required deep understanding of the underlying prompt structures.
- Unintuitive usage patterns: Without a clear example or starter project, users found it difficult to piece together how to invoke and integrate LLM4S features.
- Fragmented documentation: While comprehensive, the documentation lacked a cohesive βgetting startedβ flow that tied concepts together in a practical manner.
- IDE friction: The default project layout and dependencies sometimes clashed with common IDE expectations, leading to confusing errors or setup struggles.
Armed with these insights, the team set out to build a solution that would address these issues head-on.
Designing the template: More than just code generation
The llm4s.g8 template was envisioned as a multi-faceted toolkit:
- A clean, runnable Scala project: From the first line of code to the last test, everything should work seamlessly.
- Correct versions and compatibility: Scala 3, sbt, and JDK versions were carefully selected to maximize compatibility and future-proofing.
- Practical examples: Including a working
Main.scalaandPromptExecutor.scalathat demonstrate prompt execution using OpenAIβs API, complete with tracing and environment-based API key loading. - Testing and CI: Integration tests and GitHub Actions workflows to ensure reliability and quality.
- Documentation: A comprehensive README that walks users through setup, structure, and publishing.
- Cross-platform support: Ensuring the template works consistently on Windows, macOS, and Linux.
- Formatting and style: Integration with scalafmt and MUnit to encourage best practices and maintain code quality.
This was not just scaffolding; it was a developer experience manifesto.
Overcoming technical challenges
Creating a template that βjust worksβ involved navigating several technical hurdles:
- Template escaping issues: Giter8βs templating syntax can be tricky, especially when embedding code snippets that themselves contain template-like syntax. The team devised clever escaping strategies to ensure smooth generation.
- Java version alignment: Ensuring the Java version used in the template matched the CI environment was crucial to avoid unexpected runtime issues.
- CI reliability: Setting up GitHub Actions workflows that validate project generation, compilation, formatting, and testing required meticulous scripting and validation.
- Dependency management: Adding missing dependencies such as
munitfor testing, and ensuring all libraries aligned with the Scala 3 ecosystem.
Each challenge was met with a combination of technical rigor and collaborative problem-solving, embodying the spirit of open source development.
The result: A template that inspires confidence
After several iterations, testing cycles, and community feedback rounds, the llm4s.g8 template emerged as a polished, reliable, and user-friendly starting point. It encapsulates the essence of LLM4S while lowering the barrier to entry for newcomers.
β Core deliverables
Giter8 Template (llm4s.g8)
- Generates a clean, runnable Scala project that users can immediately build and run.
- Uses correct Scala 3, sbt, and JDK versions to ensure compatibility and performance.
- Includes a working
Main.scalaandPromptExecutor.scalathat demonstrate prompt execution via OpenAI, complete with tracing and environment-based API key loading (OPENAI_API_KEY). - Provides integration tests and CI via GitHub Actions, validating code generation, compilation, formatting, and testing.
- Contains a detailed README with usage instructions, project structure overview, and publishing guidelines.
- Supports cross-platform builds and enforces formatting consistency using scalafmt and MUnit test scaffolding.
Main application & prompt executor
The separation of concerns was a deliberate design choice to enhance clarity and maintainability. The Main.scala acts as the entry point, while PromptExecutor.scala encapsulates the logic for interacting with the OpenAI API and executing prompts.
| |
This modular approach not only clarifies responsibilities but also facilitates testing and future extensions.
π Directory structure
Every great journey needs a map. Hereβs how the llm4s.g8 template scaffolds your project, providing a clear, idiomatic foundation:
| |
This structure is more than just folders-it’s a launchpad for productivity, discoverability, and collaboration. Each piece is thoughtfully placed to minimize setup friction and maximize clarity.
π‘ Pre-commit hook setup
Why wait until CI to catch formatting or linting issues? With pre-commit hooks, you get instant feedback before code even leaves your machine. This not only saves time but also keeps your main branch sparkling clean.
The template recommends using pre-commit
to automate checks like scalafmt, whitespace, and more. Hereβs a sample .pre-commit-config.yaml:
| |
Benefits:
- π Prevents silly mistakes before they reach CI.
- π¦ Encourages a culture of code quality and consistency.
- π¦Ύ Automates the boring stuff so you can focus on building.
To enable, simply run:
| |
and enjoy seamless, automated code hygiene.
π§± build.sbt overview
At the heart of every Scala project lies the build.sbt-your buildβs spellbook. In the template, itβs crafted for clarity, flexibility, and Giter8 variable substitution:
| |
Highlights:
- Uses Giter8 variables for easy future upgrades and customization.
- Clearly separates test and main dependencies.
- Ready for extension-just add modules or plugins as your project grows.
βοΈ default.properties variables
The project/default.properties file is the templateβs secret sauce for variable management. It defines default values that Giter8 uses for substitution throughout the template:
| |
Usage:
When you run sbt new llm4s/llm4s.g8, Giter8 replaces variables in build.sbt, README.md, and elsewhere with these values.
For example:
| |
This makes upgrades and customizations a breeze-just bump a version in one place!
π§ͺ Test framework integration
Testing is not an afterthought-itβs baked in from the start. The template integrates MUnit for lightning-fast, expressive Scala testing:
build.sbt:
| |
Example test:
| |
Why MUnit?
- π Fast, zero-config, Scala 3-ready.
- π§ͺ Clean syntax and powerful assertions.
- π€ Easy integration with sbt and CI.
πͺ΅ Logging support
Every serious application needs robust logging. The template wires in logback-classic for powerful, production-grade logging, and scala-logging for a delightfully idiomatic Scala API.
build.sbt:
| |
Usage:
| |
Extensibility:
Want even richer, type-safe logging? Swap in LogStage
for next-level structured logging-your observability future is bright!
π€ GitHub Actions: CI/CD setup
No modern template is complete without CI/CD. The llm4s.g8 template ships with a ready-to-go GitHub Actions workflow that validates every project build, test, and format check:
.github/workflows/ci.yml
| |
Result:
Every push or PR is checked for compilation, formatting, and test success, giving you confidence and peace of mind-automatically.
π plugins.sbt: Plugin magic
SBT plugins unlock powerful capabilities. The templateβs project/plugins.sbt brings in the essentials:
| |
- sbt-scalafmt: Enforces code style and formatting.
- sbt-ci-release: Simplifies publishing to Maven Central and beyond.
Want more? Just add your favorite plugins-SBTβs ecosystem is your playground.
π¨ Formatting: scalafmt.conf
Code consistency is not just aesthetic-itβs a foundation for collaboration. The template includes a .scalafmt.conf with sensible defaults to keep your codebase tidy:
# scalafmt configuration
version = "3.9.8"
runner.dialect = scala213
maxColumn = 100
style = defaultWithAlign
rewrite.rules = [RedundantParens, RedundantBraces, SortImports, PreferCurlyFors]
spaces.inImportCurlyBraces = true
project.git = true
rewrite.trailingCommas.style = multiple
indentOperator.exemptScope = all
# Optional enhancements
align.preset = more
# Scalaβ3 specific (optional)
rewrite.scala3.convertToNewSyntax = true
rewrite.scala3.removeOptionalBraces = true
# Token rewrites
rewriteTokens {
"β" = "=>",
"β" = "<-",
"β" = "->";
}Why it matters:
With scalafmt, every contributor speaks the same code dialect. No more nitpicks-just clean, readable Scala everywhere.
π Reflections & value
Building the llm4s.g8 template was a journey that transcended mere coding. It was about empathy, community, and the art of crafting experiences that resonate with developers.
The Human factor: Empathy in developer experience
The team recognized that behind every line of code is a developer-sometimes a novice, sometimes a seasoned expert-seeking to understand, experiment, and create. By focusing on empathy, the template was designed to speak the developerβs language, anticipate their needs, and smooth out rough edges.
Value delivered
- π Faster adoption: The one-command starter project slashed onboarding time from around 20 minutes to under 5, a transformational improvement.
- π§ Cleaner learning curve: By providing idiomatic examples and clear structure, the template demystifies prompt engineering and SDK usage.
- π IDE integration-ready: The project layout and dependencies are optimized for popular IDEs, reducing setup friction.
- β CI-tested reliability: Automated validation builds trust and confidence in the generated projects.
- π Cross-platform consistency: Developers on any OS can expect the same seamless experience.
- π Documentation clarity: The README serves as a friendly guide, empowering users to explore and extend with ease.
Beyond the code: Community and collaboration
The creation of llm4s.g8 sparked vibrant discussions in the community, inspiring contributions, feedback, and shared learning. It became more than a template-it became a catalyst for collaboration and innovation.
π¦ Pull request summary of Issue #94
The pull request associated with Issue #94 represents a significant milestone in the LLM4S projectβs evolution. It encapsulates the collective effort to simplify onboarding and improve usability.
β Done
- Created
llm4s.g8: A Giter8-based starter template aligned with LLM4S architecture, featuring Scala 3, sbt, and idiomatic directory layout. - Main.scala + PromptExecutor: A working CLI example demonstrating OpenAI prompt execution with tracing support.
- CLI Support: Commands like
sbt run,sbt test, andscalafmtAllwork out of the box, with environment-based API key loading (OPENAI_API_KEY). - CI Integration: GitHub Actions workflows validate project generation, compilation, formatting, and testing.
- Integration Testing: Includes scripted and Scala-based tests with cleanup mechanisms to ensure reliability.
- README.md: Comprehensive usage instructions, directory structure overview, and publishing guide.
- Added IDE/editor-specific integration helpers, such as VSCode launch configurations.
- Developing optional template variants, including plugin-based or multi-module setups to cater to diverse use cases.
- Logger: Added logger / logging support
- preβcommit: pre-commit hook setup for automated code checks and formatting.
- Publishing the template to a Giter8 registry for easier discovery and usage.
β Why it matters
- Onboarding time reduced significantly, accelerating developer productivity.
- IDE-friendly scaffolding reduces cognitive load and setup errors.
- Templates encourage reuse, extension, and experimentation.
- Cross-platform and CI builds foster early trust and confidence.
β Design & Scope Questions
The journey continues with thoughtful questions to guide future directions:
- Location: Should
llm4s.g8reside undersdk/or be moved to a root-level/templates/directory for clearer structure and discoverability? - Vision Alignment: Does this approach fully capture LLM4Sβs ergonomic goals, or are there opportunities to pivot or expand?
- Template Scope: Should the project evolve into a family of templates (minimal, plugin-enabled, microservice-ready), or remain a canonical starting point?
- Target Use Cases: Is the focus on CLI prototyping, code generation experimentation, or learning Scala with LLMs-and how can the template best serve these?
π§ͺ PR Review & Feedback
The review process, enriched by Roryβs insights and Claude Code-assisted analysis, highlighted the strengths and areas for refinement.
β Strengths
- Addresses real onboarding friction with a practical solution.
- Solid Giter8 implementation with thoughtful template design.
- Comprehensive CI and testing coverage ensure reliability.
- Real-world prompt execution demo showcases SDK capabilities.
- GitHub Actions workflows validate project generation and build steps.
β οΈ Suggestions
- build.sbt: Adopt the
val llm4sVersion = "$llm4s_version$"syntax for Giter8 variable substitution to improve template flexibility. - Test dependencies: Add
munitto the build configuration to support testing. - Java version alignment: Ensure Java version consistency across CI and template output to prevent runtime issues.
The feedback was embraced as an opportunity to polish and perfect the template further, reinforcing the commitment to quality.
π§ͺ Whatβs next?
The journey of llm4s.g8 is far from over. Future milestones include:
- Publishing the template to the official Giter8 registry, making it discoverable and easy to use.
- Introducing editor launch configurations for VSCode, IntelliJ, and other popular IDEs to streamline debugging and development.
- Exploring multiple presets and variants to cater to diverse developer needs-from minimal prototypes to plugin-enabled or microservice-ready templates.
π CI Build Logs
π Want to try it out or contribute?
Dive in by cloning llm4s.g8, running:
| |
and start hacking away. Your feedback, contributions, and creativity are warmly welcomed as we continue to evolve this exciting project.
In Closing:
The creation of llm4s.g8 is a testament to the power of community-driven innovation and the importance of putting developer experience front and center. By transforming onboarding pain points into a delightful, streamlined process, we have opened the door for more Scala developers to explore, experiment, and build with LLM4S. This is just the beginning of a new chapter-one where the synergy of human creativity and machine intelligence can truly flourish.
