# What is Lawnchair?

Get a quick overview of Lawnchair and what it offers.

**Lawnchair** is a free, open-source home app for Android. It is built on Launcher3, the same base used by the default home screen on stock Android devices.

It is designed to feel similar to Google's Pixel Launcher while giving you more ways to customize your home screen.

The project is maintained by volunteers and released under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).


# Choose a version

Compare release channels and choose the right Lawnchair build.

Lawnchair is available through several release channels. Each channel balances stability and new features differently.

Choose the one that fits how you use your device.

<table><thead><tr><th width="154">Release channel</th><th width="193">Intended users</th><th>Stability</th><th>Characteristics</th></tr></thead><tbody><tr><td><a href="https://lawnchair.app/downloads">GitHub</a></td><td>Most users</td><td>Generally stable, suitable for daily use</td><td>A balance of new features and reliability. Released periodically after testing.</td></tr><tr><td><a href="https://github.com/LawnchairLauncher/lawnchair#development-builds">Nightly</a></td><td>Testers, enthusiasts, users needing a specific fix</td><td>Potentially unstable. May contain bugs.</td><td>Built automatically with the latest code changes. Has a built-in updater. Installs as a separate app from the Beta version.</td></tr><tr><td><a href="https://play.google.com/store/apps/details?id=app.lawnchair.play">Play Store</a></td><td>Users who prefer automatic updates via Google Play</td><td>Same with Official Beta</td><td>Releases for the Play Store often follow Official Beta releases but can be delayed by 1-2 weeks due to platform review processes. Uses a different package name from GitHub versions.</td></tr></tbody></table>

### Summary

* Start with **GitHub** or **Play Store** for the most stable experience.
* Use **Nightly** if you want the latest fixes and accept occasional breakage.


# Setup Lawnchair

Install Lawnchair and set it as your default home app.

Lawnchair only takes a few minutes to set up.

Install the build you chose, then set Lawnchair as your default launcher.

{% stepper %}
{% step %}

#### Install the app

Download and install the build you chose in [Choosing a version](/getting-started/choose-a-version).
{% endstep %}

{% step %}

#### Set Lawnchair as default home app

After installation, tell Android to use Lawnchair as your default launcher.

1. Long-press the home screen, then tap **Home settings**.
2. In **Home settings**, tap the card that says "To access shortcuts and additional features, set Lawnchair as your default launcher".
3. In the screen that appears, choose **Lawnchair** from the list.
   {% endstep %}
   {% endstepper %}

### Need help?

If installation fails, see [Installation issues](/troubleshooting/installation-issues).

<details>

<summary><strong>Advanced</strong>: Verify your installation</summary>

Security-conscious users can verify the cryptographic integrity of our packages by [reviewing our verification guide](/getting-started/install-and-setup/verify).

</details>


# Verify your installation

Lawnchair's APKs are cryptographically signed. You can verify the integrity and authenticity of your downloaded files using two systems:

* GitHub / SLSA attestations (available starting with Lawnchair 15 Beta 1)
* SHA-256 Android app certificate fingerprints

### SLSA attestation

Every Lawnchair release starting with Lawnchair 15 Beta 1 (excluding Nightly builds) is attested and verified with SLSA provenance. This repository meets the requirements for SLSA Level 2 compliance.

{% hint style="info" %}
You can verify the installation without using the GitHub CLI by cross-referencing checks from [GitHub Attestations](https://github.com/LawnchairLauncher/lawnchair/attestations) with [Sigstore Rekor](https://search.sigstore.dev/).
{% endhint %}

To verify using the GitHub CLI:

1. Install the [GitHub CLI](https://cli.github.com/).
2. Download the APK and its corresponding attestation from [GitHub Attestations](https://github.com/LawnchairLauncher/lawnchair/attestations).
3. Run the following command in your terminal, replacing `{APK}` with the path to your downloaded APK file:

   ```bash
   gh attestation verify {APK} -R LawnchairLauncher/lawnchair
   ```

### Android app certificate

Lawnchair uses two distinct app certificates depending on where the app was downloaded. You can verify these certificates using tools such as [AppVerifier](https://github.com/soupslurpr/AppVerifier).

{% tabs %}
{% tab title="Play Store version" %}

```
47:AC:92:63:1C:60:35:13:CC:8D:26:DD:9C:FF:E0:71:9A:8B:36:55:44:DC:CE:C2:09:58:24:EC:25:61:20:A7
```

{% endtab %}

{% tab title="GitHub version" %}

```
74:7C:36:45:B3:57:25:8B:2E:23:E8:51:E5:3C:96:74:7F:E0:AD:D0:07:E5:BA:2C:D9:7E:8C:85:57:2E:4D:C5
```

{% endtab %}
{% endtabs %}


# Theming and icons

Change icon packs, themed icons, colors, and fonts.

Lawnchair lets you customize icons, colors, and fonts. Use these settings to match your home screen to your style.

### Customize icons

Lawnchair supports two icon systems that can work together.

#### Icon packs

Icon packs provide a set of custom, full-color designs for your app icons.

<details open>

<summary>How to apply icon packs</summary>

1. Go to **Home settings** > **General**.
2. Tap **Icon style**.
3. Select the icon pack you want.

</details>

<details open>

<summary>What does <strong>Tint with accent color</strong> do?</summary>

When turned on, Lawnchair applies your current accent color to all icons.

This creates a more uniform look, but it can override an icon pack's intended colors.

</details>

<details>

<summary>Where to find icon packs</summary>

You can find supported icon packs here:

* [Play Store](https://play.google.com/store/search?q=icon+pack\&c=apps)
* [F-Droid](https://f-droid.org/en/categories/icon-pack/)

</details>

#### Themed icons

Themed icons are a modern Android feature that provides single-color, monochrome versions of icons. Lawnchair recolors them to match your wallpaper and theme.

This feature works on top of your selected icon pack.

<details open>

<summary>How to turn on themed icons</summary>

1. Navigate to **Home settings** > **General**.
2. Tap **Icon style**.
3. On the screen that appears, tap **Themed icon source**.
4. Tap **Themed icons** and choose between the following:
   * **Home screen**: Applies themed icons only to your home screen
   * **Home screen and app drawer**: Applies themed icons to both home screen and app drawer
5. Select your desired themed icon source from the list.

</details>

{% hint style="info" %}
For the best themed icon experience, make sure you have a compatible icon source.

Lawnicons is built for Lawnchair and works as both an icon pack and a themed icon source. See [Lawnicons](/integrations/lawnicons) for details.
{% endhint %}

#### Per-icon customization

You can also change the icon for a specific app on the home screen or in the app drawer.

{% hint style="warning" %}
**Important:** This feature only works for app icons. It does not support shortcuts or work profile apps.
{% endhint %}

To change one icon:

1. Long-press the app icon you want to change.
2. Tap **Customize** (or the pencil icon).
3. Tap the existing icon to open the icon editor.
   * Choose an icon from your installed icon packs.

### Customize colors and theme

Lawnchair also lets you adjust its color scheme.

<details>

<summary>Adjusting accent color source</summary>

This setting controls how Lawnchair picks its main colors.

1. Go to **Home settings** > **General**.
2. Tap **Accent color**.
3. Choose one of these options:
   1. **System**: Uses the colors provided by your device.
   2. **Wallpaper**: Uses the colors sampled from your wallpaper.
      * If you are using a live wallpaper, Lawnchair may not sample colors reliably.
   3. **Custom**: Lets you choose a preset or set a custom color.

</details>

<details>

<summary>Adjusting color style</summary>

If you use a non-system accent color, you can also change how Lawnchair applies it.

1. Go to **Home settings** > **General**.
2. Make sure **Accent color** is not set to **System**.
3. Tap **Color style**.
4. Choose a style from the list.

</details>

### Common issues

<details>

<summary>Custom font not applying or reverts</summary>

After changing fonts, you may need to restart Lawnchair.

* Go to **Home settings** > **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
* Tap **Restart Lawnchair**.

</details>

<details>

<summary>Icons appear strangely tinted or have unexpected colors</summary>

Turn off **Tint with accent color** by following the steps in [What does **Tint with accent color** do?](#what-does-tint-with-accent-color-do).

</details>


# Search

Set up dock and app drawer search, providers, and result types.

Lawnchair search helps you find apps, contacts, settings, files, and web results.

### Dock search bar

The *dock search bar* sits at the bottom of the home screen.

To change settings related to this feature, go to **Home settings** > **Search bar**, then tap the **Dock** tab.

<details>

<summary>Hide the search bar</summary>

1. Tap **Search bar widget**.
2. Select **Disabled**.

</details>

<details>

<summary>Change the search provider</summary>

A **search provider** is the service or app that opens when you tap the search bar.

1. Tap **Search provider**.
2. Choose your preferred provider from the list.
   * Some providers may require an app to be installed. Tap **Download** <i class="fa-arrow-down-to-line">:arrow-down-to-line:</i> to install it.
   * When choosing **Website**, Lawnchair will open the provider's search website in your default web browser.

</details>

<details>

<summary>Customize its appearance</summary>

You can adjust the search bar under the **Style** section.

* **Apply accent color**: Matches the search bar to the current theme.
* **Outline width**: Changes the border width. You can also set the border color when the value is not `0`.

</details>

### App drawer search bar

The *app drawer search bar* is built for searching both on-device content and the web.

To change settings related to this feature, go to **Home settings** > **Search bar**, then tap the **App drawer** tab near the top of the screen.

<details open>

<summary>What does <strong>Match dock search bar actions</strong> do?</summary>

This option links the behavior and appearance of both search bars:

* When turned on, the search bar will inherit the theme and icons of the dock search bar.
* Tapping the dock search bar will open the app drawer search UI instead of launching the selected search provider.

</details>

<details>

<summary>Choose the search algorithm</summary>

You can choose how Lawnchair finds results in the app drawer.

1. Tap **Search algorithm**.
2. Choose an option from the list:

* **App search**: Searches installed apps only.
* **Global search (on-device)**: Searches apps, contacts, files, settings, and other content stored on your device.

</details>

<details>

<summary>Choose local result types</summary>

If you choose **Global search (on-device)**, more options appear under **Show in search results**.

You can turn categories on or off. Some categories also include extra settings.

* **Apps and shortcuts**
  * Can still find results when you make small typing mistakes.
* **Web suggestions**
  * Lets you choose a built-in provider or a custom one.
  * If you use a custom provider, follow the URL instructions shown in settings.
* **People**
  * Searches contacts and related information.
* **Files**
  * Searches your device storage.
  * You can limit results to photos and videos, audio files, or all files.
  * In the Play Store version, **All files** access is not available because of Play Store restrictions.
* **Android settings**
  * Searches system settings.
* **Search history**
  * Shows recent queries when you tap the search bar.
* **Calculator**
  * Runs calculations directly in the search bar.

</details>

### Common issues

<details>

<summary>Search results are incomplete or not appearing</summary>

* Check your selected **Search algorithm**. Make sure it matches the type of results you want.
* If you use **Global search (on-device)**, make sure the right result types are turned on.
* Make sure Lawnchair has the permissions it needs.
* Check [Battery optimization](/troubleshooting/battery-optimization).

</details>

<details>

<summary>Web search or web suggestions are not working</summary>

* Check if you have a stable internet connection.
* Check if **Web suggestions** is turned on.
* Verify your selected **Web suggestions** provider.
  * If you use a custom provider, check that the URL is valid.

</details>

<details>

<summary>Tapping the home screen search bar opens the app drawer search instead of my selected provider</summary>

See [What does **Match dock search bar actions** do?](#what-does-match-dock-search-bar-actions-do).

</details>


# Backup, restore, and reset

Back up your setup, restore it later, or reset Lawnchair.

Lawnchair can back up your settings, home screen layout, and app drawer setup.

You can also restore that backup later or reset Lawnchair to its default state.

### Creating a backup

<details open>

<summary>What gets backed up</summary>

Most settings are backed up automatically, including:

* Your home screen layout, including icon positions and folders
* App drawer and search settings
* Most Lawnchair settings, including gestures and theme settings

</details>

<details open>

<summary>What is not included in a backup</summary>

* **Widgets**
  * Widget placement is saved, but widget data and internal settings are not.
  * You need to reconfigure widgets after a restore.
* **Third-party apps**
  * Integrations such as icon packs and Smartspacer still require their related apps to be installed.
  * If those apps are missing, Lawnchair falls back to its default settings.
* **Work profile apps**
  * Work profile apps may not restore reliably because Android handles them inconsistently.
* **Apps not installed**
  * If an app is missing on the target device, its icon will not appear after restore.

</details>

To create a backup:

1. Go to **Home settings** > **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
2. Tap <i class="fa-cloud-plus">:cloud-plus:</i> **Create backup**.
3. Choose what to include:
   * **Layout and settings**: Backs up everything noted above.
   * **Wallpaper**: Backs up your current wallpaper. This setting does not work if you have a live wallpaper.
4. Tap **Create**. You will be prompted to choose a name and location for your backup file.
   * Save it somewhere easy to access, such as **Downloads** or a cloud drive folder.
   * The file will have a `.lawnchairbackup` extension (e.g., `Lawnchair_Backup January 01, 2026 00:00:00.lawnchairbackup`).

### Restoring a backup

Restoring applies a previously saved `.lawnchairbackup` file to your current Lawnchair installation.

To restore a backup:

1. Go to **Home settings** > **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
2. Tap <i class="fa-arrow-rotate-left">:arrow-rotate-left:</i> **Restore backup**.
3. On the screen that appears, find and select your backup file.
4. After selecting a backup, you can restore **Layout and settings**, **Wallpaper**, or both.
   * See **What gets backed up** for details.
5. Tap **Restore**.

### Restoring a Nova backup

On Lawnchair 15 Beta 3 and later, you can import some home screen settings from a Nova Launcher backup file (`.novabackup`).

This helps if you are moving from Nova Launcher.

<details>

<summary>What gets restored from a Nova backup</summary>

* Home screen grid layout
* Icons and their positions
* Widget placement, but not widget data or setup
* Folders and their contents, if the apps are installed
* The selected icon pack, if it is installed

</details>

<details>

<summary>What is <em>not</em> restored from a backup</summary>

* Nova-specific settings such as Nova gestures and notification badges
* Subgrid layouts. Lawnchair aligns these items to the nearest standard grid position.
* App drawer layout, categories, and settings
* Lawnchair-specific settings
* Apps that are not installed on your device

</details>

To restore a Nova backup:

1. Go to **Home settings** > **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
2. Tap <i class="fa-arrow-rotate-left">:arrow-rotate-left:</i> **Restore Nova backup**.
3. On the screen that appears, find and select your backup file.
4. A confirmation screen will appear, showing a summary of what will be restored.

* If your Nova setup used subgrid positioning, Lawnchair will warn you that those items will be aligned to the standard grid.
* You can optionally tap **Add extra row to show At a Glance** if you want to show this feature.

5. Tap **Restore**.

### Reset settings to default

This resets Lawnchair to its default state.

All custom settings, including your home screen layout, will be lost.

{% hint style="danger" %}
**Important:** This action is irreversible. Make sure you have created a backup if you want to save your current setup before proceeding.
{% endhint %}

To reset Lawnchair:

1. Go to **Home settings** > **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
2. Tap <i class="fa-circle-info">:circle-info:</i> **App info**.
3. On the screen that appears, tap **Storage and cache**.
4. Tap <i class="fa-trash-can">:trash-can:</i> **Clear storage**.
5. On the warning that appears, tap **Delete**.

### Troubleshooting

<details>

<summary>Can't find backup file</summary>

Make sure the `.lawnchairbackup` file is stored on internal storage or in a cloud location your file picker can access.

</details>

<details>

<summary>Can't restore the backup file</summary>

If your backup fails to restore:

* Make sure the filename does not contain unusual or unsupported characters. Try renaming it to something simple, such as `backup.lawnchairbackup`.
* Make sure the file is fully downloaded to your device.
* Make sure the backup is compatible with your installed Lawnchair version.
* Re-download or recreate the backup if you suspect it is corrupted.

</details>


# Lawnicons

Use Lawnicons as your icon pack and themed icon source.

[Lawnicons](https://lawnchair.app/lawnicons) is a free, open-source icon pack that matches the look of Google's themed icons.

You can use it in two ways inside Lawnchair:

* As a standard icon pack.
* As a themed icon source.

### Prerequisites

* Install the Lawnicons app on your device.

### Use Lawnicons in Lawnchair

Lawnicons works as both an icon pack and a themed icon source.

#### Use it as an icon pack

1. Go to **Home settings** > **General**.
2. Tap **Icon style**.
3. On the screen that appears, choose **Lawnicons** from the list.

#### Use it as a themed icon source

When you use Lawnicons as a themed icon source, Lawnchair recolors its monochrome icons to match your current theme.

This feature works on top of your selected icon pack.

<details open>

<summary>How to turn on themed icons</summary>

1. Navigate to **Home settings** > **General**.
2. Tap **Icon style**.
3. On the screen that appears, tap **Themed icon source**.
4. Tap **Themed icons** and choose between the following:
   * **Home screen**: Applies themed icons only to your home screen
   * **Home screen and app drawer**: Applies themed icons to both home screen and app drawer
5. Select your desired themed icon source from the list.

</details>

### Common issues

<details open>

<summary>What's the difference between an icon pack and a themed icon source?</summary>

The difference is easy to miss because both options look similar.

* **As an icon pack**
  * Applies Lawnicons' default look.
  * On supported devices, that look can reflect your wallpaper colors.
* **As a themed icon source**
  * Uses Lawnicons' monochrome icons.
  * Lawnchair then recolors them to match its current theme.

</details>

<details>

<summary>Lawnicons icons don't reload or aren't colored by my wallpaper</summary>

* Check that **Themed icons** is turned on.
* Restart Lawnchair.
* Try changing your wallpaper.

</details>

<details>

<summary>An icon for a specific app is not themed</summary>

Lawnicons does not currently include a themed icon for that app.

You can request a new icon or contribute one directly.

</details>

### Contributing to Lawnicons

Lawnicons is a separate project with its own community and contribution guidelines.

If you want to request icons or contribute designs, use the [Lawnicons GitHub repository](https://github.com/lawnchairlauncher/lawnicons).


# Google Feed

Show Google Discover on the left of your home screen.

The **Google Feed**, also called **Google Discover**, shows personalized news, articles, and updates from Google.

When turned on in Lawnchair, it appears as a dedicated page to the left of your home screen.

### Prerequisites

To use Google Feed, you may need an extra app depending on your Lawnchair version:

* **Nightly**: Feed support is usually built in.
* **Other versions**: Download and install [Lawnfeed 4](https://lawnchair.app/downloads).
  * If Lawnfeed 4 does not work, try [AIDL Bridge](https://github.com/amirzaidi/AIDLBridge/releases) instead.

### Show the Google Feed in Lawnchair

1. Go to **Home settings** > **Home screen**, then turn on **Show feed**.
2. Make sure **Feed provider** is set to Google. This uses Lawnfeed 4, if installed, or the built-in integration on Nightly.
   * If you installed AIDL Bridge, change the feed provider to use **AIDL Bridge**.
3. Once selected, swipe left to show the feed.

### Common issues

<details>

<summary>Google Feed does not show up</summary>

If Google Feed does not appear or does not work correctly, try these steps:

1. Toggle the **Show feed** setting on and off.
2. Force stop the Google app, then restart Lawnchair.
3. Restart your device.

</details>

<details>

<summary>Google Feed still doesn't work</summary>

On some devices, Lawnfeed may not connect to Google Feed reliably.

If you've tried the above steps and still experience problems, consider using AIDL Bridge as your feed provider instead:

1. Make sure AIDL Bridge is installed.
2. Go to **Home settings** > **Home screen**.
3. Tap **Feed provider**, then select **AIDL Bridge** from the list.

</details>


# Smartspacer

Replace At a Glance or add a custom feed with Smartspacer.

[Smartspacer](https://github.com/KieronQuinn/Smartspacer) is an app that replaces Google's At a Glance feature and adds extra customization and plugin support.

Lawnchair supports Smartspacer as both an At a Glance provider and a feed provider.

### Prerequisites

* A device running Android 10 or later
* The Smartspacer app installed

### Use Smartspacer in Lawnchair

You can use Smartspacer for either feature, or both.

#### As an At a Glance replacement

1. Go to **Home settings** > **At a Glance**.
2. Tap **At a Glance provider**, then select **Smartspacer** from the list.
3. Return to your home screen. You will see a message that says **Smartspacer Permission Required**. Tap it.
4. In the permission dialog that appears, tap **Allow**.

#### As an alternative feed provider

1. Go to **Home settings** > **Home screen**.
2. Turn on the **Show feed** option.
3. Tap **Feed provider**, then select **Smartspacer** from the list.

### Adjust settings

Most Smartspacer features, such as plugins and appearance, are managed in the Smartspacer app itself.

You can open Smartspacer settings in one of three ways:

* Long-press At a Glance, then tap **Customize**.
* Go to **Home settings** > **At a Glance**, then tap **Open Smartspacer settings**.
* Open the **Smartspacer** app.

Lawnchair provides one specific setting for the widget:

1. Go to **Home settings** > **At a Glance**.
2. Under **Smartspacer settings**, adjust the slider for **Maximum number of targets**.

### Common issues

Some issues come from Smartspacer itself. Before reporting a Lawnchair bug, check [Smartspacer issues](https://github.com/KieronQuinn/Smartspacer/issues).

<details>

<summary>Smartspacer disappeared from my home screen</summary>

If the widget disappears, restarting Lawnchair often restores it:

1. Long press on the home screen, then tap <i class="fa-house">:house:</i> **Home settings**.
2. On the screen that appears, tap **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
3. Tap **Restart Lawnchair**.

</details>

<details>

<summary>The widget is misaligned or has incorrect padding</summary>

This is a known Lawnchair issue. Alignment can be inconsistent on some screen densities and grid layouts.

There is currently no manual fix for this in Lawnchair settings.

</details>


# QuickSwitch

Use QuickSwitch on rooted devices for better Recents integration.

[QuickSwitch](https://github.com/skittles9823/QuickSwitch) is a Magisk module that allows third-party launchers, like Lawnchair, to function as the system's Quickstep (Recents) provider.

It can improve gesture navigation, home animations, and Recents behavior.

{% hint style="warning" %}
**Important:** QuickSwitch requires **root access** on your device to function.

If your device is not rooted, this guide does not apply.
{% endhint %}

### How QuickSwitch works

QuickSwitch uses several components together:

* **Magisk Module**
  * This is the core component installed through your root solution.
  * It lets third-party launchers take over Recents.
* **QuickSwitch App**
  * This optional app gives you a simple UI for selecting the Recents provider.
  * It has its own Android version limits.
* **Lawnchair Quickstep support**
  * Lawnchair includes support for Recents, gestures, and system animations when QuickSwitch is active.

### Supported versions and devices

QuickSwitch support depends on your Android version and ROM.

### Prerequisites

* A **rooted Android device** (with Magisk, APatch, KernelSU, or a similar solution) installed and working.
* **Lawnchair** installed on your device.
* Magisk, KernelSU, or APatch installed.
* The **QuickSwitch Magisk Module** downloaded from the [official QuickSwitch releases page](https://github.com/skittles9823/QuickSwitch/releases).
  * If you are using APatch or KernelSU, download [this QuickSwitch fork](https://github.com/j7b3y/QuickSwitch) instead.

### Set up QuickSwitch

{% stepper %}
{% step %}
**Install the Magisk module**

1. Open the Magisk app (or equivalent root solution manager).
2. Go to the **Modules** section.
3. Tap **Install from storage** (or similar option).
4. Browse to and select the QuickSwitch `.zip` file you downloaded.
5. Allow the module to install.
6. **Reboot your device** when prompted.
   {% endstep %}

{% step %}
**Set Lawnchair as the default launcher**

To set Lawnchair as your default launcher, follow the steps listed in [Install and setup](/getting-started/install-and-setup).
{% endstep %}

{% step %}
**Choose Lawnchair as the Recents provider**

Choose one of the methods below based on your Android version and root solution.

{% tabs %}
{% tab title="Method A: Via the app" %}
If you are running Android 13 and below, and use Magisk:

1. Open the **QuickSwitch app** (look for it in your app drawer).
2. In the app, choose **Lawnchair** from the list of available launchers.
3. The app will prompt you to **reboot your device**. Confirm and reboot.
   {% endtab %}

{% tab title="Method B: Via a terminal command" %}
If you are running Android 14, using KernelSU or APatch, or if the app does not work, follow these steps:

1. Open a terminal emulator app on your device (e.g., Termux, or the terminal built into your root solution manager).
2. Launch a root shell (e.g., via `su`).
3. Execute the following command:

   ```shellscript
   /data/adb/modules/quickswitch/quickswitch --ch=app.lawnchair
   ```

   * The above works for the GitHub version.
   * For the Nightly and Play Store versions, use `app.lawnchair.nightly` and `app.lawnchair.play`, respectively.
   * If you are using a different package name, adjust `app.lawnchair` to match the respective package name.
4. Reboot your device to apply the changes.
   {% endtab %}
   {% endtabs %}

After rebooting, Lawnchair should be handling system gestures and the Recents screen.
{% endstep %}
{% endstepper %}

### Troubleshooting QuickSwitch

<details>

<summary>QuickSwitch app not working on Android 14 or newer</summary>

The QuickSwitch app itself does not support Android 14 or above.

You **must** use the terminal command method (Method B above) to turn on Lawnchair as the Recents provider.

</details>

<details>

<summary>After activating QuickSwitch, Lawnchair crashes immediately, I get a black screen, or the system fails to boot reliably</summary>

This usually means QuickSwitch is not compatible with your current system setup.

* Your immediate priority is to turn off the QuickSwitch module from your root solution's recovery mode, then reboot your device.
* Once your system is stable, make sure you are using the latest version listed in [Choosing a version](/getting-started/choose-a-version).
* If the issue persists, follow [Crashes](/troubleshooting/crashes) and mention QuickSwitch in your report.

</details>

<details>

<summary>After activation, I get a message saying <strong>Incompatible system integration</strong></summary>

This message appears when Lawnchair's Quickstep support cannot integrate with your system, even with QuickSwitch.

* Switch back to your system Quickstep provider.
* Make sure you are using the latest version listed in [Choosing a version](/getting-started/choose-a-version).
* If no update fixes it, your device may not be fully compatible.
* Check the [Lawnchair issue tracker](https://github.com/LawnchairLauncher/lawnchair/issues) for similar reports.

</details>

<details>

<summary>I'm experiencing other issues with the QuickSwitch magisk module</summary>

If the QuickSwitch module itself is failing, report it on the [QuickSwitch issue tracker](https://github.com/skittles9823/QuickSwitch/issues).

</details>


# Installation issues

Fix Play Protect warnings, sideload errors, and failed installs.

Android can block Lawnchair installation for a few common reasons.

This usually happens when you sideload an APK from the GitHub or Nightly release channels.

### Play Protect blocking installation

Google Play Protect scans apps for potential harm.

When you install Lawnchair from outside the Play Store, Play Protect may warn you or block the install.

To continue:

1. When prompted by Play Protect, tap **Install anyway**.
2. If installation is blocked without this option:
   1. Open the Play Store app.
   2. Tap your profile icon.
   3. Tap **Play Protect**, then tap **Settings** <i class="fa-gear">:gear:</i>.
   4. Tap **Scan apps with Play Protect**.
   5. On the message that appears, tap **Pause** or **Turn off**.
   6. Install Lawnchair.
   7. Turn Play Protect back on as soon as installation finishes.

### "App not installed" error

This is a generic Android error with several possible causes when you sideload an APK.

<details>

<summary>Check if you downloaded from an official source</summary>

You might have downloaded an APK file that has been modified or originates from an unofficial source. These often have different digital signatures that prevent installation.

**Solution:** Download Lawnchair from an official source listed in [Choosing a version](/getting-started/choose-a-version).

</details>

<details>

<summary>Check your downloaded file</summary>

The APK file you downloaded might be incomplete or damaged.

**Solution:** Delete the APK, then download it again.

</details>

<details>

<summary>Check your Lawnchair version</summary>

You might be trying to install an older version over a newer one, especially with Nightly builds.

**Solution:** Uninstall the newer version first, then install the older one.

</details>


# Restricted settings

Allow restricted settings for sideloaded Lawnchair builds on Android 13+.

On Android 13 and later, some sensitive permissions are blocked by default for apps installed outside Google Play.

This includes permissions such as notification access and accessibility services.

To use these features in Lawnchair, you may need to allow restricted settings for the app.

{% hint style="info" %}
This is usually only required for sideloaded **GitHub** and **Nightly** builds. It is usually not needed for the Play Store build.
{% endhint %}

### Allow restricted settings for Lawnchair

{% stepper %}
{% step %}

#### Trigger the restricted setting message

Try to turn on a setting that needs restricted access, such as an accessibility service.

You must see the **Restricted setting** message for the next steps to work correctly.
{% endstep %}

{% step %}

#### Grant the requested permission

{% hint style="warning" %}
**Important:** Some devicesmay not follow these exact instructions. If these steps don't work for you, [search the web](https://www.google.com/search?q=android+turn+on+restricted+settings) for the exact steps.
{% endhint %}

1. Open **Home settings**.
2. Tap **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i> > **App info**.
3. On Lawnchair's **App info** screen, tap **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
4. Tap **Allow restricted settings**.
5. Follow the on-screen instructions.
   {% endstep %}
   {% endstepper %}

For more details, see [Google's support page for restricted settings](https://support.google.com/android/answer/12623953#allowrestrictedsettings).


# Gesture navigation issues

Understand launcher gesture limits and improve navigation behavior.

Smooth gesture navigation is a big part of a good launcher experience.

On Android, results with third-party launchers can vary a lot by device, Android version, and OEM software.

{% hint style="info" %}
Gesture navigation on this page means *system navigation gestures*, not Lawnchair gestures under **Home settings** > **Gestures**.
{% endhint %}

### How does gesture navigation work?

Android gives the system launcher special privileges for handling home and Recents animations.

When you switch to a third-party launcher, those integrations may be less reliable.

### Common issues you might encounter

* Some OEMs, such as Xiaomi, block gesture navigation on custom launchers entirely
* Icons or widgets not responding for a short time after going home
* Home screen content flashing or disappearing when you tap icons too quickly after swiping home
* Home animations feeling choppy or not running at all
* App opening animations failing when you launch an app right after swiping home
* A short delay before the home screen content appears when swiping home
  * Oppo, OnePlus, and Realme introduced this issue on Android 14, but it can also appear elsewhere.

You may see some of these issues, all of them, or none of them.

### Options for improving gesture navigation

Many of these issues come from Android or OEM limits rather than Lawnchair itself. Here are the main ways to improve the experience.

#### For non-rooted users

On Android 11 and later, Lawnchair uses Google's `GestureNavContract` API to improve animations on non-rooted devices.

How well this works depends entirely on your device manufacturer.

* Devices close to stock Android, such as Pixel, Nothing, and AOSP-based ROMs, usually work better.
* Devices with heavily customized software, such as Samsung, Xiaomi, and OnePlus/Oppo, may still have major issues.

<details>

<summary>Icons are getting stuck on the screen after closing an app</summary>

A common bug causes an app icon to get stuck on screen after you close an app.

Google fixed this in Android 13, but some OEMs reintroduced it by modifying the API.

If this happens:

1. Long press on the home screen, then tap **Home settings**.
2. On the screen that appears, tap **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
3. Tap <i class="fa-flask">:flask:</i> **Experimental features**.
4. Turn off **Use GestureNavContract API**.

</details>

#### For rooted users

If your device is rooted, the **QuickSwitch Magisk module** is usually the most effective option.

QuickSwitch allows Lawnchair to integrate as the system's Recents provider. This provides a more consistent animation experience.

See [QuickSwitch](/integrations/quickswitch) for setup details.


# Widget issues

Fix common widget setup, refresh, and disappearance problems.

Widget behavior on Android can be inconsistent across apps, launchers, and device manufacturers.

These are the most common widget issues in Lawnchair and how to fix them.

<details>

<summary>Widget not appearing or crashing during setup</summary>

This can happen with widgets that open a setup screen, especially on older Android versions.

To fix it:

1. Temporarily change your default launcher to your system's default launcher (e.g., Pixel Launcher, One UI Home).
2. Open Lawnchair.
3. Attempt to add the widget you want to use.
4. Set Lawnchair as the default launcher again.

</details>

<details>

<summary>Widget data not updating</summary>

If a widget's information is not updating:

1. Resize the widget to a different size, then return it to its original size.
2. Open the app that provides the widget:
   1. Check that the app has the permissions it needs.
   2. Clear the app's cache.

</details>

<details>

<summary>All widgets disappeared from the home screen</summary>

This can happen after the home screen has been inactive for a while.

To fix it:

1. Long-press the home screen, then tap **Home settings**.
2. Tap **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>, then tap <i class="fa-arrow-rotate-left">:arrow-rotate-left:</i> **Restart Lawnchair**.

</details>


# Crashes

Capture crash logs and try the fastest recovery steps.

If Lawnchair crashes, you can usually capture a report and share it with the team.

### How Lawnchair handles crash reports

Lawnchair includes automatic crash reporting.

When the app crashes, you will usually get a notification that lets you generate a shareable crash log link.

{% hint style="warning" %}
On Android 14 and newer, you must have **notifications** turned on for Lawnchair to receive these crash reports.
{% endhint %}

### How to capture and report a crash

1. When you see the Lawnchair crash notification, tap **Upload file**.
2. A unique link to the crash log will be generated. Tap **Copy to clipboard**.
3. Report the crash on GitHub:
   1. Navigate to our [GitHub bug report form](https://github.com/LawnchairLauncher/lawnchair/issues/new?template=bug_report.yaml).
   2. Follow the steps in the form.
      1. In the "Additional Information" section of the form, paste the crash log link you copied in step 2.
   3. Submit the form.

### Basic troubleshooting steps for frequent crashes

If Lawnchair is crashing frequently, try these general steps:

<details>

<summary>Restart Lawnchair</summary>

1. Long press on the home screen, then tap <i class="fa-house">:house:</i> **Home settings**.
2. On the screen that appears, tap **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
3. Tap **Restart Lawnchair**.

</details>

<details>

<summary>Clear the app cache</summary>

1. Open **Home settings**.
2. Tap **More** <i class="fa-ellipsis-vertical">:ellipsis-vertical:</i>.
3. Tap **App info**.
4. Open **Storage and cache**.
5. Tap **Clear cache**.

</details>

<details>

<summary>Restart your device</summary>

1. On most phones, press your phone's power button for about 30 seconds, or until your phone restarts.
2. If prompted, tap **Restart** <i class="fa-repeat">:repeat:</i>.

</details>

<details>

<summary>Consider resetting Lawnchair to its default settings</summary>

**Important:** Resetting Lawnchair removes your custom settings and layout.

Before you do this, create a backup.

See [Backup, restore, and reset](/core-features/backup-restore-and-reset).

</details>


# Battery optimization

Stop background restrictions from breaking widgets, gestures, and reloads.

Android includes power-saving features that stop apps from running in the background.

That helps battery life, but it can also cause problems for launchers like Lawnchair.

### How battery optimization affects Lawnchair

If your device’s system kills Lawnchair to save battery, you may experience the following issues:

* Gestures, such as double-tap to sleep, stop working because the system disables the accessibility service
* Widgets stop updating or become unresponsive
* The home screen reloads or appears with a delay after leaving an app

#### How to fix these issues

To keep Lawnchair working reliably, turn off battery optimization for the app.

Because each manufacturer handles these settings differently, the exact steps vary by device.

Use the guide below for your device:

{% embed url="<https://dontkillmyapp.com/?app=Lawnchair>" %}


# Before you start

Contributing code to Lawnchair will take patience. This page helps you decide if it is a good fit and shows other ways to help.

{% hint style="warning" %}
Lawnchair is not a good first open-source codebase for most contributors. If you are new to Android internals or open source, start with a smaller task or one of the alternatives below.
{% endhint %}

### Who this is for

This guide fits you best if:

* You know Kotlin and the basics of Android development.
* You are comfortable reading Java, XML Views, and Compose.
* You can work through tricky debugging and slower review cycles.

### Why contributing is hard

* Lawnchair is built on Google's [Launcher3](https://cs.android.com/android/platform/superproject/main/+/main:packages/apps/Launcher3/), which means working with platform-level behavior instead of a typical app-only stack.
* The codebase mixes legacy Java and XML Views with newer Kotlin and Compose code.
* Parts of the UI are still being migrated, so patterns can change from one area to another.
* The team is small and volunteer-run, so mentoring and reviews can take time.
* Launcher work often involves Android system behavior like gesture navigation, process management, permissions, and OEM customizations.

A good first contribution is small and contained. Aim for a focused bug fix or a narrow UI change.

### Other ways to help

If you can't contribute code directly, you can still help us via the following:

1. Contribute to Lawnicons using the links in the **Lawnicons** section of the sidebar.
2. [Support project maintenance](/community/get-involved/donate-to-the-project) via Open Collective.
3. Answer questions in the [community channels](/community/get-involved/community-channels).
4. Help [translate Lawnchair](/community/get-involved/translate-lawnchair).

If you still want to contribute code, continue to [Get started](/developers/introduction/get-started) for setup steps and a practical path to your first contribution.


# Get started

Read this page once you have decided to contribute code. It covers local setup and a realistic path to a small first contribution.

### Prerequisites

* [Android Studio](https://developer.android.com/studio/preview)
* Git
* At least 8 GB of RAM
  * 16 GB of RAM is recommended to comfortably multitask with other apps.

macOS or Linux is recommended.

### Setup steps

1. Clone the repository with the `--recursive` flag.

   ```bash
   git clone --recursive https://github.com/LawnchairLauncher/lawnchair.git
   ```
2. Open the project in Android Studio.
3. Select the `lawnWithQuickstepGithubDebug` build variant.

{% hint style="info" %}
If modules ending in `lib` fail to load, run `git submodule update --init --recursive`.
{% endhint %}

### Creating your first contribution

{% stepper %}
{% step %}

#### Pick your first change

1. Pick a bug that affects you or a very small feature.
2. Prefer changes you can explain in one sentence.
3. Avoid broad refactors or multi-area rewrites for your first PR.

Check the [issue tracker](https://github.com/LawnchairLauncher/lawnchair/issues) before you start. If your bug or idea is not listed, consider opening an issue first.

If you are unsure whether a change is a good fit, ask in the [community channels](/community/get-involved/community-channels) before writing code.
{% endstep %}

{% step %}

#### Open your first PR

1. Make your change in a new branch.
2. Test it in a debug build on a device or emulator.
3. Open a [pull request on GitHub](https://github.com/LawnchairLauncher/lawnchair/pulls).
4. Follow the PR template and explain what changed.

{% hint style="info" %}
Reviews can take anywhere from a day to several weeks. The project is maintained by a small volunteer team. If your PR has no activity after two weeks, a gentle ping is fine.
{% endhint %}

If review feedback comes in, try to address it with small follow-up commits. If you get stuck, ask for clarification or close the PR and come back later.
{% endstep %}
{% endstepper %}


# Project overview

This page provides a high-level overview of Lawnchair's origins and its architectural foundation. Understanding this context is required to navigate the codebase.

### Lawnchair and Launcher3

Lawnchair is a fork of [Launcher3](https://cs.android.com/android/platform/superproject/main/+/main:packages/apps/Launcher3/), the default home screen application in the Android Open Source Project (AOSP). Lawnchair is built upon the same codebase used for the stock Android launcher.

Launcher3 is designed as a core component of the Android operating system. This distinction influences its architecture:

* AOSP components prioritize stability, performance, and resource management across diverse hardware and Android versions.
* Lawnchair inherits design philosophies and legacy structures directly from AOSP. These patterns often differ from Modern Android Development (MAD) practices used in standalone applications.

### Characteristics inherited from AOSP

Lawnchair inherits several characteristics from its AOSP foundation:

* Deep system integration for features like the Recents screen (Quickstep) and gesture navigation.
* Variable performance where core AOSP features are generally responsive, while Lawnchair-specific features or areas undergoing refactoring may not yet achieve the same level of fluidity.
* Platform-level optimizations to maintain a minimal resource footprint.
* Resilience against system-wide crashes through robust error handling.

To dive deeper into the technical principles governing the codebase, refer to [AOSP design patterns](/developers/architecture/aosp-design-patterns) and [Lawnchair design patterns](/developers/architecture/lawnchair-design-patterns). You can also consult the Glossary for definitions of project-specific terminology.

### Project structure

Lawnchair is composed of multiple Gradle modules. The most important ones are listed below:

* `lawnchair`
  * Contains Lawnchair-specific code and UI. Generally, most changes should be done here.
* `src`
  * Contains the core code of Launcher3 with modifications.
* `quickstep`
  * Contains the implementation of QuickStep, which enables Recents integration
* [`platforms/frameworks/libs/systemui`](https://github.com/LawnchairLauncher/platform_frameworks_libs_systemui)
  * Contains multiple libraries in SystemUI used by Lawnchair. See the linked repository for further information.

### Code quality and testing

Lawnchair prioritizes feature availability and user-facing stability.

Currently, the project **does not utilize unit tests or automated UI tests**. Code quality is maintained through manual verification by contributors and core maintainers, alongside feedback from our community via GitHub issues and Nightly build testers.


# AOSP design patterns

Lawnchair is an architectural hybrid. Because it is a fork of AOSP Launcher3, the codebase is divided into two distinct zones that follow different rules.

This page documents the design patterns governing the **AOSP Zone**, which primarily includes all components outside the `lawnchair` module, including `src` and `quickstep` .

If you are working in these areas, you are working on a system-level platform component. You must prioritize stability, performance, and resource management over modern application convenience.

### UI thread responsiveness

The main thread (UI thread) is responsible for drawing the interface and responding to touch input. In a launcher, even a minor delay on this thread results in dropped frames and a jarring user experience.

**Tips**

* Never perform disk I/O, network requests, or complex computations on the main thread.
* Offload heavy tasks to background threads using internal system executors or handlers.
* Update the UI only on the main thread using `Handler(Looper.getMainLooper())`.

**Example:**

```java
// Offloading search logic to a background thread
public void onSearchQueryChanged(String query) {
    MODEL_EXECUTOR.execute(() -> {
        List<SearchResult> results = performHeavySearch(query);
        MAIN_EXECUTOR.execute(() -> updateSearchUI(results));
    });
}
```

### Ephemeral and dynamic state

System state (locale, theme, orientation, or user profiles) can change at any time. Android aggressively manages resources and may kill processes that are not in the foreground.

**Tips**

* Never assume state is static or persists across process death.
* Implement robust invalidation strategies for all caches (e.g., icon caches or search result caches).
* React gracefully to `onConfigurationChanged` and system state broadcasts.

**Example:**

```java
// Invalidating cache when system theme or locale changes
public void onSystemStateChanged(Context context) {
    String currentKey = generateStateKey(context);
    if (!currentKey.equals(mLastKnownKey)) {
        mIconCache.evictAll();
        mLastKnownKey = currentKey;
    }
}
```

### Resource and memory constraints

The launcher is a persistent process. Every object allocation and memory footprint must be justified. Large allocations trigger the Low Memory Killer (LMK), which can terminate the launcher.

**Tips**

* Avoid unnecessary object allocations in performance-critical paths (e.g., `onDraw`, `onLayout`, or `onScroll`).
* Prefer primitives or light data structures like `SparseArray` over heavy collections like `HashMap` where appropriate.
* Recycle views and bitmaps whenever possible.

**Example:**

```java
// Using bitwise flags instead of object-heavy collections
public static final int FLAG_ROUNDED_CORNERS = 1 << 0;
public static final int FLAG_DROP_SHADOW = 1 << 1;

public void drawView(Canvas canvas, int flags) {
    if ((flags & FLAG_ROUNDED_CORNERS) != 0) {
        // apply drawing logic
    }
}
```

### API stability and compatibility

The launcher must support a wide range of API levels and potentially broken OEM implementations.

**Tips**

* Use runtime checks (`Utilties.ATLEAST_T`) to guard features using newer APIs.
  * If you somehow can't access the `Utilities` object, use `Build.VERSION.SDK_INT >= Build.VERSION_CODES.S` instead.
* Use compatibility wrappers to provide fallbacks for older Android versions.
* Maintain backwards compatibility for core launcher features.

**Example:**

```java
public void setBlurEffect(View view) {
    if (Utilties.ATLEAST_T) {
        view.setRenderEffect(RenderEffect.createBlurEffect(...));
    } else {
        // Fallback or no-op
    }
}
```

### Decoupling via interfaces and abstractions

Deeply coupled code is difficult to test, extend, or modify without causing cascading failures across the system.

**Tips**

* Define clear boundaries between subsystems using interfaces or abstract classes.
* Inject dependencies rather than instantiating them directly.
* Allow implementations to be swapped based on device profiles or configuration.

**Example:**

```java
// Defining a contract for search providers
public interface SearchProvider {
    void fetchResults(String query, Callback callback);
}

// Consuming the interface without knowing the concrete implementation
public class SearchController {
    private final SearchProvider mProvider;
    public SearchController(SearchProvider provider) {
        this.mProvider = provider;
    }
}
```

### Granular security and permissions

Actions impacting user privacy or device integrity must be protected. The system enforces a least-privilege principle.

**Tips**

* Perform explicit permission checks before accessing sensitive data (e.g., contacts or notification data).
* Handle the absence of permissions gracefully without crashing.

**Example:**

```java
public void loadContacts(Context context) {
    if (context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        return; // Handle gracefully
    }
    // Proceed with loading contacts
}
```

### Designed-in extensibility

As an AOSP fork, Lawnchair must be able to modify behavior without forking the entire codebase or losing the ability to upstream changes.

**Tips**

* Utilize provided AOSP extension points and hooks.
* Design new features with a "pluggable" mindset.
* Use resource overlays or build configurations to swap behaviors.

### Pervasive diagnostics and logging

Diagnosing issues in a complex, system-integrated app across millions of devices is difficult without detailed context.

**Tips**

* Use `Log.d` and `Log.v` for internal debugging, but guard them with `Log.isLoggable` checks.
* Utilize `android.os.Trace` for performance profiling.
* Provide enough context in error logs to understand the state of the system at the time of failure.

### **Immutability for predictability**

Shared mutable state is a major source of race conditions and unpredictable behavior in a multithreaded environment.

**Tips**

* Design data-carrying objects to be immutable where possible.
* Return new instances rather than modifying existing objects in place.
* Use `final` for class fields to ensure thread safety and clarity.

### Graceful degradation

Individual component failures should not bring down the entire launcher or lock the user out of their device.

**Tips**

* Anticipate and handle common failure modes (e.g., file not found, API error).
* Provide sensible defaults or fallbacks when a specific feature fails.
* Avoid "fail-fast" logic in core UI paths.

**Example:**

```java
public Drawable loadIcon(Context context, String pkg) {
    try {
        return mPm.getApplicationIcon(pkg);
    } catch (NameNotFoundException e) {
        return mPm.getDefaultActivityIcon(); // Fallback
    }
}
```


# Lawnchair design patterns

The **Lawnchair module** (everything found in `lawnchair`) represents the modern layer of the project. While the AOSP modules focuses on system-level constraints, this zone utilizes Modern Android Development (MAD) tools like Kotlin and Jetpack Compose.

However, Lawnchair follows a **pragmatic MAD** approach. Because we are bridging a modern UI with a legacy platform, we often prioritize development velocity and direct state access over strict architectural purity (such as "clean" MVVM or heavy Dependency Injection).

### **Preference-driven architecture**

Most of Lawnchair's customization is driven by a centralized preference system. This is the "brain" of the launcher.

**The Pattern:**

* **`prefs` (Legacy):** Uses `SharedPreferences` for basic types. Avoid adding new keys here.
* **`prefs2` (Modern):** Uses `Preference Datastore`. This is the preferred location for all new settings, supporting non-primitive data and default values from `config.xml`.
* The preference key is the single source of truth. The UI and the launcher logic both observe the key to ensure consistency.

### The manager pattern

Lawnchair utilizes thread-safe singletons to manage persistent subsystems that need to be accessible from both the View-based AOSP code and the Compose-based UI layer.

**The Pattern:**

* Access major subsystems (e.g., `FontCache`, `IconCache`, `LauncherAppState`) via their static `INSTANCE` or `getInstance(context)` methods.
* These managers often handle their own internal caching and state invalidation based on system changes.

### Pragmatic state management

In many modern apps, state flows from a data source through a repository to a ViewModel. In Lawnchair, we often bypass these layers to directly link the UI to our preference systems or internal registries.

Our UI structure follows a **70/20/10 complexity rule**:

* For **simple settings**, which use standard toggles and sliders, use direct state access via `getAdapter()` in the Composable. Avoid ViewModels or extra layers.
* For more **complex screens** with localized logic, such as search filters or file picking, use `remember`, `derivedStateOf`, and `produceState` within the Composable.
* Screens that mix multiple data sources or remote APIs must follow a full MVVM pattern using `AndroidViewModel` and `StateFlow` to ensure the code remains readable.

**Tips**

* Use `getAdapter()` to bridge persistent storage and the UI. This provides a `PreferenceAdapter` that handles state updates and writes automatically.
* Avoid creating ViewModels for simple settings screens. Use localized state or direct preference access instead.
* Utilize `preferenceManager2()` and `preferenceManager()` top-level functions within Compose to access data.

**Example:**

```kotlin
@Composable
fun SearchSettings() {
    val prefs2 = preferenceManager2()
    // Direct state access via adapter
    val showSearch = prefs2.showSearch.getAdapter()

    SwitchPreference(
        adapter = showSearch,
        label = stringResource(R.string.show_search_label)
    )
}
```

### Hybrid UI and interoperation

Lawnchair is in a state of "Compose-ification." We are incrementally migrating a View-based system to Jetpack Compose. This requires a hybrid approach where the two systems coexist and share state.

**The Pattern:**

* Use `ComposeView` within XML layouts or programmatically to host new UI components inside legacy Launcher3 areas (e.g., custom search results).
* Use `AndroidView` within Compose to host legacy components that are too complex to rewrite immediately.
* Pass state objects or callbacks across the boundary. Avoid complex reactive streams (like RxJava) across this boundary unless already present in the legacy code.

### Direct UI-coupled logic

For the majority of the project, we couple business logic and navigation directly to the UI components. This reduces the boilerplate required to manage a large number of independent settings and small features.

We only adopt strict MAD principles or MVVM if a screen is literally impossible to understand without them.

**The Pattern:**

* Pass `NavController` or state holders directly into Composable functions.
* Use `remember` and `derivedStateOf` within the UI layer to handle complex presentation logic that would traditionally live in a ViewModel.
* Directly trigger side effects (like updating system settings or restarting the launcher) from UI callbacks.

**Example:**

```kotlin
@Composable
fun ThemeSelector(navController: NavController) {
    val themeState = rememberThemeState()
    
    ThemeList(
        onThemeSelected = { theme ->
            themeState.apply(theme)
            navController.popBackStack() // Direct navigation coupling
        }
    )
}
```

### Simplified dependency injection

While we use frameworks like Dagger/Hilt in some areas, we frequently rely on singleton "Managers" and top-level `getInstance(context)` calls for core launcher components.

**The Pattern:**

* Access major subsystems (e.g., `IconCache`, `LauncherAppState`) via their static `INSTANCE` or `getInstance()` methods.
* Use `LocalContext.current` in Compose to fetch the required context for these singleton accessors.
* Prioritize simplicity and fast initialization over strict constructor injection in the UI layer.


# Glossary

This page defines common terms and acronyms used throughout the Launcher3 and Lawnchair codebase. Use these terms when naming variables, classes, or documenting code.

### Terminology mapping

Some terminology shown in the UI is shown differently in Launcher3's code. This is summarized in the table below:

<table><thead><tr><th width="170">UI terminology</th><th width="216">Code terminology</th></tr></thead><tbody><tr><td>Home screen</td><td>Workspace</td></tr><tr><td>Dock</td><td>Hotseat</td></tr><tr><td>App drawer</td><td>All apps</td></tr><tr><td>At a Glance</td><td>Smartspace</td></tr><tr><td>Recents screen</td><td>Overview</td></tr><tr><td>Search bar</td><td>Quick Search Bar (QSB)</td></tr><tr><td>App icon with label</td><td><code>BubbleTextView</code></td></tr></tbody></table>

### Core concepts

* **Launcher**
  * An Android app that provides the Home screen experience for a device.
* **Launcher3**
  * The default AOSP launcher codebase that Lawnchair builds on and customizes.
* **Quickstep**
  * The launcher integration layer for Recents, gesture navigation, and task transitions.
* **Home screen**
  * The main user surface containing pages of apps, widgets, and folders.
* **All Apps**
  * The app drawer surface that lists installed apps.
* **Widget**
  * A resizable app-provided view that can be placed on the Home screen.
* **Shortcut**
  * A launchable item representing an app entry point or deep link.
* **Deep shortcut**
  * A shortcut exposed by an app for a specific in-app action.

### Launcher UI surfaces

* `Workspace`
  * The paged container that holds the home screen content.
* `Hotseat`
  * The fixed dock area used for frequently accessed apps.
* `CellLayout`
  * The grid layout for a single Workspace page.
* `PagedView`
  * The base horizontally paged view used by Workspace and related surfaces.
* `AllAppsContainerView`
  * The root container responsible for presenting the All Apps UI.
* `BubbleTextView`
  * The icon-and-label view used for app and shortcut items.
* **Folder**
  * A container item that groups multiple app or shortcut items.
* `FolderIcon`
  * The Home screen representation of a Folder.
* **Folder open state**
  * The transient UI state where folder contents are shown in an overlay.
* `DragLayer`
  * The top-level overlay layer used during drag and floating UI operations.
* `AbstractFloatingView`
  * Base class for floating surfaces like open folders and popups.

### Data model

* `ItemInfo`
  * Base model type for items shown by the launcher.
* `WorkspaceItemInfo`
  * Model for app and shortcut items placed on the Workspace or Hotseat.
* `AppInfo`
  * Model representing an installed application entry in All Apps.
* `FolderInfo`
  * Model for folder metadata and its contained items.
* `LauncherAppWidgetInfo`
  * Model for widgets placed on the Workspace.
* `BgDataModel`
  * In-memory store for Workspace, Hotseat, and folder data.
* `AllAppsList`
  * In-memory list of app entries used to build All Apps.
* `LauncherModel`
  * Coordinator that loads launcher data and binds it to UI callbacks.
* `LoaderTask`
  * Background task that reads and builds launcher model data.
* `ModelCallbacks`
  * Callback contract used to bind model updates to UI surfaces.
* `PendingAddItemInfo`
  * Temporary model used while adding a new item before final placement.

### Launcher UI state

* `LauncherState`
  * A named UI mode such as `NORMAL`, `ALL_APPS`, or `OVERVIEW`.
* `StateManager`
  * Component that transitions between LauncherState values and animations.
* `NORMAL` **state**
  * Default launcher state showing the Home screen.
* `ALL_APPS` **state**
  * State where the app drawer is the primary visible surface.
* `OVERVIEW` **state**
  * State where recent tasks are shown for switching.
* `SPRING_LOADED` **state**
  * Temporary drag-focused state used during Workspace edits and rearrangement.
* `StateHandler`
  * Interface for components that apply per-state visual and behavioral changes.

### Drag and placement state

* `DragController`
  * Controller that owns drag lifecycle events from start to drop.
* `DragSource`
  * Interface for a component that initiates a drag operation.
* `DropTarget`
  * Interface for a component that can accept dropped items.
* `DragObject`
  * Runtime object carrying drag data, drag view, and coordinates.
* `DragView`
  * Floating visual copy of the dragged item shown during drag.
* `Pre-drag`
  * Early long-press phase before a full drag session begins.
* `GridOccupancy`
  * Internal grid map used to track filled and free cells.
* **Reorder**
  * Item movement logic that shifts neighbors to satisfy a drop placement.

### Device layout profile

* **Device Profile**
  * Runtime profile containing size, orientation, and layout measurements.
* **IDP (Invariant Device Profile)**
  * Base profile used without activity context to define core grid metrics.
* **Grid size**
  * The row and column configuration used for Workspace item placement.
* **Window bounds**
  * The available screen region used for layout calculations.
* **Responsive layout**
  * Layout behavior that adapts dimensions and spacing by device class.

### Lawnchair-specific features

* **Preferences screen**
  * User-facing settings UI used to configure launcher behavior.
* **Default launcher**
  * The launcher app currently selected by Android to handle Home intent.
* `PreferenceManager2`
  * Lawnchair's modern settings layer used for most feature preferences.
* `ReloadHelper`
  * Utility that triggers launcher reloads after preference or profile changes.
* **Icon Pack**
  * Third-party icon provider used to replace default app icons.
* **Icon Shape**
  * User-selectable icon mask style such as `circle` or `squircle`.
* **Themed Icons**
  * Icons tinted to match system or wallpaper-derived dynamic colors.
* **Color tokens**
  * Theme abstraction values used to keep colors consistent across UI states.
* **Hidden apps**
  * User-selected apps excluded from normal app drawer visibility.
* **Overlay mode**
  * Visual transition style used when opening or closing apps.

### Feed

* **Feed integration**
  * Optional left-page content integration such as a Discover-style feed.
* **Google Feed**
  * Also known as Google Discover. A content feed that shows news and other personalized content.
* `MINUS_ONE_PAGE`
  * The home screen page used by feed integrations, such as Google Feed.
  * One can add a new feed by [creating a service in a different app](https://github.com/FabianTerhorst/DrawerOverlayService) then adding it to Lawnchair's whitelist.

### Search

* **QSB (Quick Search Bar)**
  * Search entry surface shown in Workspace, Hotseat, and All Apps contexts.
* **Search Provider**
  * Source implementation that returns search results such as apps or web suggestions.
* **Local search**
  * On-device search mode that prioritizes launcher data and indexed content.
* **Web search**
  * Online search mode delegated to a web-capable provider.

### Smartspace

* **Smartspace**
  * The At a Glance style surface for contextual information like weather and events.
* **Smartspace provider**
  * Data source implementation that supplies Smartspace cards.
* **Predictions**
  * Suggested apps or targets ranked by usage context.

### Launcher gestures

* **Gesture handler**
  * Component that maps gesture input to launcher actions.
* **DT2S (Double Tap to Sleep)**
  * Gesture action that turns the screen off from launcher surfaces.
* **Long-press**
  * Press-and-hold interaction used to open menus or start drag operations.
* **Swipe-up**
  * Primary gesture used to open All Apps or enter task navigation flows.

### Quickstep and Recents

* **Gesture navigation**
  * Navigation mode that uses edge and swipe gestures instead of buttons.
* **Recents**
  * The task-switching surface that shows recent running tasks.
* **Overview**
  * Alternate name for the Recents task-switching surface.
* `RecentsView`
  * Core view responsible for rendering and managing task cards in Recents.
* `TaskView`
  * UI card representing a single task inside RecentsView.
* `GestureState`
  * State machine tracking the current swipe and transition lifecycle.
* `GestureEndTarget`
  * The resolved destination of a gesture, such as HOME or RECENTS.
* `AbsSwipeUpHandler`
  * Core handler that drives swipe-up transition behavior.
* `RecentsAnimation`
  * Animation pipeline that synchronizes app surfaces during task transitions.
* `RemoteAnimationTarget`
  * System object representing an app surface under remote animation.
* **Taskbar**
  * Persistent app bar surface used in supported modes and form factors.
* **Taskbar stash and unstash**
  * Taskbar collapse and restore behavior tied to app and launcher state.


# UI frameworks

Lawnchair utilizes a hybrid UI architecture. The project is currently undergoing a gradual migration from the View system to Jetpack Compose.

This results in a codebase where both toolkits coexist, each serving a specific purpose based on its architectural zone.

### The View system

The majority of the core launcher experience is built using the standard Android View system, and is currently used for the following areas:

* The core workspace and app drawer layout.
* UI components like Smartspace.
* Most legacy search result layouts and standard launcher popups.

When modifying these areas, maintain the existing View-based patterns to ensure compatibility with AOSP's internal recycling and animation logic.

### Jetpack Compose

[Jetpack Compose](https://developer.android.com/compose) is the modern standard for the Lawnchair module, and is the required toolkit for the following areas:

* The entire Lawnchair settings UI (Home settings).
* New custom bottom sheets and overlays.
* Modernized search result components and the About page.

Avoid using XML layouts for new features in these areas. Instead, use or create components in the `lawnchair/ui` package.

#### Interoperability and state

Because these two systems must work together, Lawnchair uses standard Android interoperability patterns to bridge the gap.

When bridging these systems, keep the interaction logic as simple as possible. Prefer passing simple data types or basic callbacks across the toolkit boundary rather than complex reactive streams.

#### When to use each toolkit

As a general rule, follow the existing toolkit used by the module you are touching.

* If you are adding a toggle or a new screen to the settings, use **Jetpack Compose**.
* If you are fixing a visual bug in the Workspace or dock, use the **View system**.
* If you are implementing a major new feature, consult with the core team to determine if the area is ready for Jetpack Compose or if View-based performance is required.


# Preferences

Lawnchair's customization is driven by a centralized preference system. This system acts as the single source of truth for the project's state, bridging the modern UI layer with the legacy AOSP core.

State management in Lawnchair relies on reading these preferences throughout the launcher and modifying them almost exclusively within the settings UI.

### Preference managers

Lawnchair utilizes two distinct preference managers:

* [`PreferenceManager` (`prefs`)](https://github.com/LawnchairLauncher/lawnchair/blob/16-dev/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt): The legacy manager utilizing `SharedPreferences` as the backend. Avoid adding new keys to this manager.
  * If adding keys, make sure to ensure that your key does not conflict with Launcher3's existing keys.
* [`PreferenceManager2` (`prefs2`)](https://github.com/LawnchairLauncher/lawnchair/blob/16-dev/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt): The modern *m*anager utilizing Preference Datastore. This is the required location for all new settings, as it supports non-primitive data types and allows fetching default values from `config.xml`.

### Implementing a new preference

When adding a new setting, you must define it within `PreferenceManager2`.

The following example defines a `Boolean` preference named `example_pref` that defaults to `false`.

```kotlin
// PreferenceManager2.kt
class PreferenceManger2 ... {
    // ...
    val examplePref = preference(
        key = booleanPreferencesKey(name = "example_pref"),
        defaultValue = false,
    )
}
```

A preference in `PreferenceManager` would be defined as `val examplePref = BoolPref("example_pref", false)`.

### Reading preference values

Preferences are primarily read by the core launcher logic to determine system behavior. To use a preference, you must first acquire the manager instance and then fetch the value of the specific key.

```kotlin
val prefs2 = PreferenceManager2.getInstance(context)

// Retrieve the current boolean value
val key: Boolean = prefs2.examplePref.firstBlocking()
```

For legacy `prefs`, the retrieval method is `prefs.examplePref.get()`.

Setting preference values should generally not occur within the core launcher UI or Quickstep logic. Modifying state is the responsibility of the Lawnchair settings UI.

### Using the adapter system in Compose

As seen in [Lawnchair design patterns](/developers/architecture/lawnchair-design-patterns), the app employs a Pragmatic MAD approach for its settings UI. Rather than creating ViewModels for simple settings screens, we use the `.getAdapter()` system.

The adapter provides uniform, reactive state handling directly within Jetpack Compose components.

#### **Standard preference components**

For standard settings (like toggles or sliders), pass the adapter directly to the provided Lawnchair UI components.

```kotlin
@Composable
fun BasicExample() {
    val prefs2 = preferenceManager2()
    
    // SwitchPreference automatically handles reading and writing the boolean state
    SwitchPreference(
        adapter = prefs2.examplePref.getAdapter(),
        label = stringResource(R.string.example_pref_label),
    )
}
```

#### **Custom Compose components**

When building complex or custom UI elements that require preference access, you can read the reactive state and trigger updates manually through the adapter.

```kotlin
@Composable
fun BasicExampleWithCustomComponent() {
    val prefs2 = preferenceManager2()
    val adapter = prefs2.examplePref.getAdapter()

    // Retrieve the boolean value as a reactive Compose state
    val value = adapter.state.value 

    Column {
        Text("Current state: $value")
        Button(
            onClick = {
                // Write the new value to persistent storage and update the Compose state
                adapter.onChange(value = !value)
            }
        ) {
            Text("Toggle state")
        }
    }
}
```


# Adding a search provider

The dock search bar (hotseat qsb) supports multiple search providers.

New web-based search engines can be added by implementing the search provider contract and registering them in the centralized provider list.

### Implementation contract

Search providers are defined as Kotlin objects that inherit from the `QsbSearchProvider` sealed class. Each provider requires the following metadata:

* A unique string ID used for preference storage.
* A reference to a string resource for the display name.
* A reference to a vector drawable for the icon.
* A package name (leave empty for website-only providers).
* A search URL for the website fallback.
* A provider type, typically set to `QsbProviderType.WEBSITE`.

### Steps to add a provider

{% stepper %}
{% step %}
Create a new class in `lawnchair/app/lawnchair/qsb/providers/`. Name it `SearchEngineName`.
{% endstep %}

{% step %}
Use the following template to define your engine. Replace the placeholders with your specific engine details.

```kotlin
data object MyEngine : QsbSearchProvider(
    id = "my_engine",
    name = R.string.search_provider_my_engine,
    icon = R.drawable.ic_my_engine,
    packageName = "",
    website = "https://my-engine-url.com/search?q=",
    type = QsbProviderType.WEBSITE,
)
```

{% endstep %}

{% step %}
Add the required vector drawable to the `lawnchair/res/drawable/` directory and the engine name string to `lawnchair/res/values/strings.xml`.
{% endstep %}

{% step %}
Register the provider in `QsbSearchProvider` and locate the `companion object`. Add your new engine to the list returned by the `values()` function. Maintain alphabetical order to keep the list organized.

```kotlin
sealed class QsbSearchProvider(...) {
    // ...
    companion object {
        fun values() = listOf(
            AppSearch,
            Bing,
            DuckDuckGo,
            Google,
            MyEngine, // Added provider
        )
    }
}
```

{% endstep %}
{% endstepper %}

Once registered, the new provider will appear in the search provider selection menu within Lawnchair settings.


# Development workflow

Lawnchair utilizes a tiered workflow to balance development velocity with system stability. All pull requests (PRs) must target the `16-dev` branch unless otherwise specified.

### Change tiers

The complexity and risk of a change determine the review protocol.

<table><thead><tr><th width="95">Tier</th><th>Definition</th><th>Examples</th><th>Protocol</th></tr></thead><tbody><tr><td><strong>Trivial</strong></td><td>Zero risk of regression.</td><td>Typos, documentation, style fixes.</td><td>Commit directly to the active branch.</td></tr><tr><td><strong>Simple</strong></td><td>Functionally isolated changes with low risk.</td><td>Single-file bug fixes, minor UI polish.</td><td>Create PR, assign reviewer, enable auto-merge.</td></tr><tr><td><strong>Medium</strong></td><td>Changes affecting multiple components.</td><td>New settings screens, drawer search providers.</td><td>Detailed PR, requires core team review.</td></tr><tr><td><strong>Major</strong></td><td>High-risk, core architectural changes.</td><td>Android version rebases, subsystem rewrites.</td><td>Detailed PR, mandatory formal approval required.</td></tr></tbody></table>

### Commit conventions

We follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. Commits should use the following format: `type(scope): subject`.

Allowed types include: `feat`, `fix`, `style`, `refactor`, `perf`, `docs`, `test`, and `chore`.

### Versioning scheme

Lawnchair version codes utilize a five-part structure to ensure compatibility and track development stages.

1. **Android major version**
2. **Android minor version**
3. **Development stage** (00: Dev, 01: Alpha, 02: Beta, 03: RC, 04: Release)
4. **Development version**
5. **Revision number**

The following table lists the development stages used by Lawnchair:

<table><thead><tr><th width="166">Stage</th><th width="126">Denoted by</th></tr></thead><tbody><tr><td>Development</td><td>00</td></tr><tr><td>Alpha</td><td>01</td></tr><tr><td>Beta</td><td>02</td></tr><tr><td>Release Candidate</td><td>03</td></tr><tr><td>Release</td><td>04</td></tr></tbody></table>


# Coding standards

Lawnchair code must be logical, well-formatted, and respect the architectural zone it inhabits.

### Language conventions

As seen in the [project overview](/developers/architecture/project-overview), Lawnchair uses a mix of paradigms:

* For Kotlin, follow the official [Kotlin coding conventions](https://kotlinlang.org/docs/coding-conventions.html).
  * New Lawnchair-specific features must be written in Kotlin.
* For existing Java code, follow the existing style seen in the codebase.
* Place Lawnchair-specific logic in the `lawnchair` package. Minimize changes to the `src` package to facilitate AOSP rebases.

### Modifying AOSP files

When modifying AOSP files, document changes you made with the prefix `LC-Note(<optional modifier>): <reason>` and logs with the prefix `LC-`:

```java
// Example
// LC-Note: These changes are needed to support API X.
public void onChange(Boolean value) {
    Log.d("LC-BaseActivity", "Doing something on change")
    ...
}
```

### String naming

Strings in `strings.xml` must follow the standardized naming format to ensure maintainability and ease of translation.

<table><thead><tr><th width="202">Type</th><th width="177">Format</th><th width="240">Example</th></tr></thead><tbody><tr><td>Generic word</td><td><code>$1</code></td><td><code>disagree</code></td></tr><tr><td>Action</td><td><code>$1_action</code></td><td><code>apply_action</code></td></tr><tr><td>Preference label</td><td><code>$1_label</code></td><td><code>folders_label</code></td></tr><tr><td>Preference description</td><td><code>$1_description</code></td><td><code>folders_description</code></td></tr><tr><td>Preference choice</td><td><code>$1_choice</code></td><td><code>off_choice</code></td></tr><tr><td>Feature string</td><td><code>[feature]_$1</code></td><td><code>colorpicker_hsb</code></td></tr><tr><td>Launcher string</td><td><code>$1_launcher</code></td><td><code>device_contacts_launcher</code></td></tr></tbody></table>

Avoid using generic names for feature-specific strings to prevent conflicts during rebases.


# Roadmap and future features

This page provides an overview of Lawnchair's development status, future goals, and release philosophy.

## Vision

Lawnchair's goal is to be:

* A close match to the core Pixel Launcher experience.
* Provide deep and meaningful customization.
* A rock-solid, reliable foundation.

### Development status

Lawnchair is an open-source project driven entirely by volunteers. Contributors work on the project in their free time, alongside jobs, school, and other personal commitments.

Development activity can vary, with periods of rapid progress followed by quieter times. Lawnchair is still actively developed. You can see the latest changes in the commit history on our [GitHub repository](https://github.com/LawnchairLauncher/lawnchair) or by installing Nightly builds.

### Release policy (ETAs)

We do not provide estimated release dates for new versions. Given the volunteer nature of the project, deadlines are often not feasible and create unnecessary pressure. A new version is released when it is ready.

### Future goals and roadmap

Our development is community-driven and depends on contributor availability, so specific timelines are not set. However, some of our high-level goals for future versions include:

* Port all Lawnchair Legacy features.
* Add highly requested community features.
* Simplify the Lawnchair user experience.

For more detailed planning, you can review our project's roadmap and open issues on GitHub.


# Rejected features

To keep Lawnchair stable, performant, and maintainable for our small team, we must establish clear boundaries regarding what is in-scope for a home screen app.

This page lists frequently requested features that we have decided not to implement, along with our reasoning and recommended alternatives.

### Modifying system UI elements

Users often request settings to modify the lock screen, status bar, quick settings panel, or notification shade.

However, a launcher has absolutely no system authority over these areas. They are owned and rendered by the system's SystemUI process. Modifying them from a third-party application requires fragile workarounds, root-level hacks, or accessibility overlays that degrade performance and break easily with system updates.

We suggest using your device's built-in system customization settings, custom ROMs, or dedicated system overlay utilities (such as [SystemUI Tuner](https://github.com/zacharee/Tweaker), [Good Lock](https://play.google.com/store/apps/details?id=com.samsung.android.goodlock), or specialized customization tools) to modify these areas.

### App locking

This feature would allow users to lock individual applications with a PIN, pattern, or biometric check directly within the launcher.

However, launcher-level app locking only protects the app's icon from being tapped on the home screen, without securing anything else. A user can easily bypass this "lock" by launching the target application from the Settings app, Google Assistant, notificiations, or a link from another app. Implementing this will also add significant state complexity and creates a false sense of security.

We suggest using Android's built-in [Private Space feature](https://support.google.com/android/answer/15341885) (available on Android 15 and newer) or your device manufacturer's system-level app locker, which secure the application at the OS level.

### Additional system overlays

This includes requests for persistent sidebars, floating widgets, or custom utility panels that remain visible on top of other applications.

However, managing window overlays is outside the scope of a launcher. Creating and maintaining drawing layers that display over other apps significantly increases visual bugs, compatibility issues across different Android versions, and overall project complexity.

We suggest using dedicated utility applications from the Google Play Store that are designed specifically to manage floating sidebars or overlay widgets.

### Desktop mode

This feature would adapt Lawnchair's layout into a desktop-like interface (similar to Windows or macOS) when the device is connected to an external display.

However, Android's built-in desktop mode is highly experimental, unstable, and implemented inconsistently across different device manufacturers. Launcher3's desktop code also contains additional hooks and customizations that require root access, significantly reducing the target audience for this feature.

As such, supporting this behavior would require a massive dedicated effort that could be redirected to improving Lawnchair's existing features. Furthermore, supporting desktop mode would introduce user expectations for advanced window management and customization that are far out of scope.

We suggest using your system's default desktop interface (such as Samsung DeX) if your device supports external display output.

### Built-in widgets

This includes requests for built-in, pre-designed widgets for weather, clock, calendar, or system monitoring, outside of the standard At a Glance and search bar.

However, maintaining custom widgets is a significant form of feature bloat. Designing, creating, and testing widgets, as well as adding support for many API integrations (such as weather data sources) requires constant maintenance and takes time away from improving core launcher functionality.

We suggest using dedicated third-party widget applications (such as [KWGT](https://play.google.com/store/apps/details?id=org.kustom.widget)) to design or apply highly customized clock, weather, and system widgets.

### Built-in icon packs

This includes requests to bundle custom, pre-designed icon packs directly Lawnchair.

However, icon design and app development should remain separate. Bundling static icon packs increases Lawnchair's file size unnecessarily for assets that cannot be dynamically or algorithmically updated. Our official icon pack project, Lawnicons, is already developed and distributed as a separate application for this reason.

We suggest installing third-party icon packs (including Lawnicons) instead, and applying them through [Lawnchair's icon settings](/core-features/theming-and-icons).


# Community channels

If you need help using Lawnchair, want to discuss features with other users, or just stay up-to-date with the project, you can join our official community channels.

### Discussion and support

These platforms are the primary place for user-to-user support and general discussion.

Please be respectful and courteous to other members and follow the rules of each platform.

<a href="https://t.me/lccommunity" class="button secondary" data-icon="telegram">Telegram</a><a href="https://discord.gg/3x8qNWxgGZ" class="button secondary" data-icon="discord">Discord</a>

### Official announcements and community events

Follow these channels for official news, release announcements, contests, and community showcases.

These are generally not monitored for support questions; please use the discussion channels above for help.

<a href="https://mastodon.social/@lawnchairapp" class="button secondary" data-icon="mastodon">Mastodon</a><a href="https://x.com/lawnchairapp" class="button secondary" data-icon="x-twitter">X (formerly Twitter)</a><a href="https://reddit.com/r/lawnchairlauncher" class="button secondary" data-icon="reddit-alien">Reddit</a>

### Unmonitored channels

To save developer bandwidth and prevent ignored messages, please do not use the following channels for general support or bug reporting.

The core team does not monitor these spaces for technical assistance.

The channels here include:

* Our support email at `support@lawnchair.app`
* [GitHub discussions](https://github.com/LawnchairLauncher/lawnchair/discussions)
* [XDA thread](https://xdaforums.com/t/lawnchair-customizable-pixel-launcher.3627137/)


# Report issues

Your feedback is crucial for improving Lawnchair. We use our GitHub repository to track bug reports, crashes, and feature requests.

### Reporting bugs or crashes

Before reporting a bug, please check if the issue is already known by checking our [troubleshooting guides](/troubleshooting/installation-issues) and searching [our existing issues](https://github.com/LawnchairLauncher/lawnchair/issues).

* **For crashes,** please follow the specific instructions in [our reporting crashes guide](/troubleshooting/crashes) to capture and include a crash log. A report without a crash log is often not actionable.
* **For other bugs,** provide clear, step-by-step instructions on how to reproduce the issue. Include your device model, Android version, and Lawnchair version.

<a href="https://github.com/LawnchairLauncher/lawnchair/issues/new?template=bug_report.yaml" class="button primary" data-icon="bug">Report a bug on GitHub</a>

### Requesting a feature

If you have an idea for a new feature or an enhancement to an existing one, you can submit a feature request on GitHub.

* Please check if a similar feature has already been requested before creating a new one.
* Clearly describe the feature and its potential benefits.

<a href="https://github.com/LawnchairLauncher/lawnchair/issues/new?template=feature_request.yaml" class="button primary" data-icon="square-star">Request a feature on GitHub</a>

### Triage issues

If you want to help manage Lawnchair' issue tracker, visit our page on how to triage issues.

<a href="/pages/Pd4cDgk3MMI9HF7wZBQ5" class="button primary" data-icon="circle-dot">Learn how to triage issues</a>


# Contribute code

Lawnchair is built by volunteer developers.

If you have experience with Android development and would like to contribute, we welcome your help in fixing bugs, improving performance, and building new features.

All the information you need to get started, including how to set up your development environment, our architectural overview, and our contribution workflow, is detailed in our Developer Guide.

<a href="/spaces/acjqViWIhLF2iJAW72GW" class="button primary" data-icon="code">Read our Developer Guide</a>


# Contribute translations

Help make Lawnchair accessible to more people around the world by contributing translations.

We use Crowdin to manage our translation efforts, making it easy for anyone to contribute, even without technical knowledge.

If you have any questions, it's best to ask our [community channels](/community/get-involved/community-channels) on Telegram or Discord, as the chat on Crowdin is not actively monitored.

<a href="https://lawnchair.crowdin.com/" class="button primary" data-icon="language">Translate Lawnchair on Crowdin</a>


# Triage issues

This document defines the official workflow for triaging issues on Lawnchair's GitHub repository. The goal of the triage team is to maintain a clean, organized, and actionable issue tracker, allowing developers to focus on writing code.

We utilize centralized boards to track and organize our development pipeline:

* **Bug and Issue Tracker:** [Lawnchair GitHub Projects (Issues)](https://github.com/orgs/LawnchairLauncher/projects/10)
* **Feature Request Tracker:** [Lawnchair GitHub Projects (Feature Requests)](https://github.com/orgs/LawnchairLauncher/projects/11)

### The triage lifecycle

Every issue follows a structured lifecycle managed by `status:` labels. The primary goal of triage is to move an issue from its initial reported state to a finalized, actionable state.

#### Status labels

* `status: needs triage` is the default state for all new issues, indicating they have not yet been reviewed by the triage team.
* `status: needs info` is used when an issue has been reviewed but is missing critical details from the author, such as steps to reproduce, device specifications, or crash logs. Issues will be closed after one month of no reply.
* `status: needs repro` is applied when an issue has been reviewed and seems valid, but requires independent reproduction or confirmation by other contributors or developers.
* `status: reviewed` indicates the issue has been fully validated, reproduced, and documented. This is the signal that an issue is developer-ready.

#### High-priority labels

Some validated issues may receive a high-priority label to denote their impact:

* `tracking-issue` is used for high-impact bugs or highly requested features. These issues serve as the official curated list of project priorities and are used in addition to the `status: reviewed` label. You can view the list of current [Lawnchair tracking issues on GitHub](https://github.com/LawnchairLauncher/lawnchair/issues?q=is%3Aissue+is%3Aopen+label%3A%22tracking+issue%22).

#### Topic-specific labels

We use specific category labels to route complex subsystems to the correct developers:

* `quickswitch issue` is applied to problems involving the root-based QuickSwitch integration for system Recents.
* `gesture issue` is used for non-root gesture navigation problems, which are often related to OEM-specific system behaviors.

### The triage process

{% stepper %}
{% step %}

#### Find an issue requiring review

Start by selecting an issue that has not yet been processed. You can find the list of pending reports on the [GitHub triage list](https://github.com/LawnchairLauncher/lawnchair/issues?q=is%3Aopen+is%3Aissue+label%3A"status%3A+needs+triage"+sort%3Acreated-asc).
{% endstep %}

{% step %}

#### Investigate the report

Analyze the issue to determine its correct state:

1. Search the repository (especially existing `tracking-issue` reports) to see if the problem has already been reported. If it is a duplicate, recommend closing the issue (e.g., `Recommendation: Close as duplicate of #1234`).
2. Verify if the author completed the issue template. If the report is completely empty or incomprehensible, recommend immediate closure. If it is simply missing crucial details, recommend requesting the information (e.g., `Recommendation: Change status to 'needs info'. Please provide a screen recording`).
3. If the report is clear, attempt to reproduce the behavior using the latest [Lawnchair Nightly build](https://github.com/LawnchairLauncher/lawnchair?tab=readme-ov-file#development-builds). For feature requests, assess if the concept aligns with the project's goals.
   {% endstep %}

{% step %}

#### Make a recommendation

Post a comment with your findings and a clear recommendation for the core team:

* `Recommendation: Change status to 'reviewed'. This is a valid, reproducible bug.`
* `Recommendation: Change status to 'needs repro'. The issue seems valid but requires independent testing on different hardware.`
* `Recommendation: Change status to 'reviewed' and add 'tracking-issue'. This is a major regression affecting multiple users.`
  {% endstep %}
  {% endstepper %}

#### Workflow for the core triage team

Members of the core triage team have permission to apply labels, move items on the project boards, and close issues directly. They may perform these actions based on their own investigations or by reviewing the recommendations left by other contributors.


# Write documentation

This page outlines the conventions and workflows for contributing to Lawnchair's documentation. Following these guidelines ensures that our documentation remains accurate, scannable, and easy to maintain.

## Documentation philosophy

Our documentation is divided into distinct guides, each serving a specific audience. When writing or editing, you must adhere to the core philosophy of that section:

* User guide (inverted pyramid): users are often frustrated when they open documentation. Front-load the solution with a one-sentence TL;DR, then provide clear step-by-step instructions. Keep deeper technical explanation near the end.
* Developer guide (principles over code): code changes often, but architecture and contracts are more stable. Focus on constraints, interfaces, and expectations instead of volatile implementation details.
* Community guide (direct action): keep pages short and focused on a clear next step, such as contributing on GitHub, translating on Crowdin, or donating.

## How to contribute

Lawnchair's documentation is hosted on GitBook but is managed entirely through our GitHub repository. To maintain a single, consolidated review process, all changes must be submitted as Pull Requests on GitHub.

1. Clone the repository and open the directory that contains the page you want to update.
2. Edit the Markdown files directly.
3. If you add a new page, register it in `SUMMARY.md` so it appears in sidebar navigation.
4. Open a Pull Request targeting the `main` branch. After merge, changes sync to GitBook automatically.

Important: avoid platform-specific GitBook blocks or plugins that do not render correctly in standard Markdown viewers, including GitHub.

## Style and formatting

To maintain visual consistency across all pages, adhere to the following rules:

* Headings: use sentence case for page titles and section headings. Avoid symbols and questions in headings.
* Bold text: use bold only for UI labels or short critical warnings.
* Navigation paths: use the `>` separator (example: Home settings > General > Icon style).
* More icon: refer to the vertical three-dots menu icon `⋮` as More.
* Terminology: in user-facing pages, prefer plain language. For example, use "turn on" instead of "enable" and "search bar" instead of "QSB."

## Adding visual media

Visuals are highly effective for reducing cognitive load on frustrated users.

* Screenshots and GIFs: use these for complex setup and troubleshooting flows.
* Storage: store media files in `/docs/assets/`.
* Linking: use relative paths (example: `../assets/restricted-settings-step1.png`) so assets render on both GitHub and GitBook.


# Donate to the project

As a free and open-source project, Lawnchair relies on community support to cover operational costs. These costs can include server fees, domain name registrations, and other expenses that keep the project running.

If you find Lawnchair useful and would like to support its continued development and maintenance, you can make a donation through our Open Collective page.

<a href="https://opencollective.com/lawnchair" class="button primary" data-icon="gratipay">Donate to Lawnchair on Open Collective</a>


# Branding

This page contains the official branding assets and visual guidelines for the Lawnchair project. Please adhere to these guidelines when representing the project.

## License

Unlike Lawnchair's source code, which is licensed under Apache License 2.0, the Lawnchair logo, wordmark, and other official branding elements are All Rights Reserved (ARR). They are proprietary and protected intellectual property.

Please follow the guidelines listed in the next section.

## Lawnchair brand guidelines

Please adhere to the following guidelines when representing the Lawnchair project:

You may use Lawnchair's branding for:

* Accurate representation in news articles, reviews, or educational content.
* Non-commercial community creations (for example, fan-made wallpapers or device setups) that clearly do not imply official endorsement or creation by the Lawnchair team.

You may not use Lawnchair's branding for:

* Commercial products, services, or ventures.
* Derivative products, including software, products, or services that use the Lawnchair name or logos.
* Any use that implies endorsement or affiliation with the project, its developers, or its partners.

You are also not allowed to:

* Modify, alter, or recolor official logos or wordmarks without explicit permission.
* Use assets in a misleading way.

### Assets

All assets should follow Material 3. Use these specifications as reference:

* Source color: `#47B84F`
* Typography: [Inter](https://fonts.google.com/specimen/Inter)

### Device mockups

When creating device mockups for Lawnchair, use the latest stable Lawnchair commits as the base.

Wallpapers, fonts, and icon packs are allowed as long as they are free to use under a permissive license, such as Creative Commons.

The out-of-the-box experience is recommended because it shows users what to expect from Lawnchair Launcher when they first use it.

## Brand kit

You can find the official Lawnchair branding assets, including logos and wordmarks, on our Figma design site.

{% embed url="<https://www.figma.com/design/E2iq7FaYEkJ7waxG42ZYl0/Lawnchair-brand-kit>" %}

<a href="https://www.figma.com/file/E2iq7FaYEkJ7waxG42ZYl0?type=design&#x26;mode=design" class="button primary" data-icon="figma">Open design kit on Figma</a>


# License

Lawnchair is licensed under Apache License 2.0.

In simple terms, this license allows you to:

* Freely use, modify, and distribute the software for any purpose, including commercial use.
* Sublicense the software.
* Use patents contributed to the software by its contributors.

The license requires that you:

* Include a copy of the license in any software distribution.
* Include a notice of significant changes you make to files.

This license does not grant rights to use the trademarks, names, or logos of the Lawnchair project or its contributors.

For the full legal details, you can read the [complete license text](https://www.apache.org/licenses/LICENSE-2.0).


