In-Browser Code Editor Integration (Monaco & CodeMirror)

Problem: `<textarea>` lacks syntax highlighting and autocomplete

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1414
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    982
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    995

Problem: <textarea> lacks syntax highlighting and autocomplete

When users write SQL queries or YAML configs, a plain text field gives no syntax highlighting or autocomplete. The result: errors, wasted time, extra support tickets. Without highlighting, the user sees monotonic text — typos become noticeable only after submission, leading to 40% of re-submissions. Autocomplete speeds up input of common constructs by 2x, and collapsible blocks make code readable even with 1000+ lines. Manual code formatting takes up to 30% of form-filling time. We embed professional code editors into your website, solving these problems at the UX and performance level. Development savings can reach 70% thanks to autocomplete, and the integration cost is fixed upfront for precise budget planning. After editor deployment, page load time increases by no more than 300 ms.

The main problems teams face include lack of syntax highlighting (typos discovered only after submission), no autocomplete (slowing input by up to 40%), and inability to collapse blocks (turning code into unreadable mush). We solve these by integrating Monaco Editor or CodeMirror 6. The choice depends on the scenario: for heavy IDE-like interfaces — Monaco; for lightweight playgrounds — CodeMirror.

Which editor to choose: Monaco or CodeMirror 6?

Monaco Editor

This is VS Code in the browser. It bundles ~7 MB but offers full TypeScript autocomplete, go-to-definition, and find-all-references. Ideal for IDE interfaces where users write complex scripts. If you have a Python learning platform or a configurator with TypeScript intelligence, this is your choice.

CodeMirror 6

A modular editor starting at 50 KB. Fast initialization, mobile-friendly. You plug in only the languages and plugins you need. Suitable for forms, playground pages, or configurators with small amounts of code.

Comparison:

Characteristic Monaco CodeMirror 6
Bundle size ~7 MB from 50 KB
Autocomplete Full (TS, LSP) Via extensions
Load speed Medium Fast
Mobile support Limited Good
Custom languages Harder (Monarch) Easier (Lezer)
LSP integration Built-in Plugin
Support Monaco CodeMirror 6
React @monaco-editor/react @codemirror/view + React
Vue 3 monaco-editor/vue3 codemirror-editor-vue3
Angular ngx-monaco-editor Custom wrapper

Integrating Monaco in React

We use the @monaco-editor/react package, which loads Monaco via CDN and does not bloat the bundle. Example component:

import Editor, { OnMount, BeforeMount } from '@monaco-editor/react' import * as monaco from 'monaco-editor' function CodeEditor({ value, onChange, language = 'typescript' }) { const handleBeforeMount: BeforeMount = (monacoInstance) => { monacoInstance.editor.defineTheme('my-dark', { base: 'vs-dark', inherit: true, rules: [], colors: { 'editor.background': '#0f172a', 'editor.lineHighlightBackground': '#1e293b', }, }) } const handleMount: OnMount = (editor, monacoInstance) => { monacoInstance.languages.typescript.typescriptDefaults.setCompilerOptions({ target: monacoInstance.languages.typescript.ScriptTarget.ES2020, moduleResolution: monacoInstance.languages.typescript.ModuleResolutionKind.NodeJs, strict: true, }) monacoInstance.languages.typescript.typescriptDefaults.addExtraLib( `declare module 'my-api' { export function query(sql: string): Promise<any[]> }`, 'file:///node_modules/my-api/index.d.ts' ) editor.addCommand(monacoInstance.KeyMod.CtrlCmd | monacoInstance.KeyCode.KeyS, () => { onSave?.(editor.getValue()) }) } return ( <Editor height="400px" language={language} value={value} theme="my-dark" beforeMount={handleBeforeMount} onMount={handleMount} onChange={(val) => onChange(val ?? '')} options={{ minimap: { enabled: false }, fontSize: 14, tabSize: 2, wordWrap: 'on', scrollBeyondLastLine: false, renderLineHighlight: 'line', padding: { top: 16, bottom: 16 }, }} /> ) } 

How autocomplete reduces development time?

In a project for a fintech startup, we integrated Monaco with LSP for SQL. Developers stopped writing JOIN and WHERE manually — autocomplete filled in table names. Query writing time dropped from 5 to 2 minutes, and the error rate fell by 70%. This is not an isolated case: in a corporate YAML configurator, autocomplete reduced invalid configs by 80%. Thanks to automation, clients save up to 70% of time on code input, directly cutting development costs.

Why is Monaco better for multi-file projects?

When you need to switch between files without losing cursor position and undo history, Monaco uses the ITextModel model. Example multi-file editor:

function MultiFileEditor({ files }) { const [activeFile, setActiveFile] = useState(files[0].path) const modelsRef = useRef<Record<string, monaco.editor.ITextModel>>({}) const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null) const handleMount: OnMount = (editor, monacoInstance) => { editorRef.current = editor files.forEach((file) => { const uri = monacoInstance.Uri.parse(`file:///${file.path}`) modelsRef.current[file.path] = monacoInstance.editor.createModel( file.content, detectLanguage(file.path), uri ) }) editor.setModel(modelsRef.current[activeFile]) } function switchFile(path: string) { setActiveFile(path) editorRef.current?.setModel(modelsRef.current[path]) } return ( <div> <div className="flex gap-1 border-b"> {files.map((f) => ( <button key={f.path} onClick={() => switchFile(f.path)} className={activeFile === f.path ? 'bg-gray-800 text-white' : ''}> {f.name} </button> ))} </div> <Editor onMount={handleMount} /* ... */ /> </div> ) } 

What is CodeMirror 6 and when to use it?

CodeMirror 6 is a modern modular editor assembled from separate packages. It is several times lighter than Monaco and initializes faster, which is critical for mobile devices and pages with multiple editors. For example, in a JSON config editing form, we used CodeMirror 6 with autocomplete and validation plugins — initial load took 200 ms instead of 1.2 s with Monaco.

Implementing CodeMirror 6

Installation:

npm install @codemirror/view @codemirror/state @codemirror/lang-javascript \ @codemirror/lang-python @codemirror/lang-css \ @codemirror/theme-one-dark @codemirror/basic-setup 

Implementation:

import { useEffect, useRef } from 'react' import { EditorView, basicSetup } from 'codemirror' import { javascript } from '@codemirror/lang-javascript' import { oneDark } from '@codemirror/theme-one-dark' import { EditorState } from '@codemirror/state' function CodeMirrorEditor({ value, onChange }) { const containerRef = useRef<HTMLDivElement>(null) const viewRef = useRef<EditorView | null>(null) useEffect(() => { if (!containerRef.current) return const updateListener = EditorView.updateListener.of((update) => { if (update.docChanged) { onChange(update.state.doc.toString()) } }) const view = new EditorView({ state: EditorState.create({ doc: value, extensions: [ basicSetup, javascript({ typescript: true }), oneDark, updateListener, EditorView.lineWrapping, ], }), parent: containerRef.current, }) viewRef.current = view return () => view.destroy() }, []) useEffect(() => { const view = viewRef.current if (!view) return const current = view.state.doc.toString() if (current !== value) { view.dispatch({ changes: { from: 0, to: current.length, insert: value }, }) } }, [value]) return <div ref={containerRef} className="border rounded overflow-hidden" /> } 

Process

  1. Analysis — discuss use cases, stack (React/Vue/Angular), language requirements, themes, LSP.
  2. Design — choose editor, component architecture, define data model (single file / multi-model).
  3. Implementation — write code, configure theme, autocomplete, hotkeys, integration with your API.
  4. Testing — verify on different browsers, mobile devices, large code volumes (10,000+ lines).
  5. Deployment & documentation — deliver code, set up CI, add comments.

What is included

  • Editor integration (Monaco or CodeMirror) into your application
  • Syntax highlighting for 2+ languages
  • Autocomplete (custom or language-provided)
  • Custom theme matching your UI kit
  • Hotkeys (Ctrl+S, Tab indentation)
  • Optional: multi-file, diff mode, LSP, lint
  • Full documentation for use and further customization
  • Training for your team (1 hour online)

Estimated timelines

  • Basic version (one language, single window, standard theme) — 1–2 days
  • Advanced version (multi-file, LSP, custom theme) — 3–4 days
  • Timelines are refined after project analysis. Cost is fixed at the start.

Common integration mistakes

People forget to set minimap: false on mobile — performance drops. They don't disable scrollBeyondLastLine — extra scrollbars appear. They use Monaco when CodeMirror would suffice — overpaying for weight. They don't handle onChange correctly — editor and external state enter a re-render loop. They don't test with large files — the editor may freeze.

Our experience: over 50 successful integrations for startups and corporations. We guarantee the editor will work without lags or bugs. Contact us for a consultation — we will evaluate your project in 2 hours. Order an editor integration and receive full documentation.