# Your first build

Build a program that puts text on the Kode Dot's screen and follows your finger, then flash it over USB-C. The whole loop once, end to end.

## What it is

The loop you will repeat for every app: write C, build it into an image,
write the image onto the Kode Dot over the USB-C cable, watch the log. This
page runs it once with a program that shows text on the screen and moves it
to wherever you touch, so you see the screen, the touch and the toolchain
work in one go.

With the toolchain from `build/setup`, it takes five minutes. Without it,
the play button on the code below installs the same program on a Kode Dot
from Chrome or Edge, so you can see it run before you install anything. It
goes on **as an app**, next to the ones the Kode Dot has, and kodeOS stays.

## How to run it

1. Create a project from the template, as `build/setup` shows, and put the code below in `main/app_main.c`.
2. Build it: `idf.py build`.
3. Plug the Kode Dot in over USB-C and find its port: on macOS `ls /dev/cu.usbmodem*`.
4. Flash it and stay on the log: `idf.py -p <port> flash monitor`.
5. Touch the screen. The text follows your finger, and the log shows the board coming up.

## Gotchas

> **WARNING**
>
> **`idf.py` cannot find the port halfway through the flash.** The USB port
> re-enumerates between the bootloader and the app, so its path can change
> during one flash. List the ports again rather than assuming the board is
> dead.

> **WARNING**
>
> **The flash succeeded and the screen is black.** The image landed and the
> problem is in it: the log tells you where. Reflashing the same binary
> changes nothing. If the board reboots in a loop instead, `start/unbox` has
> the reset that fixes it.

> **NOTE**
>
> **`idf.py monitor` misbehaves in a script.** It needs a real terminal. Run
> it in one, or read the log another way.

## Example code

Text in the middle of the screen that moves to wherever you touch. The play
button writes this exact program onto a Kode Dot on the cable.

```c
/*
 * first_build.c - 2026-09-18 - from Kode with love
 *
 * Draws a label in the middle of the Kode Dot's screen and moves it to the
 * last point touched. Brings the board up, which starts LVGL and the touch
 * controller, then creates the label and a timer that reads the touch state
 * thirty times a second. The text follows your finger.
 */
#include "kode.h"

static lv_obj_t *s_label;

/* Runs inside the LVGL task: read the one input device and move the label to it. */
static void follow_touch(lv_timer_t *timer)
{
    (void)timer;
    lv_indev_t *touch = lv_indev_get_next(NULL);
    if (!touch || lv_indev_get_state(touch) != LV_INDEV_STATE_PRESSED) return;
    lv_point_t p;
    lv_indev_get_point(touch, &p);
    lv_obj_set_pos(s_label, p.x - lv_obj_get_width(s_label) / 2, p.y - 12);
}

/* Board and LVGL, then the label and its timer, under the LVGL lock. */
void app_main(void)
{
    ESP_ERROR_CHECK(kode_bsp_init());

    kode_bsp_lvgl_lock();
    s_label = lv_label_create(lv_display_get_screen_active(kode_bsp_display()));
    lv_label_set_text(s_label, "Hello, Kode Dot");
    lv_obj_set_style_text_font(s_label, &lv_font_montserrat_16, 0);
    lv_obj_center(s_label);
    lv_timer_create(follow_touch, 33, NULL);
    kode_bsp_lvgl_unlock();
}
```

Compiled on the date in the header against the `kode` component with
ESP-IDF v6.1, and that build is what the play button installs. **TBD**: a run
on a V1 board from this page.

## In the SDK

- [`templates`](https://github.com/kodediy/kode-sdk/tree/main/templates): the project this one starts from, in `kode-sdk`.
