Fullmoon puts a routing and template layer on top of the Redbean single-file server
Fast and minimalistic Redbean-based Lua web framework in one file.
At a glance
- What is it?
- Fullmoon is a Lua web framework written for Redbean, a portable single-file web server. It adds routes, templates, sessions, form validation and schema migrations in roughly 1700 lines, and the deployment story stays a single executable.
- Who is it for?
- Fullmoon fits teams that want a deployable web service as one executable, already accept Lua as the application language, and need routing, templates, sessions and form validation without assembling a package tree. It does not fit projects that want a mature general-purpose framework with a large dependency ecosystem, since the README notes that other Lua frameworks exist and that Fullmoon is deliberately about 1700 lines.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 31 days ago.
- What is it written in?
- Mainly Lua, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Fullmoon fills the gap Redbean leaves open
Redbean is described as a portable, single-file distributable web server, and it does a great deal: it terminates TLS, serves static assets, embeds Lua and SQLite, and forks. What it does not do is give you a routing layer, a template engine or a session store in the shape an application wants. Fullmoon is that layer.
The README frames this as a deliberate design goal rather than a gap in the market. Fullmoon is written from the perspective of showcasing all the capabilities Redbean provides, extending and augmenting them in the simplest and most efficient way. It calls itself lightweight and minimalistic, and follows the Lua philosophy of providing a minimal set of tools to combine as needed.
The scope is stated numerically: a small package of about 1700 lines with no external dependencies. Everything needed for development and distribution comes in a single file, and after packaging with Redbean it runs on Windows, Linux or macOS.
That framing explains the trade-off. You are not getting a large framework with a community of extensions. You are getting the shortest path from a Redbean process to a working HTTP application, and you keep access to all Redbean features underneath.
Redbean supplies SSL, hashing, sandboxing and SQLite
The division of labour is explicit in the README. Redbean provides single-file deployment and distribution across Linux, Windows and macOS, integrated SSL support using MbedTLS with SSL virtual hosting, and integrated crypto hashing for SHA1, SHA224, SHA256, SHA384, SHA512 and BLAKE2B256.
It also provides cross-platform fork, socket and shared memory support, efficient serving of static and gzip encoded assets, integrated password hashing using Argon2, and pledge and unveil sandboxing where the platform supports it. There is a unix module for Unix system interfaces, an HTTP and HTTPS client for outbound requests, JSON and Lua serialization and parsing, and the runtime itself ships with Lua 5.4 and SQLite 3.40.
The practical reading for an adopter: the security-sensitive and platform-sensitive pieces are already solved inside the server binary, and Fullmoon does not reimplement them. When you need a Unix-only call or a raw socket, you are one require away from the underlying module rather than blocked by an abstraction.
The cost of that arrangement is that you inherit Redbean's runtime and its release cadence along with Fullmoon's. Two projects move, and only one of them is the framework you are reading about.
Routes carry parameters, filters and method conditions
Routing is the core of what Fullmoon adds. The README lists simple and flexible routing with parameters and custom filters, and the documentation sections outline the whole surface: basic routes, routes with parameters, optional parameters, splat parameters, custom parameters, query and form parameters, multipart parameters, named routes, multiple routes, route conflicts, external routes and internal routes.
A complete application fits in a handful of lines.
local fm = require "fullmoon"
fm.setTemplate("hello", "Hello, {%& name %}")
fm.setRoute("/hello/:name", function(r)
return fm.serveContent("hello", {name = r.params.name})
end)
fm.run()The route path carries a named parameter, the handler receives a request object, and r.params.name holds the captured value, which is then passed to the template as a parameter.
Conditions are the second half of the routing story, and they are where the framework does more than pattern matching. The README lists handling of HTTP methods, conditional routes, custom validators, responding on failed conditions, and form validation. A route can therefore be constrained by method, inspected by a validator you write, and given a defined failure response rather than falling through to a generic error.
Internal routes are listed separately from external ones, and parametrized URL rewrites and re-routing are supported. That is the mechanism for moving a request to a different handler without redirecting the client, which differs from the redirect style of response the framework also offers.
Templates, JSON output and pre-compiled routes
The template engine comes with JSON support and what the README calls efficient memory utilization. The documented surface covers passing parameters to templates, handling undefined values, including templates inside other templates, using layouts and blocks, loading templates, serving template output, and special templates. Undefined values get explicit handling, which matters for a framework that renders HTML directly.
JSON generation is listed among the batteries included, alongside the templates and routes, and it is a natural fit because Redbean already ships JSON and Lua serialization and parsing.
Performance is addressed in two specific ways rather than with a general claim. The first is pre-compiled routes, so the route table is prepared before the server starts serving. The second is lazy loaded methods, which means a request method is not resolved until it is needed. The README also lists response streaming and Server-Sent Events support, which the examples folder demonstrates in the htmx SSE example.
Templates load from the filesystem, and the deployment story still collapses to one file because the packaged archive carries them along. That is the design in miniature: features are added where they are cheap because the surrounding runtime already provides the heavy parts.
Sessions, cookies, uploads, cron and migrations
The remaining feature set is long but specific. Fullmoon generates and processes cookies, headers and sessions, with separate documentation for cookie options and session options. Multipart message processing is supported for file uploads, which the README lists as its own capability rather than folding into ordinary form parsing.
There is form validation with a variety of checks, tied into the conditional route mechanism described earlier. There is a cron syntax for scheduling Lua functions, which is the project's answer to background jobs in a runtime that is otherwise request driven. There is database management with schema migrations, and the examples folder includes a dbmanagement.lua file.
Responses cover more than a body. You can serve a response, a redirect, a static asset, an error, a directory index, or a path that triggers an internal redirect. Custom 404 and other status pages are supported, so an application can render its own error pages instead of the server's default output. Basic support to run CGI scripts is included, which is a pragmatic addition given that the deployment is a single binary.
Taken together this is a conventional web application feature list, delivered in a small package. The unusual part is not what is present but that it all fits inside a framework the author describes as about 1700 lines.
Installing means one download, two Lua files and a packaging step
Installation is a three-step process described in the README. Step one is to get the latest Redbean, version 2.0 or newer.
curl -o redbean.com https://redbean.dev/redbean-2.2.com
chmod +x redbean.comThe second command is skipped on Windows. The README also notes that the latest version number can be retrieved from https://redbean.dev/latest.txt, and that Redbean can be built from source using the instructions on the redbean.dev site.
Step two prepares the Lua sources. You copy fullmoon.lua into a .lua/ directory and save the application code to a file named .init.lua. The alternative is to put the application code in a separate file such as .lua/myapp.lua and add require "myapp" to .init.lua, and the README notes that all the included examples are presented that way.
Step three packages the Fullmoon code with Redbean, producing a single executable. The README states that after packaging it can be launched with ./redbean.com, which starts a server returning Hello, world to an HTTP or HTTPS request sent to http://localhost:8080/hello/world.
That is the whole deployment story: download a binary, arrange two files, package, run. There is no package manager, no lockfile and no dependency tree to resolve, because there are no external dependencies.
The gaps are in the edges: CGI support, releases and a small codebase
Three limits are visible from the documentation rather than hidden.
First, CGI support is explicitly described as basic. If your deployment model depends on running scripts as separate CGI processes, you should check that path against your own requirements before committing.
Second, the codebase is small. About 1700 lines is a feature, and it is also a ceiling. There is no plugin ecosystem described here, no dependency manager entry and no stated compatibility policy for the API. Anyone who needs behaviour outside the documented surface will be reading and modifying fullmoon.lua itself.
Third, packaging follows Redbean. The framework runs inside a Redbean build, so its version compatibility is tied to the server version you download, and the README asks for Redbean 2.0 or newer. Upgrading means repackaging.
On maintenance, the repository is not archived and the last push was on 2026-09-22, but it publishes no GitHub releases. The examples give a sense of scope: a showcase example, a TechEmpower benchmark example, an htmx board example, an htmx SSE example and a dbmanagement.lua file. The benchmark example is worth noting as a statement of intent, though the README does not publish results here.
How Fullmoon differs from Lapis, Lor, Sailor and Pegasus
The README names several Lua-based web frameworks, among them Lapis, Lor, Sailor and Pegasus, and makes one claim about them: none of them integrates with Redbean, although an experimental framework called anpan does.
That is the meaningful difference, and it is not a feature checklist comparison. Those frameworks are layered on a conventional Lua runtime with their own dependency sets, their own server integration and their own assumptions about the environment. Fullmoon instead treats Redbean as the host, which is why it can claim single-file deployment across three operating systems, because the server, the TLS stack, the hashing library, the password hashing, the JSON handling, the SQLite build and the Lua runtime are already inside the executable it packages with.
The tradeoff follows. Fullmoon inherits Redbean's environment model: a forked process, Unix interfaces available through a unix module, pledge and unveil sandboxing where supported. An application written for Lapis or Pegasus assumes a different host, and porting means reworking how the server is obtained and how the runtime is deployed, not just changing imports.
For a team already committed to Redbean for other reasons, that alignment is the reason to choose Fullmoon. For a team already running one of the named frameworks, the case is weaker.
Editorial conclusion
Fullmoon fits teams that want a deployable web service as one executable, already accept Lua as the application language, and need routing, templates, sessions and form validation without assembling a package tree. It does not fit projects that want a mature general-purpose framework with a large dependency ecosystem, since the README notes that other Lua frameworks exist and that Fullmoon is deliberately about 1700 lines. Before adopting, confirm the Redbean version you package against is current, read the sections on conditions and multipart handling if your app depends on form parsing, and note that the repository publishes no GitHub releases, so the last push on 2026-09-22 is the only change signal available here.
Frequently asked questions
How do I install Fullmoon and Redbean?
Download Redbean 2.0 or newer with curl -o redbean.com https://redbean.dev/redbean-2.2.com and chmod +x redbean.com, copy fullmoon.lua into a .lua/ directory, save your application code to .init.lua, then package the code with Redbean and launch the result with ./redbean.com.
What does Fullmoon add on top of Redbean?
Fullmoon adds routing with parameters and custom filters, a template engine with JSON support, pre-compiled routes and lazy loaded methods, response streaming and Server-Sent Events, cookies, headers and sessions, multipart handling for uploads, form validation, cron scheduling, and database management with schema migrations.
Which platforms can a packaged Fullmoon application run on?
Everything needed for development and distribution comes in a single file with no external dependencies, and after packaging with Redbean it runs on Windows, Linux or macOS.
What license is Fullmoon released under?
Fullmoon is released under the MIT license, with the LICENSE file at the top level of the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pkulchenko-fullmoon)Was this useful?