Everything you need to know about developing, debugging, building and deploying your LÖVE game using this template system - from local development workflows to automated multi-platform releases. This guide covers technical setup, IDE integration, build configurations, and deployment options.
Overview of the key files and directories in the template. The main components are GitHub Actions workflows, IDE configuration files, game source code, and build outputs.
.
├── .github GitHub Actions configuration
├── .editorconfig EditorConfig file
├── .vscode Visual Studio Code configuration
│ ├── extensions.json
│ ├── launch.json
│ └── tasks.json
├── builds Game builds
├── game
│ ├── conf.lua LÖVE configuration file
│ ├── main.lua main.lau with example "game" - you can delete this
│ ├── main.template.lua main.lua template - rename to main.lua
│ ├── product.env Settings shared between the game and GitHub Actions
│ ├── eyes Example "game" - you can delete this
│ ├── lib Libraries
│ └── runtime Native libraries for HTTPS support
├── resources Resources use when building the game. Icons, shared libraries, etc.
└── tools Tools for building and packaging the game
The .vscode
folder contains project specific configuration.
extensions.json
: Contains the list of recommended extensionslaunch.json
: Contains the settings for running the game or launching the debuggertasks.json
: Contains the settings for building the game
You can configure additional settings and individual preferences via your own .vscode/settings.json
that is excluded version control.
Secrets are stored in the GitHub repository settings and accessed by the GitHub Actions workflow.
https://github.com./{username}/{repository}/settings/secrets/actions
The game and build settings are configured using game/product.env
.
The most important settings to change for your game:
PRODUCT_NAME
- The name of your gamePRODUCT_ID
- Unique identifier in reverse domain notation. Can not contain spaces or hyphens.
PRODUCT_ID
is always used by t.identity
in game/conf.lua
to determine the save directory for the game. This is important to consider when changing the PRODUCT_ID
after the game has been released.
You can override the PRODUCT_ID
for specific platforms.
If a platform-specific ID is empty or not set, the base PRODUCT_ID
will be used instead. This is useful for:
- Different bundle IDs per platform
- App store requirements
# Base product ID (used as fallback)
PRODUCT_ID="com.oval-tutu.game"
# Optional platform-specific overrides
PRODUCT_ID_ANDROID="com.mygame.android"
PRODUCT_ID_IOS="com.mygame.ios"
PRODUCT_ID_LINUX="com.mygame.linux"
PRODUCT_ID_MACOS="com.mygame.osx"
PRODUCT_ID_WINDOWS="com.mygame.windows"
PRODUCT_UUID
- Generate new UUID usinguuidgen
command or the UUID GeneratorPRODUCT_DESC
- Short description of your gamePRODUCT_COPYRIGHT
- Copyright noticePRODUCT_COMPANY
- Your company/organization namePRODUCT_WEBSITE
- Your game or company website
You can disable build targets by setting them to "false"
if you don't need builds for certain platforms.
# LÖVE version to target (only 11.5 is supported)
LOVE_VERSION="11.5"
# Enable/disable microphone access
AUDIO_MIC="false"
# Android screen orientation (landscape/portrait)
ANDROID_ORIENTATION="landscape"
# Itch.io username for publishing
ITCH_USER="ovaltutu"
# Build output directory
OUTPUT_FOLDER="./builds"
# Game metadata
PRODUCT_NAME="Template"
PRODUCT_ID="com.ovaltutu.template"
PRODUCT_DESC="A template game made with LÖVE"
PRODUCT_COPYRIGHT="Copyright (c) 2025 Oval Tutu"
PRODUCT_COMPANY="Oval Tutu"
PRODUCT_WEBSITE="https://oval-tutu.com"
PRODUCT_UUID="3e64d17c-8797-4382-921f-cf488b22073f"
# Enable/disable build targets
TARGET_ANDROID="true"
TARGET_IOS="true"
TARGET_LINUX_APPIMAGE="true"
TARGET_LINUX_TARBALL="true"
TARGET_MACOS="true"
TARGET_WEB="true"
TARGET_WINDOWS_INSTALL="true"
TARGET_WINDOWS_SFX="false"
TARGET_WINDOWS_ZIP="true"
The GitHub Actions workflow will automatically build and package the game for all the supported platforms that are enabled in game/product.env
and upload them as assets to the GitHub releases page.
- Android
.apk
debug builds for testing and release builds for publishing to Itch.io.aab
release build for publishing to the Play Store
- HTML
- iOS (notarization is not yet implemented)
- Linux
- AppImage
- Tarball
- macOS
.app
Bundle (notarizing is not yet implemented).dmg
Disk Image (notarizing is not yet implemented)
- Windows (64-bit)
- Installer (NSIS installer, notarizing is not implemented)
- .exe (self-extracting, notarizing is not implemented)
- .zip
Development builds are triggered in two ways:
- Manual trigger via GitHub Actions interface ("workflow_dispatch")
- Go to "Actions" tab > "Build LÖVE" workflow > "Run workflow" button > "Run workflow"
- Any push that isn't a version tag
The build process:
- Creates a
.love
file from your game code - Packages platform-specific builds for enabled targets
- Uploads artifacts to GitHub Actions
Artifacts produced (if enabled in game/product.env
):
{PRODUCT_NAME}.love
- Base LÖVE game package{PRODUCT_NAME}-debug-signed.apk
- Android debug build{PRODUCT_NAME}-release-signed.apk
- Android release build{PRODUCT_NAME}-installer.exe
- Windows installer{PRODUCT_NAME}.exe
- Windows self-extracting executable{PRODUCT_NAME}.zip
- Windows build{PRODUCT_NAME}-html
- HTML build{PRODUCT_NAME}.app
- macOS application bundle{PRODUCT_NAME}.dmg
- macOS disk image{PRODUCT_NAME}.ipa
- iOS package
Access the builds:
- Go to your repository's Actions tab
- Select the workflow run
- Download artifacts from the "Artifacts" section
- Extract the .zip files before use
💡NOTE: Artifacts are retained for 90 days by default.
Make a new release by creating a version number git tag without the v
prefix.
- Create a new tag: Use the following command to create a new tag.
- Replace
1.0.0
with your desired version number.
- Replace
git tag 1.0.0
- Push the tag to GitHub: Push the tag to the remote repository.
git push origin 1.0.0
- GitHub Actions: The GitHub workflow will automatically create a release and upload packages for all the supported platforms as assets.
On a Release Build (a tagged version), the GitHub Actions workflow will automatically publish the game artifacts for the enabled platforms to the GitHub releases page. You can download the artifacts from the releases page and manually upload them to the appropriate stores. But you can also automate this process for the following platforms:
The GitHub Actions workflow will automatically publish the game artifacts for enabled platforms to Itch.io if BUTLER_API_KEY
secret and ITCH_USER
are set.
Get your API key from Itch.io account.
ITCH_USER
from game/product.env
will be used as the username, and PRODUCT_NAME
from game/product.env
(automatically converted to lowercase with spaces replaced with hyphens -
) will be used as the game name.
For example this template project would attempt to publish to ovaltutu/template
.
Not every artifact will be published to Itch.io, as some platforms are not supported, and some artifacts are unsuitable for distribution on Itch.io:
.love
files will be published to Itch.io as it is a requirement for LÖVE jams, is a convenient format for testing and can be hidden if required.- Android .apk files will be published to Itch.io if
TARGET_ANDROID
is enabled. - Linux AppImage files will be published to Itch.io if
TARGET_LINUX_APPIMAGE
is enabled. - macOS .dmg files will be published to Itch.io if
TARGET_MACOS
is enabled. - Windows win64 self-extracting .exe files will be published (in a .zip) to Itch.io if
TARGET_WINDOWS_SFX
is enabled. - HTML artifacts will be published to Itch.io if
TARGET_HTML
is enabled. - Itch.io does not support iOS artifacts.
If you're running Linux or macOS, have act
installed and configured to run the GitHub Actions locally then you can use ./tools/build.sh linux
to automatically push new Linux builds directly to your Steam Deck using the SteamOS DevKit Client Tool.
- Install the SteamOS DevKit: Follow the instructions in the How to load and run games on Steam Deck to install the SteamOS Devkit Client Tool and connect to your Steam Deck to your development machine.
- Execute
./tools/build.sh linux
which will build the Linux tarball and notify the SteamOS DevKit Client API to automatically push the new build to the Steam Deck. - On your Steam Deck, navigate the library to find a new title named 'Devkit Game: YourGameName' and select it to run.
In order to sign the APKs and AABs, the zipalign & Sign Android Release Action is used. You'll need to create Debug and Release keystores and set the appropriate secrets in the GitHub repository settings.
This creates a standard debug keystore matching Android Studio's defaults, except it is valid for 50 years.
keytool -genkey -v \
-keystore debug.keystore \
-alias androiddebugkey \
-keyalg RSA -keysize 2048 -validity 18250 \
-storepass android \
-keypass android \
-dname "CN=Android Debug,O=Android,C=US"
Create base64 encoded signing key to sign apps in GitHub CI.
openssl base64 < debug.keystore | tr -d '\n' | tee debug.keystore.base64.txt
Add these secrets to the GitHub repository settings:
ANDROID_DEBUG_SIGNINGKEY_BASE64
ANDROID_DEBUG_ALIAS
ANDROID_DEBUG_KEYSTORE_PASSWORD
ANDROID_DEBUG_KEY_PASSWORD
This creates a release keystore with a validity of 25 years.
keytool -genkey -v \
-keystore release-key.jks \
-alias release-key \
-keyalg RSA -keysize 2048 -validity 9125 \
-storepass [secure-password] \
-keypass [secure-password] \
-dname "CN=[your name],O=[your organisation],L=[your town/city],S=[your state/region/county],C=[your country code]"
Create base64 encoded signing key to sign apps in GitHub CI.
openssl base64 < release-key.jks | tr -d '\n' | tee release-key.jks.base64.txt
Add these secrets to the GitHub repository settings:
ANDROID_RELEASE_SIGNINGKEY_BASE64
ANDROID_RELEASE_ALIAS
ANDROID_RELEASE_KEYSTORE_PASSWORD
ANDROID_RELEASE_KEY_PASSWORD
The HTML build use love.js player from 2dengine.
The love.js player needs to be delivered via a web server, it will not work if you open index.html
locally in a browser.
You need to set the correct CORS policy via HTTP headers for the game to work in the browser.
Here are some examples of how to do that.
Use miniserve
to serve the HTML build of the game using the correct CORS policy.
tools/test-html.sh
is a convenience script that does that. It looks for builds/1/<PRODUCT_FILE>-html/<PRODUCT_FILE>-html.zip
, rewrites the index.html
to bust the cache and adds the required CORS headers.
./tools/test-html.sh
Then open http://localhost:1337
in your browser.
<IfModule mod_headers.c>
Header set Cross-Origin-Opener-Policy "same-origin"
Header set Cross-Origin-Embedder-Policy "require-corp"
</IfModule>
<IfModule mod_mime.c>
AddType application/wasm wasm
</IfModule>
example.com {
header {
Cross-Origin-Opener-Policy "same-origin"
Cross-Origin-Embedder-Policy "require-corp"
Set-Cookie "Path=/; HttpOnly; Secure"
}
# ... rest of your site configuration
}
add_header Cross-Origin-Opener-Policy "same-origin";
add_header Cross-Origin-Embedder-Policy "require-corp";
add_header Set-Cookie "Path=/; HttpOnly; Secure";
On itch.io, the required HTTP headers are disabled by default, but they provide experimental support for enabling them. Learn how to enable SharedArrayBuffer support on Itch.io.
This is not required for the project to work.
Support for running GitHub Actions locally via
act
is mainly included to test the GitHub Actions workflow locally before pushing changes to the repository and accelerating the development process of the bundled actions.
In order to use the GitHub Actions locally, you'll need to install act and Podman or Docker.
This template includes .actrc
which will source local secrets and expose them as GitHub secrets to act
.
The .actrc
file configures how act
runs GitHub Actions locally:
# Load GitHub secrets from this file
--secret-file=$HOME/.config/act/secrets
# Store build artifacts in the ./builds directory
--artifact-server-path=./builds
# Force container architecture to linux/amd64
--container-architecture=linux/amd64
# Disable automatic pulling of container images
--pull=false
Key configuration explained:
--secret-file
- Path to file containing GitHub secrets (API keys, signing keys etc.)--artifact-server-path
- Local directory where build artifacts will be stored--container-architecture
- Forces x86_64 container architecture for compatibility--pull
- Prevents automatic downloading of container images on each run
Create the secrets file at ~/.config/act/secrets
with your GitHub repository secrets before running act.
act
will run all the GitHub Actions locally.act -l
will list all the available GitHub Actions.act -j <job>
will run a specific job.
To run jobs that runs-on: macos-latest
on your Mac you'll need to use act -P macos-latest=-self-hosted
which will run the job on your Mac instead of the GitHub runner. For example:
act -j build-macos -P macos-latest=-self-hosted
In order to run the macOS jobs you'll need to install the following:
- Install Podman Desktop or Docker Desktop.
- Install Xcode:
xcode-select --install
- Install additional tools via Homebrew:
brew install act create-dmg tree
This project includes HTTPS support for LÖVE 11.5 via the lua-https library, and also included an native library loader for easily enabling HTTPS support on supported platforms.
- For LÖVE 12.0+: Uses the built-in
https
module - For LÖVE 11.5: Loads platform-specific native libraries
- For HTML builds: No lua-https support is available.
The runtime loader (game/runtime/loader.lua
) handles loading the appropriate platform-specific native library:
local https = require('runtime.loader').loadHTTPS()
if https then
-- HTTPS is available
local code, body, headers = https.request("https://oval-tutu.com")
else
-- HTTPS not available (Web platform or missing library)
end
For more information on the https
module, see the lua-https documentation.
The loader expects native libraries to be organized in the following structure:
game/runtime/https/
├── android/
│ ├── arm64-v8a/
│ │ └── https.so
│ └── armeabi-v7a/
│ └── https.so
├── linux/
│ └── x86_64/
│ └── https.so
├── osx/
│ └── https.so
└── windows/
└── win64/
└── https.dll
The template includes pre-built libraries for:
- Windows (64-bit)
- Linux (x86_64)
- macOS (Universal)
- Android (arm64-v8a, armeabi-v7a)
💡NOTE: HTTPS is not available on iOS builds, yet...
The native libraries have the following dependencies that must be available on the target system:
- Linux: cURL or OpenSSL
- Windows: No additional dependencies (libraries are statically linked)
- macOS: No additional dependencies (uses native Security framework)
- Android: No additional dependencies (included in Android system)
- But does require your Android game is built with build system provided by this project.