Open-source project
JanLunge/pog avatar
JanLunge/pog

POG: a desktop configurator for KMK keyboard firmware

A Kmk firmware flashing and configuration tool

534 stars42 forksVueMIT

At a glance

What is it?
POG is an Electron and Vue desktop tool for the KMK keyboard firmware, covering the firmware GUI, a layout editor, a keymap editor and the flashing utility in one application, with prebuilt binaries for Windows, macOS and Linux. It saves configuration as pog.json and can generate the corresponding KMK code.
Who is it for?
Adopt POG if you build KMK keyboards and want one desktop application to lay out the matrix, assign keymaps, generate the firmware code and flash the board, since that whole chain is what the tool covers. Do not adopt it if your keyboard runs QMK or ZMK, because the generated output is KMK code.
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 179 days ago.
What is it written in?
Mainly Vue, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One application for the whole KMK setup chain

POG is described in the README header as KMK GUI, Layout Editor, Keymap Editor, Flashing Utility, and the package description calls it a KMK firmware configurator.

KMK is a firmware written in CircuitPython for keyboard matrices, and a project like this exists because setting one up involves several separate artefacts that normally have to be assembled by hand: a physical matrix description, a layout file saying which key is where, a keymap saying what each key does, and the firmware configuration itself. POG's contribution is to put all four in one interface.

The four named parts are worth separating, because they are not equally complete. The Layout Editor and the Keymap Editor are the parts the tool is genuinely strong at, since a matrix layout is inherently visual and a GUI is the natural way to draw it. The Flashing Utility handles getting the result onto a board. The KMK GUI is the part where the project is most transparent about its own limits, since the task list in the README shows open items such as a way to handle differences between pog.json to KMK code, and the wishlist includes a wiring preview.

So the honest description is that POG is strongest on layout and keymap, functional on flashing, and still working toward the wiring side and the full firmware configuration surface.

The primary language is Vue, the licence is MIT, the default branch is main, and the recent releases are v2.2.3 from 2026-04-27, v2.2.0 from 2025-12-04 and v2.1.0 from 2025-09-04. The last push was on 2026-04-27, so the project has been quiet for about six months, which is worth knowing before you plan around it.

The homepage is pog.janlunge.de, and the documentation lives in a separate repository, the pog-docs project, which the README says you can feel free to contribute to. The demo/ directory holds the header and screenshot images used in the README.

An Electron shell with a Vue renderer and a Tailwind front end

The build configuration is in the repository files and it explains a lot about how the project is put together.

The application is an Electron app built with electron-vite. There are three TypeScript configurations, tsconfig.node.json for the main process, tsconfig.web.json for the renderer and a base tsconfig.json, and the typecheck script runs both, with vue-tsc handling the renderer so that Vue single-file components are type-checked.

bash
    "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
    "typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
    "typecheck": "npm run typecheck:node && npm run typecheck:web",
    "start": "electron-vite preview",
    "dev": "electron-vite dev",
    "build": "npm run typecheck && electron-vite build",

Note that the build script runs the typecheck first, so a type error fails the build rather than reaching the bundler. That is a stricter arrangement than most Electron apps take.

The front end styling is Tailwind with daisyUI as the component set, with a tailwind.config.js and a postcss.config.js, and the code is formatted with prettier and linted with eslint over the js, jsx, cjs, mjs, ts, tsx, cts, mts and vue extensions.

The dependency list tells you what the tool integrates with. The electron-toolkit packages handle preload scripts and utilities. The Vue ecosystem is substantial: @vueuse/core for composables, @floating-ui/vue for popovers, @viselect/vue for the keyboard selector preview, @mdi/font for icons, dayjs for dates, and @wlard/vue-class-store, which is the author's own class-based store library. Chroma-js is there for colour handling, which is what a visual layout editor needs.

Two dependencies stand out for what they say about the project's ambitions. drivelist enumerates connected drives, which is how the tool finds a connected keyboard in USB bootloader mode. decompress is there to unpack firmware archives. And the wallet stack, with @wagmi/core and @web3modal/ethereum, is unrelated to keyboards: the author has put a Web3 wallet connection into the application, presumably for donations or some crypto integration, which is an unusual dependency for a keyboard configurator.

The build/ directory holds a resign.js script invoked by the npm run resign script, which is what handles code signing for the macOS and Windows builds, and electron-builder.yml carries the packaging configuration with per-platform build scripts.

Building it from source on the three platforms

The build commands are per platform and each one runs the full build before packaging.

bash
# For windows
$ npm run build:win

# For macOS
$ npm run build:mac

# For Linux
$ npm run build:linux

Under the hood each script is npm run build followed by electron-builder with the right target flag and the shared --config argument, and there is a build:all that does the three of them in sequence.

The development setup is documented separately and is deliberately small. The dependencies are node 16 and yarn, you install everything with yarn, then you just run it with dev to start, which is yarn dev. To release a new version you use npm version minor or major or patch then just push and GitHub actions will do the rest.

Two things stand out. First, node 16 as the stated development dependency, which is an old baseline and is worth checking against what the current toolchain expects, since the package.json's own build scripts use npm while the README says to use yarn, and the lockfile in the repository is yarn.lock.

Second, the release flow. npm version handles the version bump and the postversion script pushes the tags, and the GitHub Actions workflow does the rest, which is the conventional electron-builder arrangement with the packaging step in CI rather than on your machine.

For ordinary users none of this matters, because the README's installation instruction is that pre-built binaries for Windows, Mac and Linux are available in the releases. So the build steps are for contributors and for anyone who needs a binary for a platform the releases do not cover.

There is also an auto-update mechanism. The dev-app-update.yml file at the root is the configuration for it, and the dependencies list electron-updater, which is what consumes that file to check for and install new versions.

The task list tells you what is finished and what is not

The README carries the project's own task list, and it is more informative than a feature list would be, because it is written by someone who knows where the sharp edges are.

Under bugs there is one open item: a maximum call stack error when closing the app. That is a crash on exit, which for a desktop tool is more annoying than it sounds, since it means the process does not shut down cleanly.

Under urgent there are two completed items and several open ones. Completed: checking if a keyboard is connected, meaning a USB drive, in the keyboard selector preview, and showing serial output in the GUI. Open: automatically getting the correct serial device by serial number, guides for the setup and split workflow plus a help menu and videos, saving wiring info in a QR code, sharing pog.json files, checking whether the controller in use even has the pin you specified with a controller lookup and serial to get pins, generating a layout based on the matrix plus a clear layout button and delete multiple, and features that are case-insensitive and settable via the GUI or pog.json.

The features wishlist is separate and entirely unchecked: a bluetooth workflow, a language switcher for German and other layouts that changes the labels on the keymap, modtap, tapdance, macros and sequences, encoder support with direct pin click, a way to handle differences between pog.json and KMK code, and a wiring preview.

Three of those are worth dwelling on because they tell you the tool's centre of gravity.

The bluetooth workflow being open means the flashing path is USB-centric today, which follows from the drivelist dependency that enumerates USB drives in bootloader mode.

The language switcher with per-layout keymap labels means the keymap editor assumes one physical layout per keymap, which is fine for a keyboard and wrong for a set of ISO layouts on the same board.

And the item about differences between pog.json and KMK code is the one that describes the boundary of the whole tool: POG's output is not KMK code itself but a pog.json that KMK reads, and the reconciliation between the two is still being worked on. That is why the description says the tool is a configurator rather than a code generator.

The split into bugs, urgent and features wishlist is itself a statement about how the author works, and it is a reasonable one.

The serial and flashing side, and the pins question

Several of the open tasks point at the same underlying difficulty, which is that a custom keyboard board is a hardware project before it is a software project.

Checking whether the controller in use even has the pin you specified is the sharpest one. A keyboard matrix is a wiring diagram, and the matrix description in a layout file is a set of row and column pins. Those pins have to exist on the specific microcontroller, and a matrix that references a pin the controller does not have will not work, and may not fail in an obvious way.

That is why the wishlist includes a controller lookup, which is the paired task of getting the pins from the serial number, and a wiring preview, which would show the matrix schematically rather than as a grid of positions.

The two completed urgent items show the direction of travel. Showing serial output in the GUI is what you need when a keyboard does not enumerate, and checking for a connected keyboard in the selector preview is what you need when the flashing target list is empty.

The flashing utility is the part of the tool with the least room for a GUI abstraction, because KMK boards in CircuitPython boot into a mass storage bootloader and you copy a firmware file onto the drive. The drivelist dependency does the enumeration and decompress unpacks the archive, so the flashing flow is essentially file copy with some device selection around it. The resign script for code signing is unrelated to the keyboard and belongs to the desktop application packaging.

The practical consequence, for a user, is that this is a tool where the hardware decides how far you can get. The layout and keymap editors are complete and independent of the board. Everything past the matrix, which is where the pins are named and the controller is identified, is the part still in progress.

The two screenshots referenced in the README, pog-header.png and pog-screenshot.png in the demo/ directory, are the practical way to see what the interface looks like before committing.

Where POG is the wrong choice

There are three limits, and the first is about firmware scope.

The first is that this is a KMK tool and nothing else. The generated output is KMK code, and the task list explicitly includes an open item about handling the differences between pog.json and KMK code. If your keyboard runs QMK, ZMK or CircuitPython firmware written by hand, POG is the wrong tool, and there is no export path described for those firmwares. QMK in particular has its own ecosystem of keymap formats and its own configurators, so the question of which tool you use is settled before any feature comparison.

The second is the hardware dependency, and it is not a limitation so much as a fact about the problem. A layout and keymap editor is only as good as the matrix description it works from, and POG's matrix input still involves naming pins, and the tool cannot yet tell you whether your controller has those pins. That is a check you would otherwise do by reading the controller's datasheet or by looking at the board's own configuration, and it is the kind of work that makes the tool less useful precisely for first-time builders, who need the guidance most.

The third is the maintenance picture and the incomplete feature set together. The last push was on 2026-04-27, with v2.2.3 published the same day, so the project has not been touched for roughly six months. That is not the same as abandoned, and the repository is not archived, but a desktop tool that depends on a specific firmware ecosystem and on device enumeration has a maintenance surface that does not stay small. The open Bluetooth workflow and the missing wiring preview are both features a keyboard builder would want, and neither is scheduled.

The honest alternatives split by what you need. For the layout editor specifically, a text editor and a text layout file is the comparison point, and for someone who already has a working KMK configuration and understands the matrix, editing the JSON directly is faster than drawing it. KMK's own documentation and examples remain the reference for what the configuration should contain. For QMK and ZMK users, the established tooling in those ecosystems is the only sensible route, since the firmware configuration formats are not interchangeable with KMK's.

What POG offers over a text editor is the part that is genuinely visual: drawing a matrix on a grid that matches the physical board, seeing the keymap labels update in place, and getting the flashing step into the same workflow. If you are building your first board and the layout is not yet in a text file, that is worth a lot. If you have a mature board with a working configuration and you are tweaking a few layers, the editor is overhead, and the gap between pog.json and KMK code is a reason to be careful.

Editorial conclusion

Adopt POG if you build KMK keyboards and want one desktop application to lay out the matrix, assign keymaps, generate the firmware code and flash the board, since that whole chain is what the tool covers. Do not adopt it if your keyboard runs QMK or ZMK, because the generated output is KMK code. Before you commit, note the last push was on 2026-04-27 with release v2.2.3 the same day, and check the open task list, since wiring preview and the Bluetooth workflow are still unchecked items.

Frequently asked questions

What is POG and what does it do for KMK keyboards?

POG is a Kmk firmware flashing and configuration tool, an Electron desktop application with a Vue front end that combines the KMK firmware GUI, a layout editor, a keymap editor and a flashing utility in one place. It saves configuration as pog.json and targets the KMK firmware for CircuitPython keyboards.

How do I install POG?

Pre-built binaries for Windows, Mac and Linux are available in the repository releases. To build from source you need node 16 and yarn, run yarn to install everything and yarn dev to start, and to release a new version use npm version minor, major or patch then push, with GitHub actions handling the rest.

How do I build POG for a specific platform?

Run npm run build:win, npm run build:mac or npm run build:linux for Windows, macOS and Linux respectively, and npm run build:all for all three. Each script runs the typecheck and the electron-vite build first, then packages with electron-builder.

Which POG features are still unfinished?

The open task list includes a maximum call stack error when closing the app, automatically detecting the correct serial device by serial number, setup guides and split workflow help, saving wiring info in a QR code, sharing pog.json files, checking that the controller has the pin you specified, and generating a layout from a matrix. The wishlist adds a bluetooth workflow, a language switcher for keymap labels, modtap, tapdance, macros and sequences, encoder support, and a wiring preview.

Where is the documentation for POG?

The documentation is in a separate repository at github.com/JanLunge/pog-docs, and the README says contributions to it are welcome. The project homepage is pog.janlunge.de, and the demo/ directory holds the header and screenshot images used in the README.

Official sources

  1. JanLunge/pog on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/janlunge-pog.svg)](https://hysenlabs.com/projects/janlunge-pog)

Was this useful?