sendnote.link
Back to blog
guides

Sharing Multimodal AI Outputs: Text, Code, and Markdown in One Note

April 24, 20266 min read

The Multimodal Output Problem

AI outputs in 2026 are rarely just text. Ask ChatGPT to help you set up a new project, and you get a mix of prose explanations, shell commands, configuration files, and code snippets. Ask Claude to analyze a dataset, and you get paragraphs of insight interspersed with tables, statistics, and code examples. Ask Gemini to draft a technical proposal, and you get headings, bullet points, comparison tables, and code blocks all in one response.

This is multimodal output -- not in the sense of images and audio, but in the sense of multiple content types woven together in a single response. Prose, code, structured data, and formatting all mixed into one coherent document.

The AI handles this beautifully in its own interface. The problem starts when you need to share that output with someone else.

Why Sharing Multimodal Output Is Hard

Chat Apps Handle One Format Well

Slack does a reasonable job with short text messages. It does an acceptable job with single code snippets in backticks. But paste a complex AI response that mixes paragraphs, tables, and multiple code blocks? The formatting collapses. Tables become unreadable text. Nested lists lose their hierarchy. Code blocks sometimes render and sometimes do not, depending on the client.

Email Strips Structure

Email clients vary wildly in their Markdown support. Some render it, most do not. A carefully structured AI response pasted into an email becomes a wall of plain text with asterisks and backticks scattered throughout. The recipient has to mentally parse the formatting rather than just reading the content.

Screenshots Lose Interactivity

Taking a screenshot of an AI response preserves the visual layout but loses everything else. The recipient cannot copy the code, cannot click the links, cannot select the text, and cannot search within the content. For AI outputs that contain code meant to be used, screenshots are particularly useless.

Document Tools Add Friction

Google Docs and Notion can handle rich formatting, but creating a new document for every AI output you want to share creates clutter. You end up with dozens of untitled documents, each containing a single AI response. Permission management adds another layer of friction -- you need to share the document with specific people or adjust link settings.

Markdown as the Universal Container

Markdown solves the multimodal sharing problem because it is exactly what AI tools already produce. When ChatGPT, Claude, or Gemini generates a response, the underlying format is Markdown. The headings, code blocks, tables, and lists you see in the AI interface are all Markdown being rendered in real time.

This means sharing AI output through a Markdown-native tool preserves every element of the original response:

  • Headings remain hierarchical and scannable
  • Code blocks get syntax highlighting for the specified language
  • Tables render as actual tables with proper alignment
  • Lists maintain their nesting and formatting
  • Inline code stays visually distinct from prose
  • Bold and italic text preserves emphasis

No re-formatting needed. What the AI produced is what the recipient sees.

Walkthrough: Sharing a Complex AI Response

Let's work through a realistic example. You asked Claude to help you set up error handling for a Node.js API, and it produced this response:

## Error Handling Setup for Express API

There are three layers to implement: a custom error class,
route-level error handling, and a global error middleware.

### 1. Custom Error Class

```typescript
export class AppError extends Error {
  constructor(
    public statusCode: number,
    public message: string,
    public isOperational = true
  ) {
    super(message);
    Object.setPrototypeOf(this, AppError.prototype);
  }
}

2. Async Route Wrapper

Wrap async route handlers to catch rejected promises automatically:

export const catchAsync = (
  fn: (req: Request, res: Response, next: NextFunction) => Promise<void>
) => {
  return (req: Request, res: Response, next: NextFunction) => {
    fn(req, res, next).catch(next);
  };
};

3. Global Error Middleware

Add this as the last middleware in your Express app:

export const errorHandler = (
  err: Error,
  req: Request,
  res: Response,
  _next: NextFunction
) => {
  if (err instanceof AppError) {
    return res.status(err.statusCode).json({
      status: "error",
      message: err.message,
    });
  }

  console.error("Unexpected error:", err);
  return res.status(500).json({
    status: "error",
    message: "Internal server error",
  });
};

Usage Example

| Layer | Purpose | Catches | |---|---|---| | AppError | Known business errors | Validation, auth, not found | | catchAsync | Unhandled promise rejections | DB errors, API timeouts | | errorHandler | Formats all errors for client | Everything |


This response mixes:
- Prose explanations
- Three separate TypeScript code blocks
- A comparison table
- Headings for structure

### Sharing It

1. Copy the entire response from Claude
2. Open [sendnote.link](https://sendnote.link)
3. Paste the content (Markdown format is selected by default)
4. Click share to get a link

The recipient opens the link and sees the response exactly as Claude formatted it -- headings, highlighted code, rendered table, and all. They can copy any code block directly. They can read the explanations in context. No formatting lost, no screenshots needed.

## When to Add Context

Sometimes the raw AI output benefits from a brief wrapper before sharing:

```markdown
## Error handling setup — from Claude

Asked Claude to design error handling for our Express API.
The approach looks solid but I want your review before
I implement it. Specifically:

- Does the AppError class fit our existing patterns?
- Should catchAsync handle specific error types differently?
- Is the error response format consistent with our other APIs?

---

[Claude's response below]

## Error Handling Setup for Express API
...

Adding your own context before the AI output helps the recipient understand why they are receiving it and what you need from them.

Best Practices for Sharing AI Outputs

Preserve the Original Format

Do not try to reformat AI output into a different structure. The AI produced Markdown; share it as Markdown. Converting it to a different format (Google Doc, Slack message, email) always loses something.

Add Attribution

Note which AI tool produced the output. This sets expectations about accuracy and helps the recipient calibrate their trust level. "Generated by Claude" or "From ChatGPT" takes two seconds and adds useful context.

Set Appropriate Expiration

Most shared AI outputs are relevant for days, not forever. A code suggestion is useful until it is reviewed and either implemented or discarded. A research summary is useful until the decision is made. Set an expiration that matches the content's useful lifespan.

Use Burn-After-Read for Sensitive Outputs

If the AI output contains proprietary logic, sensitive data, or confidential analysis, use burn-after-read to ensure it is deleted after the recipient views it.

The Takeaway

AI tools are getting better at producing complex, structured outputs. The sharing tools need to keep up. Markdown-native note sharing bridges the gap between what AI produces and what people need to receive -- preserving every heading, code block, and table without any formatting gymnastics.

The next time an AI gives you a perfect response that you need someone else to see, skip the screenshot. Share a note.

Ready to share a note?

Create and share notes instantly. No sign-up required.

Create a note