Toolaby

Quickstart

Register a tool, wire your extension and make a test purchase.

This guide takes an existing Chrome extension from nothing to a paid, working purchase on Test. It takes about ten minutes.

Before you begin

  • A Chrome extension with its manifest.json at the top of its folder, or a WXT, CRXJS or Plasmo project. No extension yet? Step 4 can create one, or start from the WXT starter: a finished React extension with a Free plan, a daily allowance and a Pro feature, where npm run setup registers your tool, prices it and wires it, and npm run dev loads it in Chrome. The extension generator makes it with your name, colour, pages and prices.
  • Another bundler, or a manifest below the top of the folder: see Frameworks.
  • Node.js 20 or later, for the command line. Nothing is needed from Stripe on Test.

1. Create a workspace

Open the dashboard at toolaby.app/test/dev and sign in with the one-time link sent to your email. If sign-up asks for an invitation, request one at toolaby.app/access.

The first sign-in asks for your workspace's name. The workspace is the seller a buyer sees: its name, support address and, later, its domain. Its name is its address on Live, <workspace>.toolaby.app. On Test its buyer pages get an address Toolaby makes, like quiet-otter-4172.toolaby.app/test.

2. Register a tool

On the Tools page, select Register a tool (New once you have tools). Enter a name. The tool id is made from it; Edit the id changes it before you create the tool, and after that it is permanent.

A tool has two ids. The short one is the one you chose, such as word-count, and is in the checkout page's address. The full one is <workspace>--word-count, shown as Tool id on the tool's page. The API and your website take either, and so do the commands when the short one names one tool across your workspaces. Webhooks and API responses name the full one.

3. Check payments on Test

On Test there is nothing to connect. Toolaby makes a Stripe test account for your workspace when the workspace is made. Configure → Payments shows it Ready a minute or two later, once Stripe has switched its card payments on.

Your own Stripe account is connected on Live, when you ship. See Ship to the Chrome Web Store.

4. Wire the extension

Open the tool. Until someone uses it, its page is Set up: five numbered steps, each ticked as it happens. The first is wiring, in one of three ways:

  • In Chrome: select Choose your extension's folder. Nothing to install.
  • Terminal: run the command it shows in your extension's folder.
  • AI agent: copy the prompt into Claude Code, Cursor, Codex or another coding agent, in your extension's folder.
npx -y toolaby@latest wire <tool-id>

The first run shows a code to approve in your browser. In a plain extension, the wiring then:

  • writes the client (toolaby.js, toolaby.config.js with your tool key, toolaby.d.ts) and the Toolaby popup beside your code;
  • adds to manifest.json the key that gives every copy the same id, the storage permission, and your workspace's address under externally_connectable. No host permission: Chrome shows your users no warning for Toolaby, at install or on an update;
  • puts the Toolaby background, toolaby.background.js, in front of your background. Yours runs as it did, importScripts() included, and Toolaby starts with it. With no background, it creates a two-line background.js;
  • sets the Toolaby popup as the action popup. It opens your popup when the device may continue, and the paywall when it may not. When your code sets or reads its own popup (chrome.action.setPopup(), getPopup()), your popup stays in front instead, and the command prints the lines that open the paywall where your paid action starts;
  • writes TOOLABY.md and .claude/skills/toolaby/SKILL.md for coding agents, and AGENTS.md and CLAUDE.md where the project has none. See Build with an agent.

It prints one row for each of these, and any step left for you with the exact code to use.

In Chrome, the page keeps the result in this browser, and Wire again runs on the same folder.

A WXT project gets a module, modules/toolaby.wxt.ts, which WXT loads by itself: there is nothing to paste. A CRXJS project with manifest.config.ts, and a Plasmo project, get the files and printed lines for the framework's config. See Frameworks.

No extension yet? npx -y toolaby@latest create <tool-id> makes a minimal one, wired — a popup and a side panel, or --surfaces popup, side-panel or none for the shape you want. See Surfaces.

5. Load it in Chrome

Load the extension at chrome://extensions (Developer mode, then Load unpacked), or reload it. A project with a build — WXT, CRXJS, Plasmo or a bundler — is loaded from its output folder, after a build.

When it worked, step 2 of Set up says Checked in.

A new tool is Everything free and asks for no account: the Toolaby popup opens straight onto your popup and offers nothing to buy.

6. Set a price

Under the tool's Pricing, add a plan with New plan: once (a lifetime licence), monthly or yearly. Each plan is a Price on your Stripe account. See Pricing.

7. Show the paywall

At the top of Pricing, the Access card says who can use the tool and what they get before paying. To see the paywall, choose Nothing free or Free uses, and select Save. The same card is step 3 of Set up. See Access and features.

Open the extension's popup. With Nothing free it shows your plans. With Free uses it opens your popup until the device has spent its uses, then shows your plans.

8. Make a test purchase

In the popup, select the plan's button, such as Buy once or Subscribe. The checkout page opens with that plan chosen: select its button there. A subscription asks you to sign in first. Pay on Stripe's page with the card 4242 4242 4242 4242, any future date, any CVC.

The after-purchase page signs the extension in to the account the purchase is on, and the popup opens your popup. Bought signed out, the page's button is Sign in to unlock: signing in there does it. You appear on the tool's Customers page.

9. Gate your own code

Everything so far ran without changing your code. Where your extension does the thing it charges for, ask first, and answer a refusal with the paywall. In your popup, inside the handler of the action you charge for:

import { toolaby } from './toolaby.js';

document.getElementById('export').addEventListener('click', async () => {
  const permit = await toolaby.gate();
  if (!permit.allowed) return toolaby.showPaywall(permit);
  runExport(); // the work you charge for
});

The popup loads that script as a module, <script type="module" src="popup.js"></script>, for the import to work. The check goes inside the handler, not at the top level of the module: a return outside a function does not run. gate() runs anywhere; showPaywall() runs in your popup or side panel. A permit refused in the background is returned to the page that asked. See Gate your extension, and Client for every method.

Next steps

On this page