SkillAgentSearch skills...

Caprese

A front-end web server specialized for real-time message exchange

Install / Use

/learn @zenywallet/Caprese
About this skill

Quality Score

0/100

Supported Platforms

Zed

README

Caprese

A front-end web server specialized for real-time message exchange

Appetizers

Can I write server-side APIs, back-end services, client-side applications, javascript, wasm, even html, in one language and in one code file, and even in one executable binary and process? 〜a certain geek〜

Yes, you can do it with the Caprese. It is free and flexible. Actually, though, it's thanks to a great Nim and libraries.

Is web3 a web? Are there any web server that can be called web3? 〜a certain tweet〜

Caprese will be the base of that system. It would be a decentralized web server with server-to-server connections that could verify the reliability of contents and applications.

Quick Trial

Install Nim

I heard you like Ubuntu, so the following are required to install Nim.

sudo apt install build-essential curl

Install with choosenim.

curl https://nim-lang.org/choosenim/init.sh -sSf | sh
echo 'export PATH='$HOME'/.nimble/bin:$PATH' >> ~/.bashrc
. ~/.bashrc

See Nim for installation details.

Build Caprese and Launch

you also require the following installation to build the SSL libraries.

sudo apt install automake autoconf libtool cmake

Do you have git installed?

sudo apt install git

Now let's build the Caprese.

git clone https://github.com/zenywallet/caprese
cd caprese
nimble install --depsOnly
nimble depsAll
nim c -r -d:EXAMPLE1 -d:release --opt:speed --threads:on --mm:orc src/caprese.nim

Open https://localhost:8009/ in your browser. You'll probably get a SSL certificate warning, but make sure it's a local server and proceed.

Build Your Custom Web Server

Install Caprese package.

nimble install https://github.com/zenywallet/caprese

It will take quite a while, so make some coffee. The Caprese body is located ~/.nimble/pkgs/caprese-0.1.0/ when installed. The version number may change, though. If you can't find it, try looking for ~/.nimble/pkgs2.

It may be easier to find the path with the following command.

nimble path caprese --verbose

In some directory, create server.nim file with the following code.

import caprese

server(ssl = true, ip = "0.0.0.0", port = 8009):
  routes:
    get "/":
      send("Hello!".addHeader())

    send("Not Found".addHeader(Status404))

serverStart()

Build and launch.

nim c -r --threads:on server.nim

Open https://localhost:8009/ in your browser. You'll get a SSL certificate warning, but do something.

Features

  • Multi-threaded server processing
  • WebSocket support
  • TLS/SSL support. BearSSL, OpenSSL, LibreSSL, or BoringSSL can be selected depending on the performance and the future security situation
  • SNI support for TLS/SSL. Servers can use multiple certificates of different hostnames with the same IP address
  • Support for automatic renewal of Let's Encrypt SSL certificates without application restart
  • Web pages are in-memory static files at compile time, dynamic file loading is also available for development
  • Reverse proxy for backend and internal services, server load balancing is available
  • Messaging functionality to send data from the server to clients individually or in groups
  • Dependency-free executable for easy server deployment
  • Build on your device from source code, this repository does not include binary modules such as SSL libraries
  • Languages - Nim 100.0%

Requirements

Closure Compiler Setup

The closure-compiler is needed to minify javascript. It thoroughly optimizes even somewhat verbose and human understandable javascript generated by Nim into short code.

sudo apt install default-jre-headless maven

Maven is used to download the closure-compiler. Caprese automatically downloads and runs the closure-compiler internally. To download manually,

mvn dependency:get -Ddest=./ -Dartifact=com.google.javascript:closure-compiler:LATEST

You can find closure-compiler-vyyyyMMdd.jar in the current path. Copy the file to ~/.cache/caprese/. If several versions of a closure-compiler are found in the path, the latest version is used.

Use scriptMinifier() to make minified javascript

import caprese

const HelloJs = staticScript:
  import std/jsffi
  var console {.importc, nodecl.}: JsObject
  var helloStr = "Hello,".cstring
  var spaceStr = " ".cstring
  var worldStr = "world!".cstring
  console.log(helloStr & spaceStr & worldStr)

const HelloMinJs = scriptMinifier(code = HelloJs, extern = "")

const HelloHtml = staticHtmlDocument:
  buildHtml(html):
    head:
      meta(charset="utf-8")
    body:
      tdiv: text "Hello"
      script: verbatim HelloMinJs

echo HelloHtml

Output

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
<div>Hello</div>
<script>console.log("Hello, world!");</script>
</body>
</html>

It's amazing. HTML is generated from Nim's code, and the wasteful script is simplified. Nothing could be more wonderful. Karax is used to generate HTML. Now that the HTML has been statically generated, all we have to do is return this as a server response with a header.

Register in extern the names of some variables and functions that should not be changed by the closure-compiler. If a string is specified for extern, it will be read directly into --externs option of the closure-compiler via a file. You can also pass extern a list of keywords you want to prevent the closure-compiler from replacing strings in seq[string]. The list of keywords will be converted to a readable format by --externs and passed to the closure-compiler. In addition to them, when the Nim generates javascript, some keywords that should not be changed are automatically added internally to extern.

Server Configuration

The server configuration is written in the config: block. The config: block should be set before the server: block. Below are the default settings. You only need to set the items you want to change or explain explicitly.

config:
  sslLib = BearSSL
  debugLog = false
  sigTermQuit = true
  sigPipeIgnore = true
  limitOpenFiles = -1
  serverWorkerNum = -1
  eventsSize = 10
  soKeepalive = false
  tcpNodelay = true
  clientMax = 32000
  connectionTimeout = 120
  recvBufExpandBreakSize = 131072 * 5
  maxFrameSize = 131072 * 5
  certsPath = "./certs"
  privKeyFile = "privkey.pem"
  fullChainFile = "fullchain.pem"
  httpVersion = 1.1
  serverName = "Caprese"
  headerServer = false
  headerDate = false
  headerContentType = true
  errorCloseMode = CloseImmediately
  connectionPreferred = ExternalConnection
  urlRootSafe = true
  postRequestMethod = false
  sslRoutesHost = SniAndHeaderHost
  • sslLib: None, BearSSL(default), OpenSSL, LibreSSL, BoringSSL
    Somewhat surprisingly, Caprese supports 4 different SSL libraries. I would like to keep it a secret that BearSSL is the most extreme, with the smallest binary size and the fastest SSL processing speed. Enjoy the differences.
    SSL libraries are built from source code in the deps folder of the repository, so there is no need to install SSL libraries on the OS. Just select the SSL library with this parameter and it will be statically linked.
    If SSL is not required, it is recommended set to None. This will enable the experimental implementation of fast dispatch processing based on number of client connections and requests. At this time, it is only available for None.
  • debugLog: true or false(default). If true, debug messages are output to the console.
  • sigTermQuit: true(default) or false. If true, handling SIGTERM at the end of the process. The code in the onQuit: block is called before the process is terminated.
  • sigPipeIgnore: Whether to ignore SIGPIPE. Caprese requires SIGPIPE to be ignored, but can be set to false if duplicated in other libraries.
  • limitOpenFiles: [Number of open files], -1(default, automatically set the maximum number of open files)
  • serverWorkerNum: [Number of processing threads], -1(default, automatically set the number of CPUs in the system)
  • connectionTimeout: [Client connection timeout in seconds], -1(disabled). The time to disconnect is not exact. Disconnection occurs between a specified second and twice the time.
  • headerServer: true or false(default), If true, include Server: in the response headers. Common benchmarks require this value to be true. In benchmark competition, even a single byte of copying can feel heavy.
  • headerDate: true or false(default), If true, include Date: in the response headers. Common benchmarks require this value to be true. It should not be the essence of benchmarking, but sometimes it is a competition of how to implement the date strings.
  • headerContentType: true(default) or false, If true, include Content-Type: in the response headers. It may be possible in some cases to set false according to benchmark requirements.
  • errorCloseMode: CloseImmediately(default) or UntilConnectionTimeout. Behavior when disconnecting clients on error.
  • connectionPreferred: ExternalConnection(default) or InternalConnection. Optimize server processing depending on whether the clients are connected from external or internal network connections. The situation is different when the clients a

Related Skills

View on GitHub
GitHub Stars85
CategoryProduct
Updated18d ago
Forks2

Languages

Nim

Security Score

100/100

Audited on Mar 18, 2026

No findings