I’ve spent years trying to find the perfect ‘command-center’ for my productivity. I tried everything from Morgen calendar for its deep integration to various CLI tools. But nothing beats the speed of Raycast. When I realized I was spending too much time clicking between my IDE and my browser just to see when my next meeting started, I decided to build a solution.

In this raycast calendar extension tutorial, I’m going to walk you through the process of creating your own calendar extension. Whether you’re using Google Calendar, Outlook, or a custom internal API, the logic remains the same: fetch data, format it for the Raycast UI, and map it to a keyboard shortcut.

Prerequisites

Before we dive into the code, make sure you have the following set up in your environment:

If you’re coming from a Linux background and are used to a command line calendar for Linux, you’ll find the Raycast SDK surprisingly similar in terms of data handling, but with a much more polished UI layer.

Step 1: Initializing Your Extension

First, we need to scaffold the project using the Raycast CLI. Open your terminal and run the following command:

npx @raycast/api@latest init

Follow the prompts: give your extension a name (e.g., “My Calendar”) and choose TypeScript as the language. TypeScript is highly recommended here because the Raycast API provides excellent type definitions that prevent 90% of common UI bugs.

Step 2: Setting Up the API Client

I prefer using a separate utility file for API calls to keep the UI logic clean. Create a file named src/api.ts. In my experience, using axios or the native fetch API works best for these lightweight requests.

import { getPreferenceValues } from "@raycast/api";

export async function fetchCalendarEvents() {
  const { apiKey } = await getPreferenceValues();
  
  const response = await fetch(`https://www.googleapis.com/calendar/v3/calendars/primary/events?key=${apiKey}`);
  const data = await response.json();
  
  return data.items.map((event: any) => ({
    title: event.summary,
    time: event.start.dateTime || event.start.date,
    location: event.location || "Remote"
  }));
}

As shown in the image below, you will need to define these preferences in your package.json so users can securely enter their own API keys without hardcoding them.

Raycast extension preferences panel showing where to enter the Calendar API Key
Raycast extension preferences panel showing where to enter the Calendar API Key

Step 3: Building the User Interface

Now, let’s create the main command. Raycast uses a declarative UI approach. You don’t write HTML; you use components like List and ListItem.

import { List, ListItem, ActionPanel, Action } from "@raycast/api";
import { fetchCalendarEvents } from "./api";

export default async function Command() {
  const events = await fetchCalendarEvents();

  return (
    <List searchability={{ enabled: true }}>
      {events.map((event) => (
        <ListItem
          title={event.title}
          subtitle={`${event.time} | ${event.location}`}
          actions={
            <ActionPanel>
              <Action.CopyToClipboard title="Copy Event Link" content={event.link} />
            </ActionPanel>
          }
        />
      ))}
    </List>
  );
}

Pro Tips for Calendar Extensions

If you find yourself needing more advanced scheduling logic, I highly recommend checking out my guide on advanced Google Calendar tips for power users to see how to structure your calendar for maximum efficiency.

Troubleshooting Common Issues

Issue: “API Key not found”
Ensure you have run the extension in development mode and gone to the Raycast Settings > Extensions > [Your Extension] to fill in the preference values.

Issue: Slow Loading Times
Calendar APIs can be sluggish. Implement a loading state using the Loading component from @raycast/api to provide visual feedback to the user.

What’s Next?

Now that you have a basic list of events, try adding a “Create Event” action. You can use a Form component to take a title and time, then send a POST request back to your calendar provider. This transforms your extension from a viewer into a full productivity tool.

Want more automation tips? Check out the rest of the productivity guides on ajmani.dev to streamline your entire dev workflow.