gpt_markdown
The Flutter renderer for AI output.
Production-grade Markdown and LaTeX rendering for streaming Flutter AI interfaces.
Render rich assistant replies, math, code, tables, citations, images, and custom inline UI in one widget.
๐ Website ยท ๐ Documentation ยท ๐ฎ Live Playground ยท ๐ฆ pub.dev
โจ Why gpt_markdown?
- Built for AI output โ Markdown, LaTeX, code blocks, tables, citations, images, task lists, and mixed rich content in one response.
- Streaming that stays fast โ only the live tail rebuilds while settled content is cached, keeping the rendering cost stable as replies grow.
- Production-level control โ style sheets, Flutter theme extensions, component builders, callbacks, and custom components.
- Extensible inline UI โ add
@mentions,#channels,:emoji:, issue references, and product-specific syntax without forking the renderer. - Designed for real-world edge cases โ RTL, text scaling, selection, malformed Markdown, autolinks, nested content, reduced motion, Flutter web, and WASM.
๐งฉ Everything AI output needs
| Rendering | Production experience | Extensibility | |||
|---|---|---|---|---|---|
| ๐ | Rich Markdown | โก | Adaptive streaming | ๐จ | Component style sheet |
| โ | Inline and block LaTeX | ๐ | Stable per-token cost | ๐งฑ | Structural builders |
| ๐ป | Inline and fenced code | โฟ | Selection and text scaling | ๐ท๏ธ | Mentions, channels, and emoji |
| ๐ | Tables and aligned columns | ๐ | RTL, web, and WASM | ๐งฉ | Custom components and scopes |
| ๐ | Links, autolinks, and images | ๐ | Theme-aware rendering | ๐ | Interaction callbacks |
| โ๏ธ | Lists, tasks, and citations | ๐ก๏ธ | Graceful malformed input | ๐ฑ | Custom URL schemes |
๐ผ๏ธ What it renders
Every image is one GptMarkdown widget with no styling applied โ the defaults, in a dark theme. Click any of them for full size.
![]() Rich text Headings, emphasis, lists, quotes, rules, autolinks. |
![]() LaTeX Inline and display equations, on the text baseline. |
![]() Tables Per-column alignment, Markdown inside cells. |
![]() Code Fenced blocks with a language header, wrapping inline code. |
![]() Task lists Checkboxes, ordered and nested lists, citation tags. |
![]() Inline patterns Mentions, channels, shortcodes. #2959 stays text. |
๐ ๏ธ Quick start
flutter pub add gpt_markdown
import 'package:gpt_markdown/gpt_markdown.dart';
GptMarkdown(
reply,
onLinkTap: (url, title) => openUrl(url),
)
The widget sizes itself to its content. Place it inside your preferred scrollable chat or document surface.
โก Streaming AI responses
Rebuild GptMarkdown with the complete text received so far. The settled prefix is cached and only the part that can still change is rebuilt.
GptMarkdown(
streamedReply,
animation: GptMarkdownAnimation.fade,
isStreaming: stillGenerating,
charactersPerSecond: 300,
)
The reveal adapts when tokens arrive quickly, fast-forwards when generation finishes, avoids unsafe splits inside code fences and block math, and automatically respects reduced-motion settings.
๐ Markdown, LaTeX, and rich AI output
GptMarkdown(
r'''
## Revenue forecast
The projected growth is **18%**, based on:
\[
R_{next} = R_{current} \times (1 + 0.18)
\]
| Quarter | Revenue |
|:-------:|--------:|
| Q1 | $120K |
| Q2 | $142K |
```dart
final growth = currentRevenue * 1.18;
```
- [x] Validate the assumptions
- [ ] Review the final forecast
Sources: [1] [2]
''',
onLinkTap: (url, title) => openUrl(url),
onSourceTagTap: (source) => openSource(source),
)
Supported output includes:
- Headings, bold, italic, strikethrough, underline, and inline code
- Ordered, unordered, nested, task, and radio lists
- Links, bare URLs, email autolinks, images, and citations
- Tables with column alignment and horizontal overflow
- Inline and block LaTeX using
\( ... \)and\[ ... \] - Optional dollar-sign LaTeX through
useDollarSignsForLatex: true - Fenced code blocks with language labels, copy controls, and open-fence streaming support
Wrap the renderer with SelectionArea when selectable output is needed:
SelectionArea(
child: GptMarkdown(reply),
)
๐จ Make it match your product
Use style objects for appearance and builders when you need to replace structure.
GptMarkdown(
reply,
styleSheet: const GptMarkdownStyleSheet(
blockQuote: BlockQuoteStyle(
barWidth: 4,
barColor: Colors.indigo,
),
inlineCode: InlineCodeStyle(
fontFamily: 'GeistMono',
borderRadius: Radius.circular(6),
),
codeBlock: CodeBlockStyle(
borderRadius: Radius.circular(12),
showCopyButton: true,
),
table: TableStyle(
cellPadding: EdgeInsets.all(10),
),
),
onCodeCopy: (code) => trackCopy(code),
onImageTap: (url) => openImage(url),
)
Set the same styles app-wide with GptMarkdownThemeData, or use builders such as codeBuilder, tableBuilder, headingBuilder, blockQuoteBuilder, and imageBuilder for full structural control.
๐ท๏ธ App-specific inline UI
Render mentions, channels, emoji, issue references, and other product syntax alongside Markdown:
GptMarkdown(
reply,
inlinePatterns: [
InlinePattern.prefixed(
prefix: '#',
knownNames: channelNames,
builder: (context, match, style) => WidgetSpan(
alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic,
child: ChannelChip(
name: match.group(0)!.substring(1),
),
),
),
],
)
Known names are matched longest-first, and patterns do not claim link labels by default. This prevents ambiguous tokens such as #2959 from becoming channels and avoids nested inline widgets that do not paint correctly on iOS.
For deeper integrations, use MarkdownComponent, InlineMd, and BlockMd. Components can declare support for content, linkLabel, tableCell, and heading scopes.
๐ Autolinks
Bare URLs, www. hosts, email addresses, and CommonMark angle autolinks work without preprocessing:
GptMarkdown(
'Visit https://gptmarkdown.com or email hello@example.com',
)
Autolinks follow GFM trimming rules, preserve balanced parentheses, and avoid leaking surrounding Markdown into the URL. Add app-specific schemes or turn bare autolinking off when needed:
GptMarkdown(
reply,
autolinkSchemes: const {'myapp'},
// autolink: false,
)
Explicit [label](url) links continue working when autolink is disabled.
๐ New in 1.2.0
- Adaptive streaming reveal with split-document caching
GptMarkdownStyleSheetand twelve per-component style classes- Builders and callbacks for every major output component
- Selectable, wrapping, baseline-aligned inline-code chips
InlinePatternfor product-specific inline syntaxMarkdownScopefor safe nested rendering- GFM and CommonMark autolinking
- Correct RTL inline-widget ordering
- Proportional accessibility text scaling
- Theme and runtime configuration rebuild fixes
- Safer malformed-Markdown and component dispatch behavior
Upgrading from 1.1.x? Read the migration guide.
๐ Documentation
| Guide | Covers |
|---|---|
| Getting started | Installation, syntax, taps, LaTeX, RTL, and selection |
| Customization | Style classes, themes, builders, and callbacks |
| Streaming | Pacing, performance, accessibility, and limitations |
| Inline syntax | Autolinks, mentions, channels, and scopes |
| Custom components | Block and inline extensions |
| Migration | Changes from 1.1.x to 1.2.0 |
๐ฌ Community
Issues and pull requests are welcome on GitHub. If the package helps your project, consider giving it a like on pub.dev or a star on GitHub.
๐ License
BSD 3-Clause โ see LICENSE.
Libraries
- custom_widgets/bidi_rich_text
- Workaround for https://github.com/flutter/flutter/issues/54400.
- custom_widgets/code_field
- custom_widgets/custom_divider
- custom_widgets/custom_error_image
- custom_widgets/custom_rb_cb
- custom_widgets/indent_widget
- custom_widgets/inline_code
- Inline
codedecoration. - custom_widgets/markdown_config
- custom_widgets/selectable_adapter
- custom_widgets/unordered_ordered_list
- gpt_markdown
- streaming/reveal_engine
- The arithmetic behind the streaming reveal.
- streaming/stream_split
- Finding a safe place to cut streaming Markdown in two.
- streaming/streaming_markdown
- Reveal animation for Markdown that arrives a token at a time.
- styles/block_quote_style
- styles/checkbox_style
- styles/code_block_style
- styles/gpt_markdown_style_sheet
- styles/heading_style
- styles/hr_style
- styles/image_style
- styles/latex_style
- styles/link_style
- styles/list_style
- styles/source_tag_style
- styles/style_lerp
- Interpolation helpers shared by the style classes.
- styles/table_style





