This guide provides a comprehensive overview of how to create and apply custom themes, provide verified session policies, and configure Apple App Site Association (AASA) for iOS integration with the Cartridge Controller.
Creating a Theme
To create a theme, teams should commit their theme config to the configs folder in @cartridge/presets with the icon and banner included.
{
"origin": "https://flippyflop.gg",
"theme": {
"colors": {
"primary": "#F38332"
},
"cover": "cover.png",
"icon": "icon.png",
"name": "FlippyFlop"
}
}Origin Configuration
The origin field specifies which origins are authorized to use your preset. This is important for security and preventing unauthorized use of your configuration.
Web Applications
For standard web applications, use your domain:
{
"origin": "https://yourdomain.com"
}Multiple Origins
You can specify multiple origins as an array:
{
"origin": ["https://yourdomain.com", "https://staging.yourdomain.com"]
}Capacitor Apps with Custom Hostnames
For Capacitor mobile apps using custom hostnames, include the custom hostname in your origins:
{
"origin": ["https://yourdomain.com", "my-custom-app"]
}This authorizes both your web app and your Capacitor app with the custom hostname:
- Web:
https://yourdomain.com - iOS Capacitor:
capacitor://my-custom-app - Android Capacitor:
https://my-custom-app
Note: The default localhost origin (capacitor://localhost) is always allowed for development convenience and doesn't need to be explicitly listed in presets.
See an example pull request here
Verified Sessions
Session Policies can be provided in the preset configuration, providing a smoother experience for your users.
In order to submit verified policies, create a commit with them to your applications config.json in @cartridge/presets.
For an example, see dope-wars:
{
"origin": "dopewars.game",
"chains": {
"SN_MAIN": {
"policies": {
"contracts": {
"0x051Fea...": {
"name": "VRF Provider",
"description": "Provides verifiable random functions",
"methods": [
{
"name": "Request Random",
"description": "Request a random number",
"entrypoint": "request_random"
}
]
}
}
}
}
},
...
}Paymaster Predicate Support
Session policies now support paymaster predicates, which provide additional conditional logic for transaction sponsorship. This is particularly useful for games that need to sponsor transactions based on specific conditions or game state.
Using Predicates in Presets
To add paymaster predicate support to your preset configuration, include a predicate field in your method definition:
{
"origin": "mygame.example.com",
"chains": {
"SN_MAIN": {
"policies": {
"contracts": {
"0x123...abc": {
"name": "Game Contract",
"description": "Main game contract with paymaster support",
"methods": [
{
"name": "Move Player",
"description": "Move player with conditional sponsorship",
"entrypoint": "move_player",
"is_paymastered": true,
"predicate": {
"address": "0x456...def",
"entrypoint": "check_move_eligibility"
}
},
{
"name": "Attack Enemy",
"description": "Attack with unconditional sponsorship",
"entrypoint": "attack_enemy",
"is_paymastered": true
}
]
}
}
}
}
}
}Predicate Structure
The predicate field contains:
address: The contract address that contains the predicate logicentrypoint: The function name that will be called to evaluate the condition
When a transaction is submitted:
- If a method has
is_paymastered: truewithout a predicate, it will always be sponsored - If a method has both
is_paymastered: trueand a predicate, the predicate function will be called first - The transaction will only be sponsored if the predicate function returns a truthy value
This allows for sophisticated gas sponsorship policies based on game state, user eligibility, or other conditional logic.
Apple App Site Association
The Apple App Site Association (AASA) configuration enables iOS app integration with Cartridge Controller, allowing for usage of Web Credentials (Passkeys) in native applications.
Configuration
To add your iOS app to the AASA file, include the apple-app-site-association section in your game's config.json:
JSON Configuration
{
...,
"apple-app-site-association": {
"webcredentials": {
"apps": ["ABCDE12345.com.example.yourgame"]
}
},
...,
}