How It Works
Understand how NxCreator runs your bot code, what tools are available, and how to set up automated tasks.
This page explains what happens behind the scenes when you write and save bot code on NxCreator — and how to use the built-in tools that come with every bot.
What is NxCreator doing?
When you create a bot on NxCreator, the platform takes care of everything you would normally have to set up yourself: renting a server, installing software, keeping the bot process running 24/7, and connecting to Telegram. You just write the logic — what should happen when a user sends a message — and NxCreator handles the rest.
Think of it like this: NxCreator is the kitchen, and your code is the recipe. You write the recipe, and the kitchen handles the oven, the electricity, and making sure everything stays hot.
How your code runs
Each bot runs in its own private environment, completely separate from other bots on the platform. Your code sections are combined into one unified bot program, and the platform connects that program to Telegram on your behalf.
NxCreator uses a popular bot library called Telegraf under the hood. You do not need to set it up or configure it — it is already running. Your job is simply to tell it what to do by registering handlers on the pre-existing bot object. Never create your own bot instance or import Telegraf yourself.
Saving and testing
When you hit save in the editor, NxCreator immediately applies your changes to the live running bot — no deployment steps, no waiting. Just save, switch to Telegram, and test your change. If something is wrong, fix it and save again.
Built-in tools
NxCreator provides a set of ready-to-use tools inside every bot. These are called globals — they are available automatically without needing to install or import anything. Just use them by name.
Do not use require(...) to load packages. If you need something, check the table below — it is almost certainly already available.
What is available
| What you want to do | Global to use | Notes |
|---|---|---|
| Respond to messages and commands | bot`, `Telegraf`, `Scenes`, `Markup | The main bot object is already set up. Register handlers directly on `bot`. |
| Use the Grammy bot framework instead | GrammyBot`, `Grammy`, `InlineKeyboard`, `Keyboard`, `grammySession | Only available if your bot is configured to use the Grammy framework. |
| Use node-telegram-bot-api instead | TelegramBot | Only available if your bot is configured to use node-telegram-bot-api. |
| Make HTTP requests to external APIs | axios | A standard HTTP client. Use this to fetch data from any web API. |
| Store and retrieve data | db | A built-in database helper. No configuration needed. |
| Run tasks on a schedule | cron | For repeating tasks. See the Scheduled Tasks section below for details. |
| Send emails | nodemailer | Available with some restrictions on file attachments. |
| Generate text-to-speech audio URLs | googleTTS | Useful for voice bots or audio responses. |
| Draw images or graphics | createCanvas`, `loadImage | Image creation with size limits. File and URL-based image loading is restricted. |
| Resize or process images | sharp | Image transformation with limits. Saving files directly is not allowed. |
| Generate unique IDs | uuid | Useful for creating unique keys or identifiers. |
| Hash data or generate tokens | crypto | Standard cryptographic utilities. |
Calling external APIs
Your bot can reach out to the internet and fetch data from any external service. Use the built-in axios global to make these requests. This is how you would connect your bot to a weather service, a payment API, a news feed, or anything else.
The try/catch block is important here — external APIs can fail or go down, and you want your bot to handle that gracefully instead of crashing.
Delays and repeating actions
Sometimes you want your bot to do something after a delay, or on a repeating schedule. JavaScript provides two built-in tools for this:
setTimeout(fn, ms)— runs something once after a delay. For example, send a follow-up message 5 seconds after a user signs up.setInterval(fn, ms)— runs something repeatedly on a fixed interval. For example, check a feed every 60 seconds.
Scheduled tasks that last
Imagine you want your bot to send a daily summary to a user every morning at 9am. A simple timer like setTimeout would not work for this — if the bot ever restarts, the timer is gone and the task never runs again.
NxCreator solves this with persistent scheduled tasks. These are jobs that get stored safely outside the bot process, so they survive restarts, re-saves, and updates. Even if your bot goes down and comes back up, the scheduled task will still run at the right time.
How to think about it
Setting up a persistent task is a two-step process:
- Step 1: Define what should happen. You write the function and give it a name — for example
daily-report. This is your task definition. - Step 2: Set when it should run. You use the scheduler to tell NxCreator when to trigger that task — once, or on a repeating schedule.
The key insight is that NxCreator stores the name of your task, not the code itself. When the time comes to run it, it looks up the registered task by name and executes it. This is why the name you use in Step 1 must exactly match the name you use in Step 2.
Choosing the right tool
| Tool | Best for | Survives bot restarts? |
|---|---|---|
setTimeout | A short one-time delay (e.g. wait 10 seconds) | No |
setInterval | A simple repeating action (e.g. ping every minute) | No |
cron | Time-based repeating actions while the bot is running | No |
persistentScheduler.setTimeout | A one-time future action that must not be lost | Yes |
persistentCron.schedule | A repeating time-based task that must keep running | Yes |
Example: send a daily report every morning
This example shows how to send a message every morning at 9:00 AM. Read it from top to bottom — first the task is defined, then a bot command schedules it.
Breaking down what each part does:
registerPersistentTask('daily-report', ...): registers the job logic under the namedaily-report. This is the work that will run on schedule.payload: a small piece of data that gets saved alongside the schedule and passed back to your task when it runs. Here it carries the chat ID so the bot knows who to message.persistentCron.validate(timePattern): checks that your time pattern is valid before saving it.persistentCron.schedule(...): saves the task into the persistent scheduler so it will keep running even after restarts.key: 'daily-report-main': a unique name for this particular scheduled job. If a user runs the command again, it updates the existing schedule instead of creating a duplicate.
Example: send a message after a delay
Sometimes you do not need a repeating schedule — you just need something to happen once, later. For example, sending a reminder one hour after a user signs up, even if the bot restarts in between.
This pattern works well for reminders, delayed follow-ups, expiring access codes, or anything else that should fire once at a specific time in the future.
Understanding the time pattern format
Persistent repeating schedules use a time pattern with five parts, separated by spaces. Each part controls one unit of time — minute, hour, day, month, and day of the week. A * means "every".
Some practical examples to get you started:
0 9 * * *— every day at 9:00 AM.*/15 * * * *— every 15 minutes, all day long.0 0 * * 1— every Monday at midnight.30 18 * * 5— every Friday at 6:30 PM.
Quick reference
registerPersistentTask(name, handler)— defines a named task that the scheduler can call later.persistentCron.validate(pattern)— returnstrueif the time pattern is valid,falseotherwise.persistentCron.schedule(name, pattern, payload, options)— saves a repeating scheduled task.persistentScheduler.setTimeout(name, ms, payload)— saves a one-time delayed task.persistentCron.cancel(jobId)orpersistentScheduler.cancel(jobId)— removes a saved task.
Common mistakes to avoid
- Scheduling before registering: Always call
registerPersistentTaskfirst, then schedule it. The scheduler needs the task to already exist. - Mismatched names: The name in
registerPersistentTaskand the name inpersistentCron.schedulemust be exactly the same. - No key set: If a user can trigger the scheduling command more than once, always pass a
keyin options. Without it, each run of the command creates a new copy of the job. - Too much data in payload: Only put small identifiers in the payload (like a user ID or chat ID). Store everything else in the database.
db, register a simple named task, and schedule it with a stable key. That covers most real use cases without overcomplicating things.