This is an extension to caveman2-widgets. It supplies widgets which are using Bootstrap. Before you start using it you may have a look at the basic usage documentation to understand how to use those (extra) widgets.


You can load it through Quicklisp or you can use the git repository. To use the git repository clone it into "~/quicklisp/local-projects" or (if you are using Roswell) "~/.roswell/local-projects".

To QUICKLOAD it, use:

(ql:quickload :caveman2-widgets-bootstrap)


You are very welcomed to contribute to this project! You can contribute by:
  • Using it and spreading the word!
  • Finding flaws and submitting Issues.
  • Finding flaws and removing them (as Pull-requests).
  • Adding new features (as Pull-requests). Before shooting in the dark create either an Issues or mail me. Maybe your feature is on my agenda too.
  • Showing your appreciation through a donation (please mail me for my data).

If you add new features, please document them. Otherwise other developers will have a hard time using this framework.


A new header widget

A new header widget is added which uses specific CDN links for getting Bootstrap. Please notice, that the global variables, where you can specify the locations, are not simple string variables! They are <FILE> objects.
Must be a <JS-FILE> object.
Must be a <CSS-FILE> object.

Navigation widget

The navigation widget is fully redesigned for the use with Bootstrap. The <BOOTSTRAP-MENU-NAVIGATION-WIDGET> has some special slots:
A HTML code which will be displayed in the upper left corner.
A non-nil value will fix the navbar on the upper edge.

You can use it fairly easy by just using <BOOTSTRAP-MENU-NAVIGATION-WIDGET> as KIND for the DEFNAV macro:

(defvar *first-widget*
  (make-widget :global '<string-widget>
               :text "<h1>Hello world from first</h1>"))

(defvar *second-widget*
  (make-widget :global '<string-widget>
               :text "<h1>Hello world from second</h1>"))

(defclass <proxy-widget> (<widget>)
  (:documentation "This class enables session based widgets for a

(defmethod render-widget ((this <proxy-widget>))
  (set-widget-for-session :string-widget
                          (make-widget :session '<string-widget>
                                       :text "hello world"))
  (render-widget (get-widget-for-session :string-widget)))

(defnav "/"
    ((make-instance '<bootstrap-header-widget>
                    :title "Navigation test")
      (list "First widget" "first" *first-widget*)
      (list "Second widget" "second" *second-widget*)
      (list "Third widget" "third" (make-widget :global
     :kind '<bootstrap-menu-navigation-widget>))

If you need extra header objects, you can create them via the RENDER-WIDGET-HEADER method. This means you only have to overwrite it for your own navigation class.

(defvar *first-widget*
  (make-widget :global '<string-widget>
               :text "<h1>Hello world from first</h1>"))

(defvar *second-widget*
  (make-widget :global '<string-widget>
               :text "<h1>Hello world from second</h1>"))

(defclass <my-bootstrap-nav> (<bootstrap-menu-navigation-widget>)
   :brand-text "<div id=\"brandlogo\"></div>"
    :navbar-fixed t))

(defmethod caveman2-widgets-bootstrap.navigation::render-widget-header
    ((this <my-bootstrap-nav>)
     (args (eql :right)))
  (with-output-to-string (ret-val)
    (format ret-val "<ul class=\"nav navbar-nav navbar-right\">
  <li><a href=\"~a\">GitHub</a></li>
            (let ((link (make-widget
                         :global '<link-widget>
                         :label "GitHub"
                         :callback #'(lambda ()
                         :target-foreign-p t)))
              (uri-path link)))))

(defnav "/"
    ((make-instance '<bootstrap-header-widget>
                    :title "Navigation test")
      (list "First widget" "first" *first-widget*)
      (list "Second widget" "second" *second-widget*))
     :kind '<my-bootstrap-nav>))


  • Richard Paul B?ck (


Copyright (c) 2016 Richard Paul B?ck (


Licensed under the LLGPL License.

Richard Paul B?ck