TL;DR: I built a React component for mention-based autocompletion that supports nested objects and arrays. Then I optimized it from 5MB to just 35KB. Here's the story and why you might want to use it.
The Problem: Template Hell ๐ซ
Have you ever built a feature where users need to compose messages with dynamic variables?
You know, like:
- Email templates: "Hi
{{user.name}}, your order{{order.id}}is ready!" - Notification systems: "
{{product.name}}is now{{product.price}}" - Chat bots: "Welcome
{{user.name}}from{{user.address.city}}!"
The typical solutions are either:
- Manual typing - Error-prone, users don't know what's available
- Dropdown menus - Clunky UI, breaks the flow
- Custom builders - Weeks of development time
I needed something better for my project, so I built type-ahead-mention.
The Solution: Smart Autocomplete โจ
import { MentionInput } from 'type-ahead-mention';
function EmailEditor() {
const [template, setTemplate] = useState("Hi {{user.name}}!");
const data = {
user: { name: "John", email: "john@example.com" },
order: { id: "12345", total: 99.99 }
};
return <MentionInput value={template} onChange={setTemplate} suggestions={data} />;
}
Type double opening curly braces and boom - intelligent autocomplete powered by CodeMirror.
But here's where it gets interesting...
The Magic: It Handles NESTED Data ๐ฏ
Most autocomplete libraries choke on nested objects. Not this one:
const suggestions = {
user: {
name: "Sarah Connor",
address: {
city: "Los Angeles",
street: "2144 Ventura Blvd"
},
roles: ["admin", "editor", "viewer"]
}
};
Now users can type:
-
{{user.name}}โ "Sarah Connor" -
{{user.address.city}}โ "Los Angeles" -
{{user.roles.0}}โ "admin" (yes, it does arrays!)
The autocomplete guides them through the structure as they type. No docs needed.
The Plot Twist: From 5MB to 35KB ๐ฆ
After building v1, I published it to NPM. Package size? 5 MEGABYTES. ๐ฑ
My first reaction: "That can't be right..."
But it was. Source maps + bundled dependencies = bloat city.
The Optimization Journey
Step 1: Kill the source maps
// vite.config.ts
build: {
sourcemap: false // Goodbye 3.9MB of .map files
}
Step 2: Externalize dependencies
Instead of bundling CodeMirror and friends, I made them peer dependencies:
{
"peerDependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@uiw/react-codemirror": "^4.0.0"
}
}
The Results ๐
| Metric | Before | After | Reduction |
|---|---|---|---|
| Compressed | 1.3 MB | 12 KB | 99.1% โ |
| Unpacked | 5.0 MB | 35 KB | 99.3% โ |
| ES Module | 642 KB | 13 KB | 97.9% โ |
Yeah, you read that right. 99% smaller.
Cool Features You'll Actually Use ๐จ
1. Theme It Your Way
<MentionInput
style={{
fontSize: '16px',
backgroundColor: '#1e1e1e',
color: '#e0e0e0',
borderRadius: '8px'
}}
/>
2. Single or Multi-line
// Single-line input
<MentionInput value={subject} onChange={setSubject} />
// Multi-line textarea
<MentionInput value={body} onChange={setBody} multiline />
3. Template Resolution Hook
const resolved = useMentionResolver(
"Hello {{user.name}}!",
{ user: { name: "Alice" } }
);
// Result: "Hello Alice!"
4. Full Keyboard Navigation
- Arrow keys to navigate suggestions
- Enter to select
- Escape to dismiss
- Tab to autocomplete
Real-World Use Cases ๐
1. Email Marketing Platforms
Let users create personalized emails without learning your template syntax.
2. Notification Builders
Build Slack/Discord bot message composers with dynamic fields.
3. Document Generation
Create contract templates, invoices, or reports with variable data.
4. Chat Applications
Quick replies with user context, order details, or product info.
5. Form Builders
Dynamic form field values based on user data or previous answers.
Live Demo (Try It Now!) ๐ฎ
I built an interactive demo where you can:
- โ Test 5 different themes
- โ Customize styles in real-time
- โ Edit the JSON data structure live
- โ See template resolution instantly
๐ Play with the demo
Getting Started (2 Minutes) โก
npm install type-ahead-mention
Install peer dependencies:
npm install @codemirror/autocomplete @codemirror/state @codemirror/view @uiw/react-codemirror
Basic usage:
import { MentionInput } from 'type-ahead-mention';
import { useState } from 'react';
export function App() {
const [message, setMessage] = useState("Hi {{name}}!");
const suggestions = { name: "World", count: 42 };
return (
<MentionInput
value={message}
onChange={setMessage}
suggestions={suggestions}
/>
);
}
What I Learned ๐
- Bundle size matters - Users will notice (and complain about) bloated packages
- Peer dependencies are your friend - Don't bundle what users likely already have
- Source maps in production? - Almost never a good idea
- CodeMirror is powerful - But you need to understand its extension system
- Interactive demos sell - Show, don't just tell
The Tech Stack ๐ ๏ธ
- React 18+ - Modern hooks API
- TypeScript - Full type safety
- CodeMirror 6 - The editor that powers VS Code's find/replace
- Popper.js - Smart suggestion positioning
- Vite - Lightning-fast builds
Open Questions for You ๐ค
I'd love your input on:
-
What other autocomplete patterns do you need?
- SQL-like syntax? Markdown helpers? Custom delimiters?
-
Should I add a visual builder?
- Click to insert variables vs. typing the double curly braces
-
What about autocomplete from API calls?
- Async suggestions, debouncing, caching?
-
Mobile support?
- Touch-friendly suggestion popup?
Drop your thoughts in the comments! ๐
Try It Yourself ๐
- ๐ฆ NPM:
npm install type-ahead-mention - ๐ฎ Demo: https://rahulpatwa1303.github.io/type-ahead-mention/
- ๐ป GitHub: https://github.com/rahulpatwa1303/type-ahead-mention
- ๐ Docs: Full API reference in the README
The Numbers ๐
Since launching v2.0.1:
- โ 35KB unpacked (99% smaller than v1)
- โ Full TypeScript support
- โ Zero runtime dependencies (except peers)
- โ Works with React 18+
- โ MIT licensed
What's Next? ๐ฎ
I'm considering:
-
Custom delimiters - Use
[[var]]or$varinstead of the double curly brace syntax - Formatting helpers - Date/number formatting filters
- Multi-select - Pick multiple variables at once
- Undo/redo - Built-in history management
What would YOU use most? Let me know!
Final Thoughts ๐ญ
Building this package taught me that optimization isn't just about performance - it's about respect for your users' bandwidth, disk space, and patience.
Going from 5MB to 35KB wasn't just a technical achievement. It was a statement: "I care about your bundle size."
If you're building any kind of template system, notification builder, or dynamic message composer, give type-ahead-mention a shot. It might save you weeks of development.
And if you find bugs or have feature requests, the repo is open! PRs welcome. ๐
Let's Connect! ๐ค
- Give it a โญ on GitHub
- Share your use cases in the comments
- Found a bug? Open an issue
- Built something cool? I'd love to see it!
Question for you: What's the WORST template system you've had to work with? Share your horror stories below! ๐ป
P.S. - If you're wondering why the package is called "type-ahead-mention" instead of something catchier... well, naming things is hard. ๐ Got a better name? Comment below!
Last updated: November 19, 2025
Top comments (0)