Here Is How to Build a Beautiful Raycast Extension

Here Is How to Build a Beautiful Raycast Extension

I'm a huge Raycast fan. This is a secret for nobody. The software instantly replaced Alfred and Spotlight.

The thing that set Raycast apart from the competition, besides the nice-looking UI, is the store that contains a lot of useful extensions. Extensions are installed and updated right from Raycast and not from a third-party website.

I've been wanting to create a Raycast extension ever since I discovered the program, but I've never had a case in mind.

Meet Proton Version

I started working at Proton at the end of last year. I work as a front end engineer in the inbox team. All the web frontend clients are hosted in a single mono repo, which is a first for me.

GitHub - ProtonMail/WebClients: Monorepo hosting the proton web clients
Monorepo hosting the proton web clients. Contribute to ProtonMail/WebClients development by creating an account on GitHub.

Besides that, that's also the first time for me that I work in such a large codebase. Deployments are happening several times a week, and it's hard to keep track of which version is in production, in beta and in our internal testing version.

That's why I decided to create a Raycast extension that will fetch the version of the deployed web clients. Those versions are publicly accessible for anyone and stored in simple JSON files under /assets/version.json.

The extension is very simple, default and beta version is supported and anyone can be redirected to the release tag on GitHub (the frontends are open sourced).

The extension with the command palette opened

What did I use

At first, I was a bit intimidated, I didn't know what to expect and how to build the extension I went on the developer website and felt an immense release when I read that extensions were built in React.

Everything was familiar, and I was able to quickly go through the code and know what I needed to use.

I started by creating the project with the CLI tool. A simple command is all it needs to get started, like any framework such as Next.js. Quite a nice start!

Building the UI

Raycast built a bunch of components that must be used to build an extension. This way, every extension looks the same and the general UI is respected.

Building the interface is like using a component library that doesn't offer any customization.

It's fast and there is no guessing, think about the thing you want to display and use the component that matches your need.

The number of components is limited, but they are well-built and support many useful props (such as loading state).

Data Fetching

My extension is quite simple, I fetch some data from a static file and display the information.

I naively stared by writing some fetch methods, I didn't realize that we are in a Node.js environment and not a browser. No fetch, but the Raycast team has us covered with a nice useFetch hook.

The hook offers many features, and I's possible to set headers and cookies (which I need to fetch the beta versions of the apps).

I had some trouble understanding that the hook was extending the RequestInit that allowed me to add headers (and many other things). This is written in the documentation, but I had a hard time finding the information.

Other Utilities

My application is very simple, and I'm downloading a very small amount of data. Fetching the data for all applications takes less than a second.

I don't need (for now) more advanced caching strategies. However, Raycast offers methods to get and set items in the local encrypted database. The API looks very similar to the local storage of browsers.

The set of utilities is, like the UI elements, limited but well-designed. They could come short depending on the extension you're building, but this is not something more basic extensions will face.

Deployment Process

Deploying the extensions is also pretty simple. The CLI tools does everything with three commands (it can be less, but that's what's recommended).

Getting Screenshots for your Extension

Each Raycast extension has some screenshots, time to take some screenshots for your extension before publishing it.

Getting user generated data consistently could be challenging, but Raycast has a tool to ensure consistency. The "window capture" setting offers a nice and easy way to get a screenshot of the extension.

The screenshot will even be saved in the metadata folder if the extension is running, so there is no guess work on where to save the image.

The tool that captures screenshots and place them in the appropriate folder

Publishing the Extension

Everything is now set to publish your extension. Three commands must be run to get things online (at least on GitHub, the validation takes a bit of time).

First, run lint on the project to fix any formatting issue that could occur. Then you can build the extension to make sure that it builds correctly. Lastly, publish the extension and open a PR on Raycast GitHub.

This last step will create a fork of the extension repo and create a merge request in one click.

Initial Impression

I started without knowing anything and was able to build (a very basic) extension in about two hours. The whole experience was pleasing and everything has safeguards that can be limiting but offers great stability.

Raycast is targeted at developers, and it's easy to tell. The whole process felt like using a web framework with tools and CLI that makes some of the heavy lifting for us.

What I Liked

As said before, the UI components are well-designed and are easy to use. They support the most basic props to make things work as intended.

The hooks are another great element developed by the team. The built-in hooks offer a great range of features and return what developers need to make things works.

Creating the extension is done with a great CLI tool. The project is bootstrapped in minutes. The whole process is fast and well-built.

Finally, the person responsible for the extension repo is quite reactive and offers feedback on top of code review. My initial design had some problems while fetching data, Per Nielsen Tikær suggested improving part of the application and even modified my code a bit to have a better result than before.

Suggestion made by Raycast Technical Community Manager (Per Nielsen Tikær)

What was Confusing

Although most of the experience was nice, there are still some things that were confusing or needed some adjustment on my side.

Confusing Documentation

I had (and still have) a hard time to find the place where things are in the documentation. I don't know what is causing this issue, but I cannot find the appropriate menu on the left side.

Beside confusing page structure, some of the component props are a bit hard to discover while scrolling through the documentation. This was the case for the date displayed at the right of the list. Raycast built a List.Item.Accessory type, but it's quite deep in the documentation and not so easy to find.

Validation Process

Beside this small issue, I find the validation process of the extension to be a bit long and opaque. I understand that the team has many things to do, and they must have a hard time keeping up with new extensions and updates. Some automatic messages on the PR would be great to help manage expectation and avoid confusion.

That's the two main gripe I have with the whole experience. Overall, things were very pleasing and well-thought-out. It's easy to tell that Raycast was built from the ground up with developers on the mind.

Improvement suggestion


The documentation could be improved a bit, tho. The organization is a bit hard to understand. The documentation side menu is only 2 levels deep, increasing this by one would fix some of the issues.

Current state on the left and new proposition on the right

This change would also remove some of the noise added on the right of the content. In my opinion, this navigation on the right is a bit redundant and makes the whole content of the page less visible.

Moving the menu to the right could help reduce noise on the page

Dividing the user interface in subcomponents could also reduce the amount of information in one page. Making it a bit more digest.

I'm not a designer and the previous feedback might not be as wise, and there is probably a reason why things are done this way.

However, I can say that the current documentation makes it hard to find some props or options offered by Raycast.

This resulted in a suboptimal UI that was kindly improved by Per Nielsen Tikær. Having an overview of the components without the code (screenshots could be sufficient) or even a storybook would make the whole process simpler and more pleasing.

Validation Process

Communication with third parties can be hard and apart from a message with more information there isn't much the team can do.

It could be as simple as informing that the validation process can take between one and three weeks, but this could also create unnecessary expectations.

Future Plan for the Application

As you can see, the extension is quite simple. It only fetches versions of the web clients of Proton products.

You can download the extension at this link:

Raycast - Proton Version
Get the latest default and beta version number of Proton products

It is something useful for some of my coworkers and me. I'm sure that some people on Reddit will love this extension, but this is a bit too soon to tell.

I don't have much plan in the future for this application apart from adding any new product Proton might be releasing. Besides that, mobile application could be interesting and could be interesting for more people.

Feel free to comment below or share your ideas for the extensions. I'll be happy to extend the features to suit your needs!

Final Verdict

In the end, I enjoyed the whole process, and I'm quite pleased with the result. It's easy to see that the team behind Raycast wanted to disrupt the Spotlight replacement industry, and they achieve their goal.

By targeting to the developers, they build a competent set of tools that allow any developers to build an extension in minutes.

Besides that, the whole review and approval process is standard and requires little to no adaptation from developers. The person managing the extension stores keeps up with the changes and offers some precious feedback.

I think that the documentation could be improved a bit to better showcase what the components support. Getting some inspiration from other component library could be a great start.

Creating cards with each component (and subcomponent) could help

Finally, the review process takes some time and I didn't know if I had to ask for a review on Slack or if this is done automatically. This led to some confusion and could be improved a bit.

In the end I'm quite happy with how things went and I would recommend anyone that wants to write an extentension to do it without hesitation.