I’m a huge user of Raycast: I use it for everything from window resizing, to code snippets, to screenshots and shortcuts to my Github favorites.
While I was creating my own extension Dashcam extension to capture videos, I thought, maybe I could write something so that anyone can learn how to make their extension!
I think it would become handy, eventually. This guide explains how to create and debug your Raycast extension’s while you learn how its ecosystem works.
All of what I wrote in this article can be achieved using 3 ingredients:
Raycast, your favorite code editor and the Dashcam screen recorder for developers!
Intro
Raycast is a fast, customizable macOS launcher that lets you quickly and easily create shortcuts to save time and make your workflow easier. This tiny, free app lets you open programs, search for files, and create keyboard shortcuts for literally anything! It has gained popularity as a powerful Spotlight alternative. This guide covers creating and publishing a Raycast extension from start to finish, adding a little oomph to traditional tutorials by leveraging videos and interactivity!
I hope this can help anyone get started build their own extension.
Getting started with your extension
We’re going to be using JavaScript to build our extension!
I assume you have already downloaded and set up to Raycast. This guide complements, but does not replace, the official Raycast documentation – so if you’re a complete beginner read it here.
In this article I will do a walkthrough of the full process of creating an extension from nada to hero!
Create your project
This is a Dash showing you how to create a project and extension in Raycast
I created a folder where I am going to initiate my Raycast project. To achieve this, I simply created an empty folder somewhere on my drive that I can get to easily
mkdir raycast-ext
Initiate a new extension
Next, as the Raycast documentation indicates, you have to create the scaffolding of your project.
Open Raycast and Type Create Extension
The Create Extension – Developer command shows up, run it by clicking Open Command
This part enables the proper project structure to be created by the Raycast app itself.
Then, go through the following screens and configure them as shown below.
Set up your extension details
These are the options I chose, but you can choose to pick whatever makes most sense for you:
– Organization: None
– Unless you’re part of an Organization – most likely scenario is that you are not at first, this article explains what teams are
– Template: Detail
– Extension Name: Extension Demo
– Description: This is just a demo
– Categories: Fun
– Location: Select the folder you created a moment ago
– Command name: Demo command
– Subtitle: Demo subtitle
– Description: This is just a test
After completing these fields, create the extension by using the key combo
⌘+Return
or click the Create extension text in the right corner
Congratulations! You’ll see in the next screen that the extension has been successfully created and registered inside the Raycast app!
Running the extension for the first time
Next, let’s run the demo extension for the first time!
To see your extension run for the first time, open the directory you created, locate the project, and run the command:
Pretty cool!
The extension is running, showing you a hello world message, the reason for that is that we chose a template in the previous step – we still haven’t touched the code!
So let’s do that next.
Running and editing the template
To build your own extension, you can use Raycast’s own SDK, which includes set of UI components that you can use to assemble your extensions.
Before we continue, get familiar with the Raycast SDK: There are multiple components in the SDK. You can find a listing here: https://developers.raycast.com/api-reference/user-interface
Another important thing is to become familiar with the extension folder structure: If you use an IDE editor like VScode, open your extension folder, and you should be presented with the following project structure:
Now, we’re ready to start developing our extension!
Inspecting the main file
If you open src/index.tsx
you will see the following code:
```
import { Detail } from "@raycast/api";
export default function Command() {
return <Detail markdown="# Hello World" />;
}
```
To test this command again in Raycast, ensure you’re running it with npm in your terminal.
Type demo “Demo command” should show up and now hit return:
Building your own
Now let’s change it up: let’s build an extension that.. will fetch a random picture from a dog API, as it might bring a little happiness to the world!
We can call this extension “Dogjoy” or something funny like that.
Let’s create a new file called fetchdata.tsx
inside the src
folder
We’re going to import useFetch
from the utils SDK and use it to call an endpoint.
Specifically, it is the dog.ceo API endpoint which returns random pictures of dogs, one at a time.
Installing Raycast helper library
Before we continue let’s raise a glass of your favorite cheering drink to ourselves
👏
We’re using the useFetch hook so this extension will use a helper library that we need to install called @raycast/utils
Using this helper library will allow us to use a custom React.js hook called useFetch
: using this hook, we can execute an API request to an endpoint.
Let’s go ahead and install this library through npm by executing this in the root of our project:
npm install @raycast/utils
Calling the API
We specifically want to retrieve the message
– which corresponds to the URL of the image – like in the code below.
import { useFetch } from "@raycast/utils";
export default function showDog () {
console.log('Fetching API')
return useFetch("https://dog.ceo/api/breeds/image/random").data.message;
}
Next we need to call this function from the main file
Creating the command
Let’s open index.js
and add the following code:
import { Detail } from "@raycast/api";
import showDog from "./fetchdata";
export default function Command() {
return <Detail markdown={`
## Random 🐶
![](${showDog()})`} />;
}
This imports the showDog
function from the fetchdata
file, then wraps it around the Detail
component, which renders, amongst other things, markdown!
We use markdown to render the image because it’s fast!
Debugging with the help of Dashcam
It’s never easy to fix issues in your extension, in fact there’s a whole community effort on Raycast’s community Slack trying to help each other to fix them.
While you’re developing, showing someone else what you were doing and went wrong can be quite powerful.
When you run this extension for the first time in developer mode, you will notice that when you run your extension, there are multiple console.log
functions being called.
You might wonder: is this a bug?
The short answer is no. Here’s a Dash that shows you what I am talking about
Watch 4x fetch on Dashcam
I shared this code with someone who understands really well how the render method behind useFetch
works, and they assured me that while the function might be re-rendered multiple times, the power of useFetch is that it only triggers one API call to your backend!
Let’s now change the URL on line 5 to another one. this time we’re retrieving memes from imgflip’s API:
return useFetch("https://api.imgflip.com/get_memes").data.message;
Now run the extension again and see what happens!
Watch imgflip error on Dashcam
As you can see we’re getting an error because there is no object key named message.
If we want to use this API we need to extract the URL by changing the code to look like this
return useFetch("https://api.imgflip.com/get_memes").data?.data.memes[Math.floor(Math.random() * 100)].url;
This retrieves one meme at random from the imgflip meme API.
Using Dashcam to check for bugs
Now you’re wondering, how can I verify that the API isn’t being called 4 times?
Good question and here’s the answer
You can verify this by replacing the URL on line 5 of fetchdata.tsx
with a local endpoint running on your machine (localhost) through a simple HTTP server .
Let’s do this:
Watch npm install on Dashcam
What I did is the following:
I started a simple HTTP server and changed the fetch-able URL in fetchdata.tsx
file to call my local server.
Then I look at the HTTP request logged by the local server and I see it’s only one.
Meanwhile the console.log has output 4 messages saying Fetching API
that means, that although it’s re-rendering 4x the API call is only called one.
You can see how by using Dashcam, I am sharing the full context of what I am doing, this is very beneficial when debugging with others!
Now let’s put the files back to its initial state, so I can show some Dogs!
Commands
In Raycast, you can have multiple commands. Your extension might be using them to achieve numerous things.
In this extension we created we called initially the command “Demo” – let’s now change that so our extension is complete.
You can change commands and its associated data through the package.json
file or the UI. I’ll do it in the editor – I am confident I can simply edit the data in this file and then reload the extension.
Publishing your extension: debugging build errors
The last part of this tutorial is the most fun one, publishing your extension.
To do this instead of running the code locally with npm run dev
you will have to run it through npm run build
This will alert you if the code passes the build checks…
Surprise, it’s not passing the checks YET!
So let’s go ahead and get fixing it
First we’re going to add an interface
The full code should look like this:
import { useFetch } from "@raycast/utils";
interface DogAPIResponse {
message: string;
}
export default function showDog () {
const { data } = useFetch<DogAPIResponse>("https://dog.ceo/api/breeds/image/random");
return data?.message;
}
Publishing your extension onto the Raycast Github repo
Now that your extension is valid you can ship it to the Raycast extension repo, where all other extensions live!
You can run npm run publish
to publish your extension now. You will be asked to authenticate with GitHub.
Raycast creates an open a pull request in their repository, on your behalf!
Conclusion
Hopefully, this article shows you how simple it is to create your first extension and publish it to the Raycast store.
This is a simple extension, you can add much more – especially fall back and error catching… but hopefully this gives you a good introduction to building extensions.
You’ve noticed that we had a couple of situations where we had to debug issues with the extension, luckily I was able to show you the issues using Dashcam to show you exactly how I solved them, it’s like a YouTube video but with better logs 😉 and context.
If you want to learn more about how to create & publish extensions on Raycast feel free to browse the documentation here.
If you’re interested in how Dashcam works and why it helps developers debug faster, you can find further details on the Dashcam website
👉 If you just want a Raycast PRO code to try Raycast PRO for free, ask in the comments!
Top comments (0)