---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: A Wild SDK Appears
author: cat
tags:
- Freshly Baked
---

Developers rejoice - we’ve released the first version of our [SDK 4](/sdk4)
developer preview! This SDK enables you to start building applications for the
new Diorite platform (Pebble 2), and includes a set of new APIs for interacting
with the 4.0 user experience.

In this blog post we’ll dive into the [App Glance](/docs/c/Foundation/App_Glance/),
[`UnobstructedArea`](/docs/c/User_Interface/UnobstructedArea/), and
[`AppExitReason`](/docs/c/Foundation/Exit_Reason/) APIs, and explain
how you can use them to create great experiences for your users!

## App Glance API

Let’s start with the App Glance API, which allows applications to present
information for the launcher to display. The information an application displays
in the launcher is called an app glance - and the information that is displayed
at any particular point in time is referred to as an [`AppGlanceSlice`](/docs/c/Foundation/App_Glance/#AppGlanceSlice).

![Virtual Pet App >{pebble-screenshot,pebble-screenshot--time-black}](/images/blog/2016-06-15-sdk4-preview/virtual-pet.png)

`AppGlanceSlice`s have expiration times, which means you can add multiple slices
at once. Slices will be displayed in the order they are added and removed at
their specified expiration times.

```c
static void prv_update_app_glance(AppGlanceReloadSession *session, size_t limit, void *context) {
  // This shouldn't happen, but developers should always ensure they have
  // sufficient slices, or adding slices may fail.
  if (limit < 1) return;

  // !! When layout.icon_resource_id is not set, the app's default icon is used
  const AppGlanceSlice entry = (AppGlanceSlice) {
    .layout = {
      .template_string = "Hello from the app glance"
    },
    .expiration_time = APP_GLANCE_SLICE_NO_EXPIRATION
  };

  // Add the slice, and store the result so we can check it later
  AppGlanceResult result = app_gpance_add_slice(session, entry);
}
```

To dig into this feature, we recommend you start with our new
[AppGlance C API guide](/guides/user-interfaces/appglance-c), and also give the
[API docs](/docs/c/Foundation/App_Glance/) a quick read.

> We are planning to extend the AppGlance API to include a PebbleKit JS API, as
> well as a HTTP web API, intended to allow developers to push `AppGlanceSlice`s
> from external web services to their users' smartwatches.

## UnobstructedArea API

The [`UnobstructedArea`](/docs/c/User_Interface/UnobstructedArea/) API
allows developers to create watchfaces capable of sensing, and responding to
Timeline Quick View events. Timeline Quick View is a new feature in SDK 4.0,
which displays upcoming and ongoing events on top of the user’s watchface. The
functionality added through the `UnobstructedArea` API allows developers to get
the unobstructed bounds of a layer, or subscribe to events related to the
watchface’s unobstructed area changing.

```c
static int s_offset_top_percent = 33;
static int s_offset_bottom_percent = 20;

static void prv_unobstructed_change(AnimationProgress progress, void *context) {
  // Get the total available screen real-estate
  GRect bounds = layer_get_unobstructed_bounds(window_layer);

  // Shift the Y coordinate of the top text layer
  GRect top_frame = layer_get_frame(text_layer_get_layer(s_top_text_layer));
  top_frame.origin.y = bounds.size.h * s_offset_top_percent / 100;
  layer_set_frame(top_frame, text_layer_get_layer(s_top_text_layer));

  // Shift the Y coordinate of our bottom text layer
  GRect bottom_frame = layer_get_frame(text_layer_get_layer(s_bottom_text_layer));
  bottom_frame.origin.y = bounds.size.h * s_offset_bottom_percent / 100;
  layer_set_frame(bottom_frame, text_layer_get_layer(s_bottom_text_layer));
}

static void prv_main_window_load(Window *window) {
  unobstructed_area_service_subscribe((UnobstructedAreaHandlers) {
    .change = prv_unobstructed_change
  }, NULL);
}
```

> We encourage developers to begin exploring what their existing watchfaces will
> look like when the system is displaying the Timeline Quick View dialog, and
> adjust their designs to provide the best experience possible for users.

Take a look at our [UnobstructedArea API Guide](/guides/user-interfaces/unobstructed-area/)
and the [API documentation](/docs/c/User_Interface/UnobstructedArea/) to
get started!

## AppExitReason API

One of the APIs we haven’t talked about as much is the
[`AppExitReason`](/docs/c/Foundation/Exit_Reason/) API, which enables
developers to specify why their app exited, and determines whether the system
returns the user to the launcher, or the active watchface. Take a look at our
[AppExitReason API Guide](/guides/user-interfaces/app-exit-reason),
and read [the API docs](/docs/c/Foundation/Exit_Reason) to learn more.

This feature enables developers to create "One Click Action" watchapps, that
perform an action, then immediately return the user to the watchface to create a
simple, fluid experience.

![Uber App >{pebble-screenshot,pebble-screenshot--time-black}](/images/blog/2016-06-15-sdk4-preview/uber.gif)

To help get you started thinking about and designing One Click Action apps,
we’ve created a [One Click Action App Guide](/guides/design-and-interaction/one-click-actions)
around the relatively minimal example of locking and unlocking your front door
(with a [Lockitron lock](https://lockitron.com)).

## 4.0 Emulator

The SDK 4 preview also includes an update to the emulator, which not only adds
support for Pebble 2, but includes the updated 4.0 user interface, and a few
other goodies that we’re sure developers will love.

The new emulator includes a launcher capable of displaying watchapps’ glances,
and can be accessed by pressing the `Select` button from the watchface.

CloudPebble and the Pebble Tool also include new functionality to enable
developers to toggle Timeline Quick View, allowing you to make sure your
watchface looks good in every context!

Finally, we’ve added the ability to install multiple watchfaces and watchapps
into the emulator. Watchfaces and watchapps installed into the emulator will
remain installed (even if the emulator is closed) until `pebble wipe` is called
from the command line.

Due to limitations with CloudPebble, this feature is currently only available in
the Pebble Tool.

## What’s Next

The SDK 4 developer preview is exactly that, a preview. You’ve probably noticed
a few really important and exciting features we didn’t mention - the Heart Rate
API has been designed, but is not yet fully implemented, and we have not yet
added the ability to build applications for the Emery Platform (Pebble Time 2).

The official SDK 4 release is currently planned for the end of August - and it
will include not only the Heart Rate API, and support for building Emery
applications, but the first version of Pebble’s fantastic new embedded
JavaScript SDK, [Rocky.js](http://pebble.github.io/rockyjs/).

## Show Us What You Make

While we’ve been conceptualizing and designing the new functionality in SDK 4
for quite a long time, the API itself is relatively new, even for those of us
lucky enough to ‘be on the inside’ - so we’ve only really just begun to see
what’s possible, and we’re more than excited to see what you’ll build with this
new functionality.

Send us a link to something you’ve built on Twitter (
[@pebbledev](https://twitter.com/pebbledev)) and we’ll look at including it in
an upcoming newsletter (and send some swag your way).

Happy Hacking!

Team Pebble


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Introducing Clay - App configuration made easy
author: keegan
tags:
- Freshly Baked
---

It is with great pleasure that I present to you, Clay, a Pebble package that makes it easy to add offline configuration pages to your Pebble apps. All you need to get started is a couple lines of JavaScript and a JSON file; no servers, HTML or CSS required.

![Clay Example](/images/blog/2016-06-24-introducing-clay/clay-example.png =421)

## How to get started

This post aims to provide high level explanation of how the framework works and how it came to be. Below is a quick overview of how easy it is to make your app configurable with Clay. If you would like to learn how to integrate Clay into your project, read our guide on [app configuration](/guides/user-interfaces/app-configuration/) or read the full documentation on the project [GitHub repository.](https://github.com/pebble/clay#clay)

**1) Install the module via [Pebble Packages](/guides/pebble-packages/using-packages/)**
 - SDK: `$ pebble package install pebble-clay`
 - CloudPebble: Add `pebble-clay`, version `^1.0.0` to your project dependencies.

**2) Create a configuration file that looks something like:**

```js
module.exports = [
  {
    "type": "heading",
    "defaultValue": "Example App"
  },
  {
    "type": "section",
    "items": [
      {
        "type": "color",
        "messageKey": "BackgroundColor",
        "defaultValue": "0x000000",
        "label": "Background Color"
      },
      {
        "type": "toggle",
        "messageKey": "Animations",
        "label": "Enable Animations",
        "defaultValue": false
      }
    ]
  },
  {
    "type": "submit",
    "defaultValue": "Save Settings"
  }
];
```

**3) Update your project settings with the matching `messageKeys` from the config above.**

**4) Add a few lines to your `index.js`**

```js
var Clay = require('pebble-clay');
var clayConfig = require('./config');
var clay = new Clay(clayConfig);
```

**5) Retrieve the values on the C side using standard [app messages](/guides/communication/sending-and-receiving-data/) or alternatively let [enamel](https://github.com/gregoiresage/enamel) do the work for you.**

## Why I created Clay

Clay began as a side project of mine. Whilst developing my [Segment watchface](https://apps.pebble.com/applications/560ae4754d43a36393000001), I wanted to add a configuration page to allow users to customize the colors of the watchface. However, I soon discovered this process to be rather fiddly. The old way of doing things required you to create and host HTML pages even for simple things like changing a background color or toggling an option. You would also need to write a bunch of boilerplate JavaScript to serialize and send the settings to the watch. Best case, for developers, this is super tedious. Worst case, it is terrifying. By day, I work as a web developer (mainly front-end) so if I was finding the process tiresome, I could only imagine how challenging it would be for someone who wasn't familiar with web technologies. And so I decided to create a framework that would alleviate this barrier for developers. I had a number of requirements that needed to be met in order for the framework to achieve my goals:

 - It should not require developers to write any HTML or CSS.
 - It should use JSON to define the generated config page.
 - It should all work offline
 - Developers should be able to add interactivity to the config page without manually manipulating DOM.
 - Developers should be able to create and share their own custom components.
 - The config page should be able to be versioned with the rest of the code in the project.
 - It should have extensive unit tests with 100% test coverage.

## How Clay Actually Works

Clay has two main components. The first is a very long string that is compiled from all the HTML, CSS and JavaScript that forms the skeleton of the generated config page. The second is the module that gets included in your `index.js`. This module is in charge of bundling all the dynamic elements set by the developer into a format that can be opened using `Pebble.openURL()`. It is also in charge of listening for the `webviewclosed` event and persisting the user's settings to local storage. I use Gulp and a series of Browserify transforms to compile all these components into a single module. The advantage of using a system such as Browserify, is that later, Clay can be made into a stand alone module to be used by developers who have very advanced use cases that require Clay to be run in a hosted HTML page.

The most challenging item on the requirements list was making the whole thing work offline. Neither of the Pebble mobile apps allow file system access from the config page's webview, so I had to get a little creative. It turns out that [Data URIs](https://en.wikipedia.org/wiki/Data_URI_scheme) work with more than images. You can in fact encode an entire HTML page into the URI. This was the solution to making the config pages offline. It sounds crazy but this method actually provides other advantages for developers beyond offline access. By bundling all the HTML, CSS and JavaScript into the Clay package, the version of Clay being used by the developer will not change without the developer rebuilding their app. This means developers do not need to worry about the behavior of their app's configuration page potentially breaking as new versions of Clay get released.

## Advanced Use

If developers want to add additional functionality to their config page, they can. Clay allows developers to inject, what I call a [`custom function`](https://github.com/pebble/clay#custom-function) into the generated config page. This allows developers control of their config page without needing to manipulate the DOM. Clay achieves this by exposing an API that provides a consistent way of interacting with the config page as well as making AJAX requests. Instead of manually updating the values of HTML elements, developers can use the much simpler Clay API.

## Where to find more information

 - [App configuration guide.](/guides/user-interfaces/app-configuration/)
 - [Clay GitHub repository including full documentation.](https://github.com/pebble/clay)
 - Chat to us in the `#clay` channel on [Discord]({{ site.links.discord_invite }}).
 - Visit the [Pebble Forums](https://forums.pebble.com/)
 - Tweet at [@pebbledev](https://twitter.com/pebbledev)

## How to get involved

Clay is open source and welcomes pull requests from anybody. Have a look at the [contributing guide](https://github.com/pebble/clay/blob/master/CONTRIBUTING.md) for instructions on how you can help make Clay even better. Regardless of your skill level, if you have any ideas on how Clay could be improved or if you find any bugs, we would love you to [submit an issue on GitHub](https://github.com/pebble/clay/issues/new).

This is the latest version of the internal repository from Pebble Technology providing the software to run on Pebble watches. Proprietary source code has been removed from this repository and it will not compile as-is. This is for information only.


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Introducing Rocky.js Watchfaces!
author: jonb
tags:
- Freshly Baked
---

We're incredibly excited and proud to announce the first public beta version of
Rocky.js watchfaces for Pebble. Rocky.js is ECMAScript 5.1 JavaScript running
natively on Pebble smartwatches, thanks to
[our collaboration](https://github.com/Samsung/jerryscript/wiki/JerryScriptWorkshopApril2016)
with [JerryScript](https://github.com/pebble/jerryscript). This is an incredible
feat of engineering!

## It's JavaScript on the freakin' watch!

```javascript
var rocky = require('rocky');

rocky.on('minutechange', function(event) {
  rocky.requestDraw();
});

rocky.on('draw', function(event) {
  var ctx = event.context;
  ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
  ctx.fillStyle = 'white';
  ctx.textAlign = 'center';

  var w = ctx.canvas.unobstructedWidth;
  var h = ctx.canvas.unobstructedHeight;
  ctx.fillText('JavaScript\non the watch!', w / 2, h / 2);
});
```

![Rocky >{pebble-screenshot,pebble-screenshot--time-red}](/images/blog/2016-08-16-jotw.png)

Right now we're giving you early access to this game-changing environment to
create watchfaces entirely in JavaScript. Feel free to share your code, to
install it on the emulator and on your watch (with the upcoming firmware 4.0),
but please don't upload apps to the appstore as they will stop working in a
future release.

<div class="alert alert--fg-white alert--bg-purple">
  {% markdown %}
  **Appstore Publishing**

  Rocky.js JavaScript watchfaces must not be published into the appstore at
  this time.
  {% endmarkdown %}
</div>

We can't wait to hear your feedback and see what amazing watchfaces you create!

Enough hype, let's dive into the eye of the tiger!

## Rocky.js Projects

Things are a little different in the JavaScript world, so let's take a closer
look at the structure of a Rocky.js project:

```nc|text
package.json
src/rocky/index.js
src/pkjs/index.js
common/*.js
```

#### package.json

The format of the `package.json` file remains roughly the same as existing
Pebble projects, with some minor differences:

* `"projectType": "rocky"`.
* Aplite `targetPlatform` is not supported.
* `resources` are not currently supported, but will consume space in your PBW if
specified.
* `messageKeys` are not permitted.

#### src/rocky/index.js

This is now the main entry point into our application on the watch. This is
where our Rocky.js JavaScript code resides. All code within this file will be
executed on the smartwatch. Additional scripts may be placed in this folder, see
[below](#additional-scripts).

#### src/pkjs/index.js

This file contains our [PebbleKit JS](/docs/pebblekit-js/) (pkjs) JavaScript
code. This code will execute on the mobile device connected to the smartwatch.
Additional scripts may be placed in this folder, see
[below](#additional-scripts).

For Rocky.js projects only, we've added a new simplified communication channel
[`postMessage()`](/docs/rockyjs/rocky/#postMessage) and
[`on('message', ...)`](/docs/rockyjs/rocky/#on) which allows you to send and
receive JavaScript JSON objects between the phone and smartwatch.

#### Additional Scripts

Both the `rocky` and `pkjs` folders support the use of multiple .js files, which
helps to keep your code clean and modular. Use the
[CommonJS Module](http://www.commonjs.org/specs/modules/1.0/) format for
your additional scripts, then `require()` them in your `index.js`.

```javascript
// file: src/rocky/additional.js
function test() {
  console.log('Additional File');
}

module.exports.test = test;
```

```javascript
// file: src/rocky/index.js
var additional = require('./additional');
additional.test();
```

#### common/*.js

If you need to share code between `rocky` and `pkjs`, you can create a `common`
folder, then add your JavaScript files.

```javascript
// file: src/common/shared.js
function test() {
  console.log('Hello from shared code');
}

module.exports.test = test;
```

```javascript
// file: src/rocky/index.js
var shared = require('../common/shared');
shared.test();
```

```javascript
// file: src/pkjs/index.js
var shared = require('../common/shared');
shared.test();
```

## Available APIs

In this initial release of Rocky.js, we have focused on the ability to create
watchfaces only. We will be adding more and more APIs as time progresses, and
we're determined for JavaScript to have feature parity with the rest of the
Pebble developer ecosystem.

We've developed our API in-line with standard Web APIs, which may appear strange
to existing Pebble developers, but we're confident that this will facilitate
code re-use and provide a better experience overall.

### System Events

We've provided a series of events which every watchface will likely require, and
each of these events allow you to provide a callback method which is emitted
when the event occurs.

Existing Pebble developers will be familiar with the tick style events,
including:
[`secondchange`](/docs/rockyjs/rocky/#on),
[`minutechange`](/docs/rockyjs/rocky/#on),
[`hourchange`](/docs/rockyjs/rocky/#on) and
[`daychange`](/docs/rockyjs/rocky/#on). By using these events, instead of
[`setInterval`](/docs/rockyjs), we're automatically kept in sync with the wall
clock time.

We also have a
[`message`](/docs/rockyjs/rocky/#on) event for
receiving JavaScript JSON objects from the `pkjs` component, and a
[`draw`](/docs/rockyjs/rocky/#on) event which you'll use to control the screen
updates.

```javascript
rocky.on('minutechange', function(event) {
  // Request the screen to be redrawn on next pass
  rocky.requestDraw();
});
```

###  Drawing Canvas

The canvas is a 2D rendering context and represents the display of the Pebble
smartwatch. We use the canvas context for drawing text and shapes. We're aiming
to support standard Web API methods and properties where possible, so the canvas
has been made available as a
[CanvasRenderingContext2D](/docs/rockyjs/CanvasRenderingContext2D/).

> Please note that the canvas isn't fully implemented yet, so certain methods
> and properties are not available yet. We're still working on this, so expect
> more in future updates!

```javascript
rocky.on('draw', function(event) {
  var ctx = event.context;

  ctx.fillStyle = 'red';
  ctx.textAlign = 'center';
  ctx.font = '14px Gothic';

  var w = ctx.canvas.unobstructedWidth;
  var h = ctx.canvas.unobstructedHeight;
  ctx.fillText('Rocky.js Rocks!', w / 2, h / 2);
});
```

## Limitations

We are still in the early beta phase and there are some limitations and
restrictions that you need to be aware of:

* Don't publish Rocky.js watchfaces to the Pebble appstore yet, they will stop
working.
* Rocky.js watchfaces only run on the 4.0 emulators/firmware. The 4.0 firmware
will be available soon for Basalt, Chalk and Diorite.
* No support for custom fonts, images and other resources, yet.
* No C code allowed.
* No messageKeys.
* There are file size and memory considerations with your Rocky.js projects.
If you include a large JS library, it probably won't work.

## SDK 4.0

We have published an updated version of
[CloudPebble]({{site.links.cloudpebble}}) which now supports creating
Rocky.js watchfaces in JavaScript.

If you prefer our local tools, we've also published everything you need to begin
creating Rocky.js watchfaces. Run the following command to install the Pebble
Tool and 4.0 SDK:

```nc|text
$ brew upgrade pebble-sdk
$ pebble sdk install latest
```

## How to Get Started

We created a [2-part tutorial](/tutorials/js-watchface-tutorial/part1/) for
getting started with Rocky.js watchfaces. It explains everything you need to
know about creating digital and analog watchfaces, plus how to retrieve
weather conditions from the internet.

If you're looking for more detailed information, check out the
[API Documentation](/docs/rockyjs).

## Sample Watchfaces

We've already created a few sample watchfaces:

* [Tictoc](https://github.com/pebble-examples/rocky-watchface-tutorial-part1) -
Simple analog watchface.
* [Tictoc Weather](https://github.com/pebble-examples/rocky-watchface-tutorial-part2) -
Simple analog watchface with weather data from a REST API.
* [Leco with Weather](https://github.com/orviwan/rocky-leco-weather) - Simple
digital watchface with weather data from a REST API.
* [Leco with Clay](https://github.com/orviwan/rocky-leco-clay) - Simple analog
watchface which uses Clay for configurable settings.
* [Simplicity](https://github.com/orviwan/simplicity-rockyjs) - Rocky.js version
of the classic Simplicity watchface.

## Feedback and Help

We hope you're as exicited about Rocky.js as we are. If you need assistance,
have feedback or just want to send us some love, we're in #rockyjs on
[Discord]({{ site.links.discord_invite }}) or the
[Pebble developer forums](https://forums.pebble.com/c/development).

We're already working on the next update of Rocky.js and your feedback will help
shape the future!


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Prime Time is Approaching for OS 4.0
author: jonb
tags:
- Freshly Baked
---

Pebble developers of the world unite! Pebble OS 4.0 is just around the corner
and it's now time to put those finishing touches on your projects, and prepare
them for publishing!

Pebble Time owners will be receiving OS 4.0 before Kickstarter backers receive
their Pebble 2 watches, so we're recommending that developers publish their
4.0 watchapps and watchfaces into the appstore **from August 31st onwards**.

We'll be promoting new and updated apps which utilize the new SDK 4.0 APIs and
features by creating a brand new category in the appstore called
'Optimized for 4.0'. This is your time to shine!

If you haven't even begun to prepare for 4.0, there are some really quick wins
you can use to your advantage.

## Menu Icon in the Launcher

The new launcher in 4.0 allows developers to provide a custom icon for
their watchapps and watchfaces.

  {% markdown %}
  ![Launcher Icon](/images/blog/2016-08-19-pikachu-icon.png)
  {% endmarkdown %}

  {% markdown %}
  ![Launcher >{pebble-screenshot,pebble-screenshot--time-red}](/images/blog/2016-08-19-pikachu-launcher.png)
  {% endmarkdown %}

> If your `png` file is color, we will use the luminance of the image to add
> some subtle gray when rendering it in the launcher, rather than just black
> and white. Transparency will be preserved.

You should add a 25x25 `png` to the `resources.media` section of the
`package.json` file, and set `"menuIcon": true`.
Please note that icons that are larger will be ignored and
your app will have the default icon instead.

```js
"resources": {
  "media": [
    {
      "menuIcon": true,
      "type": "png",
      "name": "IMAGE_MENU_ICON",
      "file": "images/icon.png"
    }
  ]
}
```

## Timeline Quick View

This new feature really brings your timeline into the present, with your
next appointment appearing as a modal notification over the active watchface.

We introduced the ``UnobstructedArea`` API in 4.0 to allow developers to detect
if the screen is being obstructed by a system modal. Below you can see two
examples of the Simplicity watchface. The Pebble on the left is not using the
``UnobstructedArea`` API, and the Pebble on the right is.

  {% markdown %}
  ![Simplicity >{pebble-screenshot,pebble-screenshot--time-white}](/images/blog/2016-08-19-simplicity-std.png)
  {% endmarkdown %}

Watchface not updated

  {% markdown %}
  ![Simplicity >{pebble-screenshot,pebble-screenshot--time-white}](/images/blog/2016-08-19-simplicity-qv.png)
  {% endmarkdown %}

Respects new 4.0 unobstructed area

You can detect changes to the available screen real-estate and then move, scale,
or hide their layers to achieve an optimal layout while the screen is partially
obscured. This provides a fantastic experience to your users.

There's {% guide_link user-interfaces/unobstructed-area "a dedicated guide" %}
which goes into more detail about the ``UnobstructedArea`` API, it contains
examples and links to sample implementations.

## AppGlances

While your static app icon and app title from the `package.json` are being used as the
default to present your app to the user,
_AppGlances_ allow developers to control this content at runtime and
to provide meaningful feedback to users directly from the new launcher.
The API exposes the ability to dynamically change
the `icon` and `subtitle_template_string` text of your application in the
launcher.

Preview version of 4.0 launcher

Utilizing the ``App Glance`` API doesn't need to be difficult. We've provided
guides, examples and sample applications for using the
{% guide_link user-interfaces/appglance-c "AppGlance C API" %} and the
{% guide_link user-interfaces/appglance-pebblekit-js "AppGlance PebbleKit JS API" %}.

## The Diorite Platform

The Diorite platform was created for the new Pebble 2 devices. Its display is
rectangular, 144x168 pixels, with 2 colors (black and white). It has a
microphone and heart rate monitor, but it doesn't have a compass. If your app
works with Aplite it will already work with Diorite, but there are some important considerations to note:

* If you chose to limit your app to some platforms, you need to add `"diorite"` to your `targetPlatforms` in the `package.json`.
* Check for the appropriate usage of
{% guide_link best-practices/building-for-every-pebble#available-defines-and-macros "compiler directives" %}.

In general, it's better to use capability and feature detection, rather than platform
detection. For example, when dealing with resources, use the suffix `~bw` instead of `~aplite` so they are picked on all black and white platforms.

## What's Next

We're really excited for the release of Pebble OS 4.0 and the new features it
brings. It's now time for you to take advantage of the new APIs and
enhance your existing projects, or even create entirely new ones!

Why not build something like the
{% guide_link design-and-interaction/one-click-actions "One Click Action" %}
application, which utilizes the new ``App Glance`` and ``AppExitReason`` APIs.

Please remember that we will promote watchfaces and watchapps
that make use of these new 4.0 APIs if you
submit them to the appstore **from August 31st onwards**.

Let us know on [Twitter](https://twitter.com/pebbledev) if you build something
cool using the new APIs! We'd love to hear about your experiences with the SDK.

Happy Hacking!

Team Pebble


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Announcing Pebble SDK 4.0
author: jonb
tags:
- Freshly Baked
---

Today we have the pleasure of announcing the release of Pebble SDK 4.0. We have
published an updated version of the Pebble Tool, the SDK itself, and we've
deployed 4.0 onto [CloudPebble]({{ site.links.cloudpebble }}). It's time to get
busy!

## What's New

Pebble OS 4.0 has been released and users with Pebble Time, Pebble Time Steel
and Pebble Time Round will be receiving the update today.

We covered the new features in detail
[very recently](/blog/2016/08/19/prime-time-is-approaching-for-os-4.0/), but
let's have a quick reminder of the new APIs and functionality that's included.

### Rocky.js

Javascript on the freakin' watch! Although still in beta,
[Rocky.js](/docs/rockyjs/) lets you start developing watchfaces in JavaScript
using standard Web APIs, which you can then run directly on your watch. It's an
embedded JavaScript revolution!

Read the updated
[Rocky.js blog post](/blog/2016/08/15/introducing-rockyjs-watchfaces/)
to get started.

### Timeline Quick View

Timeline Quick View displays upcoming information from your timeline on your
watchface. We introduced the ``UnobstructedArea`` API to allow developers to
detect if the screen is being obstructed by a system modal, such as Timeline
Quick View. Developers can use this new API to adapt their watchface layout
according to the available screen real estate.

Read the {% guide_link user-interfaces/unobstructed-area "UnobstructedArea guide" %}
to get started.

### AppGlances

With the new ``AppGlance`` API, developers can dynamically change the icon and
subtitle of their watchapp within the system launcher, at runtime. This allows
developers to provide meaningful feedback to users without the need for their
application to be launched.

Read the
{% guide_link user-interfaces/appglance-c "AppGlance C guide" %} and the
{% guide_link user-interfaces/appglance-pebblekit-js "AppGlance PebbleKit JS guide" %}
to get started.

### Diorite Platform

The new Pebble 2 devices use apps built for the Diorite platform, so you'll need
SDK 4.0 to develop applications which target those devices.

Take a look at the
{% guide_link tools-and-resources/hardware-information "Hardware Information guide" %}
to find out about the capabilities of the Pebble 2.

### One Click Action application

The One Click Action application pattern promotes a type of watchapp which
serves a single purpose. It launches, performs an action, and then terminates.
This pattern utilizes the new ``AppGlance`` and ``AppExitReason`` APIs.

Take a look at the
{% guide_link design-and-interaction/one-click-actions "One Click Actions guide" %}
to get started.

## Dude, Where's my HRM API?

We had planned on shipping the Heart Rate API with 4.0, but it's been pushed
back into 4.1 so that we can add even more awesomeness. Pebble 2 devices will
begin to appear on wrists after firmware 4.1 ships, so you'll still have time to
begin implementing HRM data into your watchapps and watchfaces. We will announce
details of the HRM API as soon as it's available.

## What's Next

Please remember that we will promote watchfaces and watchapps that make use of
these new 4.0 APIs if you submit them to the appstore **from August 31st
onwards**.

Let us know on [Twitter]({{ site.links.twitter }}) if you build something
cool using the new APIs! We'd love to hear about your experiences with the SDK.

Happy Hacking!

Team Pebble


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Timeline - The Future of the Past!
author: jonb
tags:
- Freshly Baked
---

If you’ve been living under a rock, or have just been sunning yourself on the
beach for the past week, you might have missed the
[launch of Pebble OS 4.0](/blog/2016/08/30/announcing-pebble-sdk4/). This new
version introduced some fantastic new features, such as the
[updated health app](https://blog.getpebble.com/2016/08/30/fw4-0/),
{% guide_link user-interfaces/unobstructed-area "timeline quick view" %},
{% guide_link user-interfaces/appglance-c "app glances" %},
[Rocky.js](/blog/2016/08/15/introducing-rockyjs-watchfaces/) and a new
[system launcher](/blog/2016/08/19/prime-time-is-approaching-for-os-4.0/#menu-icon-in-the-launcher).

### The Past and the Furious

However, there was one change which was met with mixed feedback from both users
and developers alike, the removal of timeline past. Previously accessible via
the UP button, timeline past was removed as part of the new 4.0 user
experience (UX). In 4.0 we introduced new APIs to give developers more options
to improve their application’s UX and potentially shift away from using the past
for interactions

Unfortunately, this change prevented users from accessing any timeline pin which
wasn’t in the present or future, negatively affecting a number of apps and their
use cases for the timeline.

We carefully listened to feedback and suggestions from our developer community
via the [forums](https://forums.pebble.com),
[Reddit](https://www.reddit.com/r/pebble),
[Twitter](https://twitter.com/pebbledev) and
[Discord]({{ site.links.discord_invite }}), and we are happy to announce that timeline past
has returned in the v4.0.1 update. Users who need to access the timeline past
can now assign it to one of their quick launch buttons.

![Quick Launch >{pebble-screenshot,pebble-screenshot--time-red}](/images/blog/2016-09-06-quick-launch.gif)

And so, with the reintroduction of timeline past, balanced was restored, and
that was the end of the story. Or was it?

### Back to the Future!

If you’re the developer of an application which relies upon timeline past, you
will probably want to inform your users about how they can access timeline past,
as it will not be enabled by default. Fortunately, there are multiple ways in
which you can do this easily.

#### 1. App Store Description

Use the app store description of your app to explain that your application
utilizes timeline past and that users will need to assign it to quick launch.
For example:

> This application utilizes pins in the timeline past. On your Pebble, go to
> ‘Settings’, ‘Quick Launch’, ‘Up Button’, then select ‘Timeline Past’. You can
> then access timeline past by long pressing UP.

#### 2. Display a Splash Screen

Add a splash screen to your application which only runs once, and display a
message informing users how to enable timeline past. You could use the
‘[about-window](https://www.npmjs.com/package/@smallstoneapps/about-window)’
Pebble package for a really quick and easy solution.

![About Window >{pebble-screenshot,pebble-screenshot--time-white}](/images/blog/2016-09-06-about-window.png)

#### 3. Display a One-Time Notification

Display a
[system notification](https://developer.pebble.com/guides/communication/using-pebblekit-js/#showing-a-notification)
which only fires once, and display a message informing users how to enable
timeline past.

![System Notification >{pebble-screenshot,pebble-screenshot--time-black}](/images/blog/2016-09-06-system-notification.png)

#### 4. Display a Timeline Notification

Display a
[timeline notification](https://developer.pebble.com/guides/pebble-timeline/),
and display a message informing users how to enable timeline past.

![Timeline Notification >{pebble-screenshot,pebble-screenshot--time-red}](/images/blog/2016-09-06-timeline-notification.png)

### The Future of the Past

For now, developers can continue to utilize timeline past, but over time we
would like to provide a more diverse set of functionality that allows developers
to surface information to their users. For example, some use cases of timeline
past may be more appropriate as using an app glance, or timeline quick view
instead.

### We’re Listening!

Your feedback is incredibly important to us, it’s how we keep making awesome
things. We love to receive your product and feature
[suggestions](http://pbl.io/ideas) too.

We’re particularly interested to hear about your use cases and ideas for
timeline as we travel further into the future! Let us know via
[the forums](https://forums.pebble.com),
[Twitter](https://twitter.com/pebbledev) and [Discord]({{ site.links.discord_invite }})!


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: 4.2-beta4 SDK - Emery Edition!
author: jonb
tags:
- Freshly Baked
---

We're incredibly excited to announce the first public beta of the Pebble SDK
4.2. This is the first time that developers can experience the new 'Emery'
platform which is specifically created for the upcoming
[Pebble Time 2](https://www.pebble.com/buy-pebble-time-2-smartwatch).

![Pebble Time 2](/images/blog/2016-10-11-intro.jpg)

## All About Those Pixels

The new display on the *Pebble Time 2* is almost 53% physically larger, and the
[Pixels per inch](https://en.wikipedia.org/wiki/Pixel_density) (PPI) has been
increased from 182 PPI to 202 PPI. This is a massive 200x228 pixels, compared to
144x168 on the *Pebble Time Steel*, that's an 88% increase in the total amount
of pixels!.

Take a look at our
{% guide_link tools-and-resources/hardware-information "Hardware guide" %} for
further information about the specifications of the Pebble Time 2.

Watchfaces and watchapps that have not been updated for the Emery platform will
run in *Bezel Mode*. This means they will appear centered on screen at their
original resolution (144x168), but due to the change in PPI, they appear
slightly smaller.

![Pebble Time 2 Bezel](/images/blog/2016-10-11-bezel.png)

Left: Pebble Time Steel, Middle: Pebble Time 2 -
Bezel Mode, Right: Optimized for Pebble Time 2.

Concentricity
Watchface

The increased number of pixels would immediately make you think that you can
just add more elements to your watchface design, but due to the increase in PPI,
existing elements and fonts may feel slightly smaller than expected when viewed
on an actual device.

The image below simulates how the PPI difference makes a bezel mode application
feel smaller on the Pebble Time 2.

![Pebble Time 2 PPI](/images/blog/2016-10-11-dpi-comparison.png)

Left: Pebble Time Steel, Right: Pebble Time 2 - Bezel Mode.

We've now seen that the increased amount of pixels doesn't necessarily equate to
bigger text on our devices, due to the change in PPI, that's why we've created
the new [ContentSize](/docs/c/preview/User_Interface/Preferences/#preferred_content_size)
API.

## Introducing the ContentSize API

All existing Pebble smartwatches provide the ability for users to change the
size of text for notifications and some system UI components using *Settings >
Notifications > Text Size*.

The new
[ContentSize](/docs/c/preview/User_Interface/Preferences/#preferred_content_size)
API now exposes this setting to developers, in order for
them to adapt their application design and layout based on this user preference.

In the previous section, we saw how the PPI increase on Pebble Time 2 affected
the relative size of a watchface. In the image below you can see precisely how
text sizes are affected by the PPI change.

![Pebble Time 2 ContentSize](/images/blog/2016-10-11-contentsize.png)

Yellow: Pebble Time Steel, Green: Pebble Time 2.

To negate the effects of this reduced font size, the Emery platform uses larger
fonts by default. Developers can use the
[ContentSize](/docs/c/preview/User_Interface/Preferences/#preferred_content_size)
API to match this
behaviour within their own applications.

The following table explains how the text size setting affects the content size
on each platform:

Platform | Text Size: Small | Text Size: Medium | Text Size: Large
---------|------------------|-------------------|-----------------
Aplite, Basalt, Chalk, Diorite | ContentSize: Small | ContentSize: Medium | ContentSize: Large
Emery | ContentSize: Medium | ContentSize: Large | ContentSize: Extra Large

Developers should aim to implement designs which adapt to the capabilities of
the device, but also the accessibility requirements of the user. The
[ContentSize](/docs/c/preview/User_Interface/Preferences/#preferred_content_size)
API satisfies both of these goals.

For more information, read the
{% guide_link user-interfaces/content-size "ContentSize guide" %}.

## New for Rocky.js

With the release of SDK 4.2, we're extremely proud to announce that
[Rocky.js](/docs/rockyjs/) watchfaces can be published into the Pebble appstore!
As usual, don't publish apps with the beta SDK into the appstore, please wait
for the final release.

In addition to finalizing the memory contract for Rocky.js apps, we've also
added a few new APIs to work with:

### Memory Pressure

The `memorypressure` event has been added to allow developers to handle the
situations which occur when the amount of memory available to their application
has changed. Initially we've only implemented the `high` memory pressure level,
which occurs right before your application is about to be terminated, due to a
lack of memory. If you can free sufficient memory within the callback for this
event, your application will continue to run. Please refer to the Rocky.js
[documentation](/docs/rockyjs/rocky/#RockyMemoryPressureCallback) and the memory
pressure [example application](https://github.com/pebble-examples/rocky-memorypressure).

### UserPreferences

The first watchface setting exposed in the new `UserPreferences` object is
`contentSize`. This exposes the new
[ContentSize](/docs/c/preview/User_Interface/Preferences/#preferred_content_size)
API to Rocky.js watchface
developers. Find out more in the Rocky.js
[UserPreferences documentation](/docs/rockyjs/rocky/#userPreferences).

## What's Next

Check out the [release notes](/sdk/changelogs/4.2-beta4/) for a full list of
changes and fixes that were included in SDK 4.2-beta4.

Let us know on [Twitter]({{ site.links.twitter }}) if you built something
cool using the new APIs! We'd love to hear about your experiences with the SDK.

Happy Hacking!

Team Pebble


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Announcing Pebble SDK 4.3
author: jonb
tags:
- Freshly Baked
---

Things have been a bit 'quiet' recently, but we're back with another fresh
Pebble SDK! In this release we've included one of the most frequently requested
APIs, exposed the raw HRM sensor value, released PebbleKit 4.0, plus added an
exciting new BLE HRM mode.

## It's. Oh. So quiet. Ssshhhhhh.

We've added an often requested method for developers to detect if *Quiet Time*
is enabled. To say that we had a lot of requests for this would be an
understatement.

*Quiet Time* can be enabled manually, via calendar events, or via scheduled
times, so we've made a simple method for querying whether it's currently active.

All you need to do is check each minute if it's active. This is easily done
within the tick event, as follows:

```c
static void handle_tick(struct tm *tick_time, TimeUnits units_changed) {
  if (units_changed & MINUTE_UNIT) {
    if (quiet_time_is_active()) {
      // It's nice and quiet
    } else {
      // Starts another big riot
    }
  }
}
```

You may also peek this value, for example, to prevent your application from
vibrating during *Quiet Time*:

```c
static void do_vibration() {
  if (!quiet_time_is_active()) {
    vibes_short_pulse();
  }
}
```

## Raw HRM BPM

The Pebble [Health API](``HealthService``) now exposes the raw BPM value from
the Heart Rate Monitor sensor. This raw value is not filtered and is useful for
applications which need to display the real-time sensor value, similar to the
Pebble Workout app.

For example, in order to peek the current real-time HRM sensor, you would do the
following:

```c
HealthServiceAccessibilityMask hr = health_service_metric_accessible(HealthMetricHeartRateRawBPM, time(NULL), time(NULL));
if (hr & HealthServiceAccessibilityMaskAvailable) {
  HealthValue val = health_service_peek_current_value(HealthMetricHeartRateRawBPM);
  if(val > 0) {
    // Display raw HRM value
    static char s_hrm_buffer[8];
    snprintf(s_hrm_buffer, sizeof(s_hrm_buffer), "%lu BPM", (uint32_t)val);
    text_layer_set_text(s_hrm_layer, s_hrm_buffer);
  }
}
```

Find out more in the
{% guide_link events-and-services/hrm "Heart Rate Monitor API guide" %}.

## PebbleKit 4.0

PebbleKit for [iOS](https://github.com/pebble/pebble-ios-sdk/) and
[Android](https://github.com/pebble/pebble-android-sdk/) facilitates
communication between Pebble watchapps and 3rd party companion phone apps.
Version 4.0 introduces a number of new features and bug fixes, including:

* Support for Pebble 2 *(required for iOS only)*
* Removal of Bluetooth Classic (iOS)
* Sports API - Support 3rd party HRM
* Sports API - Custom data field and label
* Sports API - Helper object to simplify usage, and minimize updates via
Bluetooth

For further information about the specific platform changes, view the full
[iOS](https://github.com/pebble/pebble-ios-sdk/), or
[Android](https://github.com/pebble/pebble-android-sdk/) changelogs.

## BLE HRM Mode

Ever wanted to use your *Pebble 2 HRM* as a dedicated BLE HRM device with your
favourite mobile fitness app? Well now you can! Firmware 4.3 now implements the
standard
[Bluetooth Heart Rate Service profile](https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=239866).
In order to enable this profile, users must enable 'Pebble Health', then enable
'Heart Rate Monitoring' within the `Pebble Health` settings within the Pebble
mobile app.

Developers who are looking to integrate directly with this profile should be
aware of the following:

The Heart Rate Service UUID will be present in the advertising payload of
Pebble, but you must open the Bluetooth settings on the Pebble to make it
advertise and be discoverable over Bluetooth.

Because it's highly likely that the Pebble is already connected to the phone, it
will not be advertising. Therefore, we recommend that your mobile app also
enumerates already connected devices, to see if any of them support the Heart
Rate Service. This is in addition to scanning for advertisements to find new
devices that support HRS. By enumerating connected devices, you improve the user
experience: users will not have to go into the Bluetooth settings menu on Pebble
if their Pebble is already connected to the phone.

The first time an application subscribes to the Heart Rate Measurement
characteristic, a UI prompt will appear on the Pebble, asking the user to allow
sharing of their heart rate data. This permission is stored for the duration of
the Bluetooth connection.

When HR data sharing is active, the HR sensor will run continuously at ~1Hz
sample rate. This means there is a significant battery impact when using this
feature for an extended period of time.

When all applications have unsubscribed from the Heart Rate Measurement
characteristic, the HR sensor automatically returns to its default state.

Mobile apps should unsubscribe from the Heart Rate Measurement characteristic as
soon as the data is no longer required. For example, a workout app should
unsubscribe when the workout has finished and/or the application is exited.

If the Heart Rate Service is used continuously for a prolonged period of time
(currently 4hrs), a notification is presented on the watch to remind the user
that the HR data is still being shared.

The user can stop sharing HRM data from *Settings > Bluetooth > Device*. If the
user chooses to stop sharing, the Bluetooth connection is briefly disconnected
and reconnected to forcefully remove all subscribers. Unfortunately the
Bluetooth GATT specification does not provide a better mechanism for a service
to unsubscribe subscribers, only subscribers can unsubscribe themselves.

Service Characteristics Notes:

* 'Sensor Contact' field is used.
* 'Body Sensor' characteristic is used. The value is constant though (It will
read "Wrist" / 0x02)
* 'RR Interval' is currently NOT used.
* 'Energy Expended' field is currently NOT used.
* 'Heart Rate Control Point' characteristic is currently NOT used.

## What's Next

Check out the [release notes](/sdk/changelogs/4.3/) for a full list of
changes and fixes that were included in SDK 4.3.

Let us know on [Twitter]({{ site.links.twitter }}) if you built something
cool using the new APIs! We'd love to hear about your experiences with the SDK.

Happy Hacking!

Team Pebble


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Pebble.js - Pebble Package Edition!
author: jonb
tags:
- Freshly Baked
---

We're pleased to announce that [Pebble.js](https://pebble.github.io/pebblejs/)
has now been [published](https://www.npmjs.com/package/pebblejs) as a
{% guide_link pebble-packages "Pebble Package" %}. Pebble.js lets developers
easily create Pebble applications using JavaScript by executing the JavaScript
code within the mobile application on a user's phone, rather than on the watch.

![Pebble.js as a Pebble Package](/images/blog/2016-12-22-pebble-js.jpg)

Making Pebble.js a Pebble Package means Pebble.js projects can be converted to
standard Pebble C projects. This gives benefits like the ability to
easily utilize other Pebble Packages, such as
[Clay for Pebble](https://www.npmjs.com/package/pebble-clay), or easily
importing and exporting the project with
[CloudPebble]({{ site.links.cloudpebble }}).

The Pebble.js package is using the
[`develop`](https://github.com/pebble/pebblejs/tree/develop) branch from the
[Pebble.js repository](https://github.com/pebble/pebblejs) on Github, and
can be updated independently from CloudPebble deployments.

**It also supports the Diorite platform!**.

## Creating a New Project

The initial steps vary if you're using CloudPebble or the Local SDK. Follow the
appropriate steps below to create a new project.

#### CloudPebble

If you're using CloudPebble, follow these initial steps:

1. Create a new project:
   * Project Type = Pebble C SDK
   * Template = Empty Project

2. Add the following dependency:
   * Package Name = pebblejs
   * Version = 1.0.0

3. Add a new `main.c` file and an `index.js` file.

Now continue to add the [default project files](#default-project-files).

#### Local SDK

If you're using the Local SDK, just create a new C project with Javascript
support:

```nc|text
$ pebble new-project PROJECTNAME --javascript
```

Now continue to add the [default project files](#default-project-files).

#### Default Project Files

Copy and paste these default project files into your project, replacing any
existing file contents:

**your-main.c**

```c
#include <pebble.h>
#include "pebblejs/simply.h"

int main(void) {
  Simply *simply = simply_create();
  app_event_loop();
  simply_destroy(simply);
}
```

**index.js**

```javascript
require('pebblejs');
var UI = require('pebblejs/ui');

var card = new UI.Card({
  title: 'Hello World',
  body: 'This is your first Pebble app!',
  scrollable: true
});

card.show();
```

At this point you should be able to compile and run your new project.

## Migrating an Existing Project

Unfortunately there isn't an automated way to migrate your existing Pebble.js
project, but the steps are fairly straightforward.

1. Create a new project, following the [steps above](#creating-a-new-project).

2. Change the project settings to match your old project settings, including the
UUID.

3. Copy your project resources (images, fonts etc.), and source files into the
new project.

4. Compile and enjoy your new C project with Pebble.js support.

> Note: `index.js` is a direct replacement for `app.js`, which may be your old
Javascript file.

## Next Steps?

Want to add Clay support to your project? It's now easy by following the
standard Clay [Getting Started](https://github.com/pebble/clay#clay)
instructions!

If you have any questions or problems, post the details on the
[developer forum](https://forums.pebble.com/t/pebble-js-pebble-package-edition/27315)
or [Discord](http://discord.gg/aRUAYFN).

Happy Holidays!

Jon Barlow + Team #PEBBLExFITBIT


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

layout: docs/markdown
title: SDK Documentation
permalink: /docs/
---

Welcome to the API Documentation section of the Pebble Developers site!

Here you will find complete listings of all the classes, objects, methods and
functions available across all the parts of the Pebble API.

## Pebble Smartwatch APIs

Pebble's smartwatch APIs provide developers with a means of developing
applications that run natively on Pebble smartwatches.

### [Pebble C API](/docs/c/)

The Pebble C API, used for creating native **watchapps and watchfaces** in C.
The Pebble C API can be used in combination with *any* of the PebbleKit APIs
listed below to extend the application's functionality.

### [Pebble JavaScript API](/docs/rockyjs/)

Pebble's embedded JavaScript API, used for creating native **watchfaces** in
JavaScript. The embedded JavaScript API can be used in combination with
PebbleKit JS to extend the application's functionality.

## PebbleKit APIs

The PebbleKit APIs provides developers with a means to extend their application's
functionality by communicating with an application on the mobile device it is
paired to.

### [PebbleKit JS](/docs/pebblekit-js/)

PebbleKit JS enables developers to extend their Pebble projects by adding a
JavaScript component that is managed by the Pebble mobile app. PebbleKit JS is
capable of bidirectional communication with with application running on the
Pebble smartwatch

### [PebbleKit iOS](/docs/pebblekit-ios/)

PebbleKit iOS is an Objective-C library that enables developers to create
companion apps for iOS devices that are capable for bi-directional communication
with their Pebble API projects.

### [PebbleKit Android](/docs/pebblekit-android/)

PebbleKit Android is a Java library that enables developers to create companion
apps for Android devices that are capable for bi-directional communication with
their Pebble API projects.

{% comment %}
## Web APIs

### [Timeline API](/docs/web-timeline/)

The Timeline API enables developers to create applications that interact with
the user's Timeline, by creating and editing Timeline Pins.

### [AppGlance API](/docs/web-appglance)

The AppGlance web API enables developers to create applications that push
information to the application's glance in the user's launcher.
 {% endcomment %}


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

layout: docs
---

  {% for language in site.data.docs_tree %}

{{ language | first }}
      {% assign tree = language[1] %}
      {% include docs/tree.html items=tree %}

  {% endfor %}


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Getting Started with Pebble Time Round
description: |
  Details on all the new features and APIs available for the Chalk platfom, or
  Pebble Time Round.
layout: sdk/markdown
permalink: /round/getting-started/
generate_toc: true
search_index: true
platform_choice: true
---

With the addition of Pebble Time Round to the Pebble hardware family, the Pebble
SDK now targets a third platform called Chalk. Feature-wise, this new hardware
is very similar to the Basalt platform with one major difference - a new display
with a round shape and increased resolution.

Pebble SDK 3.6 is available to help developers write apps
that are compatible with all hardware platforms. New graphics APIs and UI
component behaviors assist with creating layouts ideally suited for both the
rectangular and round display types.

^LC^ [Get the SDK >{center,bg-lightblue,fg-white}](/sdk/download/?sdk={{ site.data.sdk.c.version }})

^CP^ [Launch CloudPebble >{center,bg-lightblue,fg-white}]({{site.links.cloudpebble}})

## New Resources

To get you started, we have updated the following sections of the Pebble
Developer site with new content and information on designing and developing
for the new Pebble hardware platform:

* An updated
  [*Hardware Comparison*](/guides/tools-and-resources/hardware-information)
  chart - See the hardware differences between all Pebble platforms.

* [*Design in the Round*](/guides/design-and-interaction/in-the-round/) - A new
  section of the Design and Interaction guides with design guidance on how to
  best take advantage of this new display shape.

* [*Creating Circular Apps*](/guides/user-interfaces/round-app-ui/) - A new
  guide describing how to use new graphics APIs and features.

* An updated
  [*Building for Every Pebble*](/guides/best-practices/building-for-every-pebble/)
  guide - New information added on how to keep apps compatible with all three
  Pebble hardware platforms.

* Revised
  [*Platform-specific Resources*](/guides/app-resources/platform-specific/)
  guide - App resources can now be tagged according to intended usage in more
  ways than before to allow tailored resources for different display shapes.

## New Examples

A number of new example apps have been created to help illustrate the round
concept. They are listed below.

### Watchfaces

**Time Dots**

^LC^ [![time-dots >{pebble-screenshot,pebble-screenshot--time-round-silver-14}](/images/sdk/time-dots.png)]({{site.links.examples_org}}/time-dots/)

^CP^ [![time-dots >{pebble-screenshot,pebble-screenshot--time-round-silver-14}](/images/sdk/time-dots.png)]({{site.links.cloudpebble}}ide/import/github/pebble-examples/time-dots/)

**Concentricity**
{% screenshot_viewer %}
{
  "image": "/images/sdk/concentricity.png",
  "platforms": [
    {"hw": "aplite", "wrapper": "red"},
    {"hw": "basalt", "wrapper": "time-black"},
    {"hw": "chalk", "wrapper": "time-round-silver-14"}
  ]
}
{% endscreenshot_viewer %}

### Watchapps

**ContentIndicator Demo**

^LC^ [![content-indicator-demo >{pebble-screenshot,pebble-screenshot--time-round-silver-14}](/images/sdk/content-indicator-demo.png)]({{site.links.examples_org}}/content-indicator-demo/)

^CP^ [![content-indicator-demo >{pebble-screenshot,pebble-screenshot--time-round-silver-14}](/images/sdk/content-indicator-demo.png)]({{site.links.cloudpebble}}ide/import/github/pebble-examples/content-indicator-demo/)


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

layout: sdk/markdown
title: Pebble SDK Download
permalink: /sdk/download/
menu_section: sdk
menu_subsection: download
generate_toc: true
scripts:
  - sdk/index
---

## Get the Latest Pebble Tool

The `pebble` tool allows you to quickly switch between different SDK versions.
The instructions to obtain the tool vary depending on your platform. All
specific instructions are shown on this page.

## Mac OS X

The Pebble SDK can be installed automatically using Homebrew, or manually if
preferred. If you already use at least version 4.0 of the `pebble` tool, you can
install the latest SDK by running the following command:

```bash
$ pebble sdk install latest
```

### With Homebrew

If you previously used Homebrew to install older Pebble SDKs, run:

```bash
$ brew update && brew upgrade pebble-sdk
```

If you've never used Homebrew to install the Pebble SDK, run:

```bash
$ brew update && brew install pebble/pebble-sdk/pebble-sdk
```

### Without Homebrew

If you would prefer to not use Homebrew and would like to manually install the
Pebble SDK:

1. Download the
   [SDK package]({{ site.links.pebble_tool_root }}pebble-sdk-{{ site.data.sdk.pebble_tool.version }}-mac.tar.bz2).

2. Follow the [Mac manual installation instructions](/sdk/install/mac/).

## Linux

Linux users should install the SDK manually using the instructions below:

1. Download the relevant package:
   [Linux (32-bit)]({{ site.links.pebble_tool_root }}pebble-sdk-{{ site.data.sdk.pebble_tool.version }}-linux32.tar.bz2) |
   [Linux (64-bit)]({{ site.links.pebble_tool_root }}pebble-sdk-{{ site.data.sdk.pebble_tool.version }}-linux64.tar.bz2).

2. Install the SDK by following the
   [manual installation instructions](/sdk/install/linux/).

## Windows

Installing the Pebble SDK on Windows is not officially supported at this time.
However, you can choose from alternative strategies to develop watchfaces and
watchapps on Windows, which are detailed below.

### Use CloudPebble

[CloudPebble]({{site.links.cloudpebble}}) is the official online development
environment for writing Pebble apps. It allows you to create, edit, build and
distribute applications in your web browser without installing anything on your
computer.

**Pebble strongly recommends [CloudPebble]({{site.links.cloudpebble}}) for
Windows users.**

### Use a Virtual Machine

You can also download and run the Pebble SDK in a virtual machine.

 1. Install a virtual machine manager such as
   [VirtualBox](http://www.virtualbox.org) (free) or
   [VMWare Workstation](http://www.vmware.com/products/workstation/).
 2. Install [Ubuntu Linux](http://www.ubuntu.com/) in a virtual machine.
 3. Follow the standard [Linux installation instructions](/sdk/install/linux/).

## Testing Beta SDKs

Beta SDKs are released in the run up to stable SDK releases, and give interested
developers a chance to test out new features and APIs and provide feedback.

You can opt-in to the beta channel to receive beta SDKs. Once the beta period ends,
you will be notified of the update to the final stable version.

<div class="alert alert--fg-white alert--bg-dark-red">
{% markdown %}
**IMPORTANT**

Apps built with a beta SDK **must not** be uploaded to the developer portal, as
users not yet on the new firmware version will be unable to install them.
{% endmarkdown %}
</div>

Once you have the latest `pebble` tool, you can easily access and try out new
beta SDKs we release from time to time by switching to the 'beta' sdk channel:

```bash
$ pebble sdk set-channel beta
```

Install the latest beta SDK:

```bash
$ pebble sdk install latest
```


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Getting Started with SDK 4
description: |
  Details on all the new features and APIs available for use in SDK 4
layout: sdk/markdown
permalink: /sdk4/getting-started/
search_index: true
platform_choice: true
---

Pebble SDK 4 is now available for developers who are interested in using the
new APIs and features. We encourage developers to read
the [Release Notes](/sdk/changelogs/), the [SDK 4 Docs](/docs/c/), and the new
guides listed below to help familiarize themselves with the new functionality.

## Getting Started

{% platform local %}
#### Mac OS X (Homebrew)
```bash
$ brew update && brew upgrade pebble-sdk && pebble sdk install latest
````

#### Mac OS X (Manual)
1. Download the
   [SDK package]({{ site.links.pebble_tool_root }}pebble-sdk-{{ site.data.sdk.pebble_tool.version }}-mac.tar.bz2).

2. Follow the [Mac manual installation instructions](/sdk/install/mac/).

####Linux
Linux users should install the SDK manually using the instructions below:

1. Download the relevant package:
   [Linux (32-bit)]({{ site.links.pebble_tool_root }}pebble-sdk-{{ site.data.sdk.pebble_tool.version }}-linux32.tar.bz2) |
   [Linux (64-bit)]({{ site.links.pebble_tool_root }}pebble-sdk-{{ site.data.sdk.pebble_tool.version }}-linux64.tar.bz2).

2. Install the SDK by following the
   [manual installation instructions](/sdk/install/linux/).
{% endplatform %}

{% platform cloudpebble %}
Launch CloudPebble
{% endplatform %}

## Blog Posts

We've published several useful blog posts regarding SDK 4:

* [Introducing Rocky.js Watchfaces!](/blog/2016/08/15/introducing-rockyjs-watchfaces/)
* [Prime Time is Approaching for OS 4.0](/blog/2016/08/19/prime-time-is-approaching-for-os-4.0/)
* [Announcing Pebble SDK 4.0](/blog/2016/08/30/announcing-pebble-sdk4/)

## New Resources

To get you started, we have updated the following sections of the Pebble
Developer site with new content and information on designing and developing
for the new Pebble hardware platform:

* A 2-part [*Rocky.js tutorial*](/tutorials/js-watchface-tutorial/part1/) - Learn
  how to create watchfaces in JavaScript using Rocky.js.

* An updated
  [*Hardware Comparison*](/guides/tools-and-resources/hardware-information)
  chart - See the hardware differences between all Pebble platforms.

* [*AppExitReason API Guide*](/guides/user-interfaces/app-exit-reason/) - A new
  guide with information on how to use the `AppExitReason` API.

* [*AppGlance C API Guide*](/guides/user-interfaces/appglance-c/) - A new
  guide describing how to use the AppGlance API to display information in the
  system's launcher.

* [*AppGlance PebbleKit JS API Guide*](/guides/user-interfaces/appglance-pebblekit-js/) -
  A new guide describing how to use the AppGlance API to display information
  in the system's launcher.

* [*One Click Action Guide*](/guides/design-and-interaction/one-click-actions/) -
  A new guide with information on how to use one-click actions in watchapps.

* [*UnobstuctedArea API Guide*](/guides/user-interfaces/unobstructed-area) - A
  new guide that will demonstrate the basics of the `UnobstructedArea` API, and
  how to use it to create watchfaces that respond to Timeline Quick View events.


# sdk/include/*.js unit testing how-to
This folder contains tests for the .js code in sdk/include.

## Installing dependencies
1. `cd sdk/tests/include`
2. `npm install`

## Running tests
1. `cd sdk/tests/include`
2. `npm test` – this runs the tests using the [mocha](http://mochajs.org/) test runner.

You should see some output, similar to this:

```
$ npm test

> pebble-pkjs-tests@1.0.0 test /Users/martijn/tintin/sdk/tests/include
> NODE_PATH=../include ./node_modules/mocha/bin/mocha *.js

  Pebble
    interprets received postMessage API data as UTF-8
      ✓ interprets [34,34] as ""
      ✓ interprets [34,240,159,146,169,34] as "💩"
      ✓ interprets [34,237,160,181,237,188,128,34] as {}
      ✓ interprets [34,196,145,34] as "đ"
      ✓ interprets [34,224,160,149,34] as "ࠕ"
    encodes sent postMessage API data as UTF-8
sendAppMessage: [object Object]
      ✓ encodes "" as [34,34,0]
sendAppMessage: [object Object]
      ✓ encodes "💩" as [34,240,159,146,169,34,0]
sendAppMessage: [object Object]
      ✓ encodes "đ" as [34,196,145,34,0]
sendAppMessage: [object Object]
      ✓ encodes "ࠕ" as [34,224,160,149,34,0]

  9 passing (25ms)

```

## Linting the test code

1. `cd sdk/tests/include`
2. `npm run-script lint`

## Adding tests

* You can add `test_xyz.js` files in the `tests` folder. It will automatically get picked up by the test runner.
* If you need to a mock for the global `Pebble` object, check out `pebble-mock.js`. It's probably worth using and extending that than to re-invent the wheel.
* When adding additional dependencies (node packages), make sure to install them using `npm install --save-dev <PACKAGE_NAME>` so that they get added to the `devDependencies` in the `package.json` file.


Before editing a driver or writing a new one, please read through the
[driver coding guidelines on Confluence](https://pebbletechnology.atlassian.net/wiki/x/tIFQAw).


Default Header Overrides
========================

This directory contains header files which always override headers in
the firmware source tree when building unit tests. This is accomplished
by prepending this directory to the `#include` search path in
[`waftools/pebble_test.py`](../../../waftools/pebble_test.py).

Overriding the default override for a test?
-------------------------------------------

Overriding a default override header is very simple. Simply create a new
override tree and add it to your test's `clar()` build rule, just like
when overriding a header from the source tree. See the
[overrides README](../README.md) for details.

If you are considering adding a new override header
---------------------------------------------------

Only add new headers here if you are absolutely, **positively** sure
that it should always override the header of the same name in each and
every test unless explicitly overridden by yet another header in the
test's `clar()` build rule.

- Is the header being overridden used pervasively throughout the code,
  affecting the majority of tests?
- Does the header contain only inline function definitions and macros?
- Do the definitions of those functions and macros make no sense when
  compiled into a test, e.g. by containing inline ASM? Will the source
  files `#include`'ing these files always fail to compile unless
  overridden?
- Is using `#ifdef __ARM__` conditional compilation to replace
  ARM-specific code with a gneric version insufficient? Would it require
  adding test-harness code to the source tree?

If the answer to any of the above questions is "no", then adding an
override header is the wrong solution. If the answer to all of the above
questions is "yes", then adding an override header *might* be the right
solution. Adding a new default override is an action which should not be
taken lightly; it should only be done if the benefits outweigh the
risks.

### Alternatives to writing a default override header ###

- Create a stub or fake header which is `#include`'ed into the test
  which requires it.
- Create a new override directory which individual tests can opt into.


The files in this directory are used to override the generated 'resource\_ids.auto.h' (etc.) so
that we can use 'fixtures/font\_compression/system\_resources.pbpack'.

'fixtures/font\_compression/system\_resources.pbpack' was generated by adding the following stanza
to resources/normal/base/resource\_map.json:

    {
      "type": "font",
      "name": "GOTHIC_18_COMPRESSED",
      "file": "normal/base/ttf/18Cond.ttf",
      "compatibility": "2.7",
      "extended": true,
      "compress": "RLE4"
    },

and then rebuilding system\_resources.pbpack. See tools/update\_test\_system\_pbpack.sh for which
files need to be updated.


The files in this directory are used to test the override functionality of the
test infrastructure, and are `#include`'ed by
[`test_test_infra.c`](../../test_test_infra.c).


# PBL STD Overrides
The files in this directory are used to override the `app_state` header included
by `pbl_std.c`, as this header makes use of the reentry structure (`_reent`), which
is not defined when compiling non-ARM code, we override it with our own which makes
use of our faked headers.


## Setting up prerequisites

Currently, only Ubuntu 14.04+ is officially supported as primary development environment.

There are several dependencies, that should be installed manually. The following list is the absolute minimum for building:

- `gcc` or any C99-compliant compiler (native or cross, e.g., arm-none-eabi)
- `cmake` >= `2.8.12.2`

Several scripts and tools help the building and development process, thus it is recommended to have the following installed as well:

- `bash` >= `4.3.11`
- `cppcheck` >= `1.61`
- `vera++` >= `1.2.1`
- `python` >= `2.7.6`

```bash
sudo apt-get install gcc gcc-arm-none-eabi cmake cppcheck vera++ python
```

To make our scripts run correctly, several shell utilities should be available on the system:

- `awk`
- `bc`
- `find`
- `sed`

## Building JerryScript

**To build debug version for Linux**

```bash
python tools/build.py --debug
```

**To build debug version for Linux without LTO (Link Time Optimization)**

```bash
python tools/build.py --debug --lto=off
```

**Add custom arguments to CMake**

```bash
python tools/build.py --cmake-param=CMAKE_PARAM
```

**Set a profile mode (full, minimal)**

```bash
python tools/build.py --feature=full|minimal
```

**Use (jerry, compiler-default, external) libc**

The default libc is jerry-libc, but you can use compiler-default libc or an external libc:

- compiler-default libc:

```bash
python tools/build.py --jerry-libc=off
```

- external libc:

```bash
python tools/build.py --jerry-libc=off --compile-flag="-nostdlib -I/path/to/ext-libc/include" --link-lib="-lext-c"
```

**Add toolchain file**

The ```cmake``` dir already contains some usable toolchain files, which you can use in the following format:

```bash
python tools/build.py --toolchain=TOOLCHAIN
```

For example the cross-compile to RaspberryPi 2 is something like this:

```bash
python tools/build.py --toolchain=cmake/toolchain_linux_armv7l.cmake
```

**To get a list of all the available buildoptions for Linux**

```bash
python tools/build.py --help
```

## Checking patch

```bash
python tools/run-tests.py --precommit
```

### Running only one type of test

**To run build option tests**

```bash
python tools/run-tests.py --buildoption-test
```

**To run unittests**

```bash
python tools/run-tests.py --unittests
```

**To run jerry-tests**

```bash
python tools/run-tests.py --jerry-tests
```

**To run jerry-test-suite**

```bash
python tools/run-tests.py --jerry-test-suite
```

**To run signed-off check**

```bash
python tools/run-tests.py --check-signed-off
```

**To run cppcheck**

```bash
python tools/run-tests.py --check-cppcheck
```

**To run vera check**

```bash
python tools/run-tests.py --check-vera
```

**To get a list of all the available test options**

```bash
python tools/run-tests.py --help
```