Publishing Earth Engine Apps

Turn your Earth Engine scripts into shareable web applications. This module walks you through the complete process from code to published app that anyone can access.

Learning objectives

  • Convert a script into an app-ready format.
  • Create a full-screen app layout.
  • Publish and manage Earth Engine apps.
  • Share apps with specific users or the public.
  • Understand app limitations and best practices.

Why it matters

Apps democratize your analysis. A published app lets stakeholders, policymakers, or the var map = ui.Map(); map.setCenter(-82.3, 29.6, 10); // Add a simple layer var image = ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_044034_20210623') .multiply(0.0000275).add(-0.2); var ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']); map.addLayer(ndvi, {min: 0, max: 0.8, palette: ['brown', 'yellow', 'green']}, 'NDVI'); // Create a simple panel var panel = ui.Panel({ widgets: [ ui.Label('NDVI Explorer', {fontWeight: 'bold', fontSize: '20px'}), ui.Label('This app displays NDVI for a Landsat 8 scene.') ], style: {width: '300px', padding: '20px'} }); // Build the app layout var splitPanel = ui.SplitPanel({ firstPanel: panel, secondPanel: map, orientation: 'horizontal', wipe: false }); ui.root.add(splitPanel);

What you should see

A full-screen app with a sidebar panel on the left and an interactive map on the right. This is the foundation for more complex apps.

Step-by-step: Publishing an app

Step 1: Prepare your script

  • Remove all print() statements (they clutter the console).
  • Use ui.root.clear() to remove default Code Editor elements.
  • Create your own map with ui.Map().
  • Test thoroughly before publishing.

Step 2: Open the publish dialog

  1. In the Code Editor, click the Apps button (top-right).
  2. Click New App.
  3. Fill in the app details:
    • Name: Choose a descriptive name (appears in URL)
    • App URL: Will be username.users.earthengine.app/view/appname

Step 3: Configure access

Access Level Who Can View Use Case
Private Only you Testing before release
Anyone with link People you share the URL with Sharing with collaborators
Public Anyone on the internet Open access for stakeholders

Step 4: Publish and share

  1. Click Publish.
  2. Copy the generated URL.
  3. Share the link via email, social media, or embed in a website.

Complete app example: Interactive layer selector

This app lets users choose which layer to display:

ui.root.clear();

// Create map
var map = ui.Map();
map.setCenter(-82.3, 29.6, 10);

// Load image
var image = ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_044034_20210623')
  .multiply(0.0000275).add(-0.2);

// Calculate indices
var ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI');
var ndwi = image.normalizedDifference(['SR_B3', 'SR_B5']).rename('NDWI');

// Visualization parameters
var layers = {
  'True Color': {
    image: image.select(['SR_B4', 'SR_B3', 'SR_B2']),
    vis: {min: 0, max: 0.3}
  },
  'False Color': {
    image: image.select(['SR_B5', 'SR_B4', 'SR_B3']),
    vis: {min: 0, max: 0.4}
  },
  'NDVI': {
    image: ndvi,
    vis: {min: 0, max: 0.8, palette: ['brown', 'yellow', 'green']}
  },
  'NDWI': {
    image: ndwi,
    vis: {min: -0.5, max: 0.5, palette: ['brown', 'white', 'blue']}
  }
};

// Create dropdown
var select = ui.Select({
  items: Object.keys(layers),
  value: 'True Color',
  onChange: function(key) {
    map.layers().reset();
    var layer = layers[key];
    map.addLayer(layer.image, layer.vis, key);
  }
});

// Initialize with first layer
select.setValue('True Color', true);

// Create panel
var panel = ui.Panel({
  widgets: [
    ui.Label('Landsat 8 Viewer', {fontWeight: 'bold', fontSize: '24px'}),
    ui.Label('Select a layer to display:'),
    select,
    ui.Label(''),
    ui.Label('Data: Landsat 8 Collection 2', {fontSize: '12px', color: 'gray'})
  ],
  style: {width: '250px', padding: '20px'}
});

// Layout
ui.root.add(ui.SplitPanel(panel, map));

App layout patterns

Sidebar layout (most common)

ui.root.add(ui.SplitPanel({
  firstPanel: sidebarPanel,  // Controls
  secondPanel: map,           // Map
  orientation: 'horizontal'
}));

Top bar layout

ui.root.add(ui.SplitPanel({
  firstPanel: headerPanel,   // Title and controls
  secondPanel: map,          // Map
  orientation: 'vertical'
}));

Split map comparison

var leftMap = ui.Map();
var rightMap = ui.Map();
var linker = ui.Map.Linker([leftMap, rightMap]);

ui.root.add(ui.SplitPanel({
  firstPanel: leftMap,
  secondPanel: rightMap,
  wipe: true  // Enable swipe comparison
}));

Pro tips

  • Add a loading message: Use ui.Label('Loading...') that you remove when data loads.
  • Include attribution: Add data source and your name/institution.
  • Test on mobile: Many users will access via phone.
  • Version your apps: Create myapp-v1, myapp-v2 to preserve old versions.
  • Add help text: Users won't know what controls do without labels.

Managing published apps

  • Update: Edit your script and click "Publish" again to update the app.
  • Delete: Apps button → select app → Delete.
  • View analytics: Currently limited, but you can track via your own URL shortener.
  • Embed: Use an iframe: <iframe src="app-url" width="100%" height="600"></iframe>

Common mistakes

  • Leaving print() statements that clutter the console.
  • Forgetting ui.root.clear() (shows Code Editor elements).
  • Using the default Map instead of ui.Map().
  • Publishing without thorough testing.
  • Not adding instructions for users.
  • Overloading with too many features at once.

App limitations

  • Computation limits: Same as Code Editor (may time out on complex analyses).
  • No file upload: Users can't upload their own data.
  • No download: Users can't directly download results (use Export workarounds).
  • URL length: Very long URLs can break some sharing platforms.

Quick self-check

  1. Why do you need ui.root.clear() in an app?
  2. What's the difference between Map and ui.Map()?
  3. How do you update a published app?
  4. What layout widget creates a sidebar + map view?

Next steps