Skip to main content

Make an Orb

This page takes an Orb from an empty folder to one built script.

An Orb is an app inside Greyverse. Its screen is made of the platform's os-* elements, written in any framework (the base Orbs use React), and the platform draws them. Anything beyond its screen it asks of the space through the os object.

Install​

The SDK is @greyverse/orb. It is not on npm yet: depend on a checkout of the orb-sdk repository.

"dependencies": {
"@greyverse/orb": "file:../orb-sdk",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
npm install -D typescript @types/react @types/react-dom

The folder​

orb.json the manifest
icon.svg its icon
package.json
tsconfig.json
src/index.tsx its code
src/strings.ts its words
dist/orb.js written by the build

package.json:

{
"name": "rooms",
"private": true,
"type": "module",
"scripts": {
"build": "orb build src/index.tsx dist/orb.js"
}
}

tsconfig.json (type-checking only; it includes the SDK's element types):

{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"noEmit": true,
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"react": ["./node_modules/@types/react"],
"react/*": ["./node_modules/@types/react/*"]
}
},
"include": ["src", "node_modules/@greyverse/orb/src/jsx.d.ts"]
}

A minimal Orb​

src/strings.ts:

export const strings: Record<string, Record<string, string>> = {
"list.title": { ko: "방", en: "Rooms" },
"list.none": { ko: "아직 들어간 방이 없어요.", en: "You are in no room yet." },
};

src/index.tsx:

import { useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
import { os } from "@greyverse/orb";
import { strings } from "./strings";

os.strings(strings);

type Room = { id: string; name: string };

function Rooms() {
const [rooms, setRooms] = useState<Room[]>([]);
useEffect(() => {
os.zone<Room[]>("rooms:list").then(setRooms, () => {});
}, []);
return (
<os-scroll gap={4} params={{ padX: 6, padY: 5 }}>
<os-text role="label" t="list.title" params={{ weight: "semibold" }} />
{rooms.length === 0 && <os-text role="caption" t="list.none" params={{ color: "muted" }} />}
<os-list gap={1}>
{rooms.map((r) => (
<os-text key={r.id}>{r.name}</os-text>
))}
</os-list>
</os-scroll>
);
}

createRoot((globalThis as unknown as { document: { body: never } }).document.body).render(<Rooms />);

Build​

npx orb build src/index.tsx dist/orb.js

orb build [entry] [out], where entry defaults to src/index.tsx and out to dist/orb.js. The result is one minified script (IIFE, ES2020) with the SDK's runtime first and React in production mode.

What the engine gives​

There is no browser. document is a virtual one that holds only os-* elements; inserting any other tag throws. setTimeout and clearTimeout work; setInterval and clearInterval do nothing. console.log, console.warn and console.error go to the platform's log; console.info and console.debug are dropped.