Announcing Vinland

Website: https://www.vinland.dev/
Source: https://github.com/lisplizards/vinland
I’m releasing a new Common Lisp web framework today, Vinland, that builds on Eitaro Fukamachi’s Clack/Lack stack and is available under the terms of the Apache-2.0 license.
Motivation
Vinland is an unfinished, ongoing attempt at pursuing my own vision of an ideal web framework, based on the following qualities:
- written in Common Lisp, the O.G. of multiparadigm languages
- composed of loosely coupled components
- not too opinionated: not tied to “conventions” or an ORM
- HTTP friendly: better-than-average conformance to the HTTP spec
- potential for mass appeal: familiar to developers coming from other languages
Demo app
The demo application is a To-Do list task manager that shows how to use Vinland in combination with Hotwire Turbo and Stimulus to provide dynamic, SPA-like behavior using only a bare minimum of custom JavaScript. Vinland doesn’t yet actually provide any direct integration with Hotwire, and it is entirely possible to employ similar patterns with a different Common Lisp web framework, but I think that the combination is compelling, straightforward, and fun to work with.
Though the application is not complex or large, the use of ASDF system definitions, package namespaces, and S-expressions to render HTML, rather than “require” statements, Ruby modules, and a plethora of ERB templates, goes a long way, in my opinion, towards making the application feel more organized than the Rails with Hotwire apps that I have previously worked on.
Components
Vinland depends on various libraries that are also being released as open-source software. The lisplizards GitHub organization is the official home of all of these projects.
Raven
Raven is a prefix tree based router for Clack applications, extensible through the concept of route metadata and sub-protocols. If your own vision of an ideal web framework differs substantially from the direction of Vinland, you might still consider building out your own framework with Raven.
Flash
Flash provides Rails-like flash message functionality, i.e., a mechanism for storing data temporarily for either the current or a future request. This is mainly used for displaying notification or error messages, but it’s possible to store other kinds of information as well, such as form data.
Params
Params provides functions to access values in association lists. Parsed Lack request bodies and query parameters are stored in the Lack request struct as association lists, and this library aims to make them simple to work with.
Resource
Resource provides generic functions for deriving paths, URLs, or DOM IDs from your application’s domain objects. In contrast to Ruby on Rails, where this functionality is provided out-of-the-box for ActiveRecord objects, you are required to define specialization functions for each relevant class. This approach is more flexible and requires only a minimal level of effort. Like in Rails, the DOM ID functionality is particularly useful for Hotwire integration.
Lack-request
Lack-request provides an alternative constructor function for LACK/REQUEST:REQUEST
structs and extracts parsing functionality to standard functions instead of parsing cookies, query parameters, and body parameters and modifying the application environment directly from the constructor. This is important for HTTP conformance, as the request body and query parameters should only be parsed after certain other conditions have been met.
Middlewares
charset
The charset middleware allows you to specify default charset parameters for Content-Type response headers.
extra
The extra middleware adds a hash-table to the Clack environment under key LACK.EXTRA
, which can be used by other middlewares to store arbitrary data. In Ruby, the Rack environment is a hash, and it’s common for Rack-based applications to store dozens of properties in the Rack environment. In Clack, however, the environment is a property list which is not an efficient datastructure for storing a large number of properties. This library provides a workaround to this inefficiency.
flash
The flash middleware stores flash data in the Lack session hash-table and is essential for using the flash library in Clack-based applications.
head
The head middleware removes the response body from replies to HEAD requests.
http-methods
The http-methods middleware allows you to specify which HTTP methods your application understands; in case a request is received that is not included, the middleware returns a 501 response.
security-headers
The security-headers middleware adds security-related headers to each response.
user
The user middleware binds dynamically scoped variable *CURRENT-USER*
; set the current user either from a lambda passed to the middleware configuration or from your route handlers.
Roadmap
Vinland is currently considered to be in BETA because the To Do app is the only application so far built with Vinland. The next phase for the project is to build a larger, more “production-ready” application backed by PostgreSQL as its database and Redis for session and cache storage, writing any additional middlewares or components as needed.
Future goals for the project include integrations for:
Background jobs
Mail
Asset compilation / JavaScript bundlers
Websocket channels with support for broadcasting Turbo Streams (i.e., an equivalent to Rails’ Action Cable)
Additional types of handlers, including a webmachine/Cowboy REST inspired handler
Templating (for those who prefer it)
Project skeleton
Additional middlewares potentially on the docket include: parameter filtering, Postmodern (PostgreSQL) connection pooling, Beanstalkd connection pooling, per-form CSRF tokens, and connection pooling for Redis-backed session and cache storage.
Show your support
If this software interests you, you can star the project on GitHub to show your support.