<?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: member_fb93637b</title>
    <description>The latest articles on DEV Community by member_fb93637b (@member_fb93637b).</description>
    <link>https://dev.to/member_fb93637b</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4191174%2F5fe990e2-eacd-4f98-9535-55bb09af5ba2.png</url>
      <title>DEV Community: member_fb93637b</title>
      <link>https://dev.to/member_fb93637b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/member_fb93637b"/>
    <language>en</language>
    <item>
      <title>I run a Telegram Stars payment bot for $0/month forever — on GitHub Actions, not a server</title>
      <dc:creator>member_fb93637b</dc:creator>
      <pubDate>Sat, 17 Oct 2026 23:58:02 +0000</pubDate>
      <link>https://dev.to/member_fb93637b/i-run-a-telegram-stars-payment-bot-for-0month-forever-on-github-actions-not-a-server-4a5a</link>
      <guid>https://dev.to/member_fb93637b/i-run-a-telegram-stars-payment-bot-for-0month-forever-on-github-actions-not-a-server-4a5a</guid>
      <description>&lt;p&gt;Telegram Stars (currency &lt;code&gt;XTR&lt;/code&gt;) let you sell digital goods inside Telegram with no bank, no card network, no Stripe/PayPal, and no KYC on the selling side. The catch most tutorials skip: Telegram requires &lt;code&gt;answerPreCheckoutQuery&lt;/code&gt; within &lt;strong&gt;10 seconds&lt;/strong&gt; of every payment attempt — there's no auto-approve fallback. That means you need something always-on, listening. Normally that's a $5-20/month VPS or a serverless function with its own billing.&lt;/p&gt;

&lt;p&gt;I didn't want a second hosting bill for a side project, so I run the responder entirely inside a &lt;strong&gt;public GitHub repo's Actions minutes&lt;/strong&gt;, which are unlimited for public repos.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick
&lt;/h2&gt;

&lt;p&gt;A single GitHub Actions job can run up to 6 hours. So:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Long-poll Telegram's &lt;code&gt;getUpdates&lt;/code&gt; for ~5h50m inside one job.&lt;/li&gt;
&lt;li&gt;Commit the updated offset + a dedup list of already-fulfilled payment IDs back to the repo as the last step.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;cron&lt;/code&gt; schedule re-triggers the next run every 6 hours — it queues right behind the previous job (same concurrency group), so the gap between one run ending and the next starting is seconds, not minutes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Net result: near-continuous coverage, $0/month, no separate hosting account to manage or lose access to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*/6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
&lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;telegram-stars-bot&lt;/span&gt;
  &lt;span class="na"&gt;cancel-in-progress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;respond&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;355&lt;/span&gt;   &lt;span class="c1"&gt;# just under the 6h hard cap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The bug this trick hides until your first real sale
&lt;/h2&gt;

&lt;p&gt;The last step commits &lt;code&gt;state.json&lt;/code&gt; (the &lt;code&gt;getUpdates&lt;/code&gt; offset) and &lt;code&gt;fulfilled.json&lt;/code&gt; (processed payment IDs) back to &lt;code&gt;main&lt;/code&gt;. A plain &lt;code&gt;git push&lt;/code&gt; there is a trap: if &lt;em&gt;anything else&lt;/em&gt; pushes to &lt;code&gt;main&lt;/code&gt; during that ~5h50m window — even an unrelated commit to a different file — the push fails with a plain &lt;code&gt;! [rejected] (fetch first)&lt;/code&gt;. The job itself still shows green in the Actions tab (the failure is buried in one sub-step), so nothing alerts you.&lt;/p&gt;

&lt;p&gt;What actually breaks: the whole run's progress — offset &lt;em&gt;and&lt;/em&gt; the fulfilled-payment dedup list — gets silently discarded. The next run starts from the old offset, Telegram happily replays the same updates (it doesn't drop them without a confirmed offset), and because the dedup record also reverted, a real purchase could get double-processed — not a double charge to the buyer, but a duplicate delivery message, which looks broken to a paying customer on their first interaction with your bot.&lt;/p&gt;

&lt;p&gt;Fix: retry the push with a rebase instead of giving up after one attempt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in &lt;/span&gt;1 2 3 4 5&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;git push &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0
  git fetch origin main
  git rebase origin/main &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; git rebase &lt;span class="nt"&gt;--abort&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;sleep &lt;/span&gt;3
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I found this by noticing a run failure buried in email notifications, not from a customer complaint — it hadn't sold anything yet when I caught it, but it was a live landmine for the first real sale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;Live since Oct 17: dedicated bot (&lt;a href="https://t.me/freelancerkitbot" rel="noopener noreferrer"&gt;@freelancerkitbot&lt;/a&gt;), &lt;code&gt;pre_checkout_query&lt;/code&gt; answered automatically, &lt;code&gt;successful_payment&lt;/code&gt; triggers an automatic delivery message, replayed updates can't double-deliver (charge IDs are deduped). Zero sales so far — I'm not going to pretend otherwise — but the plumbing is solid and tested (unit tests mock the Telegram API, no token needed to run them).&lt;/p&gt;

&lt;p&gt;Code (MIT): &lt;a href="https://github.com/kleogeos/telegram-stars-checkout" rel="noopener noreferrer"&gt;https://github.com/kleogeos/telegram-stars-checkout&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to see it live: &lt;a href="https://kleogeos.github.io/freelancer-tools/buy-crypto.html?src=devto3" rel="noopener noreferrer"&gt;one of the checkout pages&lt;/a&gt; has a "Pay with Telegram Stars" button wired to this exact repo.&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>githubactions</category>
      <category>showdev</category>
    </item>
    <item>
      <title>6 Clauses Your Freelance Contract Needs (Or You Risk Not Getting Paid)</title>
      <dc:creator>member_fb93637b</dc:creator>
      <pubDate>Sat, 17 Oct 2026 22:44:08 +0000</pubDate>
      <link>https://dev.to/member_fb93637b/6-clauses-your-freelance-contract-needs-or-you-risk-not-getting-paid-584b</link>
      <guid>https://dev.to/member_fb93637b/6-clauses-your-freelance-contract-needs-or-you-risk-not-getting-paid-584b</guid>
      <description>&lt;p&gt;I built a free &lt;a href="https://kleogeos.github.io/freelancer-tools/contract-checklist.html?src=devto2" rel="noopener noreferrer"&gt;contract checklist tool&lt;/a&gt; that scans a pasted contract for missing clauses. Writing the checks made it obvious which 6 clauses actually matter — the rest is boilerplate.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Scope and acceptance criteria
&lt;/h2&gt;

&lt;p&gt;"Build a website" is a conversation topic, not a scope. Name the exact deliverable, format, and how the client verifies it is done. Without this, every revision request becomes an unwinnable argument about what you actually promised.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Acceptance deadline with an auto-accept clause
&lt;/h2&gt;

&lt;p&gt;Give the client a fixed number of days (3-5 business days is typical) to approve the work or send written feedback. State that silence past the deadline counts as acceptance. Without this clause, a client who goes quiet can block you from ever formally closing the project -- and from invoicing with a clean paper trail.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Payment terms with a real late fee
&lt;/h2&gt;

&lt;p&gt;Net 15 or Net 30 from invoice date, not "on completion." Add a concrete late fee (commonly 1.5%/month on the overdue balance) and the right to pause work once payment is overdue. A deadline with no penalty attached is a suggestion, not a term.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. IP assignment, tied to a specific moment
&lt;/h2&gt;

&lt;p&gt;"Client may use the work" is not an assignment. State explicitly whether full rights transfer -- and from what moment, usually full payment, not delivery -- or whether it is a license. Skip this and default copyright law applies, which can mean the client is not the sole legal owner even after paying in full.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Confidentiality / NDA
&lt;/h2&gt;

&lt;p&gt;If the work touches client data, system access, or business information, a confidentiality clause (or separate NDA) protects both sides and makes clients more comfortable sharing what you actually need to do the job well.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. A plan for when the client disappears
&lt;/h2&gt;

&lt;p&gt;A kill fee for mid-project cancellation, combined with clauses 2 and 3 above, gives you a concrete written basis to invoice and collect -- instead of an unenforceable verbal understanding.&lt;/p&gt;




&lt;p&gt;Full write-up: &lt;a href="https://kleogeos.github.io/freelancer-tools/how-to-write-a-freelance-contract.html?src=devto2" rel="noopener noreferrer"&gt;How to Write a Freelance Contract&lt;/a&gt;. The checklist tool above runs entirely in your browser -- nothing you paste is uploaded anywhere.&lt;/p&gt;

&lt;p&gt;I also build small zero-dependency CLIs for freelance admin (invoicing, NDAs, time tracking) -- &lt;a href="https://github.com/kleogeos/awesome-freelance-tools" rel="noopener noreferrer"&gt;repo list here&lt;/a&gt; if that is useful to anyone.&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>contract</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I built a suite of zero-dependency CLIs for freelancer admin (invoicing, contracts, NDAs, time tracking)</title>
      <dc:creator>member_fb93637b</dc:creator>
      <pubDate>Sat, 17 Oct 2026 21:35:56 +0000</pubDate>
      <link>https://dev.to/member_fb93637b/i-built-a-suite-of-zero-dependency-clis-for-freelancer-admin-invoicing-contracts-ndas-time-3769</link>
      <guid>https://dev.to/member_fb93637b/i-built-a-suite-of-zero-dependency-clis-for-freelancer-admin-invoicing-contracts-ndas-time-3769</guid>
      <description>&lt;p&gt;I kept rebuilding the same client paperwork for every project — proposal, NDA before the discovery call, services agreement, invoice, time tracking, and eventually a late-payment reminder — so I turned them into a set of small, zero-dependency Python CLIs. Each one takes a JSON file and outputs a clean, print-ready HTML file. No accounts, no cloud, no telemetry.&lt;/p&gt;

&lt;p&gt;The suite now covers the whole client lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;freelance-proposal-cli&lt;/strong&gt; — scope/pricing/timeline quote&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;freelance-nda-cli&lt;/strong&gt; — mutual NDA for the discovery call before scoping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;freelance-contract-cli&lt;/strong&gt; — plain-language services agreement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;contract-checklist-cli&lt;/strong&gt; — scans a contract for commonly-missing clauses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;freelance-time-cli&lt;/strong&gt; — time tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;freelance-timesheet-to-invoice-cli&lt;/strong&gt; — converts tracked hours straight into an invoice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;freelance-invoice-cli&lt;/strong&gt; — HTML invoice generator&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;freelance-late-fee-cli&lt;/strong&gt; — computes late fees and which reminder email to send&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;freelance-rate-cli&lt;/strong&gt; / &lt;strong&gt;freelance-expense-cli&lt;/strong&gt; / &lt;strong&gt;freelance-tax-cli&lt;/strong&gt; — hourly rate math, expenses, US self-employment tax&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;crypto-pay-cli&lt;/strong&gt; / &lt;strong&gt;usdt-rub-cli&lt;/strong&gt; / &lt;strong&gt;freelance-currency-cli&lt;/strong&gt; — for clients who pay in stablecoins instead of wire transfer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each one is MIT-licensed, has a test suite, and runs in CI. They're designed to chain together — timesheet hours flow into the invoice generator, the invoice generator's output matches what the late-fee calculator expects, and so on — so you're not retyping numbers between tools.&lt;/p&gt;

&lt;p&gt;Hub repo with the full list: &lt;a href="https://github.com/kleogeos/awesome-freelance-tools" rel="noopener noreferrer"&gt;https://github.com/kleogeos/awesome-freelance-tools&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you'd rather not install anything, there are free browser versions (just forms, nothing uploaded) at &lt;a href="https://kleogeos.github.io/freelancer-tools/?src=devto1" rel="noopener noreferrer"&gt;https://kleogeos.github.io/freelancer-tools/?src=devto1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Standard disclaimer: the contract/NDA generators are deliberately simple templates (not legal advice), and that's stated right on the generated document.&lt;/p&gt;

&lt;p&gt;Happy to answer questions about any of them, or hear what's still missing from the workflow.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>python</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
