Announcing Vinland

Vinland landscape

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:

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

Source

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

Source

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

Source

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

Source

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

Source

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

Source

The charset middleware allows you to specify default charset parameters for Content-Type response headers.

extra

Source

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

Source

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

Source

The head middleware removes the response body from replies to HEAD requests.

http-methods

Source

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

Source

The security-headers middleware adds security-related headers to each response.

user

Source

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:

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.