Buildfy v3.0 Documentation

Build Python desktop
apps visually

Buildfy is a drag-and-drop GUI builder that generates clean, runnable Python code for CustomTkinter — no boilerplate, no guessing the API.

🐍 CustomTkinter 5.x 🎨 Dark-first design ⚡ Node-based events 📦 Export to .py 💾 .bfy project files
B
Buildfy v3.0 FREE · 3 exports left
⬡ Nodes
</> Code
▶ Preview
100%
+
🔍 Search widgets...
T
Label
B
Button
I
Image
E
Entry
Checkbox
Switch
Slider
Frame
My App
Welcome to my app
Click Me
Enter your name...
Enable feature
Position
Size
Text
Color
Layers (3)
Button_a1b2
Label_c3d4
Entry_e5f6

Installation

Buildfy runs entirely in your browser — no installation required. Just open the app and start building. The only prerequisite is Python with CustomTkinter installed on your machine to run the exported code.

1

Open Buildfy v3.0

Navigate to the Buildfy web app in any modern browser (Chrome, Firefox, Safari, Edge). No sign-up required to start building.

2

Install Python & CustomTkinter

To run exported apps, install Python 3.10+ and CustomTkinter on your machine.

3

Run your exported app

Export your design as a .py file and run it with python app.py.

bash Terminal
# Install CustomTkinter
pip install customtkinter

# Run your exported Buildfy app
python my_app.py
💡
Python 3.10+ recommendedBuildfy generates code targeting Python 3.10 and above. CustomTkinter 5.x requires Python 3.8 minimum, but some features work best on 3.10+.

Quick start

Build your first app in under two minutes. This walkthrough creates a simple login form.

1

Set your canvas size

In the Base Properties section of the right panel, set Width to 400 and Height to 300. Type a title like Login.

2

Drag widgets onto the canvas

From the left panel, drag a Label, two Entry widgets, and a Button onto the canvas. Position them to form a login layout.

3

Edit widget properties

Click each widget to select it, then edit its text, color, and size in the right panel. Set the password Entry's show property to *.

4

Export to Python

Click File → Export Python or press ⌘E / Ctrl+E. Review the code in the preview, then download the .py file.

5

Run it

Open a terminal and run python login.py. Your CustomTkinter app launches immediately.

Login — Buildfy canvas preview
Sign In
Username
••••••••
Login
Forgot password?

Toolbar

The toolbar spans the top of the Buildfy window and is divided into three zones: left (brand + menus), center (wordmark), and right (tools + zoom).

Buildfy v3.0 — Toolbar
B
Buildfy v3.0
Buildfy v3.0 FREE · 3 exports left
Nodes
</> Code
▶ Preview
100%
+
Left zone
Logo mark · App name · File/Edit/View/About menus
Right zone
Nodes · Code · Preview · Zoom (−/100%/+)

Menu system

All three menus (File, Edit, View) use a macOS-style frosted-glass dropdown. On Mac, shortcuts display as symbols. On Windows/Linux they display as Ctrl/Shift/Alt text.

File menu — frosted glass
New⌘N
Open…⌘O
Save⌘S
Save As…⇧⌘S
Export Python…⌘E
Export as PNG⇧⌘E
Recent Projects

Widget panel

The left sidebar lists every available widget organized into collapsible categories. Use the search bar at the top to filter by name.

Widget panel
🔍 Search widgets...
T
Label
B
Button
Image
Frame
ScrollableFrame
TabView
_
Entry
Drag any widget pill onto the canvas to place it.
B
Drag to place
↓ Drop here
Double-click a widget pill to insert it at canvas center.
ℹ️
Lock icon on widgetsSome widgets (ScrollableFrame, TabView) show a lock icon — these are premium or complex widgets. All standard widgets are free to use.

Canvas

The canvas is your app's visual editor. It shows a floating inner window (your future Python app) centered on a pannable grid background. Every widget placed here maps 1:1 to Python code.

Navigation

ActionHow
Pan canvasSpace + drag
Zoom in / outCtrl+Scroll or toolbar ± buttons
Reset zoom⌘0 / Ctrl+0

Selecting widgets

Widget selection — resize handles
Click Me
x: 120 · y: 80
Single selected
Button
Entry field
2 selected
Multi-select (Shift+click)

Snapping & guides

Alignment guides
Label
Button
Snap guide (8px grid)

Right-click context menu

Context menu on widget
Button
Duplicate⌘D
Cut⌘X
Copy⌘C
Bring to Front
Send to Back
Edit Behavior (Nodes)
Lock
Delete

Properties panel

The right panel updates live whenever you select a widget. It is organized into three tabs: Layout, Style, and Behavior.

Properties panel — CTkButton selected
Click Me
Layout
Style
Behavior
Position
XY
Size
WH
Corner radius
Style
Text
Text color
Background
State

Property reference — CTkButton

PropertyTypeDescription
textstringLabel displayed on the button
widthintWidget width in pixels (set in constructor)
heightintWidget height in pixels (set in constructor)
fg_colorhex stringBackground fill color
hover_colorhex stringColor on mouse hover
text_colorhex stringLabel text color
corner_radiusintBorder radius in pixels
fonttupleFont as ("Arial", 14) or CTkFont
state"normal" | "disabled"Interactive state
commandfunction namePython callback on click
⚠️
Never pass width/height to .place()CustomTkinter requires width and height in the constructor only. Buildfy generates this correctly — if you edit the code manually, keep width/height in ctk.CTkButton(self, width=120, height=36, ...) and use only x= and y= in .place().

Layers panel

The Layers section lists every widget on the canvas in z-order (topmost first). Use it to select, reorder, rename, show/hide, and lock widgets.

Layers panel
Layers (4)
Button_a1b2 👁 🔓
Label_c3d4 👁 🔓
Entry_e5f6 🔒 🙈
Frame_g7h8 👁 🔓
Drag rows to reorder z-index. Double-click name to rename.

Basic widgets

The core display and interaction widgets. These map to fundamental CustomTkinter classes.

T

Label

Display static or dynamic text. Supports font, color, alignment, and wraplength.

CTkLabel

Button

Clickable button with customizable colors, radius, and command callback.

CTkButton
🖼

Image

Display a PIL/CTkImage inside a label. Requires an image_path to be set.

CTkLabel + CTkImage
Basic widgets preview
CTkLabel
Welcome to Buildfy
Subtitle text here
Muted caption
CTkButton
Primary Action
Secondary
Link button

Input widgets

Interactive controls that accept user input. Each generates correct Python with proper post-placement calls for value initialization.

_

Entry

Single-line text input. Use show="*" for passwords. Supports placeholder text.

CTkEntry

TextBox

Multi-line text editor. Initialized with .insert("0.0", text) after placement.

CTkTextbox

Checkbox

Toggle with a checkmark. State set with .select() or .deselect() after placement.

CTkCheckBox

Switch

On/off toggle pill. Use .select() / .deselect() for default state.

CTkSwitch

Radiobutton

Requires a shared tk.IntVar variable declared before the widget group.

CTkRadioButton

Slider

Range control. Default value set with .set(value) after placement, not in constructor.

CTkSlider

ComboBox

Editable dropdown. values= takes a Python list of strings.

CTkComboBox

OptionMenu

Non-editable dropdown. values= takes a Python list of strings.

CTkOptionMenu
▮▯

SegmentedButton

Tabbed button group. Each segment is a selectable option.

CTkSegmentedButton
Input widgets preview
CTkEntry
Enter text...
CTkCheckBox
Enable notifications
CTkSwitch
Dark mode
CTkRadioButton
Option A
Option B
CTkSlider
CTkProgressBar
CTkComboBox
Select option...
CTkSegmentedButton
Day
Week
Month
⚠️
Value initialization rulesNever pass value= to CTkSlider, CTkProgressBar, CTkSwitch, or CTkCheckBox constructors — it will crash. Buildfy handles this automatically by emitting .set() and .select() calls after .place().

Container widgets

Containers hold other widgets. In the generated Python code, child widgets placed inside a container use the container as their master.

Frame

Basic grouping container with customizable background, border, and corner radius.

CTkFrame

ScrollableFrame

Frame with a built-in scrollbar. Use label_text= for a header label.

CTkScrollableFrame

TabView

Multi-tab container. Tabs added with .add("Tab Name") after placement.

CTkTabview

Display widgets

Progressbar

Horizontal progress indicator. Value set with .set(0.0–1.0) after placement. Never pass value= to constructor.

CTkProgressBar

Canvas (drawing)

Raw drawing surface using standard tkinter tk.Canvas — not a CTk widget.

tk.Canvas

Node editor

The node editor lets you wire widget behaviors visually without writing Python event handlers. Open it via the Nodes button in the toolbar (⌘J / Ctrl+J) or by right-clicking any widget and choosing Edit Behavior (Nodes).

Node Editor — Buildfy v3.0
← Back · Node Editor
+ Add Node
Auto Layout
Done
On Click
Target widget
If / Else
trigger true →
value_a false →
Set Text
trigger done
Hide Widget
trigger done

Node categories

Trigger nodes

On Click · On Value Change · On App Start · On Key Press. These start every behavior chain.

Action nodes

Set Text · Set Value · Show/Hide Widget · Enable/Disable · Set Color · Print Message.

Logic nodes

If/Else · Counter. Branch your behavior flow based on conditions.

Data nodes

Get/Set Variable · Get Widget Value · Format String. Pass data between nodes.

Generated Python

When you export, the node graph produces a _setup_events method that is automatically called from __init__:

Python_setup_events (generated)
    def _setup_events(self):
        self.button_a1b2.configure(command=self._button_a1b2_click)

    def _button_a1b2_click(self):
        if value > 50:
            self.label_c3d4.configure(text="High!")
        else:
            self.entry_e5f6.place_forget()

Code panel

Toggle the live code panel with the Code button in the toolbar (⌘K / Ctrl+K). It opens as a resizable split pane alongside the canvas.

Code panel — live Python preview
Canvas (60%)
My Button
Entry field
Python customtkinter 5.x
↻ Sync
Copy
↓ .py
# Generated by Buildfy v3.0
import customtkinter as ctk
import tkinter as tk

ctk.set_appearance_mode("dark")

class App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.title("My App")
        self.geometry("800x600")
        self._setup_widgets()

    def _setup_widgets(self):
        self.button_a1b2 = ctk.CTkButton(
            self, width=120, height=36,
            text="My Button",
            fg_color="#F0525C"
        )
        self.button_a1b2.place(x=40, y=40)
💡
Live syncCanvas changes debounce into the code editor after 400ms. Edits you make in the code editor propagate back to the canvas after 800ms (best-effort parse). Use ↻ Sync to force a full regeneration at any time.

Export & save

Save project (.bfy)

Projects save as .bfy JSON files. Press ⌘S / Ctrl+S or use File → Save. The format captures all widget state, positions, properties, and node graphs.

JSONproject.bfy
{
  "version": "3.0",
  "canvas": {
    "width": 800, "height": 600,
    "title": "My App", "theme": "dark"
  },
  "widgets": [
    {
      "id": "btn_a1b2c3", "type": "CTkButton",
      "name": "Button_a1b2",
      "x": 120, "y": 80, "width": 120, "height": 36,
      "properties": {
        "text": "Click Me",
        "fg_color": "#F0525C"
      },
      "locked": false, "visible": true, "zIndex": 0
    }
  ],
  "nodeGraphs": { "global": {} }
}

Export Python (.py)

Use File → Export Python or ⌘E / Ctrl+E. A modal shows a syntax-highlighted preview with a validation banner before you download.

Export Python — My_App.py
Copy code
pip install cmd
↓ Download .py
✓ Code validated — ready to run. No issues found.
# Generated by Buildfy v3.0
# Requirements: pip install customtkinter
import customtkinter as ctk
import tkinter as tk

ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("blue")

class App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.title("My App")
        self.geometry("800x600")
        self.resizable(True, True)
        self._setup_widgets()

    def _setup_widgets(self):
        self.button_a1b2 = ctk.CTkButton(
            self, width=120, height=36,
            text="Click Me", fg_color="#F0525C",
            font=("Inter", 13)
        )
        self.button_a1b2.place(x=120, y=80)

def main():
    app = App()
    app.mainloop()

if __name__ == "__main__":
    main()

Export formats

FormatShortcutDescription
Python (.py)⌘EComplete runnable CustomTkinter app
PNG image⇧⌘ECanvas rendered as a flat PNG screenshot
JSON (.bfy)Raw widget tree for backup or sharing

Keyboard shortcuts

All shortcuts use on macOS and Ctrl on Windows/Linux. Buildfy detects your OS automatically.

File

ActionShortcut
New project⌘N
Open project⌘O
Save⌘S
Save As⇧⌘S
Export Python⌘E
Export PNG⇧⌘E

Edit

ActionShortcut
Undo⌘Z
Redo⇧⌘Z
Cut⌘X
Copy⌘C
Paste⌘V
Duplicate⌘D
Delete
Select all⌘A
Group⌘G
DeselectEsc

Canvas & view

ActionShortcut
Zoom in⌘+
Zoom out⌘−
Reset zoom⌘0
Pan canvasSpace + drag
Nudge widget 1px↑↓←→
Nudge widget 10px + ↑↓←→
Toggle node editor⌘J
Toggle code panel⌘K
Toggle preview⌘P

.bfy file format

Buildfy projects are stored as .bfy files — standard JSON with a defined schema. You can inspect or edit them manually.

Schema

KeyTypeDescription
versionstringBuildfy version that created the file (e.g. "3.0")
canvas.widthintApp window width in pixels
canvas.heightintApp window height in pixels
canvas.titlestringWindow title shown in the title bar
canvas.theme"dark" | "light" | "system"CustomTkinter appearance mode
widgets[]arrayOrdered array of widget objects
widgets[].idstringUnique identifier (e.g. "btn_a1b2c3")
widgets[].typestringCTk class name (e.g. "CTkButton")
widgets[].namestringPython variable name used in generated code
widgets[].x, .yintPosition on canvas (always integers)
widgets[].width, .heightintWidget size (passed to constructor)
widgets[].propertiesobjectWidget-specific props (text, fg_color, etc.)
widgets[].zIndexintStacking order (0 = bottom)
nodeGraphsobjectSerialized node editor graphs per widget

Python output reference

Every exported file follows the same template. Understanding it helps you extend or debug generated code.

PythonFull output template
# Generated by Buildfy v3.0
# Requirements: pip install customtkinter
import customtkinter as ctk
import tkinter as tk

ctk.set_appearance_mode("dark")         # "dark" | "light" | "system"
ctk.set_default_color_theme("blue")    # from Base Properties > Color


class App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.title("My Application")
        self.geometry("800x600")
        self.resizable(True, True)
        self._setup_widgets()
        self._setup_events()  # only if node graph is non-empty

    def _setup_widgets(self):
        # ── Widgets ────────────────────────────────
        self.button_a1b2 = ctk.CTkButton(
            self, width=120, height=36,
            text="Click Me",
            fg_color="#F0525C",
            font=("Inter", 13)
        )
        self.button_a1b2.place(x=120, y=80)   # x and y ONLY
        self._button_a1b2_x = 120             # stored for show/hide
        self._button_a1b2_y = 80

        # post-placement value calls:
        self.slider_b2c3.set(50)              # CTkSlider
        self.pb_c3d4.set(0.7)                # CTkProgressBar
        self.switch_d4e5.select()             # CTkSwitch (on)

    def _setup_events(self):
        # Generated from node editor
        self.button_a1b2.configure(
            command=self._button_a1b2_click
        )

    def _button_a1b2_click(self):
        self.label_e5f6.configure(text="Clicked!")


def main():
    app = App()
    app.mainloop()


if __name__ == "__main__":
    main()
🚨
Golden rules for manual edits 1. Never pass width= or height= to .place() — they belong in the constructor.
2. Never pass value= to CTkProgressBar, CTkSlider, CTkSwitch, or CTkCheckBox constructors — use .set() or .select() after .place().
3. CTkRadioButton always needs a variable=tk.IntVar().

FAQ

My app crashes with "width and height must be passed to the constructor"

You (or a previous version of Buildfy) generated code with width= and height= inside the .place() call. CustomTkinter forbids this. Move them to the widget constructor: ctk.CTkButton(self, width=120, height=36, ...), and use only x= and y= in .place().

My app crashes with "'value' are not supported arguments"

CTkProgressBar, CTkSlider, CTkSwitch, and CTkCheckBox do not accept value= in their constructors. Remove it and add a .set() or .select() call after the .place() call.

CTkRadioButton crashes on launch

RadioButtons require a shared tk.IntVar. Declare it before the widget: self.rb_var = tk.IntVar(value=0), then pass variable=self.rb_var to each button in the group.

Node connections don't stick

Drag from an output port (right side, colored circle) to an input port (left side, gray circle). Make sure to release the mouse directly on the target port. The connection appears as a colored Bezier curve.

Can I use Buildfy offline?

Buildfy is a browser-based app and requires an internet connection to load. Once loaded, most editing features work without network access. Saving files downloads them to your machine so they are always available locally.

What Python version do I need?

Python 3.10 or later is recommended. CustomTkinter 5.x requires Python 3.8 minimum, but several features behave best on 3.10+.

Buildfy v3.0 Documentation · Proxlight
Built for CustomTkinter 5.x · Python 3.10+