This is a submission for the GitHub Finish-Up-A-Thon Challenge
What I Built
Transify is a Chrome extension that translates chat messages in real time, directly inside messaging platforms like WhatsApp Web, Telegram, Discord, Microsoft Teams, Messenger, and Instagram DMs. You don't copy-paste into Google Translate or switch tabs. The translations happen right there in the chat window.
The original version was a college mini project I built with two teammates. It worked, but it was held together with duct tape. Plain JavaScript, no build tools, no framework, and it used free translation APIs (MyMemory, LibreTranslate) that gave you basic word-for-word translations with no context awareness.
The comeback version is a complete rebuild. It now runs on Llama 3.3 70B via Groq for context-aware LLM translations, has a proper Next.js serverless backend, uses the WXT framework for the extension, and everything is in TypeScript. The translations actually sound like a human wrote them now instead of robotic word-for-word output.
What makes it different from just using Google Translate:
- It works inline. You double-click a chat bubble, and the translation pops up right there
- It auto-translates both incoming messages and your outgoing text
- You can set tone profiles (Casual, Professional, Empathetic, Playful, Gen Z) and the LLM adjusts the translation style accordingly
- You can control grammatical gender for languages that need it
- You can type inline overrides like
hello [playful][female]to change tone per message
Old repo: github.com/Karam-999/Transify--An-extension-for-real-time-chat-translation
New repo: github.com/Karam-999/transify-ai
Demo
The extension works across WhatsApp Web, Telegram, Discord, Microsoft Teams, Messenger, and Instagram DMs. You install it, pick your languages and tone, and it starts translating. The video shows the full flow.
The Comeback Story
Where it was before:
The first version of Transify was a college mini project. It was a Chrome extension built with plain JavaScript, a raw manifest.json, vanilla HTML/CSS popup, and one big content-full.js file that did everything. No framework, no build step, no TypeScript.
For translations, it called free APIs like MyMemory and LibreTranslate. These give you basic machine translation, the kind where "I'm dead serious" might come back as something about death in the target language. No context, no tone awareness, just word-for-word swaps. The auto-detect for source language didn't really work either since MyMemory needs explicit language codes, so we hardcoded en as fallback.
It also had some bugs. The error handling would silently return the original text as the "translation" if the API failed, so you'd think it translated but it actually didn't. And since the extension called external APIs directly from content scripts, CORS was a constant headache.
It worked well enough for the college submission, but it wasn't something you'd actually want to use daily.
What changed in the comeback:
Pretty much everything got rebuilt from scratch, but the core idea stayed the same.
Translation engine: Replaced the free translation APIs with Llama 3.3 70B via Groq. This was the biggest upgrade. Instead of word-for-word translations, you now get context-aware translations that understand what you're trying to say. Groq's inference is fast too, usually under 200ms, which matters for real-time chat.
Tone profiles: This is the feature I'm most proud of. I built 6 tone profiles (General, Casual, Professional, Empathetic, Playful, Gen Z) with carefully engineered prompts, few-shot examples, and dynamic temperature settings. Each tone has specific instructions for what it should and shouldn't do. The Gen Z profile even has per-language youth slang guides (Hindi uses यार, भाई; Japanese uses やばい, マジ; Korean uses ㅋㅋ, 대박) so it doesn't just shove English slang into other languages.
Backend: Added a proper Next.js serverless backend deployed on Vercel. The extension calls POST /api/translate instead of hitting translation APIs directly. This solved the CORS issues, keeps the API key server-side, and lets me do prompt engineering on the server without shipping it in the extension code. Also added multi-key Groq fallback so if one API key gets rate-limited, it automatically tries the next one.
Extension framework: Moved from raw manifest.json + vanilla JS to the WXT framework with TypeScript. WXT handles hot reloading during development, proper build output for Chrome MV3, and environment-based API URL switching (localhost in dev, Vercel in production).
DOM handling: The content script has a UniversalTranslator engine that handles the messy reality of injecting text into modern web apps. WhatsApp, Discord, and Teams all use React with custom input handling (some use Slate.js). You can't just set .value on an input field since React ignores it. So the engine uses synthetic clipboard pastes and Slate.js event dispatching to actually get the translated text into the input. It also uses MutationObservers to handle SPA navigation, which is critical for Discord and Teams where changing channels doesn't reload the page.
Performance: Added a 100-entry LRU cache so the same message doesn't hit the API twice. If you scroll up in a chat and the same messages are re-rendered, the translations come from cache instantly.
Bug fixes: Fixed the silent error handling where failed translations returned the original text. Now it returns an empty string with an error flag so the UI actually shows something went wrong. Fixed CORS by adding proper headers and an OPTIONS preflight handler on the backend.
TypeScript everywhere: The old version was all JavaScript with no type safety. The new version is fully typed. TypeScript interfaces for the Groq API responses, request bodies, tone profiles, the works.
My Experience with GitHub Copilot
I used Copilot for the repetitive parts of the rebuild.
Documentation and README: Copilot helped me write the README for the new repo, the CONTRIBUTING.md, and the setup guides. Writing docs from scratch is tedious and Copilot gave me good first drafts that I cleaned up.
TypeScript types: When I was porting the old JavaScript to TypeScript, Copilot was useful for generating interfaces. Things like the GroqChatResponse, TranslateRequestBody, and ToneProfile types. It picked up on the patterns from the Groq API responses and suggested accurate types.
Bug fixing: When I was debugging the CORS issue (extension content scripts can't make cross-origin requests to localhost), Copilot helped me write the CORS header setup and the OPTIONS preflight handler in the Next.js route. It also caught a few TypeScript errors where I was using any types that should have been properly typed.
Boilerplate: The WXT extension setup, the Next.js layout.tsx and page.tsx files, the eslint config. Standard stuff that Copilot autocompleted correctly without me having to look up docs.
What I wrote myself: all the tone profile prompts and few-shot examples (those need human judgement about what sounds natural), the Gen Z per-language slang guides (I researched actual youth internet culture for each language), the DOM injection logic for React/Slate.js apps (this is tricky platform-specific stuff that Copilot would get wrong), and the LRU cache implementation.
Top comments (0)