tasmocompiler: a web interface for building custom Tasmota firmware
Web GUI for custom Tasmota compilation
At a glance
- What is it?
- Tasmota is the firmware that turns a cheap WiFi relay into a home automation device, and building it yourself means installing a toolchain, editing defines, and preparing a build configuration. TasmoCompiler puts all of that behind five browser steps, and hands back not only the firmware but the two files that record exactly how it was built.
- Who is it for?
- tasmocompiler fits somebody who flashes a handful of smart home devices and wants a build with the right features and their own network credentials without learning the platform build system. It does not fit somebody who already has a reproducible platform configuration, since the tool exists precisely to avoid that work, and it does not fit a production pipeline that needs the build to be scripted from end to end.
- 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 74 days ago.
- What is it written in?
- Mainly C, 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
The problem the tool removes
Tasmota is the firmware that turns a low cost WiFi relay or socket into something you can put in a wall and control, and for most people it is installed with a prebuilt binary. For the people who need something the prebuilt binary does not have, there is a build.
TasmoCompiler is a simple web interface that lets you compile Tasmota firmware with your own settings. What you choose is: the board the firmware is for, the features and sensors you want compiled in, the credentials for your own wireless network, the version of Tasmota to build against, the language of the firmware's own user interface, and any custom defines you want to add.
The credentials item deserves a note, because the reason is stated in the readme and it is not obvious. If the device loses its configuration completely, the credentials are still there, and the main reason is that you do not have to connect to the access point that Tasmota serves in order to configure your home network. In other words, the network details are baked into the firmware at build time rather than entered on the device afterwards.
The version choice is two options: the development branch, which is the leading edge, or the latest stable release. And there is a document in the repository describing what the available features are, because the feature list is long and a person choosing between them needs more than a list of names.
The reasons for building the project are given plainly in the readme, and they are honest in a way that is worth respecting. The first is that the author wanted to build a first application written in NodeJS and React. The second is an observation about his own workflow: every time he prepares a new device he has to start with platformio installed, configure all the defines, using a template he copies, prepare the platformio configuration file, and create a branch from the version he wants to use.
So the tool is the author's own repeated tedium turned into a form, and the second reason is the design brief. The goal is a solution that is easier to use, a few clicks, and that does not require knowledge of how to install a development environment in order to build custom firmware.
That framing matters for how you read the rest of the project. This is not a professional build service; it is one person's workflow, automated, and shared. The project is MIT licensed, the last push was on 2026-08-10, and the releases run in the 13.x line with three releases across 2026.
Five steps, and four files at the end
The how it works section defers to the screenshots, which is a reasonable choice for a graphical interface, and then lists the outputs. When the compilation finishes you get four files, or three for the ESP32 boards.
The first is the firmware binary, which is the one that matters, and the readme lists the ways to get it onto a device: the Tasmota web interface, the serial flashing tool, the flasher from the alternative project, or any other tool you already use. The second is a compressed version of the same binary, which is not available for the ESP32 boards. The third is the platformio configuration override file, and the fourth is a header file with the user configuration override.
The third and fourth files are the interesting ones, and they are the reason this tool is worth more than a hosted build service. The platformio file records exactly which options the build was compiled with, and the header records which features ended up included and which were excluded. So when a device behaves unexpectedly, or when you want to know whether a feature you thought you enabled is actually in the binary, you have the answer in a file rather than a memory.
For a firmware project where the build is customised, the difference between the binary that works and the binary that does not is often one define, and the ability to diff the header against the last one is worth a great deal.
The links to the files appear under the compiling progress field at the bottom of the last screen, and the readme is explicit that they show up only when the compilation is successful. That is a good detail: a failed build does not leave a broken binary to download, which is exactly the situation where a user would otherwise flash something that does not work.
And the readme repeats the point that only one of the four files needs to be uploaded. The firmware binary, or the compressed one, is what goes on the device. The other two are for you, not for the device, and the device's own documentation describes the upgrade procedure in detail.
So the deliverable is not just firmware. It is firmware plus a record of how it was made, which is a design choice that a build service would not make and a tool for one person would.
Running it, and the debug flags
There are two routes to a running instance, and the readme labels them easy and less easy.
The easy one is a container. You pull the image, run it with a name and a published port, and then point a browser at the local port.
docker run --rm --name tasmocompiler -p 3000:3000 benzino77/tasmocompilerThe port mapping is the only thing to think about, and the readme shows the alternative where the host port differs from the container port, which is the case where the default one is already taken by something else.
docker run --rm --name tasmocompiler -p 8080:3000 benzino77/tasmocompilerThe other route is to run it from source, and the list is eight steps: install Node and a recent Python, install the package manager, install the platform build tool, clone the repository and change into it, install the dependencies, build, start the server, and open the browser.
The interesting one is the debug output, because a compilation tool that fails silently is the worst kind. The container takes an environment variable naming the subsystems you want messages from, and the readme lists the three: the server, the git operations, and the compilation itself.
docker run --rm --name tasmocompiler -p 3000:3000 -e DEBUG=server,git,compile benzino77/tasmocompilerThe three names correspond to the three phases of what the tool does. It runs a server, it fetches and checks out the Tasmota source at the version you asked for, and then it invokes the compiler. So when a build fails, the three flags narrow the search: is the service not receiving the request, is the source not being fetched, or is the compiler unhappy.
That is a well-chosen granularity for a tool whose whole job is running a toolchain, and the fact that the flags are named after the phases rather than after modules means you can guess the right one without reading the source.
Custom parameters, and the define and undefine pattern
The section on custom parameters opens with a statement of intent about the interface, and it is a good one. The configuration options are limited on purpose, because the author does not want to overload the interface with too many options. But there is a custom parameters step, which lets you define other Tasmota parameters.
The example given is the one every user needs: an MQTT broker and its credentials. And the way you set them is the part to understand, because the pattern is not a plain assignment.
#ifdef FRIENDLY_NAME
#undef FRIENDLY_NAME
#endif
#define FRIENDLY_NAME "Watering controller"Each value is wrapped in a conditional check, an undef of the symbol, and then the definition. The undef matters because the firmware's own configuration header already defines these symbols, and a second definition of the same symbol is either an error or, depending on the compiler flags, a redefinition warning that is silently ignored. Undefining first makes the new value win.
So the pattern is three lines of preamble and one line of value, repeated for each symbol. The readme shows the same pattern for the broker host, the port, the user, and the password, and then for the device's friendly name, which is the example above.
The third example is the most interesting, because it is about behaviour rather than identity. To compile in information about the network time server, the time zone, and the location, which the readme explains is used by the timers for events such as sunrise and sunset, you define the server, the latitude, the longitude, and a time zone number.
#ifdef APP_TIMEZONE
#undef APP_TIMEZONE
#endif
#define APP_TIMEZONE 99The location values are ordinary decimal coordinates, and the time zone is a numeric identifier rather than a name, because the firmware cannot use a name database and a number is what fits in a small binary.
And the readme points at the place to find out what else can be set: the user configuration header in the Tasmota source, which is the canonical list of every symbol the firmware understands. So the tool deliberately does not enumerate the possibilities; it gives you the mechanism and the pointer to the list.
The stack behind the interface
The package manifest describes a fairly conventional modern JavaScript application, and a few of the entries explain the design.
The user interface is React 18 with a Material Design component set and its styling system, with the internationalisation library for the translations. The set of languages is a user choice, which is worth noting, because the firmware's own interface language is a compile-time option and the compiler's interface language is a separate thing that the project handles with the translation file in the repository root.
The server is Express, with a body parser, a logging library, and the socket library with its browser-side counterpart. The socket pair is the interesting one: the compilation takes a while, and a build server that only answered with a request response would either time out or leave the browser guessing. A socket connection lets the server push compilation progress to the page, which is exactly what the compiling progress field in the screenshots is.
The build machinery is in the dependency list too, and these are the entries that make it a compiler rather than a form. There is the simple git library, which is how the Tasmota source at the chosen version is fetched and checked out. There is a shell scripting library, which is how the platform build tool is invoked. There is the platform configuration file library, which is how the generated configuration is written. There is a semantic version library, which is how the chosen firmware version is compared and resolved. And there is a file system library, because a build produces files.
The scripts tell the rest of the story. The development script is the interesting one: it runs two processes at once with the kill-others flag, one being the server on a different port with the debug variables set, and the other being the development server for the interface. The port difference is explained by the proxy setting in the manifest, which points the development server at the backend, so the interface can talk to it in development exactly as it will talk to the production server in the container.
The testing setup is worth a line. The front end is tested with the standard script test runner, the backend has its own test command that runs the jest runner over the server directory, and the mocking library in the development dependencies is the network mocking one, which is how you test a front end that talks to a server without running a server.
The repository also has an Ansible directory, a mocks directory, an editor settings directory, and a file pinning the node version for the development environment.
The container image, and the two hacks in it
The Dockerfile is short and contains two choices that a careful reader will notice, one of them acknowledged in a comment as a hack and the other one not acknowledged at all.
The base is a slim Node image on a specific distribution, and the first step installs the system packages the build needs: Python, git, the packaging tools, pip, and the virtual environment module, plus a global install of the process watcher. The system package lists are cleaned up afterwards to keep the image small.
Then the application directories are copied in, the dependencies are installed, and the front end is built. And here is the first hack, with the author's own words: uninstalling the React related packages to reduce the image size is a rather dirty hack, and a multistage build would probably be better, but it would require a more complex Dockerfile.
The reasoning is sound. The React packages and the component library are build-time requirements for producing the front end bundle, and they are not needed at run time, because the built output is static files served by the server. Removing them after the build saves a substantial amount of image size. The cost is that the image is no longer reproducible by a plain rebuild of the same Dockerfile, and a multistage build would fix that at the price of a more complicated file. The author chose the simple file and said so.
The second choice is the entry point, and it is not mentioned in any comment. The container runs the process watcher as its entry point, and the process watcher is a development tool that restarts a server when its source files change. In a production image, a file watcher is not what you want: it adds a process, it watches a directory that never changes, and it is one more thing between the container starting and the server serving.
The image also does something clever with the compiler's environment. It creates a virtual environment for the platform tool in the node user's home directory, installs the tool into it with the fast package installer, and then puts that environment's bin directory at the front of the path for the rest of the image. So the compiler is found on the path without any shell profile doing it.
The rest of the file is standard: the locale is set to a UTF-8 variant in the environment, the working directory is the application, the port is exposed, and the user is switched to the unprivileged one before the Python environment is created, so the files the server writes belong to a user that is not root.
Editorial conclusion
tasmocompiler fits somebody who flashes a handful of smart home devices and wants a build with the right features and their own network credentials without learning the platform build system. It does not fit somebody who already has a reproducible platform configuration, since the tool exists precisely to avoid that work, and it does not fit a production pipeline that needs the build to be scripted from end to end. Verify first which board you are targeting, because the set of downloadable files differs between the two chip families, that the features you want exist for that board, and that the custom parameters you add use the define and undefine pattern shown, since a value set without unsetting the default will not take effect.
Frequently asked questions
What does the tasmocompiler project do?
It is a web interface for building custom Tasmota firmware. You choose the board, the features and sensors, your wireless network credentials, the firmware version, the interface language, and any custom defines, and the tool runs the build for you and gives back the firmware binary along with files recording how it was compiled.
What files do I get after a Tasmota compilation?
Four, or three for the ESP32 boards. The firmware binary, which is the one you flash to the device, a compressed version of it that the ESP32 boards do not get, the platformio configuration override recording which options the build used, and a header recording which features ended up included. The download links appear only when the compilation succeeds.
How do I run tasmocompiler?
From a container, by pulling the published image and running it with a name and a published port, then opening the local address in a browser. Or from source, by installing Node and a recent Python, the package manager, and the platform build tool, then installing the dependencies, building, and starting the server. An environment variable naming the server, git, and compile subsystems turns on debug output for the three phases.
How do I set a custom Tasmota parameter such as the MQTT broker?
In the custom parameters field, using the pattern of checking whether the symbol is defined, undefining it, and then defining it with your value. The undef matters because the firmware's own configuration header already defines the symbol, so without it your value would be ignored. The user configuration header in the Tasmota source lists every symbol that can be set this way.
What is the Tasmota development image for?
There is a branch of the compiler that follows changes in the development branch of Tasmota as closely as possible, and a matching container image tag. The readme warns that it is a leading edge version and that you should expect unexpected behaviour, so it is for testing what is new rather than for a device you depend on.
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/benzino77-tasmocompiler)Was this useful?