Skip to content

Hand-Coded JS/HTML Extension

This tutorial walks you through creating a simple JSA extension by hand. No build tools, no frameworks — just a text editor, a manifest, and some HTML + JavaScript.

A floating panel that shows the number of entities in the active model and has a button to draw a box.

Make a new folder for your extension. Call it whatever you like:

my-first-extension/

Create a file called manifest.json inside your folder:

{
"manifestFormatVersion": "1.0.0",
"id": "my-first-extension",
"name": "My First Extension",
"mainFile": "index.html",
"description": "A simple extension that counts entities and draws a box.",
"version": "1.0.0",
"window": {
"type": "floating",
"width": 300,
"height": 250
},
"commands": {
"open": {
"title": "My First Extension",
"description": "Open My First Extension"
}
},
"menuItems": [
{ "type": "item", "commandId": "open" }
]
}

This tells SketchUp:

  • Your extension is called “My First Extension”
  • It opens index.html in a 300x250 floating panel
  • There’s one menu item under Extensions that opens it

For a deeper dive into every field, see the Manifest reference.

Create index.html in the same folder:

<!DOCTYPE html>
<html>
<head>
<title>My First Extension</title>
<link rel="stylesheet" href="https://cdn.habitat.sketchup.com/dist/experimental/css/latest/sketchup-extension.css">
<script src="https://cdn.habitat.sketchup.com/dist/sketchup-js-api/v2/sketchup-js-api.js"></script>
</head>
<body>
<h3>My First Extension</h3>
<p id="info">Click a button below.</p>
<button id="count-btn">Count Entities</button>
<button id="box-btn">Draw a Box</button>
<script type="module">
await SketchUpApi.connect();
document.getElementById('count-btn').addEventListener('click', async () => {
const model = await SketchUpApi.getActiveModel();
const entities = await model.entities.get();
const faces = entities.filter(e => e.type === SketchUpApi.EntityType.Face);
const edges = entities.filter(e => e.type === SketchUpApi.EntityType.Edge);
document.getElementById('info').textContent =
`Faces: ${faces.length}, Edges: ${edges.length}, Total: ${entities.length}`;
});
document.getElementById('box-btn').addEventListener('click', async () => {
const model = await SketchUpApi.getActiveModel();
await model.performOperation((op) => {
const face = op.createFace(model, [
[0, 0, 0], [100, 0, 0], [100, 100, 0], [0, 100, 0]
]);
op.facePushPull(face, 100);
}, 'Draw a Box');
document.getElementById('info').textContent = 'Box drawn!';
});
</script>
</body>
</html>

Let’s break down what’s happening:

  1. CSS — We load SketchUp’s built-in stylesheet so buttons and text look native.
  2. SDK — We load the SketchUp JavaScript API from the CDN.
  3. Connect — SketchUpApi.connect() establishes communication with SketchUp.
  4. Count — We query the model for entities and display counts.
  5. Draw — We create geometry inside a performOperation() block (like a Ruby model.start_operation).

Select both files (manifest.json and index.html) and compress them into a zip. The zip should contain the files directly at the root — no wrapper folder.

On macOS:

Terminal window
cd my-first-extension
zip -r ../my-first-extension.zip .

On Windows, select both files → Right-click → Compress to zip file.

  1. Open the SketchUp for Web JSA Server
  2. Go to File → Extensions → Extension Manager
  3. Drag my-first-extension.zip onto the upload area
  4. Open the Extensions menu — you’ll see “My First Extension”
  5. Click it to open the panel, then try the buttons!

You’ve got the basics down. From here you can:

  • Add more buttons, inputs, and UI to your index.html
  • Explore the Examples to see code snippets for specific API features
  • Check out the getting-started repo for more complete examples (look at examples/HelloJs/ and examples/HelloHtml/)
  • Move to a localhost dev server for faster iteration without re-zipping every time