Mirrow is an AI-powered Electron desktop browser that translates visible website text into Persian using a local LM Studio model. It preserves the original page layout by replacing only text node content.
- Embedded desktop browser with URL entry, back, forward, and reload controls
- Layout-preserving page translation through injected DOM text-node extraction
- Local LM Studio translation through the OpenAI-compatible chat completions API
- Batch translation with progress, partial failure handling, and safe JSON parsing
- Dark premium desktop UI with Translate, History, Settings, and About routes
- Settings and translation history persisted across app restarts
- Safe Electron preload APIs with
contextIsolation,nodeIntegration: false, and sandboxing
- Electron
- React
- TypeScript
- Vite
- Tailwind CSS
- TanStack Router
- TanStack Query
- Electron IPC
- Node.js
v22.12.0 - pnpm
- LM Studio with a loaded local translation model
Use the project Node version before installing or running:
nvm use v22.12.0- Open LM Studio.
- Load the model:
translategemma-4b-it. - Start the local server.
- Confirm the server is available at:
http://localhost:1234/v1/chat/completions - Run Mirrow.
Default app settings now support both online and local engines. Online mode is compatible with Liara's OpenAI-compatible Chat API.
Online base URL: https://ai.liara.ir/api/6a0ccd2d298429714a4b3e25/v1
Online model: openai/gpt-4.1-mini
Local base URL: http://localhost:1234/v1/chat/completions
Local model: translategemma-4b-it
Temperature: 0.2
Batch size: 20
Target language: PersianIf the online API key field is empty on macOS, Mirrow attempts to reuse Mirook's Keychain API key (com.espitman.Mirook / openai-api-key).
nvm use v22.12.0
pnpm install
pnpm devFor a production build:
nvm use v22.12.0
pnpm buildWhen you click Translate Page, Mirrow asks the Electron main process to inject a script into the current BrowserView page. That script walks document.body with a TreeWalker, collects visible text nodes, assigns stable IDs, and stores node references in a page-local map.
The main process sends the collected text to LM Studio in batches. Each model response is parsed as JSON and applied back to the original page with:
node.textContent = translatedText;Mirrow never rewrites document.body.innerHTML, so page structure, links, images, styles, and interaction handlers are left intact.
- Some websites may block script injection.
- Dynamic SPAs may need re-translation after route changes.
- Very large pages may take time to translate.
- Local model quality depends on the selected LM Studio model.
- Replacing English text with Persian may slightly affect text wrapping.
- Shadow DOM content is not translated in the first version.
- Auto-translate after page load
- Translate selected text
- Bilingual hover mode
- Per-site translation preferences
- Translation cache
- OCR for images
- PDF translation
- Multi-language support
- Better RTL handling
- Reader mode
- Extension-like mode
- Custom prompts
- Model selector