A modern, production-ready template for developing Flipper Zero applications using the Zig programming language. This project provides a streamlined build system that integrates Zig with the Flipper Zero SDK, enabling developers to write type-safe, memory-safe applications for the Flipper Zero platform.
This template bridges Zig's powerful build system and language features with the Flipper Zero firmware development kit. It handles the complex integration between Zig's ARM Cortex-M4 cross-compilation and the Flipper SDK, providing a clean starting point for custom applications.
ufbt (unofficial build tool) for packaging FAP filesThe template uses a two-stage build process:
Zig Build Stage: Compiles Zig source to ARM Cortex-M4 object files (app.o)
thumb architecture with cortex-m4 CPU modeleabihf (Embedded Application Binary Interface, Hard Float)ReleaseSmall for minimal binary sizeUFBT Package Stage: Links object files with SDK and packages into .fap format
ufbt commandsufbt (installed to ~/.ufbt)The template is pre-configured for ARM64 macOS with the ARM toolchain path:
~/.ufbt/toolchain/arm64-darwin/arm-none-eabi/include
If you're on a different platform, you may need to adjust the arm_libc_include path in build.zig:31 to match your toolchain location.
Install UFBT:
python3 -m pip install --upgrade ufbt
ufbt update
Clone or Download This Template:
git clone https://github.com/yourusername/flipper-template.git
cd flipper-template
Initialize Your Project:
zig build init
This interactive script will prompt you for:
my_custom_app)Compile the Zig source to an object file:
zig build
This creates zig-out/bin/app.o with all the compiled application code.
Build and package the complete application:
zig build fap
This runs the full pipeline:
ufbt to link with SDK.fap file in dist/ directoryLaunch the application directly on a connected Flipper Zero:
zig build launch
This builds, packages, and transfers the app via USB, then starts it automatically.
flipper-template/
āāā application.fam # Flipper app manifest (metadata, entry points)
āāā build.zig # Zig build system configuration
āāā build.zig.zon # Zig package manifest
āāā icon.png # App icon (10x10px recommended)
āāā setup.sh # Interactive project initialization script
āāā src/
ā āāā root.zig # Main application source code
āāā zig-out/ # Build artifacts (generated)
āāā bin/
āāā app.o # Compiled object file
src/root.zig: Entry point containing the start() function and application logicapplication.fam: Flipper-specific configuration (app ID, category, dependencies, stack size)build.zig: Defines compilation targets, SDK paths, and build commandsThe template includes a "Hello World" example demonstrating core Flipper APIs:
// Import Flipper SDK functions
const flipper = @cImport({
@cInclude("furi.h");
@cInclude("gui/gui.h");
@cInclude("gui/canvas.h");
@cInclude("gui/view_port.h");
});
// Application entry point (must be named "start")
export fn start(_: ?*anyopaque) callconv(.{ .arm_aapcs = .{} }) i32 {
// Initialize GUI viewport
const gui = flipper.furi_record_open("gui");
const view_port = flipper.view_port_alloc();
// Set up callbacks and UI
// ... (see src/root.zig for complete implementation)
// Event loop
_ = flipper.furi_thread_flags_wait(1, flipper.FuriFlagWaitAny, flipper.FuriWaitForever);
return 0;
}
The build system automatically configures include paths for:
All headers are available via @cImport() in your Zig code.
Flipper SDK uses ARM AAPCS calling conventions:
start() entry point)Ensure exported functions match the expected calling convention:
export fn start(_: ?*anyopaque) callconv(.{ .arm_aapcs = .{} }) i32
export fn draw_callback(canvas: ?*Canvas, ctx: ?*anyopaque) callconv(.{ .arm_aapcs_vfp = .{} }) void
Some SDK headers contain constructs that Zig's C translator cannot process (e.g., unions with opaque types in input/input.h). For these cases, manually declare external functions:
extern fn view_port_input_callback_set(
view_port: ?*flipper.ViewPort,
callback: ?*const fn (?*anyopaque, ?*anyopaque) callconv(.{ .arm_aapcs_vfp = .{} }) void,
context: ?*anyopaque
) callconv(.{ .arm_aapcs = .{} }) void;
Issue: unable to find header 'furi.h'
~/.ufbt path incorrectufbt update to install SDK headersIssue: undefined reference to 'view_port_alloc'
zig build fap instead of zig build to complete linkingIssue: No Flipper device found
Issue: App crashes on launch
stack_size in application.fam or verify function signaturesModify addFlipperDefines() in build.zig to adjust preprocessor macros:
obj.root_module.addCMacro("FAP_VERSION", "\\\"1.0\\\"");
obj.root_module.addCMacro("CUSTOM_DEFINE", "value");
Change optimization level in build.zig:11:
const optimize = b.standardOptimizeOption(.{
.preferred_optimize_mode = .ReleaseFast, // or .ReleaseSmall, .Debug
});
The template targets Flipper Zero's STM32WB55 (ARM Cortex-M4F). To port to other ARM devices, adjust build.zig:4-9:
const target = b.resolveTargetQuery(.{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m4 },
.os_tag = .freestanding,
.abi = .eabihf,
});
Contributions are welcome! This template aims to simplify Zig development for Flipper Zero. If you encounter SDK compatibility issues or have suggestions for improving the build process, please open an issue or pull request.
This project is licensed under the MIT License - see the LICENSE file for details.
Note: This is an unofficial template and is not affiliated with Flipper Devices Inc. Always test applications thoroughly before deploying to production devices.