A modern, accessible markdown editor built with Nuxt 4 and CodeMirror 6. This is the updated version of the original ICJIA Markdown Editor, rebuilt from the ground up with modern web technologies. Full WCAG 2.1 AA compliance.
The app includes Open Graph and Twitter Card meta tags for rich social previews. The og-image.png (1200×630) in public/ is used when the page is shared. Set NUXT_PUBLIC_SITE_URL in your deployment environment (e.g. https://markdown.icjia.cloud) so social platforms receive absolute image URLs. See netlify.toml for the production configuration.
- Real-time Preview - See your formatted document as you type with synchronized scrolling
- Dark/Light Mode - Easy on the eyes with dark mode default and system preference detection
- ICJIA Branding - Header features the ICJIA logo (clickable to scroll to top)
- Keyboard Shortcuts - Speed up your workflow with comprehensive shortcuts
- Table Builder - Visual table creation modal (Cmd/Ctrl+T)
- Auto-save - Never lose your work (saves every 30 seconds with live countdown in header)
- Start Editing Button - New users see a prominent button to clear the tutorial and start fresh
- Tutorial Reset - Restore the markdown tutorial content anytime from the status bar
- Export Options - Copy as Markdown, copy as HTML, or download files with custom filenames
- Copy Notifications - High-contrast purple notifications appear in the header when content is copied
- Footnote Support - Full footnote syntax with automatic numbering and back-references
- Guided Tour - Interactive onboarding with markdown introduction slides and feature tour (runs once, restartable anytime)
- Undo/Redo - Full history support with keyboard shortcuts (Cmd/Ctrl+Z)
- Accessibility First - WCAG 2.1 Level AA compliant with full keyboard navigation and screen reader support
- Static Deployment - Deploy anywhere as a static site (Netlify-ready)
- Fully Documented - Comprehensive JSDoc comments on all composables and utilities
- Reusable Tour Module - Copy the tour module to any Nuxt project for instant onboarding
| Document | Description |
|---|---|
| Design Document | Features, UX requirements, user personas, accessibility gates |
| Technical Architecture | Implementation details, code examples, component specs |
| Accessibility Checklist | Manual testing procedures for WCAG 2.1 AA |
| Quick Start Guide | Getting started in 5 minutes |
| Browser Support | Supported browsers and screen readers |
| Troubleshooting | Common issues and solutions |
| Tour Module | Reusable guided tour module documentation |
| Status | Feature |
|---|---|
| ✅ | Nuxt 4 project setup with Nuxt UI |
| ✅ | CodeMirror 6 integration with markdown syntax highlighting |
| ✅ | Basic twin-pane layout (editor/preview) |
| ✅ | Dark/light mode theming with system preference detection |
| ✅ | markdown-it configuration with footnotes and syntax highlighting |
| ✅ | Skip link and semantic HTML structure |
| ✅ | Focus indicators on all interactive elements |
| ✅ | useAccessibility composable with screen reader announcements |
| Status | Feature |
|---|---|
| ✅ | Formatting toolbar with all buttons (Bold, Italic, Code, etc.) |
| ✅ | Keyboard shortcuts (Cmd+B, Cmd+I, Cmd+1-6, etc.) |
| ✅ | Scroll synchronization between editor and preview |
| ✅ | Copy Markdown to clipboard |
| ✅ | Copy HTML to clipboard |
| ✅ | Download as Markdown file |
| ✅ | Upload Markdown file |
| ✅ | Word count and character count in status bar |
| Status | Feature |
|---|---|
| ✅ | Table builder modal with visual grid editor |
| ✅ | Footnote support via markdown-it-footnote |
| ✅ | Auto-save to localStorage (every 30 seconds with countdown in header) |
| ✅ | Tutorial button to reset to markdown tutorial content |
| ✅ | Download modal with custom filename support |
| ✅ | HTML export with styled document wrapper |
| ✅ | Comprehensive JSDoc documentation for all composables and utilities |
| ✅ | Save indicator with visual feedback |
| Status | Feature |
|---|---|
| ✅ | Guided tour/onboarding module (WCAG 2.1 AA compliant, 19 steps) |
| ✅ | Welcome screen with ICJIA logo (first-time users + manual tour trigger) |
| ✅ | Tour progress indicator with modern pill design and WCAG AA contrast |
| ✅ | Reusable tour module architecture for other projects |
| ✅ | Safari localStorage compatibility fix |
| ✅ | WCAG 1.4.12 text spacing compliance for code blocks |
| ✅ | CodeMirror v6 type compatibility fixes (undo/redo functions) |
| ✅ | Cursor pointer styling for all interactive tour buttons |
| ✅ | ICJIA logo in header (clickable to scroll to top) |
| ✅ | "Start Editing" button to clear tutorial content for new users |
| ✅ | High-contrast purple copy notifications (WCAG AA compliant) |
| ⬜ | Full accessibility audit (axe-core, WAVE) |
| ⬜ | Screen reader testing (VoiceOver, NVDA) |
| ⬜ | Keyboard navigation refinement |
| ⬜ | Help modal with shortcuts reference |
| ⬜ | Image insertion modal with placeholder option |
| ⬜ | Link insertion modal with URL validation |
| ⬜ | Find & Replace functionality |
| ⬜ | Error handling improvements |
| ⬜ | Loading state refinements |
| Status | Feature |
|---|---|
| ⬜ | Unit tests for utilities |
| ⬜ | Component tests |
| ⬜ | E2E tests for critical paths |
| ⬜ | Cross-browser testing |
| ⬜ | Performance optimization |
| ⬜ | Lighthouse score optimization (target: 100 accessibility) |
| ⬜ | Production deployment documentation |
| Technology | Version | Purpose |
|---|---|---|
| Nuxt | 4.x | Application framework |
| Vue | 3.5+ | Reactive UI |
| TypeScript | 5.x | Type safety |
| Nuxt UI | 3.x | Component library |
| CodeMirror | 6.x | Text editor engine |
| markdown-it | 14.x | Markdown parsing |
| highlight.js | 11.x | Code syntax highlighting |
- Node.js 20+
- Yarn 1.22.22+
# Clone the repository
git clone https://github.com/ICJIA/icjia-markdown-editor-2026.git
cd icjia-markdown-editor-2026
# Install dependencies
yarn installNote: If you encounter TypeScript errors related to CodeMirror during build, the project includes type compatibility fixes for CodeMirror v6 commands (undo/redo).
# Start development server
yarn devOpen http://localhost:3000 in your browser.
# Generate static site
yarn generate
# Preview production build locally
npx serve dist| Action | Mac | Windows/Linux |
|---|---|---|
| Bold | ⌘ + B | Ctrl + B |
| Italic | ⌘ + I | Ctrl + I |
| Inline Code | ⌘ + ` | Ctrl + ` |
| Code Block | ⌘ + Shift + ` | Ctrl + Shift + ` |
| Heading 1-6 | ⌘ + 1-6 | Ctrl + 1-6 |
| Block Quote | ⌘ + Q | Ctrl + Q |
| Bullet List | ⌘ + Shift + 8 | Ctrl + Shift + 8 |
| Numbered List | ⌘ + Shift + 7 | Ctrl + Shift + 7 |
| Insert Table | ⌘ + T | Ctrl + T |
| Insert Link | ⌘ + K | Ctrl + K |
| Horizontal Rule | ⌘ + - | Ctrl + - |
| Copy Markdown | ⌘ + Shift + C | Ctrl + Shift + C |
| Copy HTML | ⌘ + Shift + H | Ctrl + Shift + H |
| Download | ⌘ + S | Ctrl + S |
| Open File | ⌘ + O | Ctrl + O |
| Action | Key |
|---|---|
| Next Step | → (Arrow Right) |
| Previous Step | ← (Arrow Left) |
| Cancel Tour | Esc |
All composables and utility files include comprehensive JSDoc documentation:
- File-level documentation with
@fileoverviewand@moduletags - Function documentation with
@param,@returns, and@exampletags - Type documentation for interfaces, types, and constants
- WCAG compliance notes in theme files with color contrast ratios
This documentation enables better IDE intellisense, easier onboarding for new developers, and serves as inline reference for the codebase.
This project is committed to WCAG 2.1 Level AA compliance. Key accessibility features include:
- Skip Link - Jump directly to the editor
- Keyboard Navigation - Full functionality without a mouse
- Screen Reader Support - ARIA labels and live region announcements
- Focus Indicators - Clear, visible focus states on all interactive elements
- Color Contrast - 4.5:1 for text, 3:1 for UI components
- Reduced Motion - Respects
prefers-reduced-motionsetting - Guided Tour - Accessible onboarding with keyboard navigation (Arrow keys, Escape)
The application includes an interactive guided tour with a welcome screen that introduces users to all major features. The tour is:
- WCAG 2.1 AA Compliant - Full keyboard navigation (←/→/Esc), screen reader announcements, AA contrast ratios
- Welcome Screen - Professional welcome modal with ICJIA logo for first-time users
- Runs Once by Default - Automatically starts for first-time visitors
- Cancellable Anytime - Users can skip with a button or press Escape
- Manually Restartable - Click the Tour button in the status bar to see the full experience again
- Modern Design - Pill-shaped progress indicator (e.g., "1 / 19") with proper spacing and contrast
- Responsive - Works on desktop and mobile devices
The tour follows a logical left-to-right, top-to-bottom order covering 19 features:
- Undo & Redo - History navigation with keyboard shortcuts
- Text Formatting - Bold, italic, inline code
- Headings - H1-H6 with keyboard shortcuts
- Block Elements - Quotes, code blocks, horizontal rules
- Lists - Bullet and numbered lists
- Tables & Links - Visual table builder, link insertion
- Scroll Sync - Synchronized scrolling toggle
- Upload & Download - File operations
- Copy to Clipboard - Markdown and HTML export
- Auto-Save - Browser localStorage with countdown timer
- View Modes - Split/editor/preview toggle
- Conversion Tools - External privacy-first utilities
- Light/Dark Mode - Theme toggle
- Editor Pane - Where to write markdown
- Preview Pane - Live rendering
- Document Statistics - Word count, character count, reading time
- Tour Button - Restart the guided tour anytime
- Tutorial - Reset to markdown tutorial content (with confirmation)
- GitHub Source Code - Link to open source repository
The tour module is designed to be portable. Copy it to any Nuxt project:
# Copy the entire tour module folder
cp -r app/modules/tour /path/to/your-project/app/modules/Add to your main CSS file:
@import "~/modules/tour/styles/tour.css";Create app/config/tour.ts:
import type { TourConfig } from "~/modules/tour/types";
export const tourConfig: TourConfig = {
version: 1,
autoStart: true,
autoStartDelay: 800,
storageKeyPrefix: "my-app-tour",
steps: [
{
id: "welcome",
target: '[data-tour="header"]',
title: "Welcome!",
content: "This is a quick tour of the main features.",
position: "bottom",
icon: "i-heroicons-hand-raised",
},
// Add more steps...
],
};Add data-tour attributes to elements you want to highlight:
<template>
<header data-tour="header">...</header>
<button data-tour="save-button">Save</button>
</template><script setup lang="ts">
import { useTour } from "~/modules/tour/composables/useTour";
import TourOverlay from "~/modules/tour/components/TourOverlay.vue";
import { tourConfig } from "~/config/tour";
const tour = useTour(tourConfig);
onMounted(() => {
if (tour.autoStart && !tour.hasCompletedTour.value) {
setTimeout(() => tour.start(), tour.autoStartDelay);
}
});
</script>
<template>
<!-- Add restart button -->
<button @click="tour.start()">Start Tour</button>
<!-- Add tour overlay -->
<TourOverlay
:is-active="tour.isActive.value"
:current-step="tour.currentStep.value"
:progress="tour.progress.value"
@next="tour.next()"
@previous="tour.previous()"
@cancel="tour.cancel()"
/>
</template>| Property | Type | Default | Description |
|---|---|---|---|
version |
number |
- | Increment to reset completion for all users |
autoStart |
boolean |
true |
Auto-start for first-time visitors |
autoStartDelay |
number |
800 |
Delay (ms) before auto-starting |
storageKeyPrefix |
string |
- | LocalStorage key prefix |
steps |
TourStep[] |
- | Array of tour step definitions |
| Property | Type | Default | Description |
|---|---|---|---|
id |
string |
- | Unique identifier |
target |
string |
- | CSS selector (e.g., [data-tour="id"]) |
title |
string |
- | Step title |
content |
string |
- | Step description |
tip |
string |
- | Optional tip shown in highlighted box |
position |
'top' | 'bottom' | 'left' | 'right' |
'bottom' |
Popover position |
icon |
string |
- | Iconify icon name |
shortcut |
string[] |
- | Keyboard shortcut to display |
See app/modules/tour/README.md for complete documentation.
The project includes a netlify.toml configuration file for seamless deployment:
# Build command
yarn generate
# Publish directory
disticjia-markdown-editor-2026/
├── app/
│ ├── components/
│ │ ├── editor/ # EditorPane, PreviewPane, EditorLayout
│ │ ├── modals/ # TableBuilderModal, DownloadModal
│ │ ├── toolbar/ # EditorToolbar, ToolbarButton, ToolbarDivider
│ │ └── ui/ # AppHeader, ColorModeToggle, SkipLink
│ ├── composables/ # Vue composables (fully documented with JSDoc)
│ │ ├── useAccessibility.ts # Screen reader announcements, focus trap
│ │ ├── useAutoSave.ts # localStorage persistence
│ │ ├── useDownloadModal.ts # Download filename modal state
│ │ ├── useEditor.ts # Editor state and text manipulation
│ │ ├── useExport.ts # Copy/download functionality
│ │ ├── useKeyboardShortcuts.ts # Global keyboard shortcuts
│ │ ├── useMarkdown.ts # Markdown rendering and stats
│ │ ├── useScrollSync.ts # Editor/preview scroll sync
│ │ └── useTableBuilderModal.ts # Table builder state
│ ├── config/ # App configuration
│ │ └── tour.ts # Tour step definitions for this app
│ ├── modules/ # Reusable modules
│ │ └── tour/ # Guided tour module (portable to other projects)
│ │ ├── README.md # Module documentation
│ │ ├── types.ts # TypeScript definitions
│ │ ├── index.ts # Module exports
│ │ ├── composables/
│ │ │ └── useTour.ts # Tour state and navigation
│ │ ├── components/
│ │ │ ├── TourOverlay.vue # Main tour dialog UI
│ │ │ └── TourTrigger.vue # Reusable trigger button
│ │ └── styles/
│ │ └── tour.css # Highlight ring animations
│ ├── pages/ # Nuxt pages
│ └── utils/ # Utility functions (fully documented with JSDoc)
│ ├── editor/ # CodeMirror config, themes, keymaps
│ ├── markdown/ # markdown-it configuration
│ └── table-builder.ts # Table generation utilities
├── documentation/ # Project documentation
├── public/ # Static assets
├── tests/ # Test files
└── nuxt.config.ts # Nuxt configuration
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Note: All contributions must pass accessibility tests before merging.
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2026 Illinois Criminal Justice Information Authority (ICJIA).
- Nuxt - The Vue Framework
- CodeMirror - Extensible code editor
- Nuxt UI - Beautiful UI components
- markdown-it - Markdown parser
