Building a Daily Python Lesson Telegram Bot with Supabase and React

Published: (December 17, 2025 at 03:45 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

Introduction

Imagine a web application that sends users a short Python lesson every day through Telegram.
With modern tools like Supabase and React, we can create this seamlessly — combining frontend, backend, and a Telegram bot. In this tutorial, we’ll walk through:

  1. Designing the application
  2. Creating the bot
  3. Integrating it with Supabase
  4. Linking it to a React frontend

Step 1: Designing the Application

Features

  • Daily Python lessons delivered via Telegram.
  • Users track progress on lessons in the app.
  • Users can configure notifications (enable/disable, delivery time, Telegram username).

Database Tables

lessons

create table public.lessons (
    id uuid primary key default gen_random_uuid(),
    day_index int not null unique,
    title text not null,
    content text,
    example_code text,
    challenge text,
    created_at timestamptz default now()
);

user_progress

create table public.user_progress (
    id uuid primary key default gen_random_uuid(),
    user_id uuid references auth.users(id) on delete cascade,
    lesson_id uuid references lessons(id) on delete cascade,
    completed boolean default false,
    completed_at timestamptz
);

user_notifications

create table public.user_notifications (
    id uuid primary key default gen_random_uuid(),
    user_id uuid references auth.users(id) on delete cascade,
    channel text not null,               -- 'telegram', 'email'
    enabled boolean default true,
    delivery_time time not null,
    timezone text default 'UTC',
    created_at timestamptz default now(),
    updated_at timestamptz default now()
);

user_telegram

create table public.user_telegram (
    id uuid primary key default gen_random_uuid(),
    user_id uuid references auth.users(id) on delete cascade unique,
    telegram_chat_id bigint,
    activation_code int not null,
    status text default 'pending',        -- pending | connected
    created_at timestamptz default now(),
    updated_at timestamptz default now()
);

Step 2: Create a Telegram Bot

  1. Open Telegram and search for BotFather.
  2. Send /newbot and follow the instructions.
  3. Choose a name and username; BotFather will give you a bot token.
  4. Keep this token safe — it’s required to send messages via the Telegram API.

Test Your Bot

curl -X POST https://api.telegram.org/bot/sendMessage \
     -d chat_id= \
     -d text="Hello from PyDaily!"

Tip: Use @userinfobot to get your Telegram chat ID for testing.

Step 3: Supabase Backend Setup

Supabase will handle:

  • Authentication
  • Database storage
  • Edge Functions (serverless backend)

1. Store Lessons

insert into public.lessons (day_index, title, content, example_code, challenge)
values
  (1, 'Variables & Types', 'Introduction to Python variables',
   'x = 5\ny = "Hello"', 'Write a program to swap two variables'),
  (2, 'Control Flow', 'If, elif, else',
   'if x > 5:\n    print("x is greater")',
   'Write a function to check even/odd');

2. User Notification Setup

  • Users can choose the delivery channel (Telegram) and time.
  • Add a row in user_telegram for each user with a generated activation code.

3. Edge Function for Telegram

Create a Supabase Edge Function that:

  1. Fetches users who have Telegram enabled.
  2. Determines today’s lesson.
  3. Checks user_progress to avoid duplicate sends.
  4. Sends the lesson via the Telegram Bot API.
  5. Updates user_progress.

Step 4: Frontend in React

Notification Settings Component

function NotificationSettings({ user }) {
  const [telegramUsername, setTelegramUsername] = useState('');
  const [activationCode, setActivationCode] = useState('');
  const [status, setStatus] = useState('pending');

  const generateCode = async () => {
    const { data } = await supabase.rpc('generate_telegram_activation_code');
    setActivationCode(data);
  };

  return (
    <div>
      <input
        placeholder="Telegram username"
        value={telegramUsername}
        onChange={e => setTelegramUsername(e.target.value)}
      />
      <button onClick={generateCode}>Generate Activation Code</button>

      <p>Status: {status}</p>

      {status === 'pending' && (
        <div>
          Send this code to the bot: {activationCode}
        </div>
      )}
    </div>
  );
}
  • On submit, save data to user_notifications and user_telegram via the Supabase client.
  • React fetches lesson history to display user progress.

Step 5: Connecting Everything

  1. User enters Telegram username in the frontend.
  2. Backend generates an activation code (via RPC).
  3. User sends the code to the bot → backend webhook validates it → updates status = connected.
  4. Daily lesson scheduler Edge Function runs:
// Pseudocode
for (const user of usersWithTelegramEnabled) {
  const lesson = await getTodaysLesson();
  const alreadySent = await checkUserProgress(user.id, lesson.id);
  if (!alreadySent) {
    await sendTelegramMessage(user.telegram_chat_id, formatLesson(lesson));
    await markLessonSent(user.id, lesson.id);
  }
}
son = getLessonForToday(user)
if !user_progress.completed:
    sendTelegram(user.telegram_chat_id, lesson.content)
    markLessonCompleted(user, lesson)

With these pieces in place, PyDaily will automatically deliver daily Python lessons to users via Telegram, while letting them track progress and control notification preferences from a React dashboard. 🚀

Scheduling

  • Can schedule via Supabase cron or an external service.
  • Lessons include Markdown formatting or code blocks.

Step 6: Testing & Going Live

  • Test the activation code flow.
  • Ensure user_telegram.status = connected.
  • Run the Edge Function manually to verify messages.
  • Schedule the Edge Function for daily execution.

Conclusion

With Supabase and React you can:

  • Manage users, lessons, and notifications seamlessly.
  • Use a Telegram bot for daily engagement without building a custom messaging service.
  • Extend the architecture to email, WhatsApp, or other channels.

Next Steps

  • Add lesson attachments (images, diagrams) via Telegram sendPhoto.
  • Extend the React UI with a lesson timeline and progress charts.
  • Add retry logic in Edge Functions for robust delivery.

This post provides a complete end‑to‑end plan to implement a daily Python‑lesson Telegram bot integrated with a React frontend using Supabase as the backend.

Back to Blog

Related posts

Read more »

Drupal: Exploring Canvas (part 2)

Exploring Components In my previous post I got acquainted with the new module, and it got off to a promising start. In this post I’m going to explore component...