<?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>Forem: Rodion Kazennov</title>
    <description>The latest articles on Forem by Rodion Kazennov (@nefayran).</description>
    <link>https://forem.com/nefayran</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%2F3643130%2Fc65fbbf1-6ab9-44e2-a28e-96e69769e9ce.jpg</url>
      <title>Forem: Rodion Kazennov</title>
      <link>https://forem.com/nefayran</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nefayran"/>
    <language>en</language>
    <item>
      <title>Japan Life Hub: Net Salary Calculator &amp; Housing Guide</title>
      <dc:creator>Rodion Kazennov</dc:creator>
      <pubDate>Thu, 04 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/nefayran/japan-life-hub-net-salary-calculator-housing-guide-2f95</link>
      <guid>https://forem.com/nefayran/japan-life-hub-net-salary-calculator-housing-guide-2f95</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyrcnuhxepgos9zk2c8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyrcnuhxepgos9zk2c8g.png" alt="Japan Life Hub: Net Salary Calculator &amp;amp; Housing Guide" width="800" height="753"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just shipped two new features for &lt;a href="https://japan.allkeep.app" rel="noopener noreferrer"&gt;Japan Life Hub&lt;/a&gt; — a Net Salary Calculator with 2025 tax rates and a comprehensive Housing Guide. Both available in English, Japanese, Russian, and Hindi.&lt;/p&gt;

&lt;p&gt;This article covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Year 1 vs Year 2 salary matters&lt;/li&gt;
&lt;li&gt;2025 Japanese tax rates and deductions&lt;/li&gt;
&lt;li&gt;Apartment rental costs breakdown&lt;/li&gt;
&lt;li&gt;Key terminology for foreigners&lt;/li&gt;
&lt;li&gt;Lessons learned building multilingual tools&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Year 1 Salary Trap
&lt;/h2&gt;

&lt;p&gt;When I moved to Japan, my first paycheck was surprisingly high. Then Year 2 hit.&lt;/p&gt;

&lt;p&gt;The catch: Japan's &lt;strong&gt;resident tax&lt;/strong&gt; (住民税 &lt;em&gt;juuminzei&lt;/em&gt;) is calculated on previous year's income and collected the following year. Your first year in Japan? Zero resident tax. Year 2? Roughly 10% of your gross salary disappears.&lt;/p&gt;

&lt;p&gt;Nobody told me this. I built the calculator I wish I had.&lt;/p&gt;

&lt;h2&gt;
  
  
  Net Salary Calculator
&lt;/h2&gt;

&lt;p&gt;The calculator shows both Year 1 and Year 2 take-home pay side by side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyrcnuhxepgos9zk2c8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyrcnuhxepgos9zk2c8g.png" alt="Net Salary Calculator Year 1 vs Year 2" width="800" height="753"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2025 Tax Rates
&lt;/h3&gt;

&lt;p&gt;Spent a day researching current rates from official sources. Here's what's deducted from your salary:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Social Insurance (Employee Share):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Rate&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Health Insurance&lt;/td&gt;
&lt;td&gt;4.955%&lt;/td&gt;
&lt;td&gt;Tokyo rate, March 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term Care&lt;/td&gt;
&lt;td&gt;0.795%&lt;/td&gt;
&lt;td&gt;Ages 40-64 only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pension&lt;/td&gt;
&lt;td&gt;9.15%&lt;/td&gt;
&lt;td&gt;Capped at ¥650k/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Employment Insurance&lt;/td&gt;
&lt;td&gt;0.55%&lt;/td&gt;
&lt;td&gt;April 2025 update&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Income Tax:&lt;/strong&gt; Progressive 5-45% across 7 brackets, plus 2.1% reconstruction surcharge until 2037.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resident Tax:&lt;/strong&gt; ~10% (6% prefectural + 4% municipal), delayed one year.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculator Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Employment type toggle:&lt;/strong&gt; Employee vs Self-employed (different deductions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Age selector:&lt;/strong&gt; Long-term care insurance kicks in at 40&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependents &amp;amp; spouse:&lt;/strong&gt; Affects deductions for employees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual breakdown bar:&lt;/strong&gt; See where your money goes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Salary presets:&lt;/strong&gt; Junior ¥3M, Mid ¥5M, Senior ¥7M, Manager ¥10M&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share button:&lt;/strong&gt; Copy summary to clipboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The "What You Get Back" section explains what you're paying for — 70% healthcare coverage, pension from 65, unemployment benefits. Japanese social insurance is actually good value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Housing Guide
&lt;/h2&gt;

&lt;p&gt;Finding an apartment in Japan as a foreigner is confusing. Unique fees, guarantor requirements, Japanese-only listings.&lt;/p&gt;

&lt;p&gt;The guide covers the entire process in 8 sections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Terminology
&lt;/h3&gt;

&lt;p&gt;Japanese rental vocabulary that confused me:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Japanese&lt;/th&gt;
&lt;th&gt;Romaji&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;敷金&lt;/td&gt;
&lt;td&gt;&lt;em&gt;shikikin&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Deposit, 1-2 months, refundable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;礼金&lt;/td&gt;
&lt;td&gt;&lt;em&gt;reikin&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;"Key money" gift to landlord, 0-2 months, gone forever&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;管理費&lt;/td&gt;
&lt;td&gt;&lt;em&gt;kanrihi&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Monthly maintenance fee, ¥3,000-15,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;更新料&lt;/td&gt;
&lt;td&gt;&lt;em&gt;koushinryo&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Renewal fee, ~1 month every 2 years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;保証会社&lt;/td&gt;
&lt;td&gt;&lt;em&gt;hoshougaisha&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Guarantor company, 30-100% of 1 month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Good news: less than 50% of renters now pay key money. Look for &lt;strong&gt;礼金なし&lt;/strong&gt; (&lt;em&gt;reikin nashi&lt;/em&gt;) listings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial Costs Example
&lt;/h3&gt;

&lt;p&gt;For ¥80,000/month rent:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;th&gt;Refundable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First month rent&lt;/td&gt;
&lt;td&gt;¥80,000&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deposit&lt;/td&gt;
&lt;td&gt;¥80,000&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key money&lt;/td&gt;
&lt;td&gt;¥80,000&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agency fee&lt;/td&gt;
&lt;td&gt;¥88,000&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guarantor&lt;/td&gt;
&lt;td&gt;¥40,000-80,000&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insurance&lt;/td&gt;
&lt;td&gt;¥15,000&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lock change&lt;/td&gt;
&lt;td&gt;¥15,000&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;¥398,000-438,000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's 5-6x monthly rent upfront. Budget accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to Search
&lt;/h3&gt;

&lt;p&gt;The Housing Guide covers all major platforms — from Japanese-only sites like SUUMO with the largest listings, to English-friendly options like Real Estate Japan and GaijinPot, plus government UR Housing with no key money or guarantor requirements.&lt;/p&gt;

&lt;p&gt;Pro tip: UR Housing has no reikin, no guarantor requirement, no renewal fees. Limited availability but worth checking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Timing Matters
&lt;/h3&gt;

&lt;p&gt;Avoid March-April. Everyone moves — new graduates, company transfers. Prices spike, competition fierce.&lt;/p&gt;

&lt;p&gt;Best time: May-February. More negotiation room, landlords eager to fill vacant units.&lt;/p&gt;

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

&lt;p&gt;Japan Life Hub now has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initial Costs Calculator&lt;/li&gt;
&lt;li&gt;Net Salary Calculator&lt;/li&gt;
&lt;li&gt;Moving to Japan Guide&lt;/li&gt;
&lt;li&gt;Housing Guide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coming soon: Monthly Budget Planner, City Comparison Tool, First Year Timeline.&lt;/p&gt;

&lt;p&gt;The goal is one place for everything you need to know about living in Japan — practical tools, not generic advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://japan.allkeep.app/en/tools/net-salary" rel="noopener noreferrer"&gt;Net Salary Calculator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://japan.allkeep.app/en/guides/housing" rel="noopener noreferrer"&gt;Housing Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://japan.allkeep.app/en/tools" rel="noopener noreferrer"&gt;All Tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built with Next.js, TypeScript, Tailwind CSS. All calculations run client-side, no data collected.&lt;/p&gt;

&lt;p&gt;If you're moving to Japan or know someone who is — share the link.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://allkeep.org/en/blog/japan-life-hub-net-salary-housing-guide" rel="noopener noreferrer"&gt;Read on AllKeep →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>japan</category>
      <category>salarycalculator</category>
      <category>housing</category>
      <category>relocation</category>
    </item>
    <item>
      <title>Build a Chrome Extension with React, TypeScript and Vite</title>
      <dc:creator>Rodion Kazennov</dc:creator>
      <pubDate>Wed, 03 Dec 2025 12:13:19 +0000</pubDate>
      <link>https://forem.com/nefayran/build-a-chrome-extension-with-react-typescript-and-vite-31ho</link>
      <guid>https://forem.com/nefayran/build-a-chrome-extension-with-react-typescript-and-vite-31ho</guid>
      <description>&lt;p&gt;This article walks through building a Chrome extension from scratch using React, TypeScript and Vite. We'll build a Freelance Rate Calculator that helps developers check their market rate.&lt;/p&gt;

&lt;p&gt;This article includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup React + Vite + TypeScript project for Chrome Extension&lt;/li&gt;
&lt;li&gt;Configure manifest.json for Manifest V3&lt;/li&gt;
&lt;li&gt;Build calculator UI with Tailwind CSS&lt;/li&gt;
&lt;li&gt;Load and test extension locally&lt;/li&gt;
&lt;li&gt;Submit to Chrome Web Store&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup Project
&lt;/h2&gt;

&lt;p&gt;Create new Vite project with React and TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm create vite@latest rate-calculator -- --template react-ts
cd rate-calculator
npm install

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add Tailwind CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure &lt;code&gt;tailwind.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add Tailwind directives to &lt;code&gt;src/index.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@tailwind base;
@tailwind components;
@tailwind utilities;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add Lucide icons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install lucide-react

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add Manifest V3
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;public/manifest.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "manifest_version": 3,
  "name": "Freelance Rate Calculator",
  "version": "1.0.0",
  "description": "Calculate your freelance rate based on tech stack, experience, and location",
  "action": {
    "default_popup": "index.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;public/icons/&lt;/code&gt; folder and add extension icons in 16x16, 48x48, and 128x128 sizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add Rate Data
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;src/data/rates.ts&lt;/code&gt; with tech stacks, experience levels, and locations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface TechStack {
  id: string;
  name: string;
  baseRate: number;
  demand: "high" | "medium" | "low";
}

export interface ExperienceLevel {
  id: string;
  name: string;
  years: string;
  multiplier: number;
}

export interface Location {
  id: string;
  name: string;
  multiplier: number;
}

export const techStacks: TechStack[] = [
  { id: "genai", name: "GenAI / LLM", baseRate: 175, demand: "high" },
  { id: "rust", name: "Rust", baseRate: 135, demand: "high" },
  { id: "react", name: "React", baseRate: 90, demand: "high" },
  { id: "typescript", name: "TypeScript", baseRate: 92, demand: "high" },
  { id: "nodejs", name: "Node.js", baseRate: 85, demand: "high" },
  { id: "python", name: "Python", baseRate: 90, demand: "high" },
  // add more stacks...
];

export const experienceLevels: ExperienceLevel[] = [
  { id: "junior", name: "Junior", years: "0-2 years", multiplier: 0.55 },
  { id: "mid", name: "Mid-level", years: "3-5 years", multiplier: 1.0 },
  { id: "senior", name: "Senior", years: "5-8 years", multiplier: 1.45 },
  { id: "lead", name: "Lead / Architect", years: "8+ years", multiplier: 1.85 },
];

export const locations: Location[] = [
  { id: "usa", name: "United States", multiplier: 1.0 },
  { id: "uk", name: "United Kingdom", multiplier: 0.85 },
  { id: "germany", name: "Germany", multiplier: 0.82 },
  { id: "japan", name: "Japan", multiplier: 0.62 },
  { id: "india", name: "India", multiplier: 0.32 },
  // add more countries...
];

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rate calculation formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getMarketRate = (
  stack: TechStack,
  exp: ExperienceLevel,
  loc: Location
) =&amp;gt; {
  const base = stack.baseRate * exp.multiplier * loc.multiplier;
  return {
    low: Math.round(base * 0.85),
    mid: Math.round(base),
    high: Math.round(base * 1.15),
  };
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: Senior React developer in Germany = &lt;code&gt;90 * 1.45 * 0.82 = $107/hr&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Calculator UI
&lt;/h2&gt;

&lt;p&gt;Update &lt;code&gt;src/App.tsx&lt;/code&gt; with calculator form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";
import { techStacks, experienceLevels, locations } from "./data/rates";
import type { TechStack, ExperienceLevel, Location } from "./data/rates";

function App() {
  const [stack, setStack] = useState&amp;lt;TechStack | null&amp;gt;(null);
  const [experience, setExperience] = useState&amp;lt;ExperienceLevel | null&amp;gt;(null);
  const [location, setLocation] = useState&amp;lt;Location | null&amp;gt;(null);
  const [myRate, setMyRate] = useState("");
  const [showResult, setShowResult] = useState(false);

  const getMarketRate = () =&amp;gt; {
    if (!stack || !experience || !location) return null;
    const base = stack.baseRate * experience.multiplier * location.multiplier;
    return {
      low: Math.round(base * 0.85),
      mid: Math.round(base),
      high: Math.round(base * 1.15),
    };
  };

  const handleCheck = () =&amp;gt; {
    if (stack &amp;amp;&amp;amp; experience &amp;amp;&amp;amp; location &amp;amp;&amp;amp; myRate) {
      setShowResult(true);
    }
  };

  // render form or results based on showResult state
  return (
    &amp;lt;div className="w-[400px] h-[600px] p-4 bg-gray-900 text-white"&amp;gt;
      {/* form inputs and results */}
    &amp;lt;/div&amp;gt;
  );
}

export default App;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set fixed popup dimensions in &lt;code&gt;src/index.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
  width: 400px;
  height: 600px;
  margin: 0;
  overflow: hidden;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Input form with dropdowns for stack, experience, location:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny6qas5a1kgvk0yy0o2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny6qas5a1kgvk0yy0o2i.png" alt="Rate Calculator Input Form" width="398" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Results screen showing market rate comparison:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4acaul3thd0c263rm67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4acaul3thd0c263rm67.png" alt="Rate Calculator Results" width="393" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Extension
&lt;/h2&gt;

&lt;p&gt;Update &lt;code&gt;vite.config.ts&lt;/code&gt; for extension build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  build: {
    outDir: "dist",
    rollupOptions: {
      input: "index.html",
    },
  },
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates &lt;code&gt;dist/&lt;/code&gt; folder with your extension files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Load Extension Locally
&lt;/h2&gt;

&lt;p&gt;Open Chrome and navigate to &lt;code&gt;chrome://extensions&lt;/code&gt;. Enable "Developer mode" in top right corner.&lt;/p&gt;

&lt;p&gt;Click "Load unpacked" and select the &lt;code&gt;dist/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fat60l8nx29x5kktwdb4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fat60l8nx29x5kktwdb4x.png" alt="Extension loaded in Chrome" width="454" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the extension icon in toolbar to test the popup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Submit to Chrome Web Store
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://chrome.google.com/webstore/devconsole" rel="noopener noreferrer"&gt;Chrome Web Store Developer Dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First time requires $5 one-time developer fee.&lt;/p&gt;

&lt;p&gt;Prepare assets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extension icon: 128x128 PNG&lt;/li&gt;
&lt;li&gt;Screenshot: 1280x800 or 640x400&lt;/li&gt;
&lt;li&gt;Promotional tile: 440x280&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create ZIP of your &lt;code&gt;dist/&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd dist &amp;amp;&amp;amp; zip -r ../extension.zip . &amp;amp;&amp;amp; cd ..

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upload ZIP, fill in description, add screenshots, submit for review.&lt;/p&gt;

&lt;p&gt;Review takes 1-3 days. Common rejection reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keyword stuffing in description&lt;/li&gt;
&lt;li&gt;Missing privacy policy (if using permissions)&lt;/li&gt;
&lt;li&gt;Incorrect screenshots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After approval:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6a83shveo5wk2zcqud3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6a83shveo5wk2zcqud3.png" alt="Extension published in Chrome Web Store" width="800" height="761"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's all. We built a Chrome extension with React, TypeScript and Vite, tested it locally, and published to Chrome Web Store.&lt;/p&gt;

&lt;p&gt;Final stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React 18&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;Manifest V3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Live extension: &lt;a href="https://chromewebstore.google.com/detail/freelance-rate-calculator/ofmocfkagkdpbkapmjmobbnomjkiphlf" rel="noopener noreferrer"&gt;Freelance Rate Calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you liked the article, follow me on &lt;a href="https://twitter.com/Nefayran" rel="noopener noreferrer"&gt;Twitter @Nefayran&lt;/a&gt; for more #buildinpublic content.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://allkeep.org/en/blog/build-chrome-extension-react-typescript-vite" rel="noopener noreferrer"&gt;Read on AllKeep →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>freelance</category>
    </item>
  </channel>
</rss>
