<?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: OdaloV</title>
    <description>The latest articles on DEV Community by OdaloV (@odalov).</description>
    <link>https://dev.to/odalov</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%2F3720244%2Fdbb171f4-1cc5-4572-b672-6e7e7da7cd84.png</url>
      <title>DEV Community: OdaloV</title>
      <link>https://dev.to/odalov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/odalov"/>
    <language>en</language>
    <item>
      <title>Building on the Blockchain: A Developer's Guide to Solidity &amp; Smart Contracts</title>
      <dc:creator>OdaloV</dc:creator>
      <pubDate>Mon, 01 Jun 2026 17:48:28 +0000</pubDate>
      <link>https://dev.to/odalov/building-on-the-blockchain-a-developers-guide-to-solidity-smart-contracts-414c</link>
      <guid>https://dev.to/odalov/building-on-the-blockchain-a-developers-guide-to-solidity-smart-contracts-414c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Code is law — and on Ethereum, it runs forever."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Is a Smart Contract?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;smart contract&lt;/strong&gt; is a self-executing program stored on a blockchain. It runs automatically when predefined conditions are met. No middlemen, no downtime, no censorship.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immutable (once deployed, the logic doesn't change)&lt;/li&gt;
&lt;li&gt;Transparent (anyone can read the code)&lt;/li&gt;
&lt;li&gt;Trustless (no central authority needed)&lt;/li&gt;
&lt;li&gt;Global (accessible from anywhere on Earth)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Solidity
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Solidity&lt;/strong&gt; is the primary language for writing smart contracts on Ethereum and EVM-compatible chains like Polygon, BNB Chain, Avalanche, Base and others.&lt;/p&gt;

&lt;p&gt;It's a statically-typed, contract-oriented language with syntax that feels familiar if you've used JavaScript, C++, or Java.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract HelloBlockchain {
    string public message = "gm, world";

    function setMessage(string calldata _msg) external {
        message = _msg;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Core Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. State Variables &amp;amp; Storage
&lt;/h3&gt;

&lt;p&gt;Everything stored on-chain costs &lt;strong&gt;gas&lt;/strong&gt;. Be deliberate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Bank {
    mapping(address =&amp;gt; uint256) public balances; // stored on-chain
    uint256 public totalDeposits;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Functions &amp;amp; Visibility
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Modifier&lt;/th&gt;
&lt;th&gt;Who Can Call&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;public&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Anyone (internal + external)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;external&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only from outside the contract&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;internal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only this contract + children&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;private&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only this contract&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Payable Functions — Receiving ETH
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function deposit() external payable {
    balances[msg.sender] += msg.value;
    totalDeposits += msg.value;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;msg.sender&lt;/code&gt; = the caller's address&lt;br&gt;&lt;br&gt;
&lt;code&gt;msg.value&lt;/code&gt; = ETH sent with the call (in wei)&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Events — Your On-Chain Logs
&lt;/h3&gt;

&lt;p&gt;Events are cheap to emit and essential for off-chain apps to track activity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event Deposited(address indexed user, uint256 amount);

function deposit() external payable {
    balances[msg.sender] += msg.value;
    emit Deposited(msg.sender, msg.value);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Modifiers — Reusable Guards
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modifier onlyOwner() {
    require(msg.sender == owner, "Not the owner");
    _;
}

function withdraw(uint256 amount) external onlyOwner {
    payable(owner).transfer(amount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  A Real Example: Simple Token
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract SimpleToken {
    string public name = "DevToken";
    string public symbol = "DEV";
    uint8 public decimals = 18;
    uint256 public totalSupply;

    mapping(address =&amp;gt; uint256) public balanceOf;

    event Transfer(address indexed from, address indexed to, uint256 value);

    constructor(uint256 _initialSupply) {
        totalSupply = _initialSupply * 10 ** decimals;
        balanceOf[msg.sender] = totalSupply;
    }

    function transfer(address to, uint256 amount) external returns (bool) {
        require(balanceOf[msg.sender] &amp;gt;= amount, "Insufficient balance");
        balanceOf[msg.sender] -= amount;
        balanceOf[to] += amount;
        emit Transfer(msg.sender, to, amount);
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the essence of an &lt;strong&gt;ERC-20&lt;/strong&gt; token. The real standard adds &lt;code&gt;approve&lt;/code&gt;, &lt;code&gt;transferFrom&lt;/code&gt;, and &lt;code&gt;allowance&lt;/code&gt;  but this gives you the foundation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security: The Non-Negotiables
&lt;/h2&gt;

&lt;p&gt;Smart contract bugs are &lt;strong&gt;permanent and public&lt;/strong&gt;. The stakes are high.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reentrancy Attack
&lt;/h3&gt;

&lt;p&gt;The infamous bug behind the $60M DAO hack (2016).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// VULNERABLE 
function withdraw() external {
    uint256 amount = balances[msg.sender];
    (bool success,) = msg.sender.call{value: amount}(""); // external call BEFORE state update
    balances[msg.sender] = 0; // too late
}

// SAFE 
function withdraw() external {
    uint256 amount = balances[msg.sender];
    balances[msg.sender] = 0;           // 1. Update state
    (bool success,) = msg.sender.call{value: amount}(""); // 2. Then interact
    require(success, "Transfer failed");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; Always update state &lt;em&gt;before&lt;/em&gt; making external calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Common Pitfalls
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integer overflow/underflow&lt;/strong&gt; — Solidity 0.8+ handles this automatically with built-in checks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tx.origin vs msg.sender&lt;/strong&gt; — Never use &lt;code&gt;tx.origin&lt;/code&gt; for authorization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unchecked return values&lt;/strong&gt; — Always check the return value of &lt;code&gt;call()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp dependence&lt;/strong&gt; — &lt;code&gt;block.timestamp&lt;/code&gt; can be manipulated slightly by miners&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Developer Toolchain
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardhat&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Local dev environment, testing, deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Foundry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Blazing-fast testing in Solidity itself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Remix IDE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Browser-based IDE, great for prototyping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenZeppelin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Battle-tested contract libraries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ethers.js / Viem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JavaScript libraries to interact with contracts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alchemy / Infura&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Node providers for mainnet/testnet access&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Quick Start with Hardhat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-contract &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-contract
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; hardhat
npx hardhat init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy a Contract
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// scripts/deploy.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SimpleToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForDeployment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Deployed to:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat run scripts/deploy.js &lt;span class="nt"&gt;--network&lt;/span&gt; sepolia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Gas Optimization Tips
&lt;/h2&gt;

&lt;p&gt;Gas efficiency = lower costs for your users = competitive advantage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//  Expensive: reading from storage in a loop
for (uint i = 0; i &amp;lt; users.length; i++) {
    total += balances[users[i]];
}

//  Cheaper: cache storage reads in memory
uint256 len = users.length;
for (uint i = 0; i &amp;lt; len; i++) {
    total += balances[users[i]];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other wins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;uint256&lt;/code&gt; over smaller types ,the EVM works in 32-byte slots.&lt;/li&gt;
&lt;li&gt;Mark functions &lt;code&gt;view&lt;/code&gt; or &lt;code&gt;pure&lt;/code&gt; when they don't modify state&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;calldata&lt;/code&gt; instead of &lt;code&gt;memory&lt;/code&gt; for external function parameters&lt;/li&gt;
&lt;li&gt;Pack struct variables to fit in fewer storage slots&lt;/li&gt;
&lt;li&gt;Emit events instead of storing data you only need off-chain&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Contract Standards Worth Knowing
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Standard&lt;/th&gt;
&lt;th&gt;What It Is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ERC-20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fungible tokens (USDC, DAI, UNI)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ERC-721&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Non-fungible tokens / NFTs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ERC-1155&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-token standard (games, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ERC-4626&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tokenized vaults (DeFi yield)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EIP-2612&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gasless approvals via signatures&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenZeppelin has production-ready implementations of all of these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    constructor() ERC20("MyToken", "MTK") {
        _mint(msg.sender, 1_000_000 * 10 ** decimals());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test/Token.test.js (Hardhat + Ethers)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SimpleToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should assign total supply to deployer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSigners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SimpleToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;totalSupply&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should transfer tokens correctly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSigners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SimpleToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recipientBalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recipientBalance&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Smart contract development is one of the most &lt;strong&gt;high-stakes&lt;/strong&gt; disciplines in software. A bug that slips through in a web app might annoy users. A bug in a smart contract holding $10M can be catastrophic and irreversible.&lt;/p&gt;

&lt;p&gt;The upside? You're building &lt;strong&gt;programmable money&lt;/strong&gt;, &lt;strong&gt;unstoppable applications&lt;/strong&gt;, and &lt;strong&gt;trustless infrastructure&lt;/strong&gt; that can outlive any company or server.&lt;/p&gt;




</description>
      <category>blockchain</category>
      <category>ethereum</category>
      <category>tutorial</category>
      <category>web3</category>
    </item>
    <item>
      <title>Middleware in Go</title>
      <dc:creator>OdaloV</dc:creator>
      <pubDate>Thu, 14 May 2026 16:26:13 +0000</pubDate>
      <link>https://dev.to/odalov/middleware-in-go-2b9n</link>
      <guid>https://dev.to/odalov/middleware-in-go-2b9n</guid>
      <description>&lt;p&gt;If you've built any web application in Go, you've probably heard about middlewares. But what exactly are they?&lt;/p&gt;

&lt;p&gt;A middleware is just a function that sits between your HTTP server and your route handlers. It can inspect, modify, or even stop a request before it reaches your main application logic.&lt;/p&gt;

&lt;p&gt;Think of it as a pipeline.Every request passes through each middleware in order before hitting your handler, and the response travels back through them on the way out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;A middleware accepts a handler and returns a new one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;MyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// runs before your handler&lt;/span&gt;
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;// runs after your handler&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  c.Next()
&lt;/h2&gt;

&lt;p&gt;When you register multiple middlewares, your framework doesn't run them independently. It builds a chain. Each middleware wraps the next one, like nested functions. &lt;code&gt;c.Next()&lt;/code&gt; is the call that says ,pass control to whatever comes next in that chain.&lt;/p&gt;

&lt;p&gt;Without it, the chain stops dead. Your route handler never runs, and the client gets no response.&lt;/p&gt;

&lt;p&gt;This also means you can intentionally skip it to reject a request early:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;RequireAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusUnauthorized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unauthorized"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// only reach here if auth passes&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Registering middleware
&lt;/h2&gt;

&lt;p&gt;Most frameworks let you attach middleware at three levels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global&lt;/strong&gt; middleware runs on every single request your app receives ,logger and panic recovery belong here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Recover&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Group&lt;/strong&gt; middleware applies only to a subset of routes. This is the right place for auth ,you probably don't want to guard your &lt;code&gt;/health&lt;/code&gt; endpoint the same way you guard &lt;code&gt;/api/users&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RequireAuth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Route-level&lt;/strong&gt; middleware is for one-off logic that doesn't belong anywhere else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;adminHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RequireAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a middleware needs to run everywhere, make it global. If it only makes sense for a set of routes, scope it to a group. Route-level is a last resort.&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Kenya's proposed AI Bill 2026</title>
      <dc:creator>OdaloV</dc:creator>
      <pubDate>Mon, 11 May 2026 08:30:49 +0000</pubDate>
      <link>https://dev.to/odalov/kenyas-proposed-ai-bill-2026-2n4h</link>
      <guid>https://dev.to/odalov/kenyas-proposed-ai-bill-2026-2n4h</guid>
      <description>&lt;p&gt;Kenya has the &lt;strong&gt;highest AI adoption rate globally&lt;/strong&gt; – 97.5% of internet users engage with AI monthly (Digital 2026). 68% of Kenyan firms aim for full AI adoption by end of 2026 (KPMG).&lt;/p&gt;

&lt;p&gt;But the proposed &lt;strong&gt;AI Bill, 2026&lt;/strong&gt; has issues:&lt;br&gt;
&lt;strong&gt;1. Prison time for locals.&lt;/strong&gt; Violations carry fines up to $38,000 and &lt;strong&gt;three years in jail&lt;/strong&gt;. Directors must prove their innocence, reversing Kenya's constitutional burden of proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A loophole for Big Tech.&lt;/strong&gt; OpenAI's clinical AI runs in 16 Nairobi clinics. A Dutch TB screener processes thousands of X-rays. Google is testing maternal ultrasound. &lt;strong&gt;None are explicitly covered.&lt;/strong&gt; A local dev faces prison. OpenAI faces nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. No evidence of harm.&lt;/strong&gt; The Bill was drafted without consulting health, agriculture, or finance sectors about what AI harms they actually experience. It defaults to maximum deterrence (prison) by reflex, not data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Remove criminal penalties, close the foreign loophole, and follow the EU model of administrative fines.&lt;/p&gt;

&lt;p&gt;Kenya's developers deserve precision.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>kenya</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>OdaloV</dc:creator>
      <pubDate>Mon, 11 May 2026 08:23:33 +0000</pubDate>
      <link>https://dev.to/odalov/-4aoa</link>
      <guid>https://dev.to/odalov/-4aoa</guid>
      <description></description>
    </item>
    <item>
      <title>Digital Hoarding</title>
      <dc:creator>OdaloV</dc:creator>
      <pubDate>Sat, 11 Apr 2026 15:52:47 +0000</pubDate>
      <link>https://dev.to/odalov/digital-hoarding-3p5h</link>
      <guid>https://dev.to/odalov/digital-hoarding-3p5h</guid>
      <description>&lt;p&gt;&lt;em&gt;A personal journey through 4GB of laptop clutter and over 800 phone screenshots I'll never look at again&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The discovery
&lt;/h2&gt;

&lt;p&gt;During some late-night reading, I stumbled across a 2025 paper by Liu &amp;amp; Liu in &lt;em&gt;Frontiers in Psychology&lt;/em&gt; on something called &lt;strong&gt;digital hoarding&lt;/strong&gt;.&lt;br&gt;
I'd never heard the term before.&lt;br&gt;
But as I kept reading, I felt Called out.&lt;/p&gt;

&lt;p&gt;They defined it as: &lt;em&gt;"The compulsive accumulation of digital files to the point of distress and disorganization."&lt;/em&gt;&lt;br&gt;
And I thought to myself ,that's not only a research subject. that's my laptop,and probably my phone too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On my laptop:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/Downloads&lt;/code&gt; – 47 PDFs, 12 driver installers, 3 tutorials I never finished. Oldest: 2019&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/Desktop&lt;/code&gt; – Screenshots of error messages I Googled and fixed. Oldest: 2021&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/code/experiments&lt;/code&gt; – 23 half-built projects, 18 with broken dependencies. Oldest: 2020&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/Documents/old-work&lt;/code&gt; – Repos from two jobs ago. Two jobs ago! Oldest: 2018&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On my phone:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Screenshots folder – 1,112 images. Error messages, tweets, "read later" articles, memes.&lt;/li&gt;
&lt;li&gt;Photos (duplicates) – The same picture saved 3-4 times.&lt;/li&gt;
&lt;li&gt;Old app caches – 2.1 GB from apps I haven't opened in months.&lt;/li&gt;
&lt;li&gt;Voice notes – 47 recordings. "Reminder to self" from 2022 to 2026.&lt;/li&gt;
&lt;li&gt;WhatsApp images – From groups I left in 2023.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was a digital hoarder with a terminal and a smartphone addiction.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Liu &amp;amp; Liu taught me
&lt;/h2&gt;

&lt;p&gt;The paper described digital hoarding as a &lt;strong&gt;"double-edged sword."&lt;/strong&gt;&lt;br&gt;
On one edge: It feels responsible. "I might need this someday." "Better to save it than lose it."&lt;br&gt;
On the other edge: It's actively hurting me — on every device I own.&lt;br&gt;
They listed consequences that hit too close to home:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cognitive load&lt;/strong&gt; – Every extra file is a tiny decision I don't make&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision fatigue&lt;/strong&gt; – Which of these 14 project folders is the real one?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anxiety&lt;/strong&gt; – "What if I delete something important?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Battery drain&lt;/strong&gt; – Your phone constantly indexing thousands of unused files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the part that really got me: &lt;em&gt;"A protective behavior that eventually becomes a burden."&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The hidden cost never measured
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before cleanup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storage used: 10 GB&lt;/li&gt;
&lt;li&gt;Boot time: 48 seconds&lt;/li&gt;
&lt;li&gt;Search time: 6-8 seconds&lt;/li&gt;
&lt;li&gt;Battery life: ~6 hours&lt;/li&gt;
&lt;li&gt;Backup time: 45 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After deleting 500+ old files and 2,000+ screenshots:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storage used: 8 GB (down 2 GB)&lt;/li&gt;
&lt;li&gt;Boot time: 31 seconds (down 35%)&lt;/li&gt;
&lt;li&gt;Search time: 1-2 seconds (down 75%)&lt;/li&gt;
&lt;li&gt;Battery life: ~8 hours (up 33%)&lt;/li&gt;
&lt;li&gt;Backup time: 12 minutes (down 73%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No hardware upgrade. No factory reset. Just… deleting things.&lt;/p&gt;




&lt;h2&gt;
  
  
  The developer-specific hoarding patterns
&lt;/h2&gt;

&lt;p&gt;Liu &amp;amp; Liu didn't study developers specifically. But I noticed patterns unique to our craft — and how they spill onto our phones.&lt;/p&gt;

&lt;h3&gt;
  
  
  1: The tutorial graveyard
&lt;/h3&gt;

&lt;p&gt;We start a tutorial. Clone the repo. Follow along for 30 minutes. Get distracted. Never finish.&lt;br&gt;
But we keep the folder. &lt;em&gt;Just in case.&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;My count:&lt;/strong&gt; 23 unfinished tutorial projects. 18 using packages that are now deprecated.&lt;/p&gt;

&lt;h3&gt;
  
  
  2: The error screenshot museum
&lt;/h3&gt;

&lt;p&gt;Something breaks. We screenshot the error on our laptop.  Then we Google it. Fix it. Feel proud.&lt;br&gt;
But we never delete some of the screenshots.&lt;br&gt;
&lt;strong&gt;My count:&lt;/strong&gt; 110 laptop screenshots + 1,110 phone screenshots. I will never look at 99% of them again.&lt;/p&gt;

&lt;h3&gt;
  
  
  3: I'll refactor this someday
&lt;/h3&gt;

&lt;p&gt;Old projects. Old code. Old mistakes. We keep them like trophies.&lt;br&gt;
&lt;strong&gt;My count:&lt;/strong&gt; 4GB of code I haven't touched in over two years.&lt;/p&gt;

&lt;h3&gt;
  
  
  4: The screenshot spiral
&lt;/h3&gt;

&lt;p&gt;See something interesting? Screenshot. Want to remember a tweet? Screenshot. Need to save a receipt? Screenshot.&lt;br&gt;
Then never organize them. Never look at them. Never delete them.&lt;br&gt;
&lt;strong&gt;My count:&lt;/strong&gt; 1,112 screenshots. I remember taking maybe 200 of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  5: The "I'll clean this later" cache (phone)
&lt;/h3&gt;

&lt;p&gt;Apps cache images, videos, and files. We ignore it. It grows. We run out of storage. &lt;br&gt;
&lt;strong&gt;My count:&lt;/strong&gt; 2 GB of "System Data" — a black hole of forgotten files.&lt;/p&gt;




&lt;h4&gt;
  
  
  Liu &amp;amp; Liu ended their paper with a question:
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;"How do we design systems that support selective retention rather than indiscriminate accumulation?"&lt;/em&gt;&lt;br&gt;
I don't have an answer. But for me,I'll start small. One old file. One screenshot. One deleted folder at a time.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Progressive Web Apps (PWAs): The Best of Both Worlds</title>
      <dc:creator>OdaloV</dc:creator>
      <pubDate>Sun, 01 Mar 2026 12:38:02 +0000</pubDate>
      <link>https://dev.to/odalov/progressive-web-apps-pwas-the-best-of-both-worlds-49gl</link>
      <guid>https://dev.to/odalov/progressive-web-apps-pwas-the-best-of-both-worlds-49gl</guid>
      <description>&lt;h2&gt;
  
  
  What is PWA?
&lt;/h2&gt;

&lt;p&gt;Progressive Web Apps are regular websites built with standard web technologies such as HTML, CSS and JavaScript, that progressively enhance to deliver an app-like experience. They work in any browser but can be installed on your device like a native app. Think of them as websites that put on an app costume.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Technologies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;HTTPS - Secure connection required for all modern web capabilities.&lt;/li&gt;
&lt;li&gt;Web App Manifest - A JSON file defining your app's name, icons, colors, and launch behavior.&lt;/li&gt;
&lt;li&gt;Service Workers - Background scripts that enable offline functionality, caching, and push notifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why PWAs Matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Users
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;    Install with one click - No app stores, no approvals, no fees.&lt;/li&gt;
&lt;li&gt;    Works offline - Access content even without internet.&lt;/li&gt;
&lt;li&gt;    Lightweight &lt;/li&gt;
&lt;li&gt;    Cross-platform - Same app works on any device with a browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Developers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Single codebase - One app for all platforms instead of separate iOS/Android builds.&lt;/li&gt;
&lt;li&gt;    Lower costs - PWA development ranges from $15,000-$150,000 versus $50,000+ per native platform.&lt;/li&gt;
&lt;li&gt;    No app store gatekeepers - Deploy updates instantly without waiting for approval.&lt;/li&gt;
&lt;li&gt;    SEO-friendly - PWAs are indexable by search engines unlike native apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Microsoft:
&lt;/h3&gt;

&lt;p&gt;Microsoft took a data-driven approach to PWAs, automatically identifying 1.5 million progressive web apps for inclusion in the Windows Store. This discovery opened up a massive ecosystem of applications that could run natively on Windows without any additional development work.&lt;/p&gt;

&lt;p&gt;The impact was twofold:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;  Users gained access to millions of apps without waiting for developers to build Windows-specific versions&lt;/li&gt;
&lt;li&gt;    Developers saw their apps appear in the Windows Store automatically—no extra effort required&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Microsoft's embrace of PWAs validated that the technology wasn't just for small projects—it was a legitimate distribution channel for the world's largest operating system.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Choose PWA
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PWAs are ideal for :
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;E-commerce - Higher conversions, better mobile experience.

Content-driven apps - News, blogs, media.

Businesses with limited budget - One app for all platforms.

Emerging markets - Works on slow connections.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The web is evolving, and PWAs are leading the charge toward a future where the line between websites and apps disappears entirely.&lt;/p&gt;

</description>
      <category>pwa</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Agentic-AI :Simple tools to autonomous partners</title>
      <dc:creator>OdaloV</dc:creator>
      <pubDate>Mon, 02 Feb 2026 09:26:32 +0000</pubDate>
      <link>https://dev.to/odalov/agentic-ai-simple-tools-to-autonomous-partners-f99</link>
      <guid>https://dev.to/odalov/agentic-ai-simple-tools-to-autonomous-partners-f99</guid>
      <description>&lt;p&gt;If you have been following AI development,then  you've seen the shift, from ChatGPT answering questions to Devin writing entire codebases. From simple chatbots to systems that plan, execute, and adapt.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes an AI Agentic?
&lt;/h2&gt;

&lt;p&gt;Agentic AI is about ,agency,the capacity to act independently toward goals. While a traditional AI model generates text based on patterns, an AI agent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sets and pursues goals&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Breaks problems into steps&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Uses tools to interact with the world&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learns from feedback&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Adapts its approach when stuck&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's like moving from a &lt;strong&gt;calculator&lt;/strong&gt;;executes commands, to a &lt;strong&gt;mathematician&lt;/strong&gt;;solves problems using tools and reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fundamental Loop: Perception → Reasoning → Action
&lt;/h2&gt;

&lt;p&gt;The simplest theoretical model of an AI agent is the &lt;strong&gt;Perception-Reasoning-Action cycle&lt;/strong&gt;:&lt;br&gt;
&lt;strong&gt;In practice with LLMs, this becomes the ReAct pattern&lt;/strong&gt; (Reason + Act):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    python

    # How an AI agent thinks and acts
    def agent_loop(objective, tools, memory):
    while not objective.achieved():
    # 1. PERCEPTION: Look around
    observation = perceive_environment()

    # 2. REASONING: Think about next step
    thought = llm_reason(objective, observation, memory)

    # 3. ACTION: Do something with tools
    action = choose_action(thought, tools)
    result = execute_action(action)

    # 4. UPDATE: Learn and continue
    memory.update(thought, action, result)

return "Task completed"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Breaking It Down with Fast Food &lt;/p&gt;

&lt;p&gt;Let's say you're craving KFC and tell an AI agent: "Get me KFC for dinner"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Old-School AI (Traditional Chatbot)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Would give you instructions:&lt;/p&gt;

&lt;p&gt;Go to the KFC website or use Glovo&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agentic AI (Autonomous Assistant)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Actually does it for you. Here's how it thinks:&lt;/p&gt;

&lt;p&gt;Agent's Thought Process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;PERCEIVES:&lt;/p&gt;

&lt;p&gt;Checks your current location&lt;/p&gt;

&lt;p&gt;Remembers you ordered KFC last Tuesday&lt;/p&gt;

&lt;p&gt;Notes you usually ask for extra ketchup&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;REASONS :&lt;/p&gt;

&lt;p&gt;They want KFC. Let me check where they are&lt;/p&gt;

&lt;p&gt;Found 3 KFCs nearby. Which one has the shortest wait time?&lt;/p&gt;

&lt;p&gt;They like the Zinger Burger based on last order.&lt;/p&gt;

&lt;p&gt;Should check for any discounts or offers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ACTS :&lt;/p&gt;

&lt;p&gt;Searches for nearby KFC locations&lt;/p&gt;

&lt;p&gt;Checks opening hours and current wait times&lt;/p&gt;

&lt;p&gt;Compares prices and specials&lt;/p&gt;

&lt;p&gt;Places the order via API&lt;/p&gt;

&lt;p&gt;Tracks the delivery in real-time&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UPDATES :&lt;/p&gt;

&lt;p&gt;Noted: they want extra ketchup. Remember for next time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The bottom line: The agent doesn't just talk about KFC ,it gets you the actual chicken.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Matters&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Agentic AI represents a fundamental shift:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You give goals, not step-by-step instructions&lt;/p&gt;

&lt;p&gt;AI handles complex multi-step processes&lt;/p&gt;

&lt;p&gt;Systems improve through experience&lt;/p&gt;

&lt;p&gt;One agent replaces what used to take multiple tools&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>agents</category>
      <category>python</category>
    </item>
  </channel>
</rss>
