Developer

Quick Start

Scaffold an applet, write a typed method, and install it locally with the rprp CLI.

This walks through building a minimal applet: scaffold it, declare a method, implement it, and install it. You need the rprp CLI (ships with RightPlace Core).

1. Scaffold

rprp applet init my-applet --template blank
cd my-applet

Templates are blank, docs-like, and table-like. Each is runnable and lint-clean out of the box. The scaffold gives you applet.json, src/index.ts, src/mount.tsx, and a methods/ folder.

2. Declare the manifest

applet.json declares the id, the scopes the applet uses, the methods it exposes, and which of those are agent tools.

{
  "schemaVersion": 2,
  "runtime": "sidecar",
  "id": "@my-org/notes",
  "version": "0.1.0",
  "name": "Notes",
  "author": "My Org",
  "resourceTypes": ["note"],
  "scopes": ["projectDb:read", "projectDb:write", "events:emit", "system:sidecar"],
  "methods": [
    { "name": "@my-org/notes.add", "permission": "projectDb:write", "handler": "backend" },
    { "name": "@my-org/notes.list", "permission": "projectDb:read", "handler": "backend" }
  ],
  "tools": ["@my-org/notes.add", "@my-org/notes.list"],
  "frontend": { "entry": "dist/index.js" }
}

Every id follows @<author>/<slug>. Every method name follows @<author>/<slug>.<verb> - one dot, one camelCase verb. See the Manifest Reference.

3. Write a method

A method is a typed unit declared with defineMethod. Params and returns are Zod schemas, so calls are validated on both sides.

// src/methods/add.ts
import { defineMethod, z } from "@rightplace/applet-sdk/v2";
import { Note } from "../entities.js";

export const add = defineMethod({
  name: "@my-org/notes.add",
  scope: "resource",
  runIn: "backend",
  permission: "projectDb:write",
  params: z.object({ title: z.string(), body: z.string() }),
  returns: Note.schema,
  async run({ title, body }, ctx) {
    const note = await Note.insert({
      id: ctx.uuid(),
      title,
      body,
      createdAt: ctx.now(),
    });
    await ctx.events.emit("@my-org/notes.added", { note });
    return note;
  },
});

Define the entity it stores into:

// src/entities.ts
import { defineEntity, z } from "@rightplace/applet-sdk/v2";

export const Note = defineEntity({
  name: "note",
  storage: "sqlite",
  schema: z.object({
    id: z.string().uuid(),
    title: z.string(),
    body: z.string(),
    createdAt: z.number().int(),
  }),
  primaryKey: "id",
});

4. Call it

From the frontend, methods are called by their full name:

const note = await ctx.methods["@my-org/notes.add"]({
  title: "First note",
  body: "Hello",
});

From the CLI:

rprp call '@my-org/notes.add' --args '{"title":"First note","body":"Hello"}'

5. Package and install

rprp applet package --sign <keypath>
rprp applet install            # scans ./dist/*.rpbundle.zip and installs

During development, rprp applet dev watches your source, rebuilds, and reinstalls on save.

Next