Hello world!

Let's create a first project now. We could do all this directly in the REPL, but that's not too useful because we want to save our code and build it as a deployable website, so we'll create a project using Quickproject. Worry not, we don't need to install it manually.

CL-USER> (ql:quickload "quickproject")
CL-USER> (quickproject:make-project "/tmp/syte.foobar" :depends-on '(sytes))
CL-USER> (ql:quickload "syte.foobar")

Quickproject creates two files in /tmp/syte.foobar. Open package.lisp for now and let's :use the Sytes package (so just add #:sytes and evaluate the form):

;; in file: /tmp/syte.foobar/package.lisp
(defpackage #:syte.foobar
  (:use #:cl #:sytes))

Now open /tmp/syte.foobar/syte.foobar.lisp and create a class for your Syte:

;; in file: /tmp/syte.foobar/syte.foobar.lisp
(defclass syte.foobar (syte)
   :names '("www.foobar.com" "foobar.com" "foobar.local")
   :root (merge-pathnames "root/"
                           (asdf:find-system :syte.foobar)))))

The above creates a Syte where the root template directory is in /tmp/syte.foobar/root/, using some ASDF wizardry to locate the directory of the “syte.foobar” system. I prefer this hack rather than using a hard-coded path, but you're not limited to it—by all means feel free to hard-code the path you pass to :root, or read it from a configuration file.

In :names we pass a list of domain names that this Syte will respond to. I'm using names ending in “.local” for development and I configure them in my /etc/hosts, like this:    foobar.local

Time to write our first page. Create the /tmp/syte.foobar/root directory and the following file: /tmp/syte.foobar/root/index.syt:

;; -*- html -*-
;; in file: /tmp/syte.foobar/root/index.syt
{[define title "Hello world!"]}
    <link href="/s/css/style.css" type="text/css" rel="stylesheet" />
    <!-- page header -->
    <div class="header">
      This is the header
    <!-- page body -->
    <div class="body">
        This is your first Syte.
    <!-- page footer -->
    <div class="footer">
      This is the footer

Note that brackets are special in Syte templates—inside brackets, you write Lisp code. I wrote some comprehensive information about the syntax, but to quickly explain the above example: we define a variable named title and initialize it to the string "Hello world!". I used square brackets there in order to not include anything in the output at the definition time. Later in the template you can see {title}—which inserts the value of the variable.

Now we need to create and register the Syte object. Back to syte.foobar.lisp and add the following:

;; in file: /tmp/syte.foobar/syte.foobar.lisp
;; create the Syte instance
(defparameter *site* (make-instance 'syte.foobar))
;; register it with Sytes
(register-syte *site*)
Evaluate all expressions now (including the (defclass) above, if you didn't already). Then go to the REPL and start the server:
CL-USER> (sytes:start-server)

If everything is OK, you should now be able to see your new page at http://foobar.local:7379 (the default port that Sytes starts on; if you're wondering why this number: 73 and 79 are the ASCII codes for “s” and ”y”).

Configure Nginx

Sytes is intended to serve dynamic requests only (i.e. stuff that it's generated on the fly). While it could easily handle static files, I prefer to pass that responsibility to Nginx in production setups. You might have noticed that the template above includes a CSS file that we didn't yet define. That is a static file and will be served by Nginx, so let's configure it first. (feel free to use any other Web server if you want, like Apache or Lighttpd, my tutorial will only cover Nginx though).

First, if you don't have it already: apt-get install nginx.

In Debian/Ubuntu, Nginx vhost configuration files are stored in /etc/nginx/sites-available/ and symlinked into /etc/nginx/sites-enabled/. Let's create a virtual host for our demo website:

## in file: /etc/nginx/sites-available/syte.foobar.com.conf
server {
    listen 80;
    server_name foobar.local www.foobar.com foobar.com
    charset utf-8;

    gzip on;
    gzip_types text/javascript application/javascript \
               text/css text/plain application/x-javascript;
    gzip_comp_level 9;

    proxy_buffering off;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 64m;
    client_body_buffer_size 2m;
    proxy_connect_timeout 90;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffer_size 2m;
    proxy_buffers 4 1m;
    proxy_busy_buffers_size 2m;
    proxy_temp_file_write_size 2m;

    location /s/ {
        alias /tmp/syte.foobar/static/;

    location ~ ^/favicon\.(png|ico)$ {
        root /tmp/syte.foobar/static/;

    location / {
        proxy_pass http://localhost:7379/;

Then symlink the file in /etc/nginx/sites-enabled/ and restart Nginx:

cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/syte.foobar.com.conf
sudo service nginx restart

Now if everything is OK (and assuming you added foobar.local in /etc/hosts as I mentioned previously) you should be able to access the syte at http://foobar.local/.

We can now create that stylesheet. Open the file /tmp/syte.foobar/static/css/style.css (create the directory if it doesn't exist) and let's say:

.header {
  margin-bottom: 1em;
  padding-bottom: 1em;
  border-bottom: 1px solid #000;
  text-align: center;
.footer {
  margin-top: 1em;
  padding-top: 1em;
  border-top: 1px solid #000;
  text-align: center;

Your site should now reflect the new stylesheet.

Fork me on Github