Welcome back! In the previous chapter, Type-Driven Contract, we built the actual logic for our usage panelβthe "plug" that fits into the system.
However, if you ran the application right now, you wouldn't see your new feature anywhere. You wrote the code, but you haven't told the application that it exists!
In this chapter, we will solve this by creating a Command Registration.
Imagine you own a restaurant. You have a chef in the kitchen who knows exactly how to cook a specific dish (this is the code we wrote in Chapter 1).
But how do customers know they can order it? You need to put it on the Menu.
The Use Case: We want our "Usage" feature to appear in the application's command list (the menu) so users can find it by name. We also want to describe what it does and limit it so it only appears for specific users (like claude-ai).
Command Registration acts as the manifesto or "ID Card" for your feature. It tells the system about the command without running the command itself.
It defines three main things:
name)description)availability)Think of the registration file as the text on a restaurant menu. It lists "Cheeseburger" and "A delicious beef patty," but it is not the burger itself. It's just the promise of a burger.
We create the registration in a file called index.ts. This is the entry point that the framework looks for.
We define a plain JavaScript object. The most important part is giving it a unique name.
// index.ts
export default {
// The internal type of command (we use local-jsx for React UIs)
type: 'local-jsx',
// The unique ID users might type to find this
name: 'usage',
// A human-readable hint about what this does
description: 'Show plan usage limits',
// ... continued below
Explanation:
name: This is the command ID. If a user searches for "usage", this entry pops up.description: This helps the user decide if this is the command they want.
Sometimes, a menu item is only available during "Lunch" or for "VIPs". We can restrict our command using the availability array.
// index.ts - continued
// ... previous code
// Only show this command if the current provider is 'claude-ai'
availability: ['claude-ai'],
// ... continued below
Explanation:
Finally, we need to point to the actual code (the chef). However, we don't want to wake the chef up until an order is placed.
// index.ts - continued
// Notice we use a function () => ...
load: () => import('./usage.js'),
} satisfies Command // Remember the contract from Chapter 1?
Explanation:
load: This tells the app where to find the logic we wrote in Chapter 1.import(). We will explain exactly why and how this works in the next chapter, Lazy Loading / Dynamic Import.What happens when the application starts up?
The application scans for these index.ts files to build its "Menu". It reads the name and description immediately, but it intentionally ignores the actual logic code (the usage.tsx file) until later.
Here is the flow of how the Menu is built:
Let's look at the complete code block for index.ts.
Because we are using TypeScript, we use the satisfies Command syntax we briefly saw in Chapter 1. This ensures we don't forget the name or spell availability incorrectly.
// index.ts
import type { Command } from '../../commands.js'
export default {
type: 'local-jsx',
name: 'usage',
description: 'Show plan usage limits',
availability: ['claude-ai'],
load: () => import('./usage.js'),
} satisfies Command
Why is this separate from the logic? If we put the "Menu" (registration) and the "Kitchen" (logic) in the same file, the application would have to load every single feature's code just to show the list of available commands. That would make the app very slow!
By splitting them, the app can read this lightweight index.ts file in milliseconds.
In this chapter, we learned that Command Registration is like creating a menu item. We defined:
name).description).availability).
We have successfully listed our command on the menu! However, you might have noticed the line load: () => import('./usage.js'). This is a very special way of connecting the menu to the kitchen.
To understand why we didn't just use a normal import, let's move on to the next concept.
Next Chapter: Lazy Loading / Dynamic Import
Generated by Code IQ