A comprehensive template demonstrating how to package Reflex web applications into native desktop executables using PyInstaller and PyWebView.
This project serves as a reference implementation for developers looking to distribute their Reflex apps as standalone desktop applications across Windows, macOS, and Linux.
If you enjoy this project, please consider giving a star ⭐️ to support the project!
Before you begin, ensure you have the following installed on your system:
- Python - The core runtime environment
- uv - Modern Python package manager for fast dependency management
- Git - Version control system
- Node.js (optional) - Required for frontend development and building
This repository provides a complete example of how to:
- Build web applications with the Reflex framework
- Use PyWebView to embed web content in native desktop windows
- Package them as standalone desktop executables using PyInstaller
- Create cross-platform desktop apps that run without requiring users to install Python
Key Technologies:
- Reflex: A full-stack Python web framework for building interactive web applications
- PyWebView: A lightweight cross-platform wrapper around WebKit/WebView for displaying HTML content in desktop applications
- PyInstaller: Converts Python applications into standalone executables
Use this template as a starting point for your own Reflex desktop applications by modifying the source code in the app/ directory.
- Current reflex version: 0.8.25
- Current pyinstaller version: 6.18.0
- Current pywebview version: 6.1
git clone https://github.com/sandyowlet/reflex-desktop-app.git
cd reflex-desktop-appuv syncFor convenience, you can install just - a command runner that simplifies build operations.
Start the development server with hot-reload:
uv run reflex runYou can develop and preview your app in the browser following the official Reflex tutorial, enjoying the hot-reload functionality for rapid development.
Follow these steps to package your Reflex application into a standalone desktop executable.
Set your production environment variables in .env.prod (adjust these for your specific application):
# Backend server configuration
REFLEX_BACKEND_HOST=127.0.0.1
REFLEX_BACKEND_PORT=23333
REFLEX_FRONTEND_PORT=3000
# Environment mode (DEV or PROD)
REFLEX_ENV_MODE=PROD
# API endpoint URL (must match REFLEX_BACKEND_HOST and REFLEX_BACKEND_PORT)
REFLEX_API_URL=http://127.0.0.1:23333
# Enable debug mode for development
PYWEBVIEW_DEBUG=falsebuild.spec: PyInstaller configuration file - customize bundle name, app icon, and build settingsapp/run_prod.py: Main application entry point - adjust app window settings and behaviorrxconfig.py: Reflex framework configuration - refer to Reflex documentation for details
Package your web application into static files for desktop distribution:
just build-frontendManual build (if not using just):
# Set your backend configuration
backend_host=127.0.0.1
backend_port=23333
# Export frontend with production settings
API_URL="http://$backend_host:$backend_port" uv run reflex export --zip-dest-dir="dist" --frontend-only --env=prod --no-ssr
# Prepare static files directory
rm -rf ./static
unzip dist/frontend.zip -d ./staticTest the built application:
uv run app/run_prod.pyThis launches the desktop app with the packaged frontend. After testing, you can proceed with the packaging and build process.
Create a standalone executable bundle using PyInstaller:
just build-backendManual build (if not using just):
uv run pyinstaller build.spec -y --distpath=dist/app --workpath=dist/app/.buildThe compiled application bundle will be available in the dist/app folder, ready for distribution.
Important notes for building and running:
-
Module Import Issues: If you encounter "Module not found" errors during runtime, add the corresponding modules to the
hidden_importslist inbuild.spec. Since some Reflex components use lazy loading, PyInstaller cannot automatically detect them and they need to be added manually. -
Build Mode: Currently only tested in folder mode, not in single-file mode.
-
Contents Directory: Due to Reflex's internal runtime details, in folder mode, you must configure
contents_directory = "."otherwise the runtime checks will fail. -
Bundle Size: A minimal demo typically packages to around 50MB. Reflex introduces many unnecessary libraries, so if you need to reduce the size, manually exclude unnecessary packages.
This project is licensed under the MIT License - see the LICENSE file for details.
For support, questions, or contributions:
- Email: sandyowlet@gmail.com
- GitHub: Create an issue