A complete, production-ready template for integrating Google Calendar into your Next.js application. This template provides OAuth authentication, event management, and a clean UI for working with Google Calendar APIs.
- 🔐 Clerk Authentication - Secure authentication with Clerk
- 📅 Calendar Integration - View and manage Google Calendar events
- ✨ Event Management - Create, edit, and delete calendar events
- 🎨 Modern UI - Clean, responsive interface built with Tailwind CSS and shadcn/ui
- 📱 Dual View Modes - Switch between Events list and Calendar grid views
- 🔧 TypeScript Ready - Full TypeScript support with Zod validation
- 🚀 Production Ready - Server actions with server-side authentication
- 🌓 Light Theme - Clean off-white design with excellent readability
- Node.js 22+ or Bun
- A Clerk account for authentication
- A Google Cloud Platform account
- Google Calendar API enabled
git clone <your-repo-url>
cd nextjs-google-calendar-template
bun install # or npm installCopy .env.local.example to .env.local and fill in your credentials:
cp .env.local.example .env.localUpdate .env.local with your credentials:
# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SECRET_KEY=your_clerk_secret_key
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
# Google Calendar API
GOOGLE_OAUTH_CLIENT_ID=your_google_client_id
GOOGLE_OAUTH_CLIENT_SECRET=your_google_client_secret
GOOGLE_OAUTH_REDIRECT_URL=http://localhost:3000/api/auth/callbackbun dev # or npm run devOpen http://localhost:3000 to see your application.
├── app/
│ ├── (auth)/ # Authentication routes
│ │ ├── sign-in/ # Clerk sign-in page
│ │ └── sign-up/ # Clerk sign-up page
│ ├── calendar/ # Calendar page with server-side rendering
│ │ └── page.tsx
│ ├── layout.tsx # Root layout with ClerkProvider
│ ├── page.tsx # Landing page
│ └── globals.css # Global styles
├── components/
│ ├── calendar/ # Calendar-specific components
│ │ ├── calendar-view.tsx # Main calendar view with dual modes
│ │ ├── add-event.tsx # Event creation dialog
│ │ └── edit-event.tsx # Event editing dialog
│ └── ui/ # Reusable UI components
│ ├── button.tsx
│ ├── card.tsx
│ ├── dialog.tsx
│ ├── input.tsx
│ ├── label.tsx
│ ├── textarea.tsx
│ └── badge.tsx
├── lib/
│ ├── actions/
│ │ └── calendar-events.ts # Server actions for CRUD operations
│ ├── schemas/
│ │ └── calendar.ts # Zod schemas for validation
│ ├── google-calendar.ts # Google Calendar API integration
│ └── utils.ts # Utility functions
├── types/
│ └── google-calendar.ts # TypeScript type definitions
├── middleware.ts # Clerk route protection
└── .env.local.example # Environment template
The template uses Next.js server actions for all calendar operations, providing type-safe, secure API calls:
// In your client component
import {
createCalendarEvent,
deleteCalendarEvent,
updateCalendarEvent,
} from "@/lib/actions/calendar-events";
// Create an event
await createCalendarEvent({
calendarId: "primary",
title: "Team Meeting",
description: "Quarterly planning session",
location: "Conference Room A",
date: new Date("2024-01-01T10:00:00"),
endDate: new Date("2024-01-01T11:00:00"),
startTime: "10:00",
endTime: "11:00",
isAllDay: false,
repeat: "none",
reminder: "at_start",
tag: "work",
});
// Update an event
await updateCalendarEvent(eventId, {
calendarId: "primary",
title: "Updated Meeting Title",
// ... other fields
});
// Delete an event
await deleteCalendarEvent(calendarId, eventId);import { CalendarView } from "@/components/calendar/calendar-view";
import { listCalendarEvents } from "@/lib/actions/calendar-events";
import { auth } from "@clerk/nextjs/server";
export default async function CalendarPage() {
const { userId } = await auth();
const events = await listCalendarEvents(userId, "primary");
return <CalendarView events={events} calendarId="primary" userId={userId} />;
}The template uses Next.js 15 server actions instead of traditional API routes for better type safety and performance:
createCalendarEvent()- Create new calendar event with server-side authupdateCalendarEvent()- Update existing eventdeleteCalendarEvent()- Delete eventlistCalendarEvents()- Fetch calendar events with filtering
All actions automatically handle authentication using Clerk's server-side auth() function.
The template uses Tailwind CSS with a light theme. Customize the appearance by modifying:
- Component classes in
components/ - Global styles in
app/globals.css - Tailwind configuration in
tailwind.config.ts
Extend the template by adding more functionality:
- Recurring events - Already supported in schema, add UI controls
- Event tags/categories - Schema exists, implement filtering UI
- Event reminders - Extend reminder options beyond current presets
- Calendar sharing - Use existing
shareCalendarWithEmail()function - Multiple calendars - Extend to support calendar switching
- All-day events - Add toggle for all-day event creation
- Server-Side Auth: All calendar operations use Clerk's server-side
auth()for security - OAuth Tokens: Google OAuth tokens are securely managed by Clerk
- HTTPS: Always use HTTPS in production
- Environment Variables: Never commit
.env.localto version control - Input Validation: All inputs are validated with Zod schemas
MIT License - see LICENSE file for details.