[{"data":1,"prerenderedAt":2933},["ShallowReactive",2],{"blog-posts-en":3},[4,357,1088,1607,2268],{"id":5,"title":6,"body":7,"date":340,"description":341,"extension":342,"meta":343,"navigation":344,"path":345,"readTime":346,"seo":347,"slug":348,"stem":349,"tags":350,"__hash__":356},"blogEn\u002Fen\u002Fblog\u002Fbusiness-automation-telegram.md","Business Automation with Telegram — What Actually Saves Time and Money",{"type":8,"value":9,"toc":322},"minimark",[10,15,19,24,27,34,40,46,49,53,58,61,72,78,82,85,90,94,97,103,107,110,126,129,133,147,150,154,157,162,166,169,171,175,253,255,259,262,268,271,273,277,304,306,310,313],[11,12,14],"h1",{"id":13},"business-automation-with-telegram-what-actually-works","Business Automation with Telegram — What Actually Works",[16,17,18],"p",{},"Telegram stopped being just a messenger a long time ago. For small and medium businesses it's a full platform: lead intake, customer support, internal tools, notifications, mini-apps. This article covers what to automate first and what it costs.",[20,21,23],"h2",{"id":22},"why-telegram-vs-a-website-or-app","Why Telegram vs a Website or App",[16,25,26],{},"Three simple reasons:",[16,28,29,33],{},[30,31,32],"strong",{},"1. Your audience is already there."," Telegram has 900M+ active users worldwide. Clients don't need to download anything extra.",[16,35,36,39],{},[30,37,38],{},"2. Launch speed."," A Telegram bot launches in 1–3 days. A mobile app — from a month.",[16,41,42,45],{},[30,43,44],{},"3. Cost."," A simple bot costs $40–100. A mobile app — from $500.",[47,48],"hr",{},[20,50,52],{"id":51},"top-7-processes-to-automate","Top 7 Processes to Automate",[54,55,57],"h3",{"id":56},"_1-lead-intake-and-booking","1. Lead Intake and Booking",[16,59,60],{},"A bot collects name, contact, and task description — then immediately notifies you or pushes to your CRM. No missed messages, no \"I replied in another chat.\"",[62,63,68],"pre",{"className":64,"code":66,"language":67},[65],"language-text","Client: \u002Fstart\nBot: Hi! What's your name?\nClient: Alex\nBot: Describe your project\nClient: I need a website...\nBot: ✅ Request received! Alex, we'll reply within 2 hours.\n→ [You get a notification with the client's details]\n","text",[69,70,66],"code",{"__ignoreMap":71},"",[16,73,74,77],{},[30,75,76],{},"Savings:"," no manager time spent manually collecting data. At 20 leads\u002Fday — that's 1–2 hours daily.",[54,79,81],{"id":80},"_2-faq-and-customer-support","2. FAQ and Customer Support",[16,83,84],{},"80% of support questions repeat: \"how do I pay\", \"where's my order\", \"what are the timelines\". The bot answers instantly, complex questions get routed to a human.",[16,86,87,89],{},[30,88,76],{}," 1 support agent instead of 3 at the same volume.",[54,91,93],{"id":92},"_3-online-shop-with-auto-delivery","3. Online Shop with Auto-delivery",[16,95,96],{},"Selling digital products: keys, access codes, files. Payment via Telegram Stars or crypto — product is delivered automatically with zero human involvement.",[16,98,99,102],{},[30,100,101],{},"Real case:"," a shop with 200+ SKUs, 50–100 sales per day — fully automatic.",[54,104,106],{"id":105},"_4-notifications-and-monitoring","4. Notifications and Monitoring",[16,108,109],{},"A bot reports to your team:",[111,112,113,117,120,123],"ul",{},[114,115,116],"li",{},"New order on the website",[114,118,119],{},"Server down \u002F recovered",[114,121,122],{},"New review on a marketplace",[114,124,125],{},"Sales anomaly",[16,127,128],{},"Integrates with any system via webhook in 2–4 hours of work.",[54,130,132],{"id":131},"_5-internal-team-tools","5. Internal Team Tools",[111,134,135,138,141,144],{},[114,136,137],{},"Daily\u002Fweekly revenue reports",[114,139,140],{},"Task assignments to team members",[114,142,143],{},"Polls and surveys",[114,145,146],{},"Searchable knowledge base",[16,148,149],{},"Especially useful for remote teams — everything in one place.",[54,151,153],{"id":152},"_6-scheduling-and-appointments","6. Scheduling and Appointments",[16,155,156],{},"Clients see available slots, pick a time, get a confirmation. The bot sends a reminder the day before. Works for: barbers, fitness trainers, doctors, tutors.",[16,158,159,161],{},[30,160,76],{}," 30–60 minutes of admin time per day on booking management.",[54,163,165],{"id":164},"_7-telegram-mini-app","7. Telegram Mini App",[16,167,168],{},"A full app inside Telegram — with a nice UI, auth, cart, and payments. Users open it with one button, no installation needed.",[47,170],{},[20,172,174],{"id":173},"how-much-does-automation-cost","How Much Does Automation Cost",[176,177,178,194],"table",{},[179,180,181],"thead",{},[182,183,184,188,191],"tr",{},[185,186,187],"th",{},"Bot type",[185,189,190],{},"What's included",[185,192,193],{},"Price",[195,196,197,209,220,231,242],"tbody",{},[182,198,199,203,206],{},[200,201,202],"td",{},"Simple FAQ",[200,204,205],{},"Commands, canned answers",[200,207,208],{},"$40–80",[182,210,211,214,217],{},[200,212,213],{},"Lead intake bot",[200,215,216],{},"FSM dialog, notify you",[200,218,219],{},"$80–150",[182,221,222,225,228],{},[200,223,224],{},"Shop with payments",[200,226,227],{},"Catalog, Stars\u002Fcrypto, auto-delivery",[200,229,230],{},"$150–300",[182,232,233,236,239],{},[200,234,235],{},"Mini App",[200,237,238],{},"Web UI, API, database",[200,240,241],{},"$300–700",[182,243,244,247,250],{},[200,245,246],{},"AI assistant",[200,248,249],{},"GPT, RAG, conversation history",[200,251,252],{},"$200–500",[47,254],{},[20,256,258],{"id":257},"when-does-automation-pay-back","When Does Automation Pay Back",[16,260,261],{},"Simple math. Say a manager spends 2 hours a day on routine: answering the same questions, manually entering leads, generating reports.",[62,263,266],{"className":264,"code":265,"language":67},[65],"Hourly rate: $10\u002Fhr\n2 hours\u002Fday × 22 working days = 44 hours\u002Fmonth\n44 × $10 = $440\u002Fmonth\n\nBot cost: $150 (one-time)\n→ Payback: \u003C 2 weeks\n",[69,267,265],{"__ignoreMap":71},[16,269,270],{},"This is conservative. In practice automation gives more: fewer errors, 24\u002F7 operation, scalability without hiring.",[47,272],{},[20,274,276],{"id":275},"how-to-start","How to Start",[278,279,280,286,292,298],"ol",{},[114,281,282,285],{},[30,283,284],{},"Find the most painful process"," — where you lose the most time or clients",[114,287,288,291],{},[30,289,290],{},"Describe the task"," — what should the bot do, who uses it",[114,293,294,297],{},[30,295,296],{},"Start simple"," — an MVP bot at $50–100 that solves one specific problem",[114,299,300,303],{},[30,301,302],{},"Scale"," — add features as you grow",[47,305],{},[20,307,309],{"id":308},"conclusion","Conclusion",[16,311,312],{},"Telegram automation is one of the best ROI plays in IT for small business. Low barrier to entry, fast results, a familiar tool for clients.",[16,314,315,316,321],{},"Want to automate a specific process? ",[317,318,320],"a",{"href":319},"\u002Fen#contact","Tell me about it"," — let's figure out what and how.",{"title":71,"searchDepth":323,"depth":323,"links":324},2,[325,326,336,337,338,339],{"id":22,"depth":323,"text":23},{"id":51,"depth":323,"text":52,"children":327},[328,330,331,332,333,334,335],{"id":56,"depth":329,"text":57},3,{"id":80,"depth":329,"text":81},{"id":92,"depth":329,"text":93},{"id":105,"depth":329,"text":106},{"id":131,"depth":329,"text":132},{"id":152,"depth":329,"text":153},{"id":164,"depth":329,"text":165},{"id":173,"depth":323,"text":174},{"id":257,"depth":323,"text":258},{"id":275,"depth":323,"text":276},{"id":308,"depth":323,"text":309},"2025-01-10","Which business processes to automate via Telegram first, how much it costs and when it pays back. Real cases and numbers.","md",{},true,"\u002Fen\u002Fblog\u002Fbusiness-automation-telegram","8 min",{"title":6,"description":341},"business-automation-telegram","en\u002Fblog\u002Fbusiness-automation-telegram",[351,352,353,354,355],"Automation","Telegram","Business","Python","Bots","t9N2YHYfiSd2h0Wf7X-8uQnOxtCmYO-qwNcRSEPk6-A",{"id":358,"title":359,"body":360,"date":1076,"description":1077,"extension":342,"meta":1078,"navigation":344,"path":1079,"readTime":1080,"seo":1081,"slug":1082,"stem":1083,"tags":1084,"__hash__":1087},"blogEn\u002Fen\u002Fblog\u002Fchatgpt-for-business.md","Integrating ChatGPT into Your Business — A Practical 2024 Guide",{"type":8,"value":361,"toc":1057},[362,366,369,373,376,380,387,391,394,398,405,409,412,414,418,421,637,648,650,654,657,663,667,820,822,826,830,901,905,925,927,931,937,945,951,957,959,963,1015,1017,1019,1022,1039,1046,1053],[11,363,365],{"id":364},"integrating-chatgpt-into-business-how-it-actually-works","Integrating ChatGPT into Business — How It Actually Works",[16,367,368],{},"\"We need ChatGPT\" — one of the most common requests from clients over the past year. But behind this request is usually something specific: automate support, process leads, or build a smart assistant. In this article I'll break down how it's actually done — with code examples and real numbers.",[20,370,372],{"id":371},"what-can-actually-be-automated-with-ai","What Can Actually Be Automated with AI",[16,374,375],{},"Not everything. Here's where AI genuinely pays off:",[54,377,379],{"id":378},"_1-customer-support","1. Customer Support",[16,381,382,383,386],{},"A bot answers typical questions 24\u002F7. ",[30,384,385],{},"60–80% of support requests are repetitive",". AI handles them instantly, complex ones get passed to a human operator.",[54,388,390],{"id":389},"_2-lead-processing-and-qualification","2. Lead Processing and Qualification",[16,392,393],{},"A bot asks clarifying questions, collects data, evaluates the lead's potential — and passes a pre-filled card to your CRM.",[54,395,397],{"id":396},"_3-search-across-internal-documents","3. Search Across Internal Documents",[16,399,400,401,404],{},"An employee asks a question in natural language, AI finds the answer in company policies, contracts, and manuals. This is called ",[30,402,403],{},"RAG (Retrieval-Augmented Generation)",".",[54,406,408],{"id":407},"_4-text-generation-and-processing","4. Text Generation and Processing",[16,410,411],{},"Writing review responses, product descriptions, meeting summaries, document translation.",[47,413],{},[20,415,417],{"id":416},"telegram-bot-with-chatgpt-basic-implementation","Telegram Bot with ChatGPT: Basic Implementation",[16,419,420],{},"The fastest way to give employees or clients access to AI is a Telegram bot. Here's a minimal working version:",[62,422,426],{"className":423,"code":424,"language":425,"meta":71,"style":71},"language-python shiki shiki-themes github-light github-dark","import asyncio\nfrom aiogram import Bot, Dispatcher, types\nfrom aiogram.filters import CommandStart\nfrom openai import AsyncOpenAI\n\nbot = Bot(token=\"YOUR_BOT_TOKEN\")\ndp = Dispatcher()\nopenai = AsyncOpenAI(api_key=\"YOUR_OPENAI_KEY\")\n\nSYSTEM_PROMPT = \"\"\"You are an assistant for [Company Name].\nAnswer questions about our services, pricing and terms.\nIf you don't know the answer — suggest contacting a manager.\"\"\"\n\n@dp.message(CommandStart())\nasync def start(message: types.Message):\n    await message.answer(\"Hi! How can I help you?\")\n\n@dp.message()\nasync def handle_message(message: types.Message):\n    thinking = await message.answer(\"⏳ Thinking...\")\n\n    response = await openai.chat.completions.create(\n        model=\"gpt-4o-mini\",  # cheaper but smart\n        messages=[\n            {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n            {\"role\": \"user\",   \"content\": message.text},\n        ],\n        max_tokens=500,\n    )\n\n    await thinking.edit_text(response.choices[0].message.content)\n\nasync def main():\n    await dp.start_polling(bot)\n\nasyncio.run(main())\n","python",[69,427,428,436,441,446,452,458,464,470,476,481,487,493,499,504,510,516,522,527,533,539,545,550,556,562,568,574,580,586,592,598,603,609,614,620,626,631],{"__ignoreMap":71},[429,430,433],"span",{"class":431,"line":432},"line",1,[429,434,435],{},"import asyncio\n",[429,437,438],{"class":431,"line":323},[429,439,440],{},"from aiogram import Bot, Dispatcher, types\n",[429,442,443],{"class":431,"line":329},[429,444,445],{},"from aiogram.filters import CommandStart\n",[429,447,449],{"class":431,"line":448},4,[429,450,451],{},"from openai import AsyncOpenAI\n",[429,453,455],{"class":431,"line":454},5,[429,456,457],{"emptyLinePlaceholder":344},"\n",[429,459,461],{"class":431,"line":460},6,[429,462,463],{},"bot = Bot(token=\"YOUR_BOT_TOKEN\")\n",[429,465,467],{"class":431,"line":466},7,[429,468,469],{},"dp = Dispatcher()\n",[429,471,473],{"class":431,"line":472},8,[429,474,475],{},"openai = AsyncOpenAI(api_key=\"YOUR_OPENAI_KEY\")\n",[429,477,479],{"class":431,"line":478},9,[429,480,457],{"emptyLinePlaceholder":344},[429,482,484],{"class":431,"line":483},10,[429,485,486],{},"SYSTEM_PROMPT = \"\"\"You are an assistant for [Company Name].\n",[429,488,490],{"class":431,"line":489},11,[429,491,492],{},"Answer questions about our services, pricing and terms.\n",[429,494,496],{"class":431,"line":495},12,[429,497,498],{},"If you don't know the answer — suggest contacting a manager.\"\"\"\n",[429,500,502],{"class":431,"line":501},13,[429,503,457],{"emptyLinePlaceholder":344},[429,505,507],{"class":431,"line":506},14,[429,508,509],{},"@dp.message(CommandStart())\n",[429,511,513],{"class":431,"line":512},15,[429,514,515],{},"async def start(message: types.Message):\n",[429,517,519],{"class":431,"line":518},16,[429,520,521],{},"    await message.answer(\"Hi! How can I help you?\")\n",[429,523,525],{"class":431,"line":524},17,[429,526,457],{"emptyLinePlaceholder":344},[429,528,530],{"class":431,"line":529},18,[429,531,532],{},"@dp.message()\n",[429,534,536],{"class":431,"line":535},19,[429,537,538],{},"async def handle_message(message: types.Message):\n",[429,540,542],{"class":431,"line":541},20,[429,543,544],{},"    thinking = await message.answer(\"⏳ Thinking...\")\n",[429,546,548],{"class":431,"line":547},21,[429,549,457],{"emptyLinePlaceholder":344},[429,551,553],{"class":431,"line":552},22,[429,554,555],{},"    response = await openai.chat.completions.create(\n",[429,557,559],{"class":431,"line":558},23,[429,560,561],{},"        model=\"gpt-4o-mini\",  # cheaper but smart\n",[429,563,565],{"class":431,"line":564},24,[429,566,567],{},"        messages=[\n",[429,569,571],{"class":431,"line":570},25,[429,572,573],{},"            {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n",[429,575,577],{"class":431,"line":576},26,[429,578,579],{},"            {\"role\": \"user\",   \"content\": message.text},\n",[429,581,583],{"class":431,"line":582},27,[429,584,585],{},"        ],\n",[429,587,589],{"class":431,"line":588},28,[429,590,591],{},"        max_tokens=500,\n",[429,593,595],{"class":431,"line":594},29,[429,596,597],{},"    )\n",[429,599,601],{"class":431,"line":600},30,[429,602,457],{"emptyLinePlaceholder":344},[429,604,606],{"class":431,"line":605},31,[429,607,608],{},"    await thinking.edit_text(response.choices[0].message.content)\n",[429,610,612],{"class":431,"line":611},32,[429,613,457],{"emptyLinePlaceholder":344},[429,615,617],{"class":431,"line":616},33,[429,618,619],{},"async def main():\n",[429,621,623],{"class":431,"line":622},34,[429,624,625],{},"    await dp.start_polling(bot)\n",[429,627,629],{"class":431,"line":628},35,[429,630,457],{"emptyLinePlaceholder":344},[429,632,634],{"class":431,"line":633},36,[429,635,636],{},"asyncio.run(main())\n",[16,638,639,640,643,644,647],{},"This is working code. The cost of such a bot at 1,000 messages per day — ",[30,641,642],{},"about $2–5 per month"," in tokens (using ",[69,645,646],{},"gpt-4o-mini",").",[47,649],{},[20,651,653],{"id":652},"rag-ai-that-knows-your-documents","RAG: AI That Knows Your Documents",[16,655,656],{},"The problem with standard ChatGPT — it doesn't know your business specifics. RAG solves this: documents are indexed into a vector database, and with each request, relevant context is found and passed to the model.",[62,658,661],{"className":659,"code":660,"language":67},[65],"User → Question\n      ↓\nVector search across documents (Qdrant\u002FChroma)\n      ↓\nFound fragments + question → GPT\n      ↓\nAnswer with source reference\n",[69,662,660],{"__ignoreMap":71},[54,664,666],{"id":665},"example-corporate-policy-assistant","Example: Corporate Policy Assistant",[62,668,670],{"className":423,"code":669,"language":425,"meta":71,"style":71},"from qdrant_client import QdrantClient\nfrom openai import AsyncOpenAI\n\nclient = QdrantClient(\":memory:\")\nopenai = AsyncOpenAI()\n\nasync def answer_with_context(question: str) -> str:\n    # 1. Get question embedding\n    embedding = await openai.embeddings.create(\n        model=\"text-embedding-3-small\",\n        input=question,\n    )\n\n    # 2. Search similar documents\n    results = client.search(\n        collection_name=\"docs\",\n        query_vector=embedding.data[0].embedding,\n        limit=3,\n    )\n\n    # 3. Build context\n    context = \"\\n\\n\".join([r.payload[\"text\"] for r in results])\n\n    # 4. Ask GPT\n    response = await openai.chat.completions.create(\n        model=\"gpt-4o-mini\",\n        messages=[\n            {\"role\": \"system\", \"content\": f\"Context from documents:\\n{context}\"},\n            {\"role\": \"user\",   \"content\": question},\n        ],\n    )\n    return response.choices[0].message.content\n",[69,671,672,677,681,685,690,695,699,704,709,714,719,724,728,732,737,742,747,752,757,761,765,770,775,779,784,788,793,797,802,807,811,815],{"__ignoreMap":71},[429,673,674],{"class":431,"line":432},[429,675,676],{},"from qdrant_client import QdrantClient\n",[429,678,679],{"class":431,"line":323},[429,680,451],{},[429,682,683],{"class":431,"line":329},[429,684,457],{"emptyLinePlaceholder":344},[429,686,687],{"class":431,"line":448},[429,688,689],{},"client = QdrantClient(\":memory:\")\n",[429,691,692],{"class":431,"line":454},[429,693,694],{},"openai = AsyncOpenAI()\n",[429,696,697],{"class":431,"line":460},[429,698,457],{"emptyLinePlaceholder":344},[429,700,701],{"class":431,"line":466},[429,702,703],{},"async def answer_with_context(question: str) -> str:\n",[429,705,706],{"class":431,"line":472},[429,707,708],{},"    # 1. Get question embedding\n",[429,710,711],{"class":431,"line":478},[429,712,713],{},"    embedding = await openai.embeddings.create(\n",[429,715,716],{"class":431,"line":483},[429,717,718],{},"        model=\"text-embedding-3-small\",\n",[429,720,721],{"class":431,"line":489},[429,722,723],{},"        input=question,\n",[429,725,726],{"class":431,"line":495},[429,727,597],{},[429,729,730],{"class":431,"line":501},[429,731,457],{"emptyLinePlaceholder":344},[429,733,734],{"class":431,"line":506},[429,735,736],{},"    # 2. Search similar documents\n",[429,738,739],{"class":431,"line":512},[429,740,741],{},"    results = client.search(\n",[429,743,744],{"class":431,"line":518},[429,745,746],{},"        collection_name=\"docs\",\n",[429,748,749],{"class":431,"line":524},[429,750,751],{},"        query_vector=embedding.data[0].embedding,\n",[429,753,754],{"class":431,"line":529},[429,755,756],{},"        limit=3,\n",[429,758,759],{"class":431,"line":535},[429,760,597],{},[429,762,763],{"class":431,"line":541},[429,764,457],{"emptyLinePlaceholder":344},[429,766,767],{"class":431,"line":547},[429,768,769],{},"    # 3. Build context\n",[429,771,772],{"class":431,"line":552},[429,773,774],{},"    context = \"\\n\\n\".join([r.payload[\"text\"] for r in results])\n",[429,776,777],{"class":431,"line":558},[429,778,457],{"emptyLinePlaceholder":344},[429,780,781],{"class":431,"line":564},[429,782,783],{},"    # 4. Ask GPT\n",[429,785,786],{"class":431,"line":570},[429,787,555],{},[429,789,790],{"class":431,"line":576},[429,791,792],{},"        model=\"gpt-4o-mini\",\n",[429,794,795],{"class":431,"line":582},[429,796,567],{},[429,798,799],{"class":431,"line":588},[429,800,801],{},"            {\"role\": \"system\", \"content\": f\"Context from documents:\\n{context}\"},\n",[429,803,804],{"class":431,"line":594},[429,805,806],{},"            {\"role\": \"user\",   \"content\": question},\n",[429,808,809],{"class":431,"line":600},[429,810,585],{},[429,812,813],{"class":431,"line":605},[429,814,597],{},[429,816,817],{"class":431,"line":611},[429,818,819],{},"    return response.choices[0].message.content\n",[47,821],{},[20,823,825],{"id":824},"how-much-does-ai-integration-cost","How Much Does AI Integration Cost",[54,827,829],{"id":828},"token-costs-monthly","Token costs (monthly)",[176,831,832,848],{},[179,833,834],{},[182,835,836,839,842,845],{},[185,837,838],{},"Scenario",[185,840,841],{},"Model",[185,843,844],{},"~Messages\u002Fday",[185,846,847],{},"Cost\u002Fmonth",[195,849,850,863,876,889],{},[182,851,852,855,857,860],{},[200,853,854],{},"Light FAQ bot",[200,856,646],{},[200,858,859],{},"500",[200,861,862],{},"$1–3",[182,864,865,868,870,873],{},[200,866,867],{},"Medium assistant",[200,869,646],{},[200,871,872],{},"2000",[200,874,875],{},"$5–15",[182,877,878,881,884,886],{},[200,879,880],{},"RAG over documents",[200,882,883],{},"gpt-4o",[200,885,859],{},[200,887,888],{},"$10–30",[182,890,891,894,896,898],{},[200,892,893],{},"Heavy agent",[200,895,883],{},[200,897,872],{},[200,899,900],{},"$50–150",[54,902,904],{"id":903},"development-cost","Development cost",[111,906,907,913,919],{},[114,908,909,910],{},"Simple Telegram bot with GPT — ",[30,911,912],{},"from $80",[114,914,915,916],{},"RAG on your documents — ",[30,917,918],{},"from $200",[114,920,921,922],{},"Full AI assistant with history, roles, analytics — ",[30,923,924],{},"from $500",[47,926],{},[20,928,930],{"id":929},"common-mistakes-when-integrating-ai","Common Mistakes When Integrating AI",[16,932,933,936],{},[30,934,935],{},"1. Expecting AI to know everything","\nGPT doesn't know your price list, products, or policies. You need either a good system prompt or RAG.",[16,938,939,942,944],{},[30,940,941],{},"2. Using GPT-4 when mini is enough",[69,943,646],{}," is 15x cheaper, and for most tasks — it's sufficient.",[16,946,947,950],{},[30,948,949],{},"3. Not limiting the scope of answers","\nWithout restrictions, the bot can answer anything. The system prompt must clearly define the role and boundaries.",[16,952,953,956],{},[30,954,955],{},"4. Ignoring conversation context","\nUsers send multiple messages. Store conversation history and pass it to the API.",[47,958],{},[20,960,962],{"id":961},"which-ai-models-to-use-in-2024","Which AI Models to Use in 2024",[176,964,965,975],{},[179,966,967],{},[182,968,969,972],{},[185,970,971],{},"Task",[185,973,974],{},"Best choice",[195,976,977,984,991,999,1007],{},[182,978,979,982],{},[200,980,981],{},"Mass FAQ bot",[200,983,646],{},[182,985,986,989],{},[200,987,988],{},"Complex analysis, code",[200,990,883],{},[182,992,993,996],{},[200,994,995],{},"Long documents",[200,997,998],{},"Claude 3.5 Sonnet",[182,1000,1001,1004],{},[200,1002,1003],{},"Fast responses",[200,1005,1006],{},"Gemini Flash",[182,1008,1009,1012],{},[200,1010,1011],{},"Multilingual support",[200,1013,1014],{},"GPT or Claude (best)",[47,1016],{},[20,1018,309],{"id":308},[16,1020,1021],{},"AI integration isn't about \"installing ChatGPT.\" It's:",[278,1023,1024,1027,1030,1033,1036],{},[114,1025,1026],{},"Understanding what process to automate",[114,1028,1029],{},"Choosing the right model",[114,1031,1032],{},"Writing a proper system prompt",[114,1034,1035],{},"Adding RAG if needed",[114,1037,1038],{},"Wrapping it in a convenient interface (Telegram, website, API)",[16,1040,1041,1042,1045],{},"Most projects pay back in ",[30,1043,1044],{},"1–3 months"," through saved working time.",[16,1047,1048,1049,1052],{},"Want to integrate AI into your business or product? ",[317,1050,1051],{"href":319},"Get in touch"," — let's figure out the task together.",[1054,1055,1056],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":71,"searchDepth":323,"depth":323,"links":1058},[1059,1065,1066,1069,1073,1074,1075],{"id":371,"depth":323,"text":372,"children":1060},[1061,1062,1063,1064],{"id":378,"depth":329,"text":379},{"id":389,"depth":329,"text":390},{"id":396,"depth":329,"text":397},{"id":407,"depth":329,"text":408},{"id":416,"depth":323,"text":417},{"id":652,"depth":323,"text":653,"children":1067},[1068],{"id":665,"depth":329,"text":666},{"id":824,"depth":323,"text":825,"children":1070},[1071,1072],{"id":828,"depth":329,"text":829},{"id":903,"depth":329,"text":904},{"id":929,"depth":323,"text":930},{"id":961,"depth":323,"text":962},{"id":308,"depth":323,"text":309},"2024-12-20","How to actually integrate ChatGPT and other AI models into business processes: Telegram bots with GPT, support automation, RAG on your own data. Real examples and costs.",{},"\u002Fen\u002Fblog\u002Fchatgpt-for-business","11 min",{"title":359,"description":1077},"chatgpt-for-business","en\u002Fblog\u002Fchatgpt-for-business",[1085,1086,351,354,353],"AI","ChatGPT","ydiSTBQzJLtox1McOqeU84mYlglAocPdakqfm0q64UU",{"id":1089,"title":1090,"body":1091,"date":1595,"description":1596,"extension":342,"meta":1597,"navigation":344,"path":1598,"readTime":1599,"seo":1600,"slug":1601,"stem":1602,"tags":1603,"__hash__":1606},"blogEn\u002Fen\u002Fblog\u002Ffastapi-vs-django-2024.md","FastAPI vs Django in 2024 — Which One Should You Choose",{"type":8,"value":1092,"toc":1585},[1093,1097,1104,1108,1114,1120,1124,1131,1161,1164,1189,1195,1199,1290,1294,1319,1372,1376,1400,1472,1476,1482,1499,1505,1509,1512,1518,1521,1525,1575,1578,1583],[11,1094,1096],{"id":1095},"fastapi-vs-django-in-2024","FastAPI vs Django in 2024",[16,1098,1099,1100,1103],{},"One of the most common questions from clients: ",[30,1101,1102],{},"\"Should I use FastAPI or Django for the backend?\""," The answer depends on the project, and in this article I'll compare both frameworks honestly.",[20,1105,1107],{"id":1106},"quick-overview","Quick Overview",[16,1109,1110,1113],{},[30,1111,1112],{},"Django"," — \"batteries included\". Created in 2005, battle-tested. ORM, admin panel, auth, forms — all out of the box.",[16,1115,1116,1119],{},[30,1117,1118],{},"FastAPI"," — a modern async framework. Created in 2018. Maximum API development speed, auto-documentation, full typing support.",[20,1121,1123],{"id":1122},"performance","Performance",[16,1125,1126,1127,1130],{},"FastAPI is built on ",[30,1128,1129],{},"Starlette + Pydantic",", fully asynchronous:",[62,1132,1134],{"className":423,"code":1133,"language":425,"meta":71,"style":71},"# FastAPI — async endpoint\n@app.get(\"\u002Fusers\u002F{user_id}\")\nasync def get_user(user_id: int, db: AsyncSession = Depends(get_db)):\n    user = await db.get(User, user_id)\n    return user\n",[69,1135,1136,1141,1146,1151,1156],{"__ignoreMap":71},[429,1137,1138],{"class":431,"line":432},[429,1139,1140],{},"# FastAPI — async endpoint\n",[429,1142,1143],{"class":431,"line":323},[429,1144,1145],{},"@app.get(\"\u002Fusers\u002F{user_id}\")\n",[429,1147,1148],{"class":431,"line":329},[429,1149,1150],{},"async def get_user(user_id: int, db: AsyncSession = Depends(get_db)):\n",[429,1152,1153],{"class":431,"line":448},[429,1154,1155],{},"    user = await db.get(User, user_id)\n",[429,1157,1158],{"class":431,"line":454},[429,1159,1160],{},"    return user\n",[16,1162,1163],{},"Django is traditionally synchronous, but native async was added in Django 4.1+:",[62,1165,1167],{"className":423,"code":1166,"language":425,"meta":71,"style":71},"# Django — async view\nasync def get_user(request, user_id):\n    user = await User.objects.aget(id=user_id)\n    return JsonResponse({\"name\": user.name})\n",[69,1168,1169,1174,1179,1184],{"__ignoreMap":71},[429,1170,1171],{"class":431,"line":432},[429,1172,1173],{},"# Django — async view\n",[429,1175,1176],{"class":431,"line":323},[429,1177,1178],{},"async def get_user(request, user_id):\n",[429,1180,1181],{"class":431,"line":329},[429,1182,1183],{},"    user = await User.objects.aget(id=user_id)\n",[429,1185,1186],{"class":431,"line":448},[429,1187,1188],{},"    return JsonResponse({\"name\": user.name})\n",[16,1190,1191,1194],{},[30,1192,1193],{},"Benchmarks:"," FastAPI handles ~50,000 req\u002Fs, Django ~5,000 req\u002Fs under the same conditions. But for most projects this difference doesn't matter.",[20,1196,1198],{"id":1197},"out-of-the-box-features","Out-of-the-box Features",[176,1200,1201,1212],{},[179,1202,1203],{},[182,1204,1205,1208,1210],{},[185,1206,1207],{},"Feature",[185,1209,1112],{},[185,1211,1118],{},[195,1213,1214,1225,1236,1246,1257,1268,1279],{},[182,1215,1216,1219,1222],{},[200,1217,1218],{},"ORM",[200,1220,1221],{},"✅ built-in",[200,1223,1224],{},"❌ needs SQLAlchemy",[182,1226,1227,1230,1233],{},[200,1228,1229],{},"Admin panel",[200,1231,1232],{},"✅",[200,1234,1235],{},"❌ needs third-party",[182,1237,1238,1241,1243],{},[200,1239,1240],{},"Auth & sessions",[200,1242,1232],{},[200,1244,1245],{},"❌ needs fastapi-users",[182,1247,1248,1251,1254],{},[200,1249,1250],{},"Swagger \u002F ReDoc",[200,1252,1253],{},"❌",[200,1255,1256],{},"✅ automatic",[182,1258,1259,1262,1265],{},[200,1260,1261],{},"WebSockets",[200,1263,1264],{},"partial",[200,1266,1267],{},"✅ native",[182,1269,1270,1273,1276],{},[200,1271,1272],{},"Validation",[200,1274,1275],{},"forms\u002Fserializers",[200,1277,1278],{},"✅ Pydantic",[182,1280,1281,1284,1287],{},[200,1282,1283],{},"Type safety",[200,1285,1286],{},"basic",[200,1288,1289],{},"✅ excellent",[20,1291,1293],{"id":1292},"when-to-choose-django","When to Choose Django",[111,1295,1296,1303,1310,1313],{},[114,1297,1298,1299,1302],{},"Need a quick ",[30,1300,1301],{},"admin panel"," (models → CRUD in 5 minutes)",[114,1304,1305,1306,1309],{},"Standard ",[30,1307,1308],{},"website"," with templates",[114,1311,1312],{},"Team already knows Django",[114,1314,1315,1318],{},[30,1316,1317],{},"Monolith"," with auth, profiles, content management",[62,1320,1322],{"className":423,"code":1321,"language":425,"meta":71,"style":71},"# Django — 5 lines and you have a full CRUD admin\nfrom django.db import models\n\nclass Article(models.Model):\n    title   = models.CharField(max_length=200)\n    content = models.TextField()\n    created = models.DateTimeField(auto_now_add=True)\n\n    class Meta:\n        ordering = [\"-created\"]\n",[69,1323,1324,1329,1334,1338,1343,1348,1353,1358,1362,1367],{"__ignoreMap":71},[429,1325,1326],{"class":431,"line":432},[429,1327,1328],{},"# Django — 5 lines and you have a full CRUD admin\n",[429,1330,1331],{"class":431,"line":323},[429,1332,1333],{},"from django.db import models\n",[429,1335,1336],{"class":431,"line":329},[429,1337,457],{"emptyLinePlaceholder":344},[429,1339,1340],{"class":431,"line":448},[429,1341,1342],{},"class Article(models.Model):\n",[429,1344,1345],{"class":431,"line":454},[429,1346,1347],{},"    title   = models.CharField(max_length=200)\n",[429,1349,1350],{"class":431,"line":460},[429,1351,1352],{},"    content = models.TextField()\n",[429,1354,1355],{"class":431,"line":466},[429,1356,1357],{},"    created = models.DateTimeField(auto_now_add=True)\n",[429,1359,1360],{"class":431,"line":472},[429,1361,457],{"emptyLinePlaceholder":344},[429,1363,1364],{"class":431,"line":478},[429,1365,1366],{},"    class Meta:\n",[429,1368,1369],{"class":431,"line":483},[429,1370,1371],{},"        ordering = [\"-created\"]\n",[20,1373,1375],{"id":1374},"when-to-choose-fastapi","When to Choose FastAPI",[111,1377,1378,1384,1387,1394,1397],{},[114,1379,1380,1381],{},"Pure ",[30,1382,1383],{},"REST \u002F GraphQL API",[114,1385,1386],{},"Microservice architecture",[114,1388,1389,1390,1393],{},"Need ",[30,1391,1392],{},"auto-documentation"," out of the box",[114,1395,1396],{},"High performance requirements",[114,1398,1399],{},"AI\u002FML services (great integration with Python ecosystem)",[62,1401,1403],{"className":423,"code":1402,"language":425,"meta":71,"style":71},"# FastAPI — typing, validation, documentation automatically\nfrom pydantic import BaseModel, EmailStr\n\nclass UserCreate(BaseModel):\n    email: EmailStr\n    name: str\n    age: int | None = None\n\n@app.post(\"\u002Fusers\", response_model=UserResponse, status_code=201)\nasync def create_user(payload: UserCreate, db: AsyncSession = Depends(get_db)):\n    user = User(**payload.model_dump())\n    db.add(user)\n    await db.commit()\n    return user\n",[69,1404,1405,1410,1415,1419,1424,1429,1434,1439,1443,1448,1453,1458,1463,1468],{"__ignoreMap":71},[429,1406,1407],{"class":431,"line":432},[429,1408,1409],{},"# FastAPI — typing, validation, documentation automatically\n",[429,1411,1412],{"class":431,"line":323},[429,1413,1414],{},"from pydantic import BaseModel, EmailStr\n",[429,1416,1417],{"class":431,"line":329},[429,1418,457],{"emptyLinePlaceholder":344},[429,1420,1421],{"class":431,"line":448},[429,1422,1423],{},"class UserCreate(BaseModel):\n",[429,1425,1426],{"class":431,"line":454},[429,1427,1428],{},"    email: EmailStr\n",[429,1430,1431],{"class":431,"line":460},[429,1432,1433],{},"    name: str\n",[429,1435,1436],{"class":431,"line":466},[429,1437,1438],{},"    age: int | None = None\n",[429,1440,1441],{"class":431,"line":472},[429,1442,457],{"emptyLinePlaceholder":344},[429,1444,1445],{"class":431,"line":478},[429,1446,1447],{},"@app.post(\"\u002Fusers\", response_model=UserResponse, status_code=201)\n",[429,1449,1450],{"class":431,"line":483},[429,1451,1452],{},"async def create_user(payload: UserCreate, db: AsyncSession = Depends(get_db)):\n",[429,1454,1455],{"class":431,"line":489},[429,1456,1457],{},"    user = User(**payload.model_dump())\n",[429,1459,1460],{"class":431,"line":495},[429,1461,1462],{},"    db.add(user)\n",[429,1464,1465],{"class":431,"line":501},[429,1466,1467],{},"    await db.commit()\n",[429,1469,1470],{"class":431,"line":506},[429,1471,1160],{},[20,1473,1475],{"id":1474},"my-personal-pick","My Personal Pick",[16,1477,1478,1479,1481],{},"In 90% of projects I choose ",[30,1480,1118],{},":",[278,1483,1484,1487,1490,1493],{},[114,1485,1486],{},"Pydantic typing eliminates a whole class of bugs",[114,1488,1489],{},"Swagger\u002FReDoc — clients immediately see the API",[114,1491,1492],{},"Async — the right architecture for I\u002FO-heavy workloads",[114,1494,1495,1496],{},"Easy to test with ",[69,1497,1498],{},"httpx",[16,1500,1501,1502,1504],{},"I choose Django when I need a quick ",[30,1503,1301],{}," or CMS-like logic.",[20,1506,1508],{"id":1507},"django-fastapi-together","Django + FastAPI Together",[16,1510,1511],{},"A popular pattern — use both:",[62,1513,1516],{"className":1514,"code":1515,"language":67},[65],"├── backend\u002F\n│   ├── api\u002F          # FastAPI — REST endpoints\n│   └── admin\u002F        # Django — internal admin panel\n",[69,1517,1515],{"__ignoreMap":71},[16,1519,1520],{},"This gives you FastAPI speed for the client API and Django admin convenience for internal operations.",[20,1522,1524],{"id":1523},"summary","Summary",[176,1526,1527,1537],{},[179,1528,1529],{},[182,1530,1531,1534],{},[185,1532,1533],{},"Use Case",[185,1535,1536],{},"Choice",[195,1538,1539,1546,1553,1561,1568],{},[182,1540,1541,1544],{},[200,1542,1543],{},"SaaS, microservice, API",[200,1545,1118],{},[182,1547,1548,1551],{},[200,1549,1550],{},"CMS, corporate website",[200,1552,1112],{},[182,1554,1555,1558],{},[200,1556,1557],{},"Telegram bot with admin",[200,1559,1560],{},"FastAPI + Django admin",[182,1562,1563,1566],{},[200,1564,1565],{},"ML\u002FAI service",[200,1567,1118],{},[182,1569,1570,1573],{},[200,1571,1572],{},"Quick MVP with auth",[200,1574,1112],{},[16,1576,1577],{},"Both frameworks are excellent tools. It's all about the task.",[16,1579,1580,1581,404],{},"Need help choosing your stack or building something? ",[317,1582,1051],{"href":319},[1054,1584,1056],{},{"title":71,"searchDepth":323,"depth":323,"links":1586},[1587,1588,1589,1590,1591,1592,1593,1594],{"id":1106,"depth":323,"text":1107},{"id":1122,"depth":323,"text":1123},{"id":1197,"depth":323,"text":1198},{"id":1292,"depth":323,"text":1293},{"id":1374,"depth":323,"text":1375},{"id":1474,"depth":323,"text":1475},{"id":1507,"depth":323,"text":1508},{"id":1523,"depth":323,"text":1524},"2024-12-03","A detailed comparison of FastAPI and Django: performance, ecosystem, and the right use cases for each. Helping you pick the right tool for your project.",{},"\u002Fen\u002Fblog\u002Ffastapi-vs-django-2024","9 min",{"title":1090,"description":1596},"fastapi-vs-django-2024","en\u002Fblog\u002Ffastapi-vs-django-2024",[354,1118,1112,1604,1605],"Backend","API","OJblu9TutGEnCDBkG71VZh3bSewUQ61admj3dgCHjA4",{"id":1608,"title":1609,"body":1610,"date":2256,"description":2257,"extension":342,"meta":2258,"navigation":344,"path":2259,"readTime":2260,"seo":2261,"slug":2262,"stem":2263,"tags":2264,"__hash__":2267},"blogEn\u002Fen\u002Fblog\u002Fflutter-vs-react-native.md","Flutter vs React Native in 2024 — Which One to Choose for Your App",{"type":8,"value":1611,"toc":2240},[1612,1616,1623,1625,1631,1637,1639,1641,1648,1651,1693,1735,1741,1743,1747,1750,1764,1767,1781,1787,1789,1793,1796,1854,1860,1866,1868,1872,1878,1881,1892,1898,1900,1904,1969,1972,1974,1978,1983,1997,2002,2016,2018,2021,2024,2069,2071,2073,2079,2110,2113,2115,2119,2191,2193,2198,2209,2214,2225,2231,2238],[11,1613,1615],{"id":1614},"flutter-vs-react-native-what-to-choose-in-2024","Flutter vs React Native — What to Choose in 2024",[16,1617,1618,1619,1622],{},"One of the most common questions when ordering a mobile app: ",[30,1620,1621],{},"Flutter or React Native?"," Both solve the same problem — one codebase, two stores. But they do it differently. Let me break it down honestly, without bias.",[20,1624,1107],{"id":1106},[16,1626,1627,1630],{},[30,1628,1629],{},"Flutter"," — Google's framework, released in 2018. Language: Dart. Renders UI itself, doesn't use native components.",[16,1632,1633,1636],{},[30,1634,1635],{},"React Native"," — from Meta (Facebook), since 2015. Language: JavaScript\u002FTypeScript. Maps components to native UI elements of the platform.",[47,1638],{},[20,1640,1123],{"id":1122},[16,1642,1643,1644,1647],{},"Flutter runs on its own rendering engine ",[30,1645,1646],{},"Skia\u002FImpeller"," — it draws every pixel itself. This gives stable 60\u002F120fps without platform dependency.",[16,1649,1650],{},"React Native communicates with the native layer through a JavaScript Bridge (or the newer JSI architecture). This adds overhead on animations and complex interfaces.",[62,1652,1656],{"className":1653,"code":1654,"language":1655,"meta":71,"style":71},"language-dart shiki shiki-themes github-light github-dark","\u002F\u002F Flutter — smooth animation, no JS bridge\nAnimatedContainer(\n  duration: Duration(milliseconds: 300),\n  curve: Curves.easeInOut,\n  width: isExpanded ? 300 : 100,\n  child: MyWidget(),\n)\n","dart",[69,1657,1658,1663,1668,1673,1678,1683,1688],{"__ignoreMap":71},[429,1659,1660],{"class":431,"line":432},[429,1661,1662],{},"\u002F\u002F Flutter — smooth animation, no JS bridge\n",[429,1664,1665],{"class":431,"line":323},[429,1666,1667],{},"AnimatedContainer(\n",[429,1669,1670],{"class":431,"line":329},[429,1671,1672],{},"  duration: Duration(milliseconds: 300),\n",[429,1674,1675],{"class":431,"line":448},[429,1676,1677],{},"  curve: Curves.easeInOut,\n",[429,1679,1680],{"class":431,"line":454},[429,1681,1682],{},"  width: isExpanded ? 300 : 100,\n",[429,1684,1685],{"class":431,"line":460},[429,1686,1687],{},"  child: MyWidget(),\n",[429,1689,1690],{"class":431,"line":466},[429,1691,1692],{},")\n",[62,1694,1698],{"className":1695,"code":1696,"language":1697,"meta":71,"style":71},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F React Native — through Animated API\nconst width = useRef(new Animated.Value(100)).current;\nAnimated.timing(width, {\n  toValue: isExpanded ? 300 : 100,\n  duration: 300,\n  useNativeDriver: false,\n}).start();\n","javascript",[69,1699,1700,1705,1710,1715,1720,1725,1730],{"__ignoreMap":71},[429,1701,1702],{"class":431,"line":432},[429,1703,1704],{},"\u002F\u002F React Native — through Animated API\n",[429,1706,1707],{"class":431,"line":323},[429,1708,1709],{},"const width = useRef(new Animated.Value(100)).current;\n",[429,1711,1712],{"class":431,"line":329},[429,1713,1714],{},"Animated.timing(width, {\n",[429,1716,1717],{"class":431,"line":448},[429,1718,1719],{},"  toValue: isExpanded ? 300 : 100,\n",[429,1721,1722],{"class":431,"line":454},[429,1723,1724],{},"  duration: 300,\n",[429,1726,1727],{"class":431,"line":460},[429,1728,1729],{},"  useNativeDriver: false,\n",[429,1731,1732],{"class":431,"line":466},[429,1733,1734],{},"}).start();\n",[16,1736,1737,1740],{},[30,1738,1739],{},"Performance winner:"," Flutter, especially on complex animations.",[47,1742],{},[20,1744,1746],{"id":1745},"development-speed","Development Speed",[54,1748,1635],{"id":1749},"react-native",[111,1751,1752,1755,1758,1761],{},[114,1753,1754],{},"If the team knows React — minimal learning curve",[114,1756,1757],{},"Huge npm package ecosystem",[114,1759,1760],{},"Hot reload works fast",[114,1762,1763],{},"Easier to find developers (more JS devs around)",[54,1765,1629],{"id":1766},"flutter",[111,1768,1769,1772,1775,1778],{},[114,1770,1771],{},"Dart is learned in 1–2 weeks if you know any C-like language",[114,1773,1774],{},"Rich widget library out of the box",[114,1776,1777],{},"Fewer third-party dependencies",[114,1779,1780],{},"Excellent hot reload too",[16,1782,1783,1786],{},[30,1784,1785],{},"In practice:"," React Native is faster for a team with a JS background. Flutter is faster when you need complex custom UI.",[47,1788],{},[20,1790,1792],{"id":1791},"ui-and-design","UI and Design",[16,1794,1795],{},"This is the main architectural difference:",[176,1797,1798,1808],{},[179,1799,1800],{},[182,1801,1802,1804,1806],{},[185,1803],{},[185,1805,1629],{},[185,1807,1635],{},[195,1809,1810,1821,1832,1843],{},[182,1811,1812,1815,1818],{},[200,1813,1814],{},"Rendering",[200,1816,1817],{},"Own engine",[200,1819,1820],{},"Native components",[182,1822,1823,1826,1829],{},[200,1824,1825],{},"Looks",[200,1827,1828],{},"Same on iOS and Android",[200,1830,1831],{},"Like a native platform app",[182,1833,1834,1837,1840],{},[200,1835,1836],{},"Customization",[200,1838,1839],{},"Complete",[200,1841,1842],{},"Limited by native capabilities",[182,1844,1845,1848,1851],{},[200,1846,1847],{},"Animations",[200,1849,1850],{},"Easy, any kind",[200,1852,1853],{},"Harder, bridge limitations",[16,1855,1856,1859],{},[30,1857,1858],{},"When Flutter is better:"," unique design, branded components, game-like interfaces.",[16,1861,1862,1865],{},[30,1863,1864],{},"When React Native is better:"," need it to look \"native\" (like iOS system settings).",[47,1867],{},[20,1869,1871],{"id":1870},"ecosystem-and-packages","Ecosystem and Packages",[62,1873,1876],{"className":1874,"code":1875,"language":67},[65],"Flutter pub.dev:    ~40,000 packages\nReact Native npm:   ~1,000,000+ packages (all of npm)\n",[69,1877,1875],{"__ignoreMap":71},[16,1879,1880],{},"Sounds like an RN win, but in practice:",[111,1882,1883,1886,1889],{},[114,1884,1885],{},"Flutter packages are specifically written for mobile",[114,1887,1888],{},"npm has a lot of abandoned junk",[114,1890,1891],{},"Flutter pub.dev has a package quality rating system",[16,1893,1894,1897],{},[30,1895,1896],{},"Conclusion:"," Flutter has fewer packages, but they're more reliable.",[47,1899],{},[20,1901,1903],{"id":1902},"platform-support","Platform Support",[176,1905,1906,1917],{},[179,1907,1908],{},[182,1909,1910,1913,1915],{},[185,1911,1912],{},"Platform",[185,1914,1629],{},[185,1916,1635],{},[195,1918,1919,1928,1937,1948,1959],{},[182,1920,1921,1924,1926],{},[200,1922,1923],{},"iOS",[200,1925,1232],{},[200,1927,1232],{},[182,1929,1930,1933,1935],{},[200,1931,1932],{},"Android",[200,1934,1232],{},[200,1936,1232],{},[182,1938,1939,1942,1945],{},[200,1940,1941],{},"Web",[200,1943,1944],{},"✅ (beta)",[200,1946,1947],{},"✅ (via RN Web)",[182,1949,1950,1953,1956],{},[200,1951,1952],{},"Desktop",[200,1954,1955],{},"✅ (Windows\u002FMac\u002FLinux)",[200,1957,1958],{},"❌ limited",[182,1960,1961,1964,1967],{},[200,1962,1963],{},"Telegram Mini App",[200,1965,1966],{},"✅ via WebView",[200,1968,1966],{},[16,1970,1971],{},"Flutter wins on platform coverage.",[47,1973],{},[20,1975,1977],{"id":1976},"real-world-examples","Real-World Examples",[16,1979,1980],{},[30,1981,1982],{},"Companies using Flutter:",[111,1984,1985,1988,1991,1994],{},[114,1986,1987],{},"BMW App",[114,1989,1990],{},"eBay Motors",[114,1992,1993],{},"Google Pay (parts)",[114,1995,1996],{},"Alibaba (Xianyu)",[16,1998,1999],{},[30,2000,2001],{},"Companies using React Native:",[111,2003,2004,2007,2010,2013],{},[114,2005,2006],{},"Facebook",[114,2008,2009],{},"Instagram (partially)",[114,2011,2012],{},"Airbnb (moved back to native)",[114,2014,2015],{},"Discord",[47,2017],{},[20,2019,2020],{"id":903},"Development Cost",[16,2022,2023],{},"Cost is roughly equal — it depends on complexity, not the framework.",[176,2025,2026,2037],{},[179,2027,2028],{},[182,2029,2030,2033,2035],{},[185,2031,2032],{},"App type",[185,2034,1629],{},[185,2036,1635],{},[195,2038,2039,2049,2059],{},[182,2040,2041,2044,2047],{},[200,2042,2043],{},"MVP \u002F simple",[200,2045,2046],{},"from $100",[200,2048,2046],{},[182,2050,2051,2054,2057],{},[200,2052,2053],{},"Medium (auth, API, 10+ screens)",[200,2055,2056],{},"from $300",[200,2058,2056],{},[182,2060,2061,2064,2067],{},[200,2062,2063],{},"Complex (payments, real-time, offline)",[200,2065,2066],{},"from $800",[200,2068,2066],{},[47,2070],{},[20,2072,1475],{"id":1474},[16,2074,2075,2076,2078],{},"I use ",[30,2077,1629],{}," in 90% of projects. Reasons:",[278,2080,2081,2087,2093,2098,2104],{},[114,2082,2083,2086],{},[30,2084,2085],{},"Dart"," — strictly typed, fewer bugs",[114,2088,2089,2092],{},[30,2090,2091],{},"Widgets"," — huge selection of beautiful UI components",[114,2094,2095,2097],{},[30,2096,1123],{}," — stable, predictable",[114,2099,2100,2103],{},[30,2101,2102],{},"One codebase"," — iOS, Android, and web if needed",[114,2105,2106,2109],{},[30,2107,2108],{},"Flutter + FastAPI"," — excellent combination for backend-heavy apps",[16,2111,2112],{},"I only take React Native when the client insists, or when there's already a large JS codebase.",[47,2114],{},[20,2116,2118],{"id":2117},"summary-table","Summary Table",[176,2120,2121,2132],{},[179,2122,2123],{},[182,2124,2125,2128,2130],{},[185,2126,2127],{},"Criterion",[185,2129,1629],{},[185,2131,1635],{},[195,2133,2134,2144,2153,2163,2172,2182],{},[182,2135,2136,2138,2141],{},[200,2137,1123],{},[200,2139,2140],{},"⭐⭐⭐⭐⭐",[200,2142,2143],{},"⭐⭐⭐⭐",[182,2145,2146,2149,2151],{},[200,2147,2148],{},"Dev speed",[200,2150,2143],{},[200,2152,2143],{},[182,2154,2155,2158,2160],{},[200,2156,2157],{},"UI customization",[200,2159,2140],{},[200,2161,2162],{},"⭐⭐⭐",[182,2164,2165,2168,2170],{},[200,2166,2167],{},"Ecosystem",[200,2169,2143],{},[200,2171,2140],{},[182,2173,2174,2177,2179],{},[200,2175,2176],{},"Learning curve",[200,2178,2143],{},[200,2180,2181],{},"⭐⭐⭐⭐⭐ (if you know JS)",[182,2183,2184,2187,2189],{},[200,2185,2186],{},"Platform coverage",[200,2188,2140],{},[200,2190,2143],{},[20,2192,309],{"id":308},[16,2194,2195],{},[30,2196,2197],{},"Choose Flutter if:",[111,2199,2200,2203,2206],{},[114,2201,2202],{},"You need a beautiful custom design",[114,2204,2205],{},"The team doesn't know JavaScript",[114,2207,2208],{},"You want to cover iOS + Android + Web with one codebase",[16,2210,2211],{},[30,2212,2213],{},"Choose React Native if:",[111,2215,2216,2219,2222],{},[114,2217,2218],{},"The team already knows React",[114,2220,2221],{},"You need a native look & feel",[114,2223,2224],{},"The npm ecosystem is critical",[16,2226,2227,2228,2230],{},"In most cases — ",[30,2229,1629],{},". It's younger, developing faster, and surprises you less.",[16,2232,2233,2234,2237],{},"Need a mobile app? ",[317,2235,2236],{"href":319},"Let's discuss"," — I'll help choose the right stack for your task.",[1054,2239,1056],{},{"title":71,"searchDepth":323,"depth":323,"links":2241},[2242,2243,2244,2248,2249,2250,2251,2252,2253,2254,2255],{"id":1106,"depth":323,"text":1107},{"id":1122,"depth":323,"text":1123},{"id":1745,"depth":323,"text":1746,"children":2245},[2246,2247],{"id":1749,"depth":329,"text":1635},{"id":1766,"depth":329,"text":1629},{"id":1791,"depth":323,"text":1792},{"id":1870,"depth":323,"text":1871},{"id":1902,"depth":323,"text":1903},{"id":1976,"depth":323,"text":1977},{"id":903,"depth":323,"text":2020},{"id":1474,"depth":323,"text":1475},{"id":2117,"depth":323,"text":2118},{"id":308,"depth":323,"text":309},"2024-11-28","An honest comparison of Flutter and React Native: performance, ecosystem, development speed, cost. Helping you pick the right framework for your project.",{},"\u002Fen\u002Fblog\u002Fflutter-vs-react-native","10 min",{"title":1609,"description":2257},"flutter-vs-react-native","en\u002Fblog\u002Fflutter-vs-react-native",[1629,1635,2265,2085,2266],"Mobile","JavaScript","ZhXDAP7Xo1j4xXLym_OTl1nPQTIdItS-NF7GHG2qCW4",{"id":2269,"title":2270,"body":2271,"date":2922,"description":2923,"extension":342,"meta":2924,"navigation":344,"path":2925,"readTime":2926,"seo":2927,"slug":2928,"stem":2929,"tags":2930,"__hash__":2932},"blogEn\u002Fen\u002Fblog\u002Ftelegram-bot-python-2024.md","How to Build a Telegram Bot with Python in 2024 — Complete Guide",{"type":8,"value":2272,"toc":2909},[2273,2277,2284,2288,2318,2322,2325,2339,2343,2376,2379,2385,2389,2451,2455,2543,2547,2613,2617,2709,2713,2785,2789,2833,2837,2892,2894,2901,2906],[11,2274,2276],{"id":2275},"how-to-build-a-telegram-bot-with-python-in-2024","How to Build a Telegram Bot with Python in 2024",[16,2278,2279,2280,2283],{},"Telegram bots are one of the fastest ways to automate business processes or build a full product. In this article I'll show you how to build a ",[30,2281,2282],{},"production-ready bot"," with a database, proper architecture, and deployment from scratch.",[20,2285,2287],{"id":2286},"what-well-build","What We'll Build",[111,2289,2290,2297,2303,2309,2315],{},[114,2291,2292,2293,2296],{},"Bot on ",[30,2294,2295],{},"Aiogram 3"," (async, modern API)",[114,2298,2299,2302],{},[30,2300,2301],{},"PostgreSQL"," for data storage",[114,2304,2305,2308],{},[69,2306,2307],{},".env","-based configuration",[114,2310,2311,2314],{},[30,2312,2313],{},"Docker"," for deployment",[114,2316,2317],{},"FSM (finite state machine) for multi-step scenarios",[20,2319,2321],{"id":2320},"why-aiogram-3","Why Aiogram 3",[16,2323,2324],{},"Aiogram 3 is the de facto standard for serious Python bots:",[111,2326,2327,2330,2333,2336],{},[114,2328,2329],{},"Fully async (asyncio)",[114,2331,2332],{},"Routers and middlewares like FastAPI",[114,2334,2335],{},"Convenient FSM for dialogs",[114,2337,2338],{},"Active maintenance and good documentation",[20,2340,2342],{"id":2341},"setup-and-project-structure","Setup and Project Structure",[62,2344,2348],{"className":2345,"code":2346,"language":2347,"meta":71,"style":71},"language-bash shiki shiki-themes github-light github-dark","pip install aiogram==3.* sqlalchemy asyncpg python-dotenv\n","bash",[69,2349,2350],{"__ignoreMap":71},[429,2351,2352,2356,2360,2363,2367,2370,2373],{"class":431,"line":432},[429,2353,2355],{"class":2354},"sScJk","pip",[429,2357,2359],{"class":2358},"sZZnC"," install",[429,2361,2362],{"class":2358}," aiogram==3.",[429,2364,2366],{"class":2365},"sj4cs","*",[429,2368,2369],{"class":2358}," sqlalchemy",[429,2371,2372],{"class":2358}," asyncpg",[429,2374,2375],{"class":2358}," python-dotenv\n",[16,2377,2378],{},"Project structure:",[62,2380,2383],{"className":2381,"code":2382,"language":67},[65],"bot\u002F\n├── handlers\u002F\n│   ├── __init__.py\n│   ├── common.py      # \u002Fstart, \u002Fhelp\n│   └── user.py        # user scenarios\n├── middlewares\u002F\n│   └── database.py    # inject session into handlers\n├── models\u002F\n│   └── user.py        # SQLAlchemy models\n├── keyboards\u002F\n│   └── reply.py\n├── config.py\n└── main.py\n",[69,2384,2382],{"__ignoreMap":71},[20,2386,2388],{"id":2387},"configuration","Configuration",[62,2390,2392],{"className":423,"code":2391,"language":425,"meta":71,"style":71},"# config.py\nfrom pydantic_settings import BaseSettings\n\nclass Settings(BaseSettings):\n    BOT_TOKEN: str\n    DATABASE_URL: str\n    ADMIN_ID: int\n\n    class Config:\n        env_file = \".env\"\n\nsettings = Settings()\n",[69,2393,2394,2399,2404,2408,2413,2418,2423,2428,2432,2437,2442,2446],{"__ignoreMap":71},[429,2395,2396],{"class":431,"line":432},[429,2397,2398],{},"# config.py\n",[429,2400,2401],{"class":431,"line":323},[429,2402,2403],{},"from pydantic_settings import BaseSettings\n",[429,2405,2406],{"class":431,"line":329},[429,2407,457],{"emptyLinePlaceholder":344},[429,2409,2410],{"class":431,"line":448},[429,2411,2412],{},"class Settings(BaseSettings):\n",[429,2414,2415],{"class":431,"line":454},[429,2416,2417],{},"    BOT_TOKEN: str\n",[429,2419,2420],{"class":431,"line":460},[429,2421,2422],{},"    DATABASE_URL: str\n",[429,2424,2425],{"class":431,"line":466},[429,2426,2427],{},"    ADMIN_ID: int\n",[429,2429,2430],{"class":431,"line":472},[429,2431,457],{"emptyLinePlaceholder":344},[429,2433,2434],{"class":431,"line":478},[429,2435,2436],{},"    class Config:\n",[429,2438,2439],{"class":431,"line":483},[429,2440,2441],{},"        env_file = \".env\"\n",[429,2443,2444],{"class":431,"line":489},[429,2445,457],{"emptyLinePlaceholder":344},[429,2447,2448],{"class":431,"line":495},[429,2449,2450],{},"settings = Settings()\n",[20,2452,2454],{"id":2453},"main-entry-point","Main Entry Point",[62,2456,2458],{"className":423,"code":2457,"language":425,"meta":71,"style":71},"# main.py\nimport asyncio\nfrom aiogram import Bot, Dispatcher\nfrom aiogram.fsm.storage.memory import MemoryStorage\nfrom handlers import common, user\nfrom config import settings\n\nasync def main():\n    bot = Bot(token=settings.BOT_TOKEN)\n    dp = Dispatcher(storage=MemoryStorage())\n\n    dp.include_router(common.router)\n    dp.include_router(user.router)\n\n    await dp.start_polling(bot)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n",[69,2459,2460,2465,2469,2474,2479,2484,2489,2493,2497,2502,2507,2511,2516,2521,2525,2529,2533,2538],{"__ignoreMap":71},[429,2461,2462],{"class":431,"line":432},[429,2463,2464],{},"# main.py\n",[429,2466,2467],{"class":431,"line":323},[429,2468,435],{},[429,2470,2471],{"class":431,"line":329},[429,2472,2473],{},"from aiogram import Bot, Dispatcher\n",[429,2475,2476],{"class":431,"line":448},[429,2477,2478],{},"from aiogram.fsm.storage.memory import MemoryStorage\n",[429,2480,2481],{"class":431,"line":454},[429,2482,2483],{},"from handlers import common, user\n",[429,2485,2486],{"class":431,"line":460},[429,2487,2488],{},"from config import settings\n",[429,2490,2491],{"class":431,"line":466},[429,2492,457],{"emptyLinePlaceholder":344},[429,2494,2495],{"class":431,"line":472},[429,2496,619],{},[429,2498,2499],{"class":431,"line":478},[429,2500,2501],{},"    bot = Bot(token=settings.BOT_TOKEN)\n",[429,2503,2504],{"class":431,"line":483},[429,2505,2506],{},"    dp = Dispatcher(storage=MemoryStorage())\n",[429,2508,2509],{"class":431,"line":489},[429,2510,457],{"emptyLinePlaceholder":344},[429,2512,2513],{"class":431,"line":495},[429,2514,2515],{},"    dp.include_router(common.router)\n",[429,2517,2518],{"class":431,"line":501},[429,2519,2520],{},"    dp.include_router(user.router)\n",[429,2522,2523],{"class":431,"line":506},[429,2524,457],{"emptyLinePlaceholder":344},[429,2526,2527],{"class":431,"line":512},[429,2528,625],{},[429,2530,2531],{"class":431,"line":518},[429,2532,457],{"emptyLinePlaceholder":344},[429,2534,2535],{"class":431,"line":524},[429,2536,2537],{},"if __name__ == \"__main__\":\n",[429,2539,2540],{"class":431,"line":529},[429,2541,2542],{},"    asyncio.run(main())\n",[20,2544,2546],{"id":2545},"the-start-handler","The \u002Fstart Handler",[62,2548,2550],{"className":423,"code":2549,"language":425,"meta":71,"style":71},"# handlers\u002Fcommon.py\nfrom aiogram import Router\nfrom aiogram.filters import CommandStart\nfrom aiogram.types import Message\n\nrouter = Router()\n\n@router.message(CommandStart())\nasync def cmd_start(message: Message):\n    await message.answer(\n        f\"Hey {message.from_user.first_name}! 👋\\n\\n\"\n        \"I'm here to automate your tasks.\"\n    )\n",[69,2551,2552,2557,2562,2566,2571,2575,2580,2584,2589,2594,2599,2604,2609],{"__ignoreMap":71},[429,2553,2554],{"class":431,"line":432},[429,2555,2556],{},"# handlers\u002Fcommon.py\n",[429,2558,2559],{"class":431,"line":323},[429,2560,2561],{},"from aiogram import Router\n",[429,2563,2564],{"class":431,"line":329},[429,2565,445],{},[429,2567,2568],{"class":431,"line":448},[429,2569,2570],{},"from aiogram.types import Message\n",[429,2572,2573],{"class":431,"line":454},[429,2574,457],{"emptyLinePlaceholder":344},[429,2576,2577],{"class":431,"line":460},[429,2578,2579],{},"router = Router()\n",[429,2581,2582],{"class":431,"line":466},[429,2583,457],{"emptyLinePlaceholder":344},[429,2585,2586],{"class":431,"line":472},[429,2587,2588],{},"@router.message(CommandStart())\n",[429,2590,2591],{"class":431,"line":478},[429,2592,2593],{},"async def cmd_start(message: Message):\n",[429,2595,2596],{"class":431,"line":483},[429,2597,2598],{},"    await message.answer(\n",[429,2600,2601],{"class":431,"line":489},[429,2602,2603],{},"        f\"Hey {message.from_user.first_name}! 👋\\n\\n\"\n",[429,2605,2606],{"class":431,"line":495},[429,2607,2608],{},"        \"I'm here to automate your tasks.\"\n",[429,2610,2611],{"class":431,"line":501},[429,2612,597],{},[20,2614,2616],{"id":2615},"fsm-multi-step-dialogs","FSM — Multi-step Dialogs",[62,2618,2620],{"className":423,"code":2619,"language":425,"meta":71,"style":71},"from aiogram.fsm.context import FSMContext\nfrom aiogram.fsm.state import State, StatesGroup\n\nclass OrderForm(StatesGroup):\n    waiting_name    = State()\n    waiting_phone   = State()\n    waiting_comment = State()\n\n@router.message(Command(\"order\"))\nasync def start_order(message: Message, state: FSMContext):\n    await state.set_state(OrderForm.waiting_name)\n    await message.answer(\"What's your name?\")\n\n@router.message(OrderForm.waiting_name)\nasync def got_name(message: Message, state: FSMContext):\n    await state.update_data(name=message.text)\n    await state.set_state(OrderForm.waiting_phone)\n    await message.answer(\"Your phone number:\")\n",[69,2621,2622,2627,2632,2636,2641,2646,2651,2656,2660,2665,2670,2675,2680,2684,2689,2694,2699,2704],{"__ignoreMap":71},[429,2623,2624],{"class":431,"line":432},[429,2625,2626],{},"from aiogram.fsm.context import FSMContext\n",[429,2628,2629],{"class":431,"line":323},[429,2630,2631],{},"from aiogram.fsm.state import State, StatesGroup\n",[429,2633,2634],{"class":431,"line":329},[429,2635,457],{"emptyLinePlaceholder":344},[429,2637,2638],{"class":431,"line":448},[429,2639,2640],{},"class OrderForm(StatesGroup):\n",[429,2642,2643],{"class":431,"line":454},[429,2644,2645],{},"    waiting_name    = State()\n",[429,2647,2648],{"class":431,"line":460},[429,2649,2650],{},"    waiting_phone   = State()\n",[429,2652,2653],{"class":431,"line":466},[429,2654,2655],{},"    waiting_comment = State()\n",[429,2657,2658],{"class":431,"line":472},[429,2659,457],{"emptyLinePlaceholder":344},[429,2661,2662],{"class":431,"line":478},[429,2663,2664],{},"@router.message(Command(\"order\"))\n",[429,2666,2667],{"class":431,"line":483},[429,2668,2669],{},"async def start_order(message: Message, state: FSMContext):\n",[429,2671,2672],{"class":431,"line":489},[429,2673,2674],{},"    await state.set_state(OrderForm.waiting_name)\n",[429,2676,2677],{"class":431,"line":495},[429,2678,2679],{},"    await message.answer(\"What's your name?\")\n",[429,2681,2682],{"class":431,"line":501},[429,2683,457],{"emptyLinePlaceholder":344},[429,2685,2686],{"class":431,"line":506},[429,2687,2688],{},"@router.message(OrderForm.waiting_name)\n",[429,2690,2691],{"class":431,"line":512},[429,2692,2693],{},"async def got_name(message: Message, state: FSMContext):\n",[429,2695,2696],{"class":431,"line":518},[429,2697,2698],{},"    await state.update_data(name=message.text)\n",[429,2700,2701],{"class":431,"line":524},[429,2702,2703],{},"    await state.set_state(OrderForm.waiting_phone)\n",[429,2705,2706],{"class":431,"line":529},[429,2707,2708],{},"    await message.answer(\"Your phone number:\")\n",[20,2710,2712],{"id":2711},"database-integration","Database Integration",[62,2714,2716],{"className":423,"code":2715,"language":425,"meta":71,"style":71},"# models\u002Fuser.py\nfrom sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column\nfrom sqlalchemy import BigInteger, String, DateTime, func\n\nclass Base(DeclarativeBase):\n    pass\n\nclass User(Base):\n    __tablename__ = \"users\"\n\n    id:         Mapped[int]    = mapped_column(BigInteger, primary_key=True)\n    username:   Mapped[str | None] = mapped_column(String(64))\n    first_name: Mapped[str]    = mapped_column(String(128))\n    created_at: Mapped[DateTime] = mapped_column(server_default=func.now())\n",[69,2717,2718,2723,2728,2733,2737,2742,2747,2751,2756,2761,2765,2770,2775,2780],{"__ignoreMap":71},[429,2719,2720],{"class":431,"line":432},[429,2721,2722],{},"# models\u002Fuser.py\n",[429,2724,2725],{"class":431,"line":323},[429,2726,2727],{},"from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column\n",[429,2729,2730],{"class":431,"line":329},[429,2731,2732],{},"from sqlalchemy import BigInteger, String, DateTime, func\n",[429,2734,2735],{"class":431,"line":448},[429,2736,457],{"emptyLinePlaceholder":344},[429,2738,2739],{"class":431,"line":454},[429,2740,2741],{},"class Base(DeclarativeBase):\n",[429,2743,2744],{"class":431,"line":460},[429,2745,2746],{},"    pass\n",[429,2748,2749],{"class":431,"line":466},[429,2750,457],{"emptyLinePlaceholder":344},[429,2752,2753],{"class":431,"line":472},[429,2754,2755],{},"class User(Base):\n",[429,2757,2758],{"class":431,"line":478},[429,2759,2760],{},"    __tablename__ = \"users\"\n",[429,2762,2763],{"class":431,"line":483},[429,2764,457],{"emptyLinePlaceholder":344},[429,2766,2767],{"class":431,"line":489},[429,2768,2769],{},"    id:         Mapped[int]    = mapped_column(BigInteger, primary_key=True)\n",[429,2771,2772],{"class":431,"line":495},[429,2773,2774],{},"    username:   Mapped[str | None] = mapped_column(String(64))\n",[429,2776,2777],{"class":431,"line":501},[429,2778,2779],{},"    first_name: Mapped[str]    = mapped_column(String(128))\n",[429,2781,2782],{"class":431,"line":506},[429,2783,2784],{},"    created_at: Mapped[DateTime] = mapped_column(server_default=func.now())\n",[20,2786,2788],{"id":2787},"dockerfile","Dockerfile",[62,2790,2793],{"className":2791,"code":2792,"language":2787,"meta":71,"style":71},"language-dockerfile shiki shiki-themes github-light github-dark","FROM python:3.12-slim\n\nWORKDIR \u002Fapp\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\n\nCOPY . .\nCMD [\"python\", \"main.py\"]\n",[69,2794,2795,2800,2804,2809,2814,2819,2823,2828],{"__ignoreMap":71},[429,2796,2797],{"class":431,"line":432},[429,2798,2799],{},"FROM python:3.12-slim\n",[429,2801,2802],{"class":431,"line":323},[429,2803,457],{"emptyLinePlaceholder":344},[429,2805,2806],{"class":431,"line":329},[429,2807,2808],{},"WORKDIR \u002Fapp\n",[429,2810,2811],{"class":431,"line":448},[429,2812,2813],{},"COPY requirements.txt .\n",[429,2815,2816],{"class":431,"line":454},[429,2817,2818],{},"RUN pip install --no-cache-dir -r requirements.txt\n",[429,2820,2821],{"class":431,"line":460},[429,2822,457],{"emptyLinePlaceholder":344},[429,2824,2825],{"class":431,"line":466},[429,2826,2827],{},"COPY . .\n",[429,2829,2830],{"class":431,"line":472},[429,2831,2832],{},"CMD [\"python\", \"main.py\"]\n",[20,2834,2836],{"id":2835},"deploying-to-vps","Deploying to VPS",[62,2838,2840],{"className":2345,"code":2839,"language":2347,"meta":71,"style":71},"git clone your-repo && cd bot\ncp .env.example .env  # fill in tokens\ndocker compose up -d\n",[69,2841,2842,2863,2878],{"__ignoreMap":71},[429,2843,2844,2847,2850,2853,2857,2860],{"class":431,"line":432},[429,2845,2846],{"class":2354},"git",[429,2848,2849],{"class":2358}," clone",[429,2851,2852],{"class":2358}," your-repo",[429,2854,2856],{"class":2855},"sVt8B"," && ",[429,2858,2859],{"class":2365},"cd",[429,2861,2862],{"class":2358}," bot\n",[429,2864,2865,2868,2871,2874],{"class":431,"line":323},[429,2866,2867],{"class":2354},"cp",[429,2869,2870],{"class":2358}," .env.example",[429,2872,2873],{"class":2358}," .env",[429,2875,2877],{"class":2876},"sJ8bj","  # fill in tokens\n",[429,2879,2880,2883,2886,2889],{"class":431,"line":329},[429,2881,2882],{"class":2354},"docker",[429,2884,2885],{"class":2358}," compose",[429,2887,2888],{"class":2358}," up",[429,2890,2891],{"class":2365}," -d\n",[20,2893,1524],{"id":1523},[16,2895,2896,2897,2900],{},"A properly built Telegram bot is not just a script with ",[69,2898,2899],{},"if '\u002Fstart'",". It's a full application with routers, middlewares, a database and CI\u002FCD. Aiogram 3 gives you all the tools for that.",[16,2902,2903,2904,404],{},"Need help building a bot? ",[317,2905,1051],{"href":319},[1054,2907,2908],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":71,"searchDepth":323,"depth":323,"links":2910},[2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921],{"id":2286,"depth":323,"text":2287},{"id":2320,"depth":323,"text":2321},{"id":2341,"depth":323,"text":2342},{"id":2387,"depth":323,"text":2388},{"id":2453,"depth":323,"text":2454},{"id":2545,"depth":323,"text":2546},{"id":2615,"depth":323,"text":2616},{"id":2711,"depth":323,"text":2712},{"id":2787,"depth":323,"text":2788},{"id":2835,"depth":323,"text":2836},{"id":1523,"depth":323,"text":1524},"2024-11-15","Step-by-step guide to building a production-ready Telegram bot using Aiogram 3, PostgreSQL and Docker deployment. From zero to a working product.",{},"\u002Fen\u002Fblog\u002Ftelegram-bot-python-2024","12 min",{"title":2270,"description":2923},"telegram-bot-python-2024","en\u002Fblog\u002Ftelegram-bot-python-2024",[354,352,2931,2301,2313],"Aiogram","O40LKFlUrPTY9Gmb-f6n4KzmMy0HpcXjTp6pMbH80as",1781783025978]