I’ve spent years trying to optimize my workflow, and the biggest friction point has always been the ‘calendar jump’—that momentary lapse in focus when I leave my IDE to check when my next meeting starts. While the official Raycast calendar integration is great, I found that I needed something more tailored to my specific API requirements and workflow. That’s why I decided to put together this raycast calendar extension tutorial.

Whether you’re looking to integrate a niche scheduling tool or just want a more streamlined way to view your availability, building your own extension is the way to go. In my experience, the Raycast SDK makes this surprisingly trivial if you’re comfortable with TypeScript and React.

Prerequisites

Before we dive into the code, make sure you have the following installed and configured on your macOS machine:

Step 1: Initialize Your Extension

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

raycast create extension "my-calendar-tool"

When prompted, choose the TypeScript template. This gives us the type safety we need when dealing with complex date-time objects. Once the folder is created, navigate into it and install the dependencies:

cd my-calendar-tool
npm install

Step 2: Defining the Calendar Data Model

A calendar extension is only as good as its data handling. I prefer creating a separate service file to handle the API calls. This keeps the UI logic clean. Create a file named src/calendarService.ts:

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

export interface CalendarEvent {
  title: string;
  startTime: string;
  endTime: string;
  location: string;
}

export async function fetchUpcomingEvents(apiKey: string): Promise<CalendarEvent[]> {
  const response = await fetch(`https://api.yourcalendar.com/v1/events?key=${apiKey}`);
  const data = await response.json();
  return data.events.map((event: any) => ({
    title: event.summary,
    startTime: event.start.dateTime,
    endTime: event.end.dateTime,
    location: event.location || "Remote",
  }));
}

Step 3: Building the List View UI

Now, let’s bring that data into the Raycast interface. We’ll use the List component, which is perfect for showing a sequence of upcoming appointments. Open src/index.tsx and implement the following logic:

import { List, ActionPanel, Action } from "@raycast/api";
import { fetchUpcomingEvents } from "./calendarService";

export default async function Command() {
  // In a real app, you'd fetch this from Raycast preferences
  const API_KEY = "your_api_key_here"; 
  const events = await fetchUpcomingEvents(API_KEY);

  return (
    <List
      searchable
    >
      {events.map((event) => (
        <List.Item
          key={event.startTime}
          title={event.title}
          subtitle={`${new Date(event.startTime).toLocaleTimeString()} - ${event.location}`}
          actions={
            <ActionPanel>
              <Action.CopyToClipboard title="Copy Event Details" content={event.title} />
            </ActionPanel>
          }
        />
      ))}
    </List>
  );
}

As shown in the image below, the key is to keep the subtitle concise. Raycast users value speed; if they have to squint to see the time, the extension fails its primary purpose.

Raycast extension code and UI preview showing a list of calendar events
Raycast extension code and UI preview showing a list of calendar events

Pro Tips for Calendar Extensions

Troubleshooting Common Issues

During my testing, I encountered two main hurdles:

  1. CORS Errors: If you’re fetching from a browser-based environment, CORS can be a pain. However, Raycast extensions run in a Node-like environment, so standard fetch usually works fine. If it doesn’t, double-check your API headers.
  2. Auth Expiry: OAuth tokens expire. I recommend implementing a “Refresh Token” flow or providing a clear error message that directs the user to the preferences panel to re-authenticate.

What’s Next?

Now that you’ve mastered this raycast calendar extension tutorial, you can expand your productivity suite. If you’re working in a Linux environment during the day, you might find that a best command line calendar for linux complements your macOS Raycast setup. Alternatively, if you’re looking for a full-fledged app replacement, I’ve written a detailed Morgen calendar review for developers that compares these custom builds with professional software.

Ready to take your automation further? Explore our other guides on development and productivity tools at ajmani.dev.