Are you happy with your logging solution? Would you help us out by taking a 30-second survey? Click here


A sinatra-like web framework for Nim.

Subscribe to updates I use jester

Statistics on jester

Number of watchers on Github 542
Number of open issues 45
Average time to close an issue about 1 month
Main language Nimrod
Average time to merge a PR 5 days
Open pull requests 8+
Closed pull requests 2+
Last commit about 2 years ago
Repo Created almost 8 years ago
Repo Last Updated about 2 years ago
Size 269 KB
Organization / Authordom96
Latest Releasev0.1.1
Page Updated
Do you use jester? Leave a review!
View open issues (45)
View jester activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating jester for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)


The sinatra-like web framework for Nim. Jester provides a DSL for quickly creating web applications in Nim.

Note: Jester requires Nim version 0.15.0.

# example.nim
import jester, asyncdispatch, htmlgen

  get "/":
    resp h1("Hello world")


Compile and run with:

  cd tests/example
  nim c -r example.nim

View at: localhost:5000


  get "/":
    # do something here.

All routes must be inside a routes block.

Routes will be executed in the order that they are declared. So be careful when halting.

The route path may contain a special pattern or just a static string. Special patterns are almost identical to Sinatra's, the only real difference is the use of @ instead of the :.

get "/hello/@name":
  # This matches "/hello/fred" and "/hello/bob".
  # In the route ``@"name"`` will be either "fred" or "bob".
  # This can of course match any value which does not contain '/'.
  resp "Hello " & @"name"

The patterns in Jester are currently a bit more limited, there is no wildcard patterns.

You can use the '?' character to signify optional path parts.

get "/hello/@name?":
  # This will match what the previous code example matches but will also match
  # "/hello/".
  if @"name" == "":
    resp "No name received :("
    resp "Hello " & @"name"

In this case you might want to make the leading '/' optional too, you can do this by changing the pattern to /hello/?@name?. This is useful because Jester will not match /hello if the leading '/' is not made optional.


Regex can also be used as a route pattern. The subpattern captures will be placed in request.matches when a route is matched. For example:

get re"^\/([0-9]{2})\.html$":
  resp request.matches[0]

This will match URLs of the form /15.html. In this case request.matches[0] will be 15.


Jester supports conditions, however they are limited to a simple cond template.

  get "/@name":
    cond @"name" != "daniel"
    # ``cond`` will pass execution to the next matching route if @"name" is not
    # "daniel".
    resp "Correct, my name is daniel."

  get "/@name":
    # This will be the next route that is matched.
    resp "No, that's not my name."

Return values

Route bodies all have an implicit request object. This object is documented in jester.nim and documentation can be generated by executing nim doc jester.nim.

Returning a response from a route should be done using one of the following functions:

  • One of the resp functions.
  • By setting body, headers and/or status and calling return.
  • redirect function
  • attachment function

There might be more. Take a look at the documentation of jester.nim for more info.

Manual routing

It is possible not to use the routes macro and to do the routing yourself.

You can do this by writing your own match procedure. Take a look at example2 for an example on how to do this.

Static files

By default Jester looks for static files in ./public. This can be overriden using the setStaticDir function. Files will be served like so:

./public/css/style.css ->

Note: Jester will only serve files, that are readable by others. On Unix/Linux you can ensure this with chmod o+r ./public/css/style.css.


Cookies can be set using the setCookie function.

get "/":
  # Set a cookie "test:value" and make it expire in 5 days.
  setCookie("test", @"value", daysForward(5))

They can then be accessed from the request.cookies PStringTable.

Request object

The request object holds all the information about the current request. You can access it from a route using the request variable. It is defined as:

PRequest* = ref object
  params*: StringTableRef       ## Parameters from the pattern, but also the
                                ## query string.
  matches*: array[MaxSubpatterns, string] ## Matches if this is a regex
                                          ## pattern.
  body*: string                 ## Body of the request, only for POST.
                                ## You're probably looking for ``formData``
                                ## instead.
  headers*: StringTableRef      ## Headers received with the request.
                                ## Retrieving these is case insensitive.
  formData*: TMultiData         ## Form data; only present for
                                ## multipart/form-data
  port*: int
  host*: string
  appName*: string              ## This is set by the user in ``run``, it is
                                ## overriden by the "SCRIPT_NAME" scgi
                                ## parameter.
  pathInfo*: string             ## This is ``.path`` without ``.appName``.
  secure*: bool
  path*: string                 ## Path of request.
  cookies*: StringTableRef      ## Cookies from the browser.
  ip*: string                   ## IP address of the requesting client.
  reqMeth*: TReqMeth            ## Request method, eg. HttpGet, HttpPost
  settings*: PSettings


Github service hooks

The code for this is pretty similar to the code for Sinatra given here:

import jester, asyncdispatch, json

  post "/":
    var push = parseJson(@"payload")
    resp "I got some JSON: " & $push


Demo webapp

import jester, asyncdispatch, json
import httpcore

  post "/receive_json":
      let j = parseJson(request.body)
      resp Http400, "Unable to parse JSON payload"

  # Using an HTML template from
  get "/generated_page":
    resp generateHTMLPage("foo", "bar", "baz")

jester open issues Ask a question     (View All Issues)
  • over 3 years Template `attachment` has problem when setting `Content-Type`
  • over 3 years MultiData parsing doesn't handle preamble properly
  • over 3 years Please disable pcre32.dll, nimx's examples are trying to load it
  • over 3 years `attachment` either not working or mis-documented
  • over 3 years How to stop gracefully when SIGINT, SIGHUP or SIGTERM is received ?
  • over 3 years Having the choice of the weak caching headers
  • over 3 years multiple excepts
  • over 3 years resp may be problematic in templates
  • over 3 years documentation :(
  • almost 4 years Nitpick: required version note
  • almost 4 years Custom 404 response?
  • about 4 years middleware support
  • about 4 years Participate in Todo-Backend project
  • over 4 years Separation of jester routes between different modules or files.
  • over 4 years Problem with devel version of Nim
  • over 4 years Investigate problems with settings block
  • over 4 years Resoinse doesn't work with string, which len <=5
  • over 4 years Make sure you repr the Request object
  • almost 5 years Memory consumption seems high
  • almost 5 years Template processing in a route is broken
  • about 5 years Top level exception handler
  • about 5 years Better support for authentication
  • about 5 years Thoughts about Jester and practical header handling
  • over 6 years Document filters
jester open pull requests (View All Pulls)
  • Add a feature to write separate routes in multiple files
  • Preserve MultipartData order
  • Improve example webapp #73
  • Add serveFuture and routesFuture
  • Add caching example
  • Fix Nimble warnings about incorrect package structure
  • Added support for having multiple matchers
  • readme and fix deprecated
jester questions on Stackoverflow (View All Questions)
  • Where do I check the results of Mahout's jester example?
  • How can I get recommendation result of Mahout's jester example?
jester list of languages used
jester latest release notes
v0.1.1 v0.1.1


v0.1.0 v0.1.0

The initial release.

More projects by dom96 View all
Other projects in Nimrod