In this tutorial, we will build a custom Raycast extension that fetches the latest articles from Dev.to and displays them in a list and opens the selected article in the browser.
Visit the Raycast Doc to learn more about the system requirements you need to start building extensions.
Create a new extension
- Open the Create Extension command in Raycast
- Choose the Template Static List
- Name your extension Devto Articles
- Name the command Latest Articles
- Click Create Extension from the bottom right corner
This will create a new directory called devto-articles
in your extensions directory.
Install the dependencies
Now, let's dive into the code.
Open the extension directory devto-articles
in your favorite code editor.
Install the dependencies by running the following command:
npm install
Before continuing, let's install the @raycast/api
package. It contains a set of components that make it easier to build extensions.
npm install @raycast/utils
Build the extension
Now we are ready to start building the extension.
Open the src/index.tsx
file, this is where we will write the code that fetches the latest articles from Dev.to and displays them in a list.
Remove the existing code from the src/index.tsx
so that we can start from scratch.
Now, let's import the useFetch
hook from @raycast/utils
. useFetch
can be used to fetch data from an API.
import { ActionPanel, Action, List } from "@raycast/api";
import { useFetch } from "@raycast/utils";
Define the type of the article object to map the response from the API.
type Article = {
id: number;
title: string;
readable_publish_date: string;
comments_count: number;
url: string;
};
Now, let's use the useFetch
hook to fetch the latest articles from Dev.to.
export default function Command() {
const { isLoading, data: articles } = useFetch<Article[]>(
"https://dev.to/api/articles"
);
}
useFetch
returns an object with two properties: isLoading
and data
.
isLoading
is a boolean that indicates whether the data is being fetched or not.data
is the response that is fetched from the API.
Now, let's use the List
component to display the articles in a list.
return (
<List isLoading={isLoading}>
{(articles || []).map((article) => (
<List.Item
key={article.id}
icon="list-icon.png"
title={article.title}
subtitle={`${article.comments_count} comments`}
accessories={[{ text: article.readable_publish_date }]}
actions={
<ActionPanel>
<Action.OpenInBrowser url={article.url} />
</ActionPanel>
}
/>
))}
</List>
);
The List
component takes an isLoading
prop that indicates whether the data is being fetched or not.
It also takes a children
prop that is an array of List.Item
components.
The ActionPanel
is a component that contains a set of actions that can be performed on the selected item.
In our case, we want to open the selected article in the browser. So, we will use the Action.OpenInBrowser
component to open the article in the browser when the user selects it.
Here is the final code:
import { ActionPanel, Action, List } from "@raycast/api";
import { useFetch } from "@raycast/utils";
type Article = {
id: number;
title: string;
readable_publish_date: string;
comments_count: number;
url: string;
};
export default function Command() {
const { isLoading, data: articles } = useFetch<Article[]>(
"https://dev.to/api/articles"
);
return (
<List isLoading={isLoading}>
{(articles || []).map((article) => (
<List.Item
key={article.id}
icon="list-icon.png"
title={article.title}
subtitle={`${article.comments_count} comments`}
accessories={[{ text: article.readable_publish_date }]}
actions={
<ActionPanel>
<Action.OpenInBrowser url={article.url} />
</ActionPanel>
}
/>
))}
</List>
);
}
Run the extension
You can run the extension by running the following command:
npm run dev
Find the extension in Raycast by searching for Devto Articles and run the command Latest Articles.