This content originally appeared on Telerik Blogs and was authored by Jonathan Gamble
Use the Google Tasks API and Google OAuth 2.0 to create your own task system!
Google has a JavaScript package that allows you to connect to the Google Tasks API directly. Using this and Google OAuth 2.0, you can display and modify your Google Tasks with your own design touches. The database is already there to connect to.
TL;DR
Using your own JavaScript framework, you can connect to the Google Tasks API using an OAuth 2.0 token and the googleapis Node JS package. Each user must have the Google Tasks API enabled. The API is extremely comprehensive and feature-rich.
Microsoft Hits the Spot
If you’re like me, you were paying attention when Microsoft decided to buy Wunderlist and completely dismantle, reengineer and rebrand it as Microsoft Todo.
Google, on the other hand … (crickets).
Google Tasks Is Terrible IMO
The UI has not been updated for years. It does integrate with Google Calendar, but it is easy to tell Google Tasks is an afterthought for Google, with features that aren’t much different.
Building a Better Application
Countless task applications use an external database. However, why not use the free database already available to any Google user?
Configuration
Enable Google Tasks API
Unfortunately, an application cannot be built for any Google user without each user manually enabling the Google Tasks API. This means you can build a one-stop application that works. However, connecting to the API is one click. Click the following link and enable the Tasks API:
Get a Key
While technically optional, getting an API key is the best way to get an OAuth 2.0 Client ID.
- Go to Credentials in Google Cloud
- Create an OAuth 2.0 Client ID
- Add the Authorized URLs for both local and production
- Add the Authorized Redirect URI for both local and production
- Copy the Client ID and Client Secret
Save to .env File
Save the API credentials.
PRIVATE_CLIENT_ID=...
PRIVATE_CLIENT_SECRET=...
My application uses SvelteKit, but the process is the same in any JS Framework.
Install Google Package
Install the desired packages.
npm i -D googleapis
⚠️ The googleapis for Node.js will only work in Node environments. You must use the REST API directly with fetch
for Deno, Vercel Edge, Cloudflare or Bun.
Google Auth Functions
Here, I created a few functions to connect to OAuth 2.0, and get permission for Google Tasks.
// google-auth.ts
import { google } from 'googleapis';
import type { OAuth2Client } from 'google-auth-library';
import { PRIVATE_CLIENT_ID, PRIVATE_CLIENT_SECRET } from '$env/static/private';
export const COOKIE_NAME = 'user';
const REDIRECT_URI = '/auth/callback/google';
export const createOAuth2Client = (origin: string) => {
return new google.auth.OAuth2(
PRIVATE_CLIENT_ID,
PRIVATE_CLIENT_SECRET,
origin + REDIRECT_URI
);
};
export const getAuthUrl = (client: OAuth2Client) => {
return client.generateAuthUrl({
access_type: 'offline',
scope: [
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/tasks'
]
});
};
The tasks
scope allows users to connect to Google Tasks and general profile and email information.
Google Tasks Functions
There are different task lists and different tasks. We must get both in this app.
// tasks.ts
import { google } from 'googleapis';
import { type OAuth2Client } from 'google-auth-library';
export async function getTaskLists(auth: OAuth2Client) {
try {
const taskAPI = google.tasks({
version: 'v1',
auth
});
const taskList = await taskAPI.tasklists.list();
return {
data: taskList.data
};
} catch (error) {
console.error('Error fetching tasks:', (error as Error).message);
return {
error
};
}
}
export async function getTasksByList(auth: OAuth2Client, tasklist: string) {
try {
const taskAPI = google.tasks({
version: 'v1',
auth
});
const tasks = await taskAPI.tasks.list({
tasklist
});
return {
data: tasks.data
};
} catch (error) {
console.error('Error fetching tasks:', (error as Error).message);
return {
error
};
}
}
The tasks API can insert, patch, and remove tasks AND task lists. This is just getting started.
Login
A login event is handled by redirecting to the appropriate Login with Google page.
// /routes/login/+server.ts
import { createOAuth2Client, getAuthUrl } from '$lib/google-auth';
import { redirect } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ url }) => {
// Redirect to Google login page
const client = createOAuth2Client(url.origin);
const authUrl = getAuthUrl(client);
return redirect(307, authUrl);
};
Our functions handle the nitty-gritty; we only need to redirect to the appropriate URL.
Handle the Return Function
We must get the code from the URL, translate it to a token and save it to cookies.
// /routes/auth/callback/google
import { COOKIE_NAME, createOAuth2Client } from '$lib/google-auth';
import { google } from 'googleapis';
import type { RequestHandler } from './$types';
import { redirect } from '@sveltejs/kit';
export const GET: RequestHandler = async ({ url, cookies }) => {
const code = url.searchParams.get('code');
if (!code) {
return new Response('No code returned from Google', { status: 400 });
}
try {
const client = createOAuth2Client(url.origin);
// Exchange the code for tokens
const { tokens } = await client.getToken(code);
client.setCredentials(tokens);
// Fetch user info
const oauth2 = google.oauth2({
auth: client,
version: 'v2'
});
const userInfo = await oauth2.userinfo.get();
const session = {
user: userInfo.data,
tokens
};
// Store user data in a cookie or session as needed
cookies.set(COOKIE_NAME, JSON.stringify(session), { path: '/' });
} catch (error) {
console.error('Error during authentication:', error);
return new Response('Authentication failed', { status: 500 });
}
// Redirect to the homepage or a dashboard
return redirect(302, '/');
};
We can save the user information with the token.
Handle Session
We need to get the cookie for each server request, if applicable.
// hooks.server.ts
import { COOKIE_NAME, createOAuth2Client } from "$lib/google-auth";
import type { Handle } from "@sveltejs/kit";
export const handle: Handle = async ({ event, resolve }) => {
event.locals.getGoogleSession = () => {
const session = event.cookies.get(COOKIE_NAME);
if (!session) {
return null;
}
const client = createOAuth2Client(event.url.origin);
const data = JSON.parse(session) as GoogleSession;
client.setCredentials(data.tokens);
return {
data,
client
};
};
return resolve(event);
};
SvelteKit handles this in hooks, but Next or other Frameworks may use middleware. In all cases, the pattern is the same.
Get the Task Lists
This example uses an endpoint, but you could easily load this directly with the data.
// routes/task
import { getTaskLists } from '$lib/tasks';
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { getGoogleSession } }) => {
const session = getGoogleSession();
if (!session) {
return error(401, 'Not Logged In!');
}
const { data, error: taskError } = await getTaskLists(session.client);
if (taskError) {
return error(404, (taskError as Error).message);
}
if (!data || !data.items) {
return error(404, 'No Tasks Apparently!');
}
return {
taskLists: data.items
};
}) as PageServerLoad;
Get the List of Tasks
We must get the tasks for each task list as well.
// /routes/task/[id]
import { getTasksByList } from "$lib/tasks";
import { error } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
export const load = (async ({ params, locals: { getGoogleSession } }) => {
const id = params.id;
const session = getGoogleSession();
if (!session) {
return error(401, 'Not Logged In!');
}
const { data, error: taskError } = await getTasksByList(session.client, id);
if (taskError) {
return error(404, (taskError as Error).message);
}
if (!data || !data.items) {
return error(404, 'No Tasks Apparently!');
}
return {
tasks: data.items
};
}) satisfies PageServerLoad;
Display the Data
Now we can build a UI however we like!
Going Further
Google Tasks, like Microsoft Todo, has many features for repeated events, calendar integrations and tasks with subtasks. You could build a habit tracker or even a kanban board on top of this API. You could also use this base code to connect to other Google APIs in your JavaScript Application.
Live Data
Google Tasks does not have webhooks to create web sockets or live data. You could build one manually or sync it with a Firebase Todo App to emulate it in real-time.
Bonus: Microsoft Todo
You could do something similar with Microsoft Todo.
- Create a MS Azure App
- Install MSAL.js to connect to Microsoft Oauth 2.0
- Use the scopes
openid
,profile
,User.Read
- Fetch with the Microsoft Graph API
There is no demo for this, but the pattern would be the same.
Google Demo
- Repo: GitHub
- Demo: Vercel Serverless
About the Demo
- Before you login, you must enable Google Tasks API in Google Console.
- Because the app is for demo purposes only, it is not registered. Make sure to hit Advanced, then proceed to login anyway to avoid the warning.
This content originally appeared on Telerik Blogs and was authored by Jonathan Gamble

Jonathan Gamble | Sciencx (2025-01-09T16:03:53+00:00) A Better Google Task App. Retrieved from https://www.scien.cx/2025/01/09/a-better-google-task-app/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.