11 KiB
title | description | guide_group | order | platform_choice | related_examples | |||||
---|---|---|---|---|---|---|---|---|---|---|
App Configuration | How to allow users to customize an app with a configuration page. | user-interfaces | 0 | true |
|
Many watchfaces and watchapps in the Pebble appstore include the ability to customize their behavior or appearance through the use of a configuration page.
Clay for Pebble is the recommended approach for creating configuration pages, and is what will be covered in this guide. If you need to host your own configuration pages, please follow our {% guide_link user-interfaces/app-configuration-static "Manual Setup" %} guide.

Clay for Pebble dramatically simplifies the process of creating a configuration page, by allowing developers to define their application settings using a simple JSON file. Clay processes the JSON file and then dynamically generates a configuration page which matches the existing style of the Pebble mobile application, and it even works without an Internet connection.
Enabling Configuration
^LC^ For an app to be configurable, it must include the 'configurable' item in
package.json
.
^CP^ For an app to be configurable, it must include the 'configurable' item in 'Settings'.
The presence of this value tells the mobile app to display the gear icon that is associated with the ability to launch the config page next to the app itself.
Installing Clay
Clay is available as a {% guide_link pebble-packages "Pebble Package" %}, so it takes minimal effort to install.
^LC^ Within your project folder, just type:
^CP^ Go to the 'Dependencies' tab, type 'pebble-clay' into the search box and press 'Enter' to add the dependency.
Choosing messageKeys
When passing data between the configuration page and the watch application, we
define messageKeys
to help us easily identify the different values.
In this example, we're going to allow users to control the background color, foreground color, whether the watchface ticks on seconds and whether any animations are displayed.
^LC^ We define messageKeys
in the package.json
file for each configuration
setting in our application:
^CP^ We define messageKeys
in the 'Settings' tab for each configuration
setting in our application. The 'Message Key Assignment Kind' should be set to
'Automatic Assignment', then just enter each key name:
Creating the Clay Configuration
^LC^ The Clay configuration file (config.js
) should be created in your
src/pkjs/
folder. It allows the easy definition of each type of HTML form
entity that is required. These types include:
^CP^ The Clay configuration file (config.js
) needs to be added to your project
by adding a new 'Javascript' source file. It allows the easy definition of
each type of HTML form entity that is required. These types include:
- Section
- Heading
- Text
- Input
- Toggle
- Select
- Color Picker
- Radio Group
- Checkbox Group
- Generic Button
- Range Slider
- Submit Button
In our example configuration page, we will add some introductory text, and group our fields into two sections. All configuration pages must have a submit button at the end, which is used to send the JSON data back to the watch.

Now start populating the configuration file with the sections you require, then
add the required elements to each section. Be sure to assign the correct
messageKey
to each field.
module.exports = [
{
"type": "heading",
"defaultValue": "App Configuration"
},
{
"type": "text",
"defaultValue": "Here is some introductory text."
},
{
"type": "section",
"items": [
{
"type": "heading",
"defaultValue": "Colors"
},
{
"type": "color",
"messageKey": "BackgroundColor",
"defaultValue": "0x000000",
"label": "Background Color"
},
{
"type": "color",
"messageKey": "ForegroundColor",
"defaultValue": "0xFFFFFF",
"label": "Foreground Color"
}
]
},
{
"type": "section",
"items": [
{
"type": "heading",
"defaultValue": "More Settings"
},
{
"type": "toggle",
"messageKey": "SecondTick",
"label": "Enable Seconds",
"defaultValue": false
},
{
"type": "toggle",
"messageKey": "Animations",
"label": "Enable Animations",
"defaultValue": false
}
]
},
{
"type": "submit",
"defaultValue": "Save Settings"
}
];
Initializing Clay
To initialize Clay, all you need to do is add the following JavaScript into
your index.js
file.
// Import the Clay package
var Clay = require('pebble-clay');
// Load our Clay configuration file
var clayConfig = require('./config');
// Initialize Clay
var clay = new Clay(clayConfig);
Receiving Config Data
Within our watchapp we need to open a connection with AppMessage
to begin
listening for data from Clay, and also provide a handler to process the data
once it has been received.
void prv_init(void) {
// ...
// Open AppMessage connection
app_message_register_inbox_received(prv_inbox_received_handler);
app_message_open(128, 128);
// ...
}
Once triggered, our handler will receive a DictionaryIterator
containing
Tuple
objects for each messageKey
. Note that the key names need to be
prefixed with MESSAGE_KEY_
.
static void prv_inbox_received_handler(DictionaryIterator *iter, void *context) {
// Read color preferences
Tuple *bg_color_t = dict_find(iter, MESSAGE_KEY_BackgroundColor);
if(bg_color_t) {
GColor bg_color = GColorFromHEX(bg_color_t->value->int32);
}
Tuple *fg_color_t = dict_find(iter, MESSAGE_KEY_ForegroundColor);
if(fg_color_t) {
GColor fg_color = GColorFromHEX(fg_color_t->value->int32);
}
// Read boolean preferences
Tuple *second_tick_t = dict_find(iter, MESSAGE_KEY_SecondTick);
if(second_tick_t) {
bool second_ticks = second_tick_t->value->int32 == 1;
}
Tuple *animations_t = dict_find(iter, MESSAGE_KEY_Animations);
if(animations_t) {
bool animations = animations_t->value->int32 == 1;
}
}
Persisting Settings
By default, Clay will persist your settings in localStorage within the mobile application. It is common practice to also save settings within the persistent storage on the watch. This creates a seemless experience for users launching your application, as their settings can be applied on startup. This means there isn't an initial delay while the settings are loaded from the phone.
You could save each individual value within the persistent storage, or you could create a struct to hold all of your settings, and save that entire object. This has the benefit of simplicity, and because writing to persistent storage is slow, it also provides improved performance.
// Persistent storage key
#define SETTINGS_KEY 1
// Define our settings struct
typedef struct ClaySettings {
GColor BackgroundColor;
GColor ForegroundColor;
bool SecondTick;
bool Animations;
} ClaySettings;
// An instance of the struct
static ClaySettings settings;
// AppMessage receive handler
static void prv_inbox_received_handler(DictionaryIterator *iter, void *context) {
// Assign the values to our struct
Tuple *bg_color_t = dict_find(iter, MESSAGE_KEY_BackgroundColor);
if (bg_color_t) {
settings.BackgroundColor = GColorFromHEX(bg_color_t->value->int32);
}
// ...
prv_save_settings();
}
// Save the settings to persistent storage
static void prv_save_settings() {
persist_write_data(SETTINGS_KEY, &settings, sizeof(settings));
}
You can see a complete implementation of persisting a settings struct in the [Pebble Clay Example]({{ site.links.examples_org }}/clay-example).
What's Next
If you're thinking that Clay won't be as flexible as hand crafting your own configuration pages, you're mistaken.
Developers can extend the functionality of Clay in a number of ways:
- Define a custom function to enhance the interactivity of the page.
- Override events and transform the format of the data before it's transferred to the watch.
- Create and share your own custom components.
Why not find out more about Clay for Pebble and perhaps even contribute to the project, it's open source!