<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nikolai Aralkin</title>
    <description>The latest articles on DEV Community by Nikolai Aralkin (@fate161).</description>
    <link>https://dev.to/fate161</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3975672%2F03b238fb-9897-45df-a1f6-f015d4cd7948.jpg</url>
      <title>DEV Community: Nikolai Aralkin</title>
      <link>https://dev.to/fate161</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fate161"/>
    <language>en</language>
    <item>
      <title>I built an AI task manager in Russia because I was tired of paying for Notion</title>
      <dc:creator>Nikolai Aralkin</dc:creator>
      <pubDate>Tue, 09 Jun 2026 09:52:54 +0000</pubDate>
      <link>https://dev.to/fate161/i-built-an-ai-task-manager-in-russia-because-i-was-tired-of-paying-for-notion-1gli</link>
      <guid>https://dev.to/fate161/i-built-an-ai-task-manager-in-russia-because-i-was-tired-of-paying-for-notion-1gli</guid>
      <description>&lt;h2&gt;
  
  
  What the product actually does
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TaskFly&lt;/strong&gt; is an AI-powered task manager. The main differentiator: you can create tasks by talking — send a voice message to a Telegram bot, it transcribes it and creates structured tasks with deadlines, priorities, and assignees.&lt;/p&gt;

&lt;p&gt;You can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send a photo of a whiteboard or sticky notes → AI extracts tasks&lt;/li&gt;
&lt;li&gt;Forward a PDF or Word document → AI pulls out action items&lt;/li&gt;
&lt;li&gt;Type naturally ("remind me to call Ivan on Friday morning") → AI parses intent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's built for small teams, mostly Russian-speaking market for now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech choices (and why)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Next.js 16 + TypeScript + Tailwind v4&lt;/strong&gt; — the obvious modern stack. No regrets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL + Prisma&lt;/strong&gt; — I considered MongoDB early on. Stuck with SQL because relationships (tasks → projects → organizations → users) are genuinely relational.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two AI providers, not one&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was a key architectural decision. I started with Claude (Anthropic) for everything. Then discovered Groq — their llama-3.3-70b-versatile is fast and cheap for text extraction.&lt;/p&gt;

&lt;p&gt;So I split it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text → tasks: &lt;strong&gt;Groq&lt;/strong&gt; (primary) with Claude as fallback if rate-limited&lt;/li&gt;
&lt;li&gt;Voice transcription: &lt;strong&gt;Groq Whisper&lt;/strong&gt; with OpenAI as fallback&lt;/li&gt;
&lt;li&gt;Images, PDFs, documents: &lt;strong&gt;Claude Sonnet&lt;/strong&gt; (better at vision)&lt;/li&gt;
&lt;li&gt;Project analytics: &lt;strong&gt;Claude Sonnet&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Groq hits a rate limit, the system automatically switches to Claude and sends me a Telegram notification. Users don't notice anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Telegram bot (aiogram 3, Python)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This turned out to be the most-loved feature. People don't want to open a browser — they're already in Telegram. The bot talks to the Next.js API over HTTP. Authentication is two headers: a static secret + the user's Telegram ID.&lt;/p&gt;




&lt;h2&gt;
  
  
  Revenue model
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Team size&lt;/th&gt;
&lt;th&gt;AI requests/day&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;~$9&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team&lt;/td&gt;
&lt;td&gt;~$28&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Business&lt;/td&gt;
&lt;td&gt;~$67&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Payments through YooKassa (Russian payment processor). Automatic recurring billing. Built it myself — no Stripe, no external auth providers, no Supabase. Everything runs on my own server.&lt;/p&gt;

&lt;p&gt;Current status: 5 total users, 0 paying, MRR $0. Early days.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistakes I made (the real ones)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. UTC vs local time in AI prompts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I pass the current time to AI so it can understand "tomorrow" and "next Friday", I was using &lt;code&gt;new Date().toISOString()&lt;/code&gt;. That returns UTC. My server is in Moscow timezone. A user saying "remind me at 3pm" was getting tasks created at 6pm.&lt;/p&gt;

&lt;p&gt;The fix: use &lt;code&gt;getFullYear()/getMonth()/getDate()&lt;/code&gt; components directly instead of ISO string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. JavaScript's silent month overflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For recurring monthly tasks, I had:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMonth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMonth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A task created on January 31st would roll over to March 3rd. JavaScript doesn't throw an error — it just keeps counting days. The fix: always reset to day 1 before adding months, then restore the last-day logic separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. I forgot to log AI usage from the Telegram bot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My admin panel showed AI usage statistics. It was showing near-zero despite real usage. Turns out every web request went through &lt;code&gt;logAI()&lt;/code&gt;, but I'd forgotten to add it to the 5 Telegram bot API routes. Six months of bot usage isn't recorded anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Security audit found IDOR vulnerabilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I ran a security audit after launch and found that several API endpoints accepted a &lt;code&gt;taskId&lt;/code&gt; without checking if it belonged to the current user's organization. A user could technically read or modify another organization's tasks by guessing IDs.&lt;/p&gt;

&lt;p&gt;Fix: always use &lt;code&gt;findFirst&lt;/code&gt; with &lt;code&gt;organizationId&lt;/code&gt; in the where clause, not &lt;code&gt;findUnique&lt;/code&gt; by ID alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. SVG uploads = stored XSS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Users could upload any file as a task attachment. SVG files render as HTML in the browser — meaning a malicious SVG could execute JavaScript. I'm now blocking a list of dangerous extensions server-side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Deployment was killing the site during updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Original deploy process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pm2 restart taskfly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This caused ~30 seconds of downtime every deploy because &lt;code&gt;pm2 restart&lt;/code&gt; kills all workers at once, and the build was writing to &lt;code&gt;.next&lt;/code&gt; while workers were reading from it.&lt;/p&gt;

&lt;p&gt;Current process: build into &lt;code&gt;.next_building&lt;/code&gt;, atomic swap (&lt;code&gt;rm -rf .next &amp;amp;&amp;amp; mv .next_building .next&lt;/code&gt;), then &lt;code&gt;pm2 reload&lt;/code&gt; (rolling replace, one worker at a time). Zero downtime.&lt;/p&gt;

&lt;p&gt;Also: adding &lt;code&gt;nice -n 19&lt;/code&gt; to the build command on a 1-core VPS made a huge difference. The build takes ~90 seconds and saturates the CPU — without niceness, the live workers started timing out.&lt;/p&gt;




&lt;h2&gt;
  
  
  Distribution: what worked, what didn't
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;VC.ru&lt;/strong&gt; (Russian tech/business blog): published, got some traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Habr&lt;/strong&gt; (Russian tech blog, like a Russian Dev.to): rejected for "looking like advertising." Working on a purely technical article now about architecture and bugs — that format tends to pass moderation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Startpack&lt;/strong&gt; (Russian SaaS directory): rejected because "the site is less than 6 months old and has no external mentions." Will reapply in ~3 months.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Telegram channels&lt;/strong&gt;: decent. The Russian startup/productivity community on Telegram is active.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Hunt&lt;/strong&gt;: haven't done it yet. Need to prepare an English landing page first.&lt;/p&gt;

&lt;p&gt;Honest summary: distribution is harder than building. The product is in decent shape. Getting people to know it exists is the real challenge.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start distribution earlier.&lt;/strong&gt; I spent 9 months building features. I should have shipped the MVP in month 2 and spent the rest of the time talking to users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't build your own auth + payments from scratch.&lt;/strong&gt; I did it because I wanted full control. It took 3 weeks. A hosted solution would have taken 3 hours. In retrospect, the control isn't worth it at this stage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One AI provider first.&lt;/strong&gt; The fallback system is elegant now, but adding it early was premature optimization. I spent time on infrastructure that mattered to approximately zero users at launch.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Google Calendar integration (most-requested feature)&lt;/li&gt;
&lt;li&gt;React Native mobile app&lt;/li&gt;
&lt;li&gt;English-language version for international market&lt;/li&gt;
&lt;li&gt;SEO blog on taskfly.ru&lt;/li&gt;
&lt;li&gt;Re-apply to Startpack in September&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you're building something similar or have questions about any of the technical decisions, happy to discuss in the comments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stack: Next.js 16 · TypeScript · Tailwind v4 · Prisma · PostgreSQL · Groq · Claude API · aiogram 3 · PM2 · VPS&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>ai</category>
      <category>saas</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
