Modules differ in two independent ways: where their code runs (the hosting type) and what they do (the category, and for some, the core service they provide). For someone installing a module, both are shown on the catalog card. For someone building one, the hosting type is the first decision.
Where the code runs#
Every module is a manifest (a JSON file that declares what the module is, what it needs and what it adds) plus code — or, for an elements module, only elements. The manifest's hosting field says where that code runs:
| Type | Who writes the code | Where it runs | What you ship | Good for |
|---|---|---|---|---|
| Connected | you (or your agency) | your own HTTPS server — any host, any language | the manifest (+ optional assets); the code stays on your server | integrations that already have a backend, long-running work, any stack |
| Connected · in your space cloud | you | Cloud Functions the platform deploys for you into your space's own Firebase project | the manifest + the function source in src/ |
a Node.js module without running a server yourself |
| Hosted | you | the platform's module runner, as a WebAssembly package | the manifest + module.wasm |
small, fast, sandboxed logic; no server to run at all |
| Platform | the platform | the platform's module runner | — (published by the platform) | the modules every project can install from the public catalog |
Elements (none) |
you (or your agency) | nowhere — no code runs on the platform; the elements are mounted into the project's library and render on its pages | the manifest + element kits (kit/) with a shared stylesheet and script |
a component library, a design system, a set of ready page sections |
The type is invisible to the project that installs a module. It installs, configures and updates every module the same way. What differs is who operates the code and what it is allowed to do.
Connected#
The platform calls your server with signed HTTPS requests (the envelope). Your server verifies each signature and answers. To read or write project data it calls the platform's API back with the install token. It receives that token once, at install, after proving the server is really yours. Ready-made helpers exist for Node.js (expressModuleRouter in drop-core-server). Any other stack just needs to verify the signature and call the REST API.
Connected · in your space cloud is the same contract (deploy: 'managed'). The difference is that the platform builds your src/ folder and deploys it as a function into the Firebase project your space connected under Space › Cloud. It hands the function its credentials, so you never run or secure a server. Uninstalling removes the function.
Hosted and platform#
The code is a WebAssembly module exporting one function, call. It receives the same envelope, as JSON, and returns {status, headers?, body?}. It runs in a sandbox on the platform's runner with fixed limits on CPU, memory, call time, outgoing HTTP calls and calls per day. It may only call the hosts its manifest lists under egress. It never sees its token: it reaches the platform through host functions (platform_fetch, a small key-value store, log, now). Any language that compiles to WebAssembly with an Extism plug-in kit works. The platform's own modules are written in Rust.
Platform modules are hosted modules published by the platform for every project, with more generous limits. They update automatically unless a new version asks for more permissions.
Elements#
An elements module (hosting: "none") is only an element library: the manifest lists its kits (kits: ["…"]) and the package carries them under kit/{kitId}/, the element-kit format — elements plus each kit's shared global.css and global.js. There is no endpoint, no token, no events, no configuration and no /m/{id}/… routes; a manifest that declares any of them, or access / scope, is refused. Installing one mounts its elements into the project's library with no permissions step; the shared stylesheet and script load once, before the elements' own files, on exactly the pages that place one of the module's elements. Updates replace the elements the project has not edited and skip the ones it has, and uninstalling removes them. The upload checks the package without a runner dry run.
Which one to choose#
- You already have a server, or need long-running jobs, big dependencies or a language without WebAssembly support → connected.
- You write Node.js and don't want to operate a server, and your space has a cloud connected → connected in your space cloud.
- Your logic is small and you want zero infrastructure → hosted.
- You only ship elements — a component library, a design system, ready page sections — and no logic → elements.
The project's plan must admit the type. Connected modules come with the lower plans, and hosted modules with the higher ones. Elements modules install on every plan; a plan may cap how many (element_modules_max), counted apart from the other modules.
What a module does#
Category#
Every module has exactly one category. It groups the catalog and lists installed modules on the matching setup pages. It grants nothing.
| Category | For example |
|---|---|
shipping |
carriers, pickup points, labels, tracking |
payments |
payment gateways, BNPL, gift cards, payment matching |
accounting |
invoicing systems, accounting and ERP exports |
data |
ERP / CRM / PIM sync, imports and exports |
products |
stock feeds, pricing rules, catalog enrichment |
orders |
fulfilment, warehouses, returns, order workflows |
customers |
CRM, loyalty, reviews, support desks |
mailing |
newsletters, transactional e-mail, SMS |
marketplaces |
marketplaces and price-comparison feeds |
booking |
reservations, appointments, rentals, tickets |
content |
translation, search, media, SEO tooling |
forms |
lead routing, anti-spam, e-signatures, surveys |
analytics |
tracking, consent, conversion relays, BI exports |
ai |
generation, classification, assistants |
compliance |
GDPR tooling, VAT / OSS, age verification |
tools |
developer and operations utilities |
elements |
element libraries — the default home of an elements module |
Provider modules#
Some modules don't just add features. They replace a service the platform has built in. A module declares this with provides, and the project can then pick it wherever it would pick the built-in option:
| Provides | The module acts as | Picked in |
|---|---|---|
carrier |
a shipping carrier: rates, pickup points, shipments, labels, tracking | the delivery methods |
invoicer |
the invoicing system that issues, sends and renders invoices | the project's invoicing provider |
payment |
a redirect payment gateway beside the built-in Stripe | a payment method |
orders |
an order-processing system (ERP / warehouse) that orders are pushed to | the project's order processor |
A provider module must be enabled and verified before it can be picked. It cannot be uninstalled while orders still depend on it. Each contract is described in The manifest › provides.
Building blocks#
Whatever its category, a module is made of the same parts. It uses only the ones it declares:
- Events — the project's writes (orders, invoices, data, forms, files, the module's own records) delivered as signed calls, retried on failure (Events and retries).
- Callbacks — synchronous questions the platform asks during a flow, such as validating an order at checkout (
order.validate) or a carrier's shipment calls (Points). - Website routes — endpoints on the project's own site under
/m/{id}/…, optionally behind the site's form protection. - Inbound webhooks — a URL the platform exposes for a third party, so the module's own address stays private.
- A schedule — a call every 5 minutes up to once a day.
- Console additions — configuration fields, forms, buttons, cards, full admin pages and Overview widgets.
- Data — its own content collections (editable under Data), private records and state, and fields on orders, products and customers (
{entity}.modules.{id}). - Website assets — element kits with an optional shared stylesheet and script (
global.css/global.js, loaded on the pages that place the module's elements), e-mail templates and translations. An elements module uses only the kits (and translations).
What a module can never do#
Every module, whatever its type, runs with a token limited to what its manifest declared and the manager accepted. It can never read the project's payment, SMTP, hook or analytics setup, its members, or another module's secrets. It can never spend credits, mint tokens, or widen its own permissions: a version that asks for more waits for a manager. The full list is in the Overview.