A lightweight web application framework for Common Lisp

"ningle" is a lightweight web application framework for Common Lisp.


(defvar *app* (make-instance 'ningle:<app>))

(setf (ningle:route *app* "/")
      "Welcome to ningle!")

(setf (ningle:route *app* "/login" :method :POST)
      #'(lambda (params)
          (if (authorize (getf params :|username|)
                         (getf params :|password|))
            "Failed...Try again.")))

(clack:clackup *app*)

Now you can access to http://localhost:5000/ and then ningle should show you "Welcome to ningle!".


(ql:quickload :ningle)


ningle is a fork project of Caveman. ningle doesn't require you to generate a project skeleton.

As this is a thin framework, you need to have subtle knowledge about Clack. It is a server interface ningle bases on.

Getting started


ningle has the Sinatra-like routing system.

;; GET request (default)
(setf (ningle:route *app* "/" :method :GET) ...)

;; POST request
(setf (ningle:route *app* "/" :method :POST) ...)

;; PUT request
(setf (ningle:route *app* "/" :method :PUT) ...)

;; DELETE request
(setf (ningle:route *app* "/" :method :DELETE) ...)

;; OPTIONS request
(setf (ningle:route *app* "/" :method :OPTIONS) ...)

Route pattern may contain "keyword" to put the value into the argument.

(setf (ningle:route *app* "/hello/:name")
      #'(lambda (params)
          (format nil "Hello, ~A" (getf params :name))))

The above controller will be invoked when you access to "/hello/Eitarow" or "/hello/Tomohiro", and then (getf params :name) will be "Eitarow" and "Tomohiro".

Route patterns may also contain "wildcard" parameters. They are accessible by (getf params :splat).

(setf (ningle:route *app* "/say/*/to/*")
      #'(lambda (params)
          ; matches /say/hello/to/world
          (getf params :splat) ;=> ("hello" "world")

(setf (ningle:route *app* "/download/*.*")
      #'(lambda (params)
          ; matches /download/path/to/file.xml
          (getf params :splat) ;=> ("path/to/file" "xml")

Request & Response

ningle provides two special variables named *request* and *response*. They will be bound to an instance Clack.Request and Clack.Response for each request.

For example, by using them, you can change the response status code, Content-Type or something like that in each controllers.


ningle provides an useful function named context. It is an accessor to an internal hash table.

(setf (context :database)
      (dbi:connect :mysql
                   :database-name "test-db"
                   :username "nobody"
                   :password "nobody"))

(context :database)

Using Session

ningle doesn't provide Session system in the core, but recommends to use Clack.Middleware.Session with Clack.Builder.

(import 'clack.builder:builder


Of course, you can use other Clack Middlewares with ningle.

See Also



Copyright (c) 2012 Eitarow Fukamachi (


Licensed under the LLGPL License.