MiniContent - a mini-app for Telegram, enabling community leaders to create exclusive articles for their audience with Telegram Premium subscriptions.
๐ค Telegram Mini-app
๐ข Telegram Channel with articles examples
MiniContent has tools to help you share and manage your articles on Telegram:
-
๐ Write for Everyone: Make articles for both free and Premium Telegram users.
-
๐จ Rich Formatting: Use easy tools to make your articles look nice.
-
๐ Instant Links: Add links in your articles that open instantly in Telegram.
-
๐ See Views: Check how many people read each article.
With MiniContent, you can make special articles just for people who pay for a Premium subscription on Telegram. What This Means:
- More Boosts: Premium subscribers will want to read what you make and give more boots to your channel.
- Support Telegram: When you offer special articles, more people might want to get a Premium subscription.
- ๐ MiniContent
The motivation of this project is to make it easy for people to build mini-apps for their communities. You can use this repo like a starting step. From here, you can make many great projects.
MiniContent lets you make articles with two parts:
- For Everyone: A part that everyone can read.
- For Premium Users: A part that only people with a Telegram Premium subscription can see.
Here's how you use it:
- Open MiniContent mini-app.
- Click on "Create New Article."
- Write in two separate fields: one for everyone, one for premium users.
- When you're done, click publish. You'll get a link.
- Share this link anywhere on Telegram: in channels, groups, or private chats.
When someone clicks on your article link:
- MiniContent verify a data recived from Telegram and generate a JWT token with user data as a payload.
- The server looks at
user.is_premium
field to see if they have a Premium Telegram subscription. - If they do, they get to see the premium part of your article.
This project is made using one programming language: TypeScript.
- Backend: NestJS - is a framework for building efficient and scalable server-side applications. It uses JavaScript, and it's easy to learn if you know JavaScript.
- Frontend: NextJS - is a popular framework for building web applications. It makes it easy to build both static websites and server-rendered pages. This means your website can load and run very fast, giving visitors a smooth experience.
- Database: MongoDB.
To effectively develop and test your mini-app, it's essential to use the Telegram test server. Here's why:
-
Local Host Testing: The Telegram test server allows you to run your mini-app on localhost, making development more manageable.
-
No HTTPS Requirement: Unlike the production server, the test server doesn't mandate the use of HTTPS. This simplifies the setup and testing process during development.
First you need to create account in Telegram test server using your phone. You can use your phone number. Learn more about Telegram Test Server.
- Fastly tap Settings section 10 times;
- Tap Accounts button;
- Tap Login to another account;
- Tap Test button;
- Create a new account.
- Install Telegram Beta;
- Open Telegram Beta;
- Check "Test server" and create a new account.
Then open Telegram Desktop. Ensure you're using the official Telegram Desktop client.
- Open side menu;
- Expand the menu item, where current username is specified;
- Hold Shift + Alt and press right mouse button on Add Account button;
- Select Test Server;
- Scan the QR code using a phone with an account on the test server (open "Devices" setting in Telegram and click "Link Desktop Device").
- click the Settings icon 10 times to open the Debug Menu
- Hold โ and click โAdd Accountโ
- Scan the QR code using a phone with an account on the test server (open "Devices" setting in Telegram and click "Link Desktop Device").
Open @BotFather in Test Server and create your bot as usual.
Then create an app using /newapp
command using settings like that:
Direct Link: https://t.me/MiniContentBot/view
Description: View
GIF: ๐ซ has no GIF
Web App URL: http://127.0.0.1:3000/auth/view/
Than you need to set a domain to bot:
- Run
/mybots
in BotFather and select your bot - Click Bot Settings -> Domain -> Set Domain
- Send
127.0.0.1
to the BotFather.
Before setting up MiniContent, you must have MongoDB installed on your machine.
Install MongoDB from MongoDB Download Center.
Also, you need to create a user in MongoDB: instruction here.
Clone the project
git clone https://github.com/tonusdev/mini-content.git
Go to the project directory
cd mini-content
Install dependencies for backend
cd backend
npm install
Install dependencies for frontend
cd frontend
npm install
To run this project, you will need to add the following environment variables to your .env
file in backend
folder:
# Settings for the backend server
APP_PORT=3001
APP_ADDRESS=127.0.0.1
# Settings for handling cross-origin requests
CORS_ALLOWED_HEADERS=Content-Type,Authorization
CORS_CREDENTIALS=true
CORS_METHODS=GET,POST,OPTIONS
CORS_ORIGIN=*
# Telegram server setting
# Use Telegram's test server instead of the production one
TELEGRAM_TEST_SERVER=true
# Settings for GraphQL
# Enable GraphQL's Integrated Development Environment (IDE)
GRAPHQL_ENABLE_IDE=true
# Allow introspection of your GraphQL schema
GRAPHQL_ENABLE_INTROSPECTION=true
# MongoDB database connection string
MONGODB_URI=mongodb://<username>:<password>@localhost:27017/minicontent?authSource=admin
# Telegram bot token
BOT_TOKEN=2200244087:** # The token for the Telegram bot
# Settings for JSON Web Tokens (JWT)
JWT_ALGORITHM=HS256 # The algorithm used for JWT
JWT_EXPIRES_IN=1h # How long the JWT will remain valid
JWT_SECRET=secret # The secret key for JWT
# The domain for the backned
DOMAIN=127.0.0.1
# The environment the app is running in (development, production, etc.)
NODE_ENV=development
# The link to the mini-app for bot authentication (Port 3000 is set - this is the port of the NextJS )
BOT_MINIAPP_LINK=http://127.0.0.1:3000/auth/articles
Next, you need to update environment variables in frontend
frolder in .env.development
file:
# Endpoint for graphql requests
NEXT_PUBLIC_GRAPHQL_ENDPOINT=/graphql
# Link to mini app created in BotFather
NEXT_PUBLIC_MINI_APP_LINK=https://t.me/MiniContentBot/view
# Endpoint for the GraphQL server where Next will proxy the requests (it is used in /frontend/next.config.mjs file)
GRAPHQL_SERVER_ENDPOINT=http://localhost:3001/graphql
To run both the frontend and backend services simultaneously, you can use Visual Studio Code's 'Run and Debug' feature or execute them in two separate terminal windows.
Run backend:
cd backend
npm run start:dev
Run frontend:
cd frontend
npm run dev
After starting up, you can type /start
in your bot chat. This will send you a welcome message with a button that launches the mini-app in Telegram.
It is necessary that the frontend and backend work simultaneously for developing api.
- Run Your Bot: Start your bot to access the mini-app.
- Open Debug Mode: This lets you see what's happening in the console.
- Look for a Message: In the console, there's a message saying, Enter this into authenticate mutation in Apollo IDE for development:, followed by some data from Telegram.
- Copy the Data: Highlight and copy the Telegram data.
- Open Apollo IDE: In your web browser, go to http://127.0.0.1:3000/graphql. This is where you can test and develop your GraphQL API.
- Set Up the Mutation: Type in this code:
mutation Mutation($input: AuthenticateInput!) {
authenticate(input: $input)
}
- Add Your Data: On the side, there's a section for "variables." Enter this:
{
"input": {
"initDataRaw": "PASTE YOUR COPIED TELEGRAM DATA HERE"
}
}
- Run It: Click the "Run" or "Mutation" button.
Doing this logs you in and lets you develop your GraphQL API in the Apollo IDE.
With Next.js, you can use the rewrites feature in the configuration. This lets you redirect frontend requests to your backend without running into CORS (Cross-Origin Resource Sharing) errors. Basically, it's a way to make sure your frontend and backend can talk to each other without any problems. You can see this configuration in ./frontend/next.config.mjs
file.
Ngrok is a handy tool that creates a secure tunnel from a public endpoint (like a URL) to a local server on your machine. By using Ngrok's tunnel feature, you can test your mini-app in a production-like environment even when it's running locally. This is especially useful for testing features and integrations that require a live URL.
In short, Ngrok ensures that you can test your mini-app thoroughly before officially deploying it to production.
- Go to ngrok egde dashboard: https://dashboard.ngrok.com/cloud-edge/edges
- Click on "New Edge" button
- Get edge id, like that:
edge=edghts_
- Run on your local machine:
ngrok tunnel --label edge=edghts_****** http://127.0.0.1:3000
- Click "Refresh" in ngrok page and verify that tunnel works
- Copy domain with https, like that
https://********.ngrok.app
- Update backend .env file with domain
- Update bot configs in BotFather with this domain
NestJS provides first-class support for GraphQL, allowing developers to create flexible and strongly-typed APIs quickly. Here's a basic outline of its organization:
- Modules: NestJS promotes a modular architecture. Each feature of the application is split into its module, allowing for a clear separation of concerns. Modules are declared using the @Module() decorator.
- Resolvers: In the GraphQL context, resolvers handle the incoming queries and mutations. They're classes adorned with the @Resolver() decorator. Inside, methods with @Query() handle GraphQL queries, and methods with @Mutation() handle mutations.
- Schema: NestJS with GraphQL often uses a code-first approach, meaning the GraphQL schema is automatically generated from your TypeScript classes (DTOs and Resolvers). However, you can also use a schema-first approach where you define your schema using SDL (Schema Definition Language).
- Providers: Providers can be services, repositories, factories, or any other classes that the system needs to function. They are decorated with @Injectable(), and are responsible for the business logic of your application.
- Middleware: Middleware in NestJS works similarly to Express middleware, allowing you to run specific code before the request reaches the route handler.
- Interceptors: Interceptors have a set of useful capabilities, like transforming the response returned from a method execution or manipulating request objects.
- Guards: Guards determine if a request will be handled by the route handler. They are used mainly for authentication and authorization purposes.
- Decorators: Custom decorators allow you to create annotations for your classes, methods, or method parameters.
- DTOs (Data Transfer Objects): DTOs are used to define the data structure for both incoming and outgoing requests. They can help in validating data using class-validator.
- Models: Represent the data models and their relationships, especially when using ORMs like Mongoose with databases.
Below is an overview of the main components and their responsibilities in our NestJS backend:
- app.config.ts: Contains the application's main configuration.
- app.interceptor.ts: Defines the global interceptor for the app.
- app.module.ts: The root module of the application. This is where core modules are imported.
Handles everything related to articles:
- articles.module.ts: Module for articles-related components.
- articles.resolver.ts: Resolves the GraphQL queries and mutations related to articles.
- articles.service.ts: Service that contains business logic for articles.
- dto: Contains data transfer objects for articles operations:
- entities: Contains the main entity related to articles:
- models: Contains the main model for articles:
Handles authentication:
- auth.decorators.ts: Contains decorators related to authentication.
- auth.guard.ts: Defines the guard for routes requiring authentication.
- auth.module.ts: Module for authentication components.
- auth.resolver.ts: Resolves the GraphQL queries and mutations related to authentication.
- auth.service.ts: Service containing the business logic for authentication.
- auth.utils.ts: Contains utility functions for authentication.
- dto: Contains data transfer object for authentication:
- entities: Contains the main entity related to users:
- models: Contains the main model for users:
- strategies: Contains strategies for authentication:
Handles the Telegram bot interactions:
- bot.module.ts: Module for bot-related components.
- bot.service.ts: Service containing the business logic for the bot.
- bot.update.ts: Contains updates handler for the bot.
This section provides an overview of the main components and their responsibilities in our frontend setup:
-
@types: Contains custom type declarations.
- global.d.ts: Global type definitions.
- gql: GraphQL-related type declarations.
- index.d.ts: Main GraphQL type definitions.
-
Dockerfile: Contains the instructions to containerize the frontend application using Docker.
Handles the primary application logic, structured by localization:
-
[locale]: Locale-specific directory (e.g., 'en', 'ru', 'uk'). Contains localized routes.
-
articles: Handles article-related views.
- layout.tsx: The main layout for the articles section.
- page.tsx: The main page rendering articles.
-
auth: Handles authentication views.
- [...slug]: Dynamic route handling various authentication paths.
- layout.tsx: The main layout for the authentication section.
- page.tsx: The main authentication page.
- [...slug]: Dynamic route handling various authentication paths.
-
edit: Allows editing articles.
- [articleId]: Dynamic route for individual article editing.
- layout.tsx: The layout for the article editing section.
- page.tsx: The main page to edit articles.
- [articleId]: Dynamic route for individual article editing.
-
view: For viewing individual articles.
- [articleId]: Dynamic route to view specific articles.
- layout.tsx: The main layout for viewing an article.
- page.tsx: The page rendering the article content.
- [articleId]: Dynamic route to view specific articles.
-
layout.tsx: The primary layout for the application.
-
page.tsx: The primary page component.
-
providers.tsx: Providers setup for state and context management.
-
-
codegen.ts: Configuration for generating types and operations from GraphQL.
Contains reusable UI components:
- CustomLink.tsx: A custom link component for navigation.
- PublishModal.tsx: Modal component for publishing actions.
- SDKLoader.tsx: Component to load the Telegram SDK.
- SetLinkModal.tsx: Modal component to set article links.
- Tiptap.tsx: Component related to the Tiptap text editor.
Handles the environment-specific configurations:
- client.ts: Client-side environment configuration.
Handles internationalization:
- client.ts: Client-side i18n configurations.
- server.ts: Server-side i18n configurations.
- locales: Contains language-specific translations.
Contains service utilities, often relating to data fetching or business logic:
- graphql: GraphQL client configuration and related utilities.
- client.ts: GraphQL client setup.
- keyFactory.ts: Utility for key generation for React Query.
- useArchiveArticleMutation.ts: Hook for archiving articles.
- useArticleQuery.ts: Hook to fetch a single article.
- useArticlesQuery.ts: Hook to fetch multiple articles.
- useAuthenticateMutation.ts: Hook for user authentication.
- useCreateArticleMutation.ts: Hook to create articles.
- useUpdateArticleMutation.ts: Hook to update articles.
- useUserQuery.ts: Hook to fetch user data.
-
NestJS - is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. With its modular architecture and expressive API, it provides an out-of-the-box application architecture.
-
Mongoose - provides a straight-forward, schema-based solution createing models for MongoDB. It includes built-in type casting, validation, and more, out of the box.
-
Telegraf - is a modern Telegram bot framework for Node.js. It provides a simple and efficient way to handle updates and create Telegram bots.
-
GraphQL - is a query language for your API, and a runtime for executing those queries with your existing data. Instead of multiple endpoints, GraphQL provides a more efficient, powerful, and flexible alternative to REST.
-
nestjs-i18n-telegraf - is a module that provides i18n support for NestJS applications with support of Telegraf
-
NextJS - is a React framework that enables features such as server-side rendering and static site generation. It's designed for building highly scalable and optimized React applications.
-
nextui - offers a collection of high-quality React components, hooks, and themes. With a focus on simplicity and usability, it helps in crafting beautiful interfaces with ease.
-
React Query - is a data-fetching and state management library for React. It automates many repetitive tasks involved in fetching, caching, synchronizing, and updating server-state in your applications, leading to a more efficient data handling process.
-
Tiptap - is a headless and framework-agnostic rich-text editor. It provides the tools to create rich-text editors with a clean JSON output and is highly extensible through its plugin-based architecture.
-
@tma.js/sdk-react - React bindings for the Telegram mini-app client SDK. It includes hooks, components, and other useful tools that enable the use of React alongside the Web Apps client SDK. It automatically tracks changes to SDK components.
-
Tailwind CSS - is a utility-first CSS framework that allows developers to quickly build custom user interfaces. Instead of writing custom CSS classes for each design or component, Tailwind provides a set of utility classes to add directly to your HTML.
-
next-international - is a library for internationalization in Next.js with type-safety.
Deploying the application becomes simple with Docker Compose. It allows us to define and run multi-container Docker applications.
Ensure you have both Docker and Docker Compose installed on your VPS. You can open docker-compose.yaml
file to see deployment configuration.
Steps:
- Clone the repository:
git clone https://github.com/tonusdev/mini-content.git
cd mini-content
- Create one
.env
file with environment variables for backend and frontend both:
MONGODB_USER=admin
MONGODB_PASS=******
MONGODB_DATABASE=minicontent
BOT_TOKEN=58117:******
DOMAIN=domain.dev
JWT_SECRET=secret
BOT_MINIAPP_LINK=https://domain.dev/auth/articles
NEXT_PUBLIC_GRAPHQL_ENDPOINT=/graphql
NEXT_PUBLIC_MINI_APP_LINK=https://t.me/MiniContentBot/view
- Build the Docker images:
docker-compose build
- Run the application:
docker-compose up