DEV Community

Cover image for Add a 3D globe to your Next.js site with one prompt
Alejandro Vizio
Alejandro Vizio

Posted on

Add a 3D globe to your Next.js site with one prompt

I make Globestudio, a free, open-source studio for dotted maps and 3D globes. I recently added an agent skill to it: a folder of markdown that teaches coding agents like Claude Code, Codex and Cursor how to put a Globestudio globe in your project.

This post walks through it in a Next.js app. You install the skill, ask for a globe in one prompt, and get a component short enough to read in a minute. The code in section 3 is what Claude Code wrote when I ran the prompt in a fresh app, unedited. After that: the same thing without an agent, how to change the look in the studio and hand it back, the MCP server as another route, and the limits.

The video is the same skill on a small Vite page I made for the demo. The walkthrough below is Next.js.

What you need

  • A Next.js app with the App Router. npx create-next-app@latest gives you one.
  • A coding agent that reads skills, such as Claude Code, Codex or Cursor.
  • Node 22.20 or later (the skills CLI needs it).

1. Install the skill

From the root of your project:

npx skills add alevizio/globestudio
Enter fullscreen mode Exit fullscreen mode

It asks which agents you use. Codex, Cursor and the others that read .agents/skills are always included. For Claude Code, tick it with the space bar, or skip the question with npx skills add alevizio/globestudio -a claude-code. Commit the folders it adds and your team gets the skill too. Add -g to install it for all your projects instead. npx skills sends anonymous install data to skills.sh unless you set DISABLE_TELEMETRY=1.

There are two other ways in. With the GitHub CLI:

gh skill install alevizio/globestudio globestudio
Enter fullscreen mode Exit fullscreen mode

Or, in Claude Code, as a plugin that brings the skill and the Globestudio MCP server together:

/plugin marketplace add alevizio/globestudio
/plugin install globestudio@globestudio
Enter fullscreen mode Exit fullscreen mode

The same three installs are in the studio too: press D for the export dialog and open the Skill tab. There the plugin one is the shell form, claude plugin marketplace add alevizio/globestudio && claude plugin install globestudio@globestudio.

A skill is instructions your agent will follow, so read it before you install it. This one is a SKILL.md and three reference files in skills/globestudio. The reference files are generated from the app's own code, and a test in the repo fails when they fall behind it. The skill also has a page on skills.sh with its installs and security audits.

2. The prompt

Open your agent in the project and ask:

Add a slowly spinning dotted globe to the hero on the home page. Mark our offices in New York, London and Tokyo and join them with arcs. Use our brand blue, #2563eb, on a transparent background.

You don't have to say "Globestudio". The skill's description covers dotted maps, 3D globes and spinning earths, so the agent loads it when you ask for one. If your project already draws globes with another library, like cobe or globe.gl, the skill tells the agent to keep using that one unless you ask to switch.

3. What the agent wrote

I ran that prompt once in Claude Code, in a fresh create-next-app app with nothing added but the skill. Its first step was to load the skill. Then it read the page, the embedding and config references and the looks table, and installed the React package:

npm install @globestudio/react
Enter fullscreen mode Exit fullscreen mode

You want 0.1.1 or later. 0.1.0 dropped the look whenever you also passed a config, so the globe came out in the Default look.

Then it wrote one component, app/office-globe.tsx, with the design in one constant:

import { Globe } from "@globestudio/react";

const BRAND_BLUE = "#2563eb";

const OFFICES = [
  { name: "New York", lat: 40.71, lng: -74.01 },
  { name: "London", lat: 51.51, lng: -0.13 },
  { name: "Tokyo", lat: 35.68, lng: 139.69 },
];

// Changes layered over Globestudio's "default" look. Arcs join the offices in list order.
const OFFICE_GLOBE = {
  v: 2,
  selection: "world",
  dotColor: BRAND_BLUE,
  backgroundStyle: "transparent",
  globeSettings: {
    autoSpinSpeed: 10,
    network: false,
    gridColor: BRAND_BLUE,
    glowColor: BRAND_BLUE,
    dataPoints: OFFICES.map(({ lat, lng }) => ({ lat, lng, value: 10 })),
    dataArcs: true,
    dataMarkerColor: BRAND_BLUE,
  },
};

export function OfficeGlobe({ className }: { className?: string }) {
  return (
    <Globe
      look="default"
      config={JSON.stringify(OFFICE_GLOBE)}
      height={480}
      loading="eager"
      className={className}
      title={`Spinning dotted globe with arcs joining our offices in ${OFFICES.map((o) => o.name).join(", ")}`}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

And it put the component in app/page.tsx. A fresh create-next-app page has no hero, so the globe went between the Next.js logo and the headline:

 import Image from "next/image";
+import { OfficeGlobe } from "./office-globe";

 export default function Home() {
...
           priority
         />
+        <OfficeGlobe className="my-10" />
         <div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
Enter fullscreen mode Exit fullscreen mode

That's the whole change: one new file, two lines in the page and the dependency. It ran npm run build, which passed, and ended with this:

The globe is in the home page hero and the site builds, but I haven't seen it render: I couldn't open a browser in this session, so the look on the page is unchecked.

The skill asks for exactly that: check the render by reading the code and the /embed address it builds, which you can open to see the globe, and say so when no one has seen it render. If your agent tells you the globe works without having looked at it, ask it to look.

It also warned that on a light page the look's dark sphere fill might show as a dark disc, and it was right:

The agent's globe on a light page: as written, with surface off, and with surface and glow off

On the left is the globe as written: blue dots on a gray disc with a halo. The agent suggested "surface": false in globeSettings. That alone (middle) still leaves a blue haze from the glow. With "glow": false as well (right), you get blue dots and grid lines on white. On a dark page there's no gray disc. theme="light", new in 0.2.0, doesn't help here: it's for the looks that paint white ink (see Limits).

<Globe> renders an iframe of https://globestudio.app/embed. Three.js, the shaders and the map data run on globestudio.app. The package itself is about 1 KB (650 bytes gzipped), and in a server component like this one none of it reaches the browser. It's a plain iframe with no state, so it works in a server component as is, with no "use client". You only need a client component if you pass onLoad or a ref. On the server, the component renders this:

<iframe src="https://globestudio.app/embed?look=default&amp;c=%7B%22v%22%3A2%2C%22selection%22%3A%22world%22%2C%22dotColor%22%3A%22%232563eb%22%2C%22backgroundStyle%22%3A%22transparent%22%2C%22globeSettings%22%3A%7B%22autoSpinSpeed%22%3A10%2C%22network%22%3Afalse%2C%22gridColor%22%3A%22%232563eb%22%2C%22glowColor%22%3A%22%232563eb%22%2C%22dataPoints%22%3A%5B%7B%22lat%22%3A40.71%2C%22lng%22%3A-74.01%2C%22value%22%3A10%7D%2C%7B%22lat%22%3A51.51%2C%22lng%22%3A-0.13%2C%22value%22%3A10%7D%2C%7B%22lat%22%3A35.68%2C%22lng%22%3A139.69%2C%22value%22%3A10%7D%5D%2C%22dataArcs%22%3Atrue%2C%22dataMarkerColor%22%3A%22%232563eb%22%7D%7D" width="100%" height="480" style="border:0" class="my-10" title="Spinning dotted globe with arcs joining our offices in New York, London, Tokyo" loading="eager"></iframe>
Enter fullscreen mode Exit fullscreen mode

config takes the JSON string, JSON.stringify(design), and the component encodes it for the address. Don't encode it yourself, or it gets encoded twice.

look="default" is the starting point, and the config holds only the changes; the look fills in everything else. "v": 2 tells Globestudio the JSON was encoded once, so every value arrives as written. Since 1.2.0, "v": 3 says the same and also renders each color as its exact hex. With 2 the colors come out darker than their hex, as they always have: these dots draw as rgb(5, 32, 212), not #2563eb. For a brand color, write 3. The skill's examples do now, and so does section 4.

network: false turns off the city pulses and route arcs the Default look draws for decoration, so the only markers are your three offices. dataArcs joins the points in list order: New York to London, then London to Tokyo. Marker area follows value. The agent also tinted the grid and the glow blue with gridColor and glowColor, so they show on a light page, and set autoSpinSpeed to 10 out of 100 for "slowly" (the look's own is 35).

title is what a screen reader announces, so it says what the globe shows. An iframe doesn't size itself, so the height is set; 480 is also the default. loading="eager" loads it with the page, since it sits near the top. The default is "lazy", which suits a globe further down.

The look decides whether your color shows at all. Default keeps dotColor. Halftone, Wireframe, Toon and Threshold paint their own white ink whatever you set, and Risograph or Aurora shift it. The skill has the table, so the agent puts a brand color on a look that keeps it.

The skill also has the agent hand you a studio link for the same design. This is the one I got:

https://globestudio.app/looks/default?c=%7B%22v%22%3A2%2C%22selection%22%3A%22world%22%2C%22dotColor%22%3A%22%232563eb%22%2C%22backgroundStyle%22%3A%22transparent%22%2C%22globeSettings%22%3A%7B%22autoSpinSpeed%22%3A10%2C%22network%22%3Afalse%2C%22gridColor%22%3A%22%232563eb%22%2C%22glowColor%22%3A%22%232563eb%22%2C%22dataPoints%22%3A%5B%7B%22lat%22%3A40.71%2C%22lng%22%3A-74.01%2C%22value%22%3A10%7D%2C%7B%22lat%22%3A51.51%2C%22lng%22%3A-0.13%2C%22value%22%3A10%7D%2C%7B%22lat%22%3A35.68%2C%22lng%22%3A139.69%2C%22value%22%3A10%7D%5D%2C%22dataArcs%22%3Atrue%2C%22dataMarkerColor%22%3A%22%232563eb%22%7D%7D
Enter fullscreen mode Exit fullscreen mode

4. The same thing by hand

Without an agent it's the same three steps: install the package, paste the component, put it on the page. What the agent saves you is reading the config reference to find keys like network and dataArcs.

Not on React? The web component works in Vue, Svelte, Astro or plain HTML. With no build step:

<script type="module" src="https://cdn.jsdelivr.net/npm/@globestudio/element@0.2.0/index.js" integrity="sha384-aHQOT3XnyObS+Dk0lMsAKS3J7YeIz8VRlHconYo2YYtEy7UqCytVre6dLWPYxKqM" crossorigin="anonymous"></script>

<globe-studio
  look="default"
  config='{"v":3,"selection":"world","dotColor":"#2563eb","backgroundStyle":"transparent","globeSettings":{"autoSpinSpeed":10,"network":false,"gridColor":"#2563eb","glowColor":"#2563eb","dataPoints":[{"lat":40.71,"lng":-74.01,"value":10},{"lat":51.51,"lng":-0.13,"value":10},{"lat":35.68,"lng":139.69,"value":10}],"dataArcs":true,"dataMarkerColor":"#2563eb"}}'
  height="480"
  title="Spinning dotted globe with arcs joining our offices in New York, London, Tokyo"
></globe-studio>
Enter fullscreen mode Exit fullscreen mode

The version is pinned in the script address, so the page runs the code you tested. With a bundler, npm install @globestudio/element and import "@globestudio/element" in client code instead. The element only draws in the browser, so under server rendering (Nuxt, SvelteKit, Astro) load it on the client.

For Webflow, Framer, WordPress or anything else that takes HTML, a plain iframe does the same:

<iframe
  src="https://globestudio.app/embed?look=default&c=%7B%22v%22%3A3%2C%22selection%22%3A%22world%22%2C%22dotColor%22%3A%22%232563eb%22%2C%22backgroundStyle%22%3A%22transparent%22%2C%22globeSettings%22%3A%7B%22autoSpinSpeed%22%3A10%2C%22network%22%3Afalse%2C%22gridColor%22%3A%22%232563eb%22%2C%22glowColor%22%3A%22%232563eb%22%2C%22dataPoints%22%3A%5B%7B%22lat%22%3A40.71%2C%22lng%22%3A-74.01%2C%22value%22%3A10%7D%2C%7B%22lat%22%3A51.51%2C%22lng%22%3A-0.13%2C%22value%22%3A10%7D%2C%7B%22lat%22%3A35.68%2C%22lng%22%3A139.69%2C%22value%22%3A10%7D%5D%2C%22dataArcs%22%3Atrue%2C%22dataMarkerColor%22%3A%22%232563eb%22%7D%7D"
  width="100%"
  height="480"
  style="border: 0;"
  loading="lazy"
  title="Spinning dotted globe with arcs joining our offices in New York, London, Tokyo"
></iframe>
Enter fullscreen mode Exit fullscreen mode

The c parameter is encodeURIComponent(JSON.stringify(design)). Encode it exactly once: a raw # in a color starts the address's fragment and cuts the design off.

5. Change the look in the studio, then hand it back

Writing the config by hand is fine for data. For the look itself, I'd rather see it.

  1. Open the studio link the agent gave you, or start at globestudio.app.
  2. Try other looks, colors, densities and dot shapes until you like it.
  3. Press D to open the export dialog. In the Share tab, click Copy share link.
  4. Paste it to your agent: "Make the hero globe match this design:" and the link.

The link carries the whole design in its ?c= parameter, so the agent decodes it and replaces the constant. A link the studio writes holds every setting, so the component doesn't need a look on top of it.

Without an agent, the same Share tab has an Embed code section. Pick React and copy: you get a <Globe config=... /> with your design in it. Pick Web component or iframe for other stacks, or Open in CodePen to try it in a pen first. The web component code there is already pinned to a version, with an integrity hash.

6. Or use the MCP server

Globestudio also runs a hosted MCP server at https://globestudio.app/mcp, with no account or key. In Claude Code:

claude mcp add --transport http globestudio https://globestudio.app/mcp
Enter fullscreen mode Exit fullscreen mode

Skip this if you installed the plugin in step 1; it already brings the server.

In Codex it's codex mcp add globestudio --url https://globestudio.app/mcp. In Cursor, add it to ~/.cursor/mcp.json:

{ "mcpServers": { "globestudio": { "url": "https://globestudio.app/mcp" } } }
Enter fullscreen mode Exit fullscreen mode

The server has six tools. find_presets matches a look to a word like "print" or "synthwave", build_share_url builds the links for a design, and read_share_url opens a link you paste so the agent can change it. For the prompt above, build_share_url returns a share_url for the studio, an embed_url for an iframe, and the look and config to give <Globe>. Any key it couldn't use comes back in an ignored list.

So which one? The skill teaches the agent the rules, like which look keeps a color and where the limits are. The server builds and checks the links. In a code project the skill is the part that matters, and the server is worth adding if you keep making designs, or if you work in a chat app like claude.ai. The Claude Code plugin gives you both.

Limits

Things to know before this goes on a production page:

  • It's an iframe. You can't reach into the scene from your page, and the viewer's browser needs WebGL 2. With reduced motion on, the globe holds still.
  • The whole design is in the address, data points included. Anyone who views your page source can read them, so keep private numbers out.
  • An embed address must stay under 32,000 characters, and a config keeps at most 250 data points. A custom dot shape image is the usual way past the limit.
  • Countries are country: plus an uppercase ISO 3166-1 alpha-3 code, like country:JPN. country:jpn and country:JP are dropped without a warning. Data points take coordinates, not country names.
  • On a light page, the white ink looks (Halftone, Wireframe, Toon, Threshold) need theme="light", which turns their ink graphite. Both packages take it from 0.2.0, and a plain iframe takes &theme=light. Halftone, Toon and Threshold paint a dark page of their own, so give them "backgroundStyle": "transparent" too. Or keep them on a solid dark background.
  • An embed draws the look as the studio does, density, dot size and background included. With no look it draws Default.
  • The agent can't export from the studio. PNG, SVG, GLB, video and GIF exports happen there (press D). SVG keeps clean vector dots and approximates six of the shader effects with SVG filters; for the full look, use PNG or video.
  • Installed skills don't update on their own. Run npx skills update once in a while.

Everything here is MIT licensed and on GitHub: the studio, the two packages, the MCP server and the skill. If your agent gets something wrong with the skill installed, open an issue with your prompt and what it wrote. That kind of report is the easiest for me to fix.

Top comments (0)