Hosting: Cyclic
This guide tells you how you can host your grammY bots on Cyclic.
Prerequisites
To follow along, you need to have a Github and Cyclic account. First, initialize your project and install some dependencies:
# Initialize the project.
mkdir grammy-bot
cd grammy-bot
npm init -y
# Install main dependencies.
npm install grammy express dotenv
# Install development dependencies.
npm install -D typescript ts-node nodemon @types/express @types/node
# Initialize TypeScript config.
npx tsc --init
2
3
4
5
6
7
8
9
10
11
12
13
We will store our TypeScript files inside src
, and our compiled files in dist
. After creating both of them, cd into src
, and create a file named bot
. Your project’s root directory should now look like this:
.
├── node_modules/
├── dist/
├── src/
│ └── bot.ts
├── package.json
├── package-lock.json
└── tsconfig.json
Then, open tsconfig
, and rewrite its contents to use this configuration:
{
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true
}
}
2
3
4
5
6
7
8
9
And then we have to add start
, build
and dev
scripts to our package
. Our package
should now be similar to this:
{
"name": "grammy-bot",
"version": "1.0.0",
"description": "",
"main": "dist/bot.js",
"scripts": {
"build": "tsc",
"start": "node dist/bot.js",
"dev": "nodemon src/bot.ts"
},
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"grammy": "^1.17.2",
"dotenv": "^16.3.1"
},
"devDependencies": {
"@types/express": "^4.17.17",
"@types/node": "^20.4.9",
"typescript": "^5.1.6",
"nodemon": "^3.0.1",
"ts-node": "^10.9.1"
},
"keywords": []
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Webhooks
Open src
write the following contents to it:
import express from "express";
import { Bot, webhookCallback } from "grammy";
import "dotenv/config";
const bot = new Bot(process.env. BOT_TOKEN || "");
bot.command("start", (ctx) => ctx.reply("Hello World!"))
if (process.env. NODE_ENV === "DEVELOPMENT") {
bot.start();
} else {
const port = process.env. PORT || 3000;
const app = express();
app.use(express.json());
app.use(`/${bot.token}`, webhookCallback(bot, "express"));
app.listen(port, () => console.log(`listening on port ${port}`));
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
We recommend that you have your webhook handler on a secret path rather than /
. As shown in the highlighted line above, we are using the /<bot
instead of /
.
Local Development
Create a .env
file at the root of your project with the following contents:
BOT_TOKEN=<bot-token>
NODE_ENV=DEVELOPMENT
2
After that, run your dev
script:
npm run dev
Nodemon will watch your bot
file and restart your bot on every code change.
Deploying
- Create a repository on GitHub, it can be either private or public.
- Push your code.
It is recommended that you have a single stable branch and you do your testing in separate branches, so that you won’t land unexpected behaviors to production.
- Visit your Cyclic dashboard.
- Click “Link Your Own” and select your repository.
- Go to Advanced > Variables and add your
BOT
._TOKEN - Deploy your bot with “Connect Cyclic”.
Setting the Webhook URL
If you are using webhooks, after your first deployment, you should configure your bot’s webhook settings to point to your app. To do that, send a request to
https://api.telegram.org/bot<token>/setWebhook?url=<url>/<token>
replacing <token>
with your bot token, and <url>
with the full URL of your app along with the path to the webhook handler.
Congratulations! Your bot should now be up and running.