# 🕊️ The Day the "Mai Calendar" Began to Dance: A Record of Breaking Through the Labyrinth of Voice Calendar and Google Integration
The AI made this for me... though I'm actually thinner than this in real life...
Introduction
In the rural countryside of Yamaguchi Prefecture, I grow pesticide-free rice while working a part-time job at a supermarket in the early morning. During the day, I work as a solo developer, self-teaching and operating the Android/Web app "Voice Calendar." This app continues to evolve daily as a "personal planner" that allows users to register schedules via voice input.
This challenge was implementing the integration feature with Google Calendar. I aimed for the moment when the Voice Calendar and Google would join hands so that schedules would "dance" into my life.
Technologies and Architecture Used
Node.js (v22.12.0)
Express
Google Calendar API v3
OAuth2 Authentication (for desktop apps)
Save authentication information in `token.json`
Implement API integration logic in `server.js`
Authentication Information (Actually Used)
const oAuth2Client = new google.auth.OAuth2(
'*******************.apps.googleusercontent.com', // クライアントID
'GOCSPX-****************************', // クライアントシークレット
'urn:ietf:wg:oauth:2.0:oob' // デスクトップアプリ用リダイレクトURI
);Contents of `token.json` (upon successful retrieval)
{
"access_token": "ya29.a0AQQ_BDSB0hpM-...",
"refresh_token": "1//0ez2KjAKorWLoCgYIARAAGA4SNwF-...",
"scope": "https://www.googleapis.com/auth/calendar",
"token_type": "Bearer",
"refresh_token_expires_in": 604799,
"expiry_date": 1757917487404
}Completed `server.js` (excerpt)
const fs = require('fs');
const { google } = require('googleapis');
const express = require('express');
const app = express();
const PORT = 8080;
app.use(express.json());
app.use(express.static('public'));
const credentials = JSON.parse(fs.readFileSync('token.json'));
const oAuth2Client = new google.auth.OAuth2(
'*******************.apps.googleusercontent.com',
'GOCSPX-****************************',
'urn:ietf:wg:oauth:2.0:oob'
);
oAuth2Client.setCredentials(credentials);
// 予定追加と取得のAPI処理(省略)Troubles and Breakthroughs
❌ `unauthorized_client`
→ Cause: Used `token.json` with an old client ID
→ Solution: Re-authenticated with the new ID and secret for "Desktop App"
❌ `No access, refresh token...`
→ Cause: The calling order of `setCredentials()` was incorrect
→ Solution: Fixed to call `setCredentials()` immediately after defining `oAuth2Client`
✅ The Moment of Success
When the event "Test" appeared on my Google Calendar, I couldn't help but shout, "It danced!"

