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
- Analysis — discuss use cases, stack (React/Vue/Angular), language requirements, themes, LSP.
- Design — choose editor, component architecture, define data model (single file / multi-model).
- Implementation — write code, configure theme, autocomplete, hotkeys, integration with your API.
- Testing — verify on different browsers, mobile devices, large code volumes (10,000+ lines).
- 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.







