Claude Skills Guide

Chrome Extension Google Calendar Sidebar: Build Your Own Calendar Integration

Chrome extensions that display Google Calendar in a sidebar offer significant productivity gains for users who constantly switch between their calendar and other web applications. This guide walks you through building a Chrome extension that renders Google Calendar in a sidebar panel, covering the necessary APIs, implementation strategies, and practical code examples.

Understanding the Google Calendar Integration Options

When building a Chrome extension that interacts with Google Calendar, you have several approaches available. The most common method involves using the Google Calendar API to fetch calendar events and display them in a custom-built sidebar interface. Alternatively, you can embed Google’s official calendar view using an iframe, though this approach comes with limitations around customization.

For developers seeking full control over the sidebar experience, fetching events via the Google Calendar API and rendering them with your own UI components provides the greatest flexibility. This approach lets you create a sidebar that matches your exact design requirements while maintaining full functionality.

Setting Up Your Chrome Extension Project

Every Chrome extension requires a manifest file. For sidebar implementations targeting Google Calendar, you’ll need Manifest V3 (the current standard). Here’s a minimal manifest configuration:

{
  "manifest_version": 3,
  "name": "Calendar Sidebar",
  "version": "1.0",
  "permissions": [
    "storage",
    "identity"
  ],
  "oauth2": {
    "client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
    "scopes": [
      "https://www.googleapis.com/auth/calendar.readonly"
    ]
  },
  "action": {
    "default_popup": "sidebar.html",
    "default_title": "Toggle Calendar"
  },
  "host_permissions": [
    "https://www.googleapis.com/calendar/v3/*"
  ]
}

The OAuth2 configuration is essential for accessing user calendar data. You’ll need to set up a project in the Google Cloud Console to obtain your client ID and enable the Calendar API.

Implementing the Sidebar Panel

The sidebar itself is an HTML file that loads when users activate your extension. Create a well-structured sidebar.html with proper styling for the collapsible panel:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div id="sidebar" class="sidebar-collapsed">
    <header class="sidebar-header">
      <h2>My Calendar</h2>
      <button id="toggle-btn"></button>
    </header>
    <div id="calendar-content" class="hidden">
      <div id="auth-status">
        <button id="authorize-btn" class="hidden">Sign In</button>
      </div>
      <div id="events-list"></div>
    </div>
  </div>
  <script src="sidebar.js"></script>
</body>
</html>

The CSS controls the sidebar behavior and appearance:

.sidebar-collapsed {
  position: fixed;
  right: 0;
  top: 0;
  height: 100vh;
  width: 40px;
  transition: width 0.3s ease;
}

.sidebar-collapsed #calendar-content {
  display: none;
}

.sidebar-expanded {
  width: 350px;
  background: #fff;
  box-shadow: -2px 0 10px rgba(0,0,0,0.1);
}

#events-list {
  padding: 16px;
  overflow-y: auto;
  max-height: calc(100vh - 60px);
}

.event-item {
  padding: 12px;
  margin-bottom: 8px;
  border-radius: 8px;
  background: #f8f9fa;
  border-left: 4px solid #4285f4;
}

.event-time {
  font-size: 12px;
  color: #666;
  margin-bottom: 4px;
}

.event-title {
  font-weight: 600;
  font-size: 14px;
}

Authenticating with Google Calendar API

The authentication flow uses Google’s Identity Services for secure OAuth2 implementation. Your sidebar.js handles the complete auth workflow:

const CLIENT_ID = 'YOUR_CLIENT_ID.apps.googleusercontent.com';
const API_KEY = 'YOUR_API_KEY';
const DISCOVERY_DOC = 'https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest';
const SCOPES = 'https://www.googleapis.com/auth/calendar.readonly';

let tokenClient;
let gapiInitialized = false;
let gisInitialized = false;

async function initializeGapi() {
  await gapi.load('client', async () => {
    await gapi.client.init({
      apiKey: API_KEY,
      discoveryDocs: [DISCOVERY_DOC],
    });
    gapiInitialized = true;
    maybeEnableButtons();
  });
}

async function initializeGis() {
  tokenClient = google.accounts.oauth2.initTokenClient({
    client_id: CLIENT_ID,
    scope: SCOPES,
    callback: (response) => {
      if (response.error !== undefined) {
        console.error('Auth error:', response);
      }
    },
  });
  gisInitialized = true;
  maybeEnableButtons();
}

function maybeEnableButtons() {
  if (gapiInitialized && gisInitialized) {
    document.getElementById('authorize-btn').classList.remove('hidden');
  }
}

function handleAuthClick() {
  tokenClient.requestAccessToken({ prompt: 'consent' });
}

This implementation follows Google’s recommended pattern for browser-based OAuth, using the newer token model instead of the legacy gapi.auth2 approach.

Fetching and Displaying Calendar Events

Once authenticated, you can retrieve calendar events using the Calendar API. The following function fetches events for the current day:

async function fetchTodayEvents() {
  const now = new Date();
  const startOfDay = new Date(now.setHours(0, 0, 0, 0));
  const endOfDay = new Date(now.setHours(23, 59, 59, 999));

  try {
    const response = await gapi.client.calendar.events.list({
      calendarId: 'primary',
      timeMin: startOfDay.toISOString(),
      timeMax: endOfDay.toISOString(),
      singleEvents: true,
      orderBy: 'startTime',
    });

    displayEvents(response.result.items);
  } catch (err) {
    console.error('Error fetching events:', err);
  }
}

function displayEvents(events) {
  const container = document.getElementById('events-list');
  container.innerHTML = '';

  if (!events || events.length === 0) {
    container.innerHTML = '<p class="no-events">No events today</p>';
    return;
  }

  events.forEach(event => {
    const start = event.start.dateTime || event.start.date;
    const time = new Date(start).toLocaleTimeString([], { 
      hour: '2-digit', 
      minute: '2-digit' 
    });

    const eventEl = document.createElement('div');
    eventEl.className = 'event-item';
    eventEl.innerHTML = `
      <div class="event-time">${time}</div>
      <div class="event-title">${event.summary}</div>
      ${event.location ? `<div class="event-location">📍 ${event.location}</div>` : ''}
    `;
    container.appendChild(eventEl);
  });
}

The API returns events with both date-time formatted events and all-day events (which use the date field instead of dateTime). The display function handles both formats gracefully.

Adding Practical Features

A truly useful calendar sidebar includes additional functionality beyond basic event display. Consider implementing these features:

Quick Event Creation: Add a simple form that uses the Calendar API’s insert endpoint to create new events directly from the sidebar.

Date Navigation: Implement previous and next day buttons that adjust the timeMin and timeMax parameters in your API call.

Multiple Calendars: Fetch events from multiple calendar IDs (not just ‘primary’) to show team calendars alongside personal events.

Real-time Updates: Use the Calendar API’s watch endpoint to receive push notifications when calendar changes occur, then refresh your display automatically.

Handling Edge Cases and Errors

Robust error handling improves the extension experience significantly. Common scenarios to handle include:

Security Considerations

When building extensions that handle OAuth credentials, follow security best practices:

Deployment and Distribution

Once your extension is functional, package it for distribution through the Chrome Web Store. You’ll need to create a ZIP file containing your manifest, HTML, CSS, JavaScript, and any icon assets. The store review process typically takes 1-3 days for new extensions.

For internal distribution within organizations, you can use Chrome Enterprise policies to deploy extensions managed fashion without public listing.

Building a Google Calendar sidebar extension requires understanding OAuth flows, the Calendar API, and Chrome extension architecture. The investment pays off in a productivity tool that keeps your calendar visible while working in other browser tabs.

Built by theluckystrike — More at zovo.one