edge.js: a Node template engine that reads like JavaScript
Node.js template engine with a breath of fresh air
At a glance
- What is it?
- Edge describes itself as a simple, modern, batteries included template engine for Node.js, and the pitch is that it is similar to writing JavaScript, so if you know JavaScript you know Edge. The repository shows a project that has been organised like a library rather than a script collection, with a build that produces type declarations, a test runner of its own and a plugin export for migrating between versions.
- Who is it for?
- Adopt Edge if your Node application needs a template layer and you want it to stay recognisably JavaScript rather than a separate expression language, because that is the design the project commits to. Do not adopt it if you need a feature set you would have to assemble from plugins yourself, since the project describes itself as batteries included but the core package is small and the extension points are separate packages.
- 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 155 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The pitch is that there is no new language to learn
Edge is described as a simple, modern and batteries included template engine for Node.js, and the sentence that sells it is short: Edge is similar to writing JavaScript, and if you know JavaScript you know Edge.
That is a different proposition from most template engines, which introduce a small expression language with their own syntax, their own escaping rules and their own set of surprises. Edge's claim is that the template is close enough to the host language that the learning curve is the one you already have.
The project is MIT licensed, the source is TypeScript, the documentation lives on its own site at edgejs.dev, and the package is published to npm as edge.js, which is a name difference from the repository that will trip up anyone installing it by repository name. The development branch is named for the major line, six.x, and the release history shows version 6.5.1 with the release notes described as a dependency update.
The repository listing shows a project with the shape of a maintained library rather than a script collection: a source directory, a tests directory, a test helpers directory, several fixture directories, an examples directory, a command line binary directory, an entry point at the root, and the usual configuration files.
The build emits an ES module with its own types
The package configuration is the clearest description of what consumers actually get.
The package is an ES module, with a main entry pointing at the built index file, and the exports map publishes three things. The root entry, a types entry, and a migration plugin entry, which is the interesting one, because it means the package ships a tool for converting templates written for an older version of the engine.
The build itself has two stages. A bundler produces the JavaScript, and then the TypeScript compiler runs in declaration-only mode to emit the type definitions. The compile step is preceded by a lint step, and the publish hook runs a build first, as does the version script, so the artefacts in the registry are always built from a tree that passed the checks.
The published files are the build directory, with explicit exclusions for the command line binaries, the examples and the test directories, which keeps the installed package small. The engine requires Node 18.16 or newer.
The runtime dependencies are worth noting for a template engine, because they explain what the engine does for you: a macro package for compile-time tags, an error type and a lexer package, an inspection utility and a general utilities package. A lexer as a dependency tells you the engine tokenises the template rather than evaluating it as JavaScript directly, and a macro package tells you there is a compile step for tags that expand into JavaScript.
Lint runs before the tests and before the compile
The scripts in the package file are arranged so that the cheap checks gate the expensive ones, and the ordering is visible rather than implied.
The test script calls a quick test script, and there is a pretest hook that runs the lint first. The compile script has the same arrangement, with a precompile hook that runs the lint, so a build never produces an artefact from a tree with lint errors. The release script uses a conventional changelog tool, and the publish hook runs the build.
The test runner itself is unusual. Instead of a conventional test framework invocation, the quick test script runs a TypeScript entry point through a TypeScript execution helper with source maps enabled:
"quick:test": "node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts"So the suite runs straight from TypeScript, with source maps on, through a binary in the repository's own command line directory. The test dependencies are the Japa assertion library, a file system helper and a runner, so the assertions and the runner are Japa's while the orchestration is the project's own.
The formatting and linting setup is shared with a larger framework ecosystem rather than invented for this project. The development dependencies include a shared ESLint configuration, a shared Prettier configuration and a shared TypeScript configuration, all from the same family, plus the standalone linter and formatter. The project also has a separate typecheck script that runs the compiler with no output, which is a cheap extra check that a project using TypeScript as its source language can afford.
The fixture directories tell you what the engine is tested against
The repository listing has three fixture directories, and their names are a decent description of what a template engine has to get right.
There is a plain fixtures directory, an async fixtures directory and a newline fixtures directory. The third one is the most telling: a template engine that renders text has to deal with the difference between the newline conventions of different platforms, and the fact that there is a dedicated directory of newline fixtures suggests that behaviour is pinned down rather than assumed.
The async fixtures point at the other half of the problem, since a template engine that awaits things, a data fetch inside a template, has to have defined semantics for ordering and for errors.
Alongside them sit the tests directory, a test helpers directory, and an examples directory with an index file and a views subdirectory, which is where a template engine keeps its demonstration templates. The example views are the fastest way to see what the engine's syntax looks like in practice, and the README's promise that Edge is similar to writing JavaScript is something you can check in a few lines of a view file rather than take on trust.
There is also a command line binary directory and a root entry point, so the package exposes more than a library import, and the tests can run the whole thing end to end rather than only the template compiler.
Recent releases are small and specific
The three most recent releases tell you what kind of project this is in 2026.
Version 6.5.1, in May, is described as a dependency update. Version 6.5.0, in February, added two tags, one that pushes to the top and a variant that does it once. Version 6.4.0, in December 2025, removed a dependency called fs-readdir-recursive and added support for an update expression.
Two details are worth pulling out of that list. The removal of a recursive directory reader suggests a move to a platform built-in, which is the kind of change that follows a runtime's own capability rather than the engine's needs. And the new tags are exactly the kind of small, additive feature that a template engine accumulates once people use it in production: a stack operation, not a redesign.
The export map reinforces the versioning story. The migration plugin is published as a separate entry point, so a project upgrading across major versions has a conversion tool rather than a note telling it to rewrite templates by hand.
And the branch name completes it. The default branch is six.x, named for the major line rather than for the current release, so the branch receives the fixes for the whole line, and a consumer picks a tag. The last push was on 2026-05-21, the same day as the newest release, so the project is being worked on rather than merely tagged.
What to weigh before choosing it
A few practical observations for anyone considering Edge for a Node application.
The first is the ecosystem coupling. The shared configuration packages, the macro and inspection utilities, the execution helper used to run the tests, all come from one family of packages. That is not a problem in itself, but it means the project sits inside an ecosystem rather than standing alone, and a change in those packages reaches you.
The second is the documentation split. The README here is a few paragraphs and a table of sponsors, and everything else lives on the documentation site. That is a reasonable choice for a project with an active community, and it does mean the repository is not where you will find the syntax reference.
The third is the licensing and the size, which are both simple. MIT, a small runtime dependency set, and a published package that excludes its own tests, examples and binaries.
The fourth is the branch layout, which is the one to get right on day one. Because the default branch is the major line rather than a release, a project that installs from the repository tip rather than from a version will get something different from what the registry offers. Pin a version, and if you find yourself upgrading across major versions, look for the migration plugin first, because the project ships one for exactly that case.
The last point is the hardest to quantify from the outside. A template engine that looks like JavaScript is easy to start with and hard to review, because template code and application code end up looking the same in a pull request. That is the cost of the design, and it is worth weighing against the convenience.
Editorial conclusion
Adopt Edge if your Node application needs a template layer and you want it to stay recognisably JavaScript rather than a separate expression language, because that is the design the project commits to. Do not adopt it if you need a feature set you would have to assemble from plugins yourself, since the project describes itself as batteries included but the core package is small and the extension points are separate packages. Before you pin a version, note that the repository develops on a branch named for the major line, so take the release you want rather than the tip of the default branch, and check the migration plugin export, which suggests the project expects upgrades to need a conversion step.
Frequently asked questions
What is the Edge template engine?
It is a Node.js template engine described as simple, modern and batteries included, whose design goal is that it looks like writing JavaScript, so if you know JavaScript you know Edge. The package is published on npm as edge.js, it is MIT licensed, and the documentation lives at edgejs.dev.
How is the Edge package built and published?
A bundler produces the JavaScript and the TypeScript compiler runs in declaration-only mode to emit the type definitions, with a lint step running first. The package is an ES module that publishes a root entry, a types entry and a migration plugin entry, and the installed files exclude the binaries, examples and tests.
How are the Edge tests run?
Through a script that starts a TypeScript entry point with the project's execution helper and source maps enabled, using the Japa assertion library, runner and file system helper. Linting runs automatically before the tests, and a separate typecheck script runs the compiler with no output.
What changed in the recent Edge releases?
Version 6.5.1 updated dependencies, version 6.5.0 added tags that push content to the top, one of them doing it once, and version 6.4.0 removed a recursive directory reader dependency and added support for an update expression. The project develops on a branch named for the major version line.
Is there a way to migrate Edge templates between versions?
The package exports a migration plugin as its own entry point, alongside the root entry and the types entry, which suggests the project expects template conversions to be needed when moving between major versions rather than left to manual rewriting.
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/edge-js-edge)Was this useful?