fzgen
May 28, 2026 · View on GitHub
A Perl script that scaffolds Flipper Zero external application (FAP) projects from a simple INI config file. Generates all the boilerplate — app header, main C file, scene manager wiring, scene stubs — so you can start writing actual logic immediately.
Designed to work with Unleashed firmware but compatible with stock firmware and other forks.
Requirements
- Perl (any modern version — uses only core modules plus
MIME::Base64) - Unleashed firmware repo with
fbtfor building the generated project
Usage
perl fzgen.pl myapp.ini ./myapp
Then drop the output folder into the firmware tree and build:
cp -r ./myapp unleashed-firmware/applications_user/
cd unleashed-firmware
./fbt fap_myapp
What gets generated
myapp/
├── application.fam — FAP manifest (appid, name, category, etc.)
├── myapp_icon.png — Placeholder 10x10 1-bit icon (box border)
├── myapp_app.h — App struct, scene/view/event enums
├── myapp.c — Entry point, alloc/free, view dispatcher
└── scenes/
├── myapp_scene.h — Forward declarations for all scenes
├── myapp_scene_config.c — Handler array table (wires scenes together)
├── myapp_scene_splash.c — Scene stub (on_enter / on_event / on_exit)
├── myapp_scene_menu.c — Scene stub
└── myapp_scene_*.c — One stub per scene in your config
Regeneration — safe by design
Running fzgen.pl on an existing project updates it without stomping your code.
| File | Behavior |
|---|---|
application.fam | Always regenerated — never hand-edit this |
myapp_icon.png | Created once, never overwritten — replace with your own icon |
myapp_scene_config.c | Always regenerated — never hand-edit this |
myapp_app.h | Marker-based updates only — your custom code is preserved |
myapp.c | Marker-based updates only — your custom code is preserved |
scenes/myapp_scene.h | Marker-based updates only |
scenes/myapp_scene_*.c | Created once, never overwritten — you own these |
Adding a new scene to the config creates only the new scene file. Existing scene files are skipped entirely.
Marker system
Generated sections in .h and main .c files are wrapped in markers:
// @FZGEN_BEGIN scene_enum
typedef enum {
MyappSceneSplash,
MyappSceneMenu,
MyappSceneCount,
} MyappScene;
// @FZGEN_END scene_enum
On regeneration, only the content between markers is replaced. Everything outside the markers — your custom includes, functions, and logic — is untouched.
Config file format
See framework.ini for a fully commented template. The short version:
[app]
id = myapp
name = My App
author = YourName
category = Misc
stack_size = 2 * 1024
[scenes]
Splash = default # must have exactly one default
Menu
Detail
Result
[struct]
bool show_hints
uint8_t selected_index
[events]
AppExit
SplashNext
MenuSelect
Sections
[app] — metadata written into application.fam
| Key | Description |
|---|---|
id | Lowercase app identifier — used in filenames and function names |
name | Human-readable name shown in the Flipper app browser |
author | Your name or handle |
category | App browser folder: RFID, NFC, Bluetooth, GPIO, Tools, Games, Misc |
stack_size | Stack in bytes — 2 * 1024 for simple apps, 4 * 1024 for heavier work |
[scenes] — one scene per line in PascalCase, exactly one marked = default
[struct] — extra fields added to the app struct, written as C declarations without the semicolon
[events] — custom event names added to the CustomEvent enum
Comments (#) are supported anywhere.
Generated scene stub
Each scene file starts as:
#include "myapp_scene.h"
// @FZGEN_BEGIN splash_on_enter
void myapp_scene_splash_on_enter(void* context) {
furi_assert(context);
MyappApp* app = context;
UNUSED(app);
// @FZGEN_END splash_on_enter
// TODO: add your on_enter logic here
// @FZGEN_BEGIN splash_on_enter_close
view_dispatcher_switch_to_view(app->view_dispatcher, MyappViewSplash);
}
// @FZGEN_END splash_on_enter_close
Your logic goes in the // TODO sections. The markers at the top and bottom
of each function allow the generator to update the function signature if
needed without touching your implementation.
Notes
- All views are generated as
Widget*by default. If a scene needs aSubmenu,Popup, orVariableItemList, change the type inmyapp_app.hand update the alloc/free inmyapp.cmanually. - The placeholder icon is a 10x10 1-bit PNG box border embedded in the
script as base64. Replace
myapp_icon.pngwith your own icon — it will never be overwritten. scenes/myapp_scene_config.cis always regenerated since it's pure boilerplate. Never hand-edit it.
License
Do what you want with it.