Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ jobs:
- name: Install documentation dependencies
run: pip install -r requirements-docs.txt

- name: Validate documentation conversion script
run: pip install pytest && pytest docs/scripts/test_convert_docs.py

- name: Convert Admonitions in Documentation
run: python docs/scripts/convert_docs.py --mode github-to-mkdocs

- name: Build Documentation (PR Check)
if: github.event_name == 'pull_request'
run: mkdocs build
Expand Down
5 changes: 3 additions & 2 deletions docs/community.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ A2UI is an open-source project licensed under Apache 2.0. We welcome contributio

## Community Showcase

!!! info "Coming soon..."
We are considering how best to showcase community projects, examples, themes, renderers, custom components, and more. A 4 minute (or less) demo video and code sample linked in Github discussions is a great way to show off your work.
> ℹ️ **Coming soon...**
>
> We are considering how best to showcase community projects, examples, themes, renderers, custom components, and more. A 4 minute (or less) demo video and code sample linked in Github discussions is a great way to show off your work.

## Project Partners

Expand Down
5 changes: 3 additions & 2 deletions docs/guides/agent-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ Select `my_agent` from the list, and ask questions about restaurants in New York

Getting the LLM to generate A2UI messages requires some prompt engineering.

!!! warning "Attention"
This is an area we are still designing. The developer ergonomics of this are not yet finalized.
> ⚠️ **Attention**
>
> This is an area we are still designing. The developer ergonomics of this are not yet finalized.

For now, let's copy the `a2ui_schema.py` from the contact lookup example. This is the easiest way to get the A2UI schema and examples for your agent (subject to change).

Expand Down
14 changes: 8 additions & 6 deletions docs/guides/client-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ Integrate A2UI into your application using the renderer for your platform.

## Web Components (Lit)

!!! warning "Attention"
The Lit client library is not yet published to NPM. Check back in the
coming days.
> ⚠️ **Attention**
>
> The Lit client library is not yet published to NPM. Check back in the
> coming days.

```bash
npm install @a2ui/web-lib lit @lit-labs/signals
Expand All @@ -35,9 +36,10 @@ TODO: Add verified setup example.

## Angular

!!! warning "Attention"
The Angular client library is not yet published to NPM. Check back in the
coming days.
> ⚠️ **Attention**
>
> The Angular client library is not yet published to NPM. Check back in the
> coming days.

```bash
npm install @a2ui/angular @a2ui/web-lib
Expand Down
11 changes: 6 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ A2UI enables AI agents to generate rich, interactive user interfaces that render

</div>

!!! warning "️Status: Early Stage Public Preview"
A2UI is currently in **v0.8 (Public Preview)**. The specification and
implementations are functional but are still evolving. We are opening the project to
foster collaboration, gather feedback, and solicit contributions (e.g., on client renderers).
Expect changes.
> ⚠️ **️Status: Early Stage Public Preview**
>
> A2UI is currently in **v0.8 (Public Preview)**. The specification and
> implementations are functional but are still evolving. We are opening the project to
> foster collaboration, gather feedback, and solicit contributions (e.g., on client renderers).
> Expect changes.

## At a Glance

Expand Down
5 changes: 3 additions & 2 deletions docs/introduction/agent-ui-ecosystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ The space for agentic UI is evolving rapidly, with excellent tools emerging to s

The A2UI approach is to send JSON as a message to the client, which then uses a renderer to convert it into native UI components. LLMs can generate the component layout on the fly or you can use a template.

!!! tip ""
**This makes it secure like data, and expressive like code.**
> 💡
>
> **This makes it secure like data, and expressive like code.**

This rest of this page will help you understand A2UI in relationship to other options.

Expand Down
15 changes: 9 additions & 6 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ Before you begin, make sure you have:
- **Node.js** (v18 or later) - [Download here](https://nodejs.org/)
- **A Gemini API key** - [Get one free from Google AI Studio](https://aistudio.google.com/apikey)

!!! warning "Security Notice"
This demo runs an A2A agent that uses Gemini to generate A2UI responses. The agent has access to your API key and will make requests to Google's Gemini API. Always review agent code before running it in production environments.
> ⚠️ **Security Notice**
>
> This demo runs an A2A agent that uses Gemini to generate A2UI responses. The agent has access to your API key and will make requests to Google's Gemini API. Always review agent code before running it in production environments.

## Step 1: Clone the Repository

Expand Down Expand Up @@ -59,8 +60,9 @@ This command will:
4. Launch the development server
5. Open your browser to `http://localhost:5173`

!!! success "Demo Running"
If everything worked, you should see the web app in your browser. The agent is now ready to generate UI!
> ✅ **Demo Running**
>
> If everything worked, you should see the web app in your browser. The agent is now ready to generate UI!

## Step 5: Try It Out

Expand Down Expand Up @@ -185,8 +187,9 @@ This populates the data model that components can bind to.

This tells the client it has enough information to render the UI.

!!! tip "It's Just JSON"
Notice how readable and structured this is? LLMs can generate this easily, and it's safe to transmit and render—no code execution required.
> 💡 **It's Just JSON**
>
> Notice how readable and structured this is? LLMs can generate this easily, and it's safe to transmit and render—no code execution required.

## Exploring Other Demos

Expand Down
144 changes: 144 additions & 0 deletions docs/scripts/convert_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import os
import re
import argparse

# Registry for bidirectional format conversion:
#
# Key: The MkDocs admonition type (the target for '!!! type' syntax).
# Value:
# - emoji: Used for mapping GitHub-style emoji quotes (> ⚠️) to MkDocs.
# - tag: Reserved for mapping official GitHub Alert syntax (> [!WARNING]).
MAPPING = {
"warning": {"emoji": "⚠️", "tag": "WARNING"},
"tip": {"emoji": "💡", "tag": "TIP"},
"info": {"emoji": "ℹ️", "tag": "NOTE"},
"success": {"emoji": "✅", "tag": "SUCCESS"},
"danger": {"emoji": "🚫", "tag": "CAUTION"},
"note": {"emoji": "📝", "tag": "NOTE"}
}

# Reverse lookup: mapping emojis back to their respective MkDocs types
EMOJI_TO_TYPE = {v["emoji"]: k for k, v in MAPPING.items()}

# Emoji Pattern: Handles optional bold titles and standard emojis
EMOJI_PATTERN = r'>\s*(⚠️|💡|ℹ️|✅|🚫|📝)(?:\s*\*\*(.*?)\*\*)?\s*\n((?:>\s*.*\n?)*)'

# GitHub Alert Pattern [!TYPE]
GITHUB_ALERT_PATTERN = r'>\s*\[\!(WARNING|TIP|NOTE|IMPORTANT|CAUTION)\]\s*\n((?:>\s*.*\n?)*)'

# MkDocs Pattern: Captures '!!! type "Title"' blocks
MKDOCS_PATTERN = r'!!!\s+(\w+)\s+"(.*?)"\n((?:\s{4}.*\n?)*)'


def clean_body_for_mkdocs(body_text):
"""
Cleans blockquote content for MkDocs:
1. Removes leading '>' markers.
2. Strips ALL leading blank lines to close the gap with the title.
3. Strips ALL trailing blank lines to prevent extra lines at the end.
4. Preserves internal paragraph breaks.
"""
# Remove leading '>' and trailing whitespace from each line
raw_lines = [re.sub(r'^>\s?', '', line).rstrip() for line in body_text.split('\n')]

# Find the first line with actual text (to strip leading blank lines)
start_idx = -1
for i, line in enumerate(raw_lines):
if line.strip():
start_idx = i
break

if start_idx == -1:
return ""

# Slice from the first content line
content_lines = raw_lines[start_idx:]

# Join lines and rstrip the entire block to remove trailing blank lines
body = "\n".join([f" {l}".rstrip() for l in content_lines]).rstrip()
return body

def to_mkdocs(content):
"""Converts GitHub style to MkDocs style."""

def emoji_replacer(match):
emoji_char, title, raw_body = match.groups()
adm_type = EMOJI_TO_TYPE.get(emoji_char, "note")
body = clean_body_for_mkdocs(raw_body)
title_val = title if title else ""
# Return block with exactly one newline at the end
return f'!!! {adm_type} "{title_val}"\n{body}\n'


def alert_replacer(match):
alert_type = match.group(1).lower()
type_map = {"important": "info", "caution": "danger"}
mkdocs_type = type_map.get(alert_type, alert_type)
raw_body = match.group(2)

first_line_match = re.search(r'^>\s*\*\*(.*?)\*\*\s*\n', raw_body)
title = first_line_match.group(1) if first_line_match else ""
if first_line_match:
raw_body = raw_body[first_line_match.end():]

body = clean_body_for_mkdocs(raw_body)
return f'!!! {mkdocs_type} "{title}"\n{body}\n'

content = re.sub(EMOJI_PATTERN, emoji_replacer, content, flags=re.MULTILINE)
content = re.sub(GITHUB_ALERT_PATTERN, alert_replacer, content, flags=re.MULTILINE)
return content

def to_github(content):
"""Converts MkDocs style to GitHub style."""

def mkdocs_replacer(match):
adm_type, title, body = match.groups()
# Safely retrieve the emoji, default to 'note' (📝) for unknown/unmapped types
emoji = MAPPING.get(adm_type, {"emoji": "📝"})["emoji"]

# Strip trailing whitespace from captured body to prevent hanging '>'
clean_body = body.rstrip()
raw_lines = clean_body.split('\n')
content_lines = [re.sub(r'^\s{4}', '', line).rstrip() for line in raw_lines]

# Header line logic
github_lines = [f"> {emoji} **{title}**"] if title.strip() else [f"> {emoji}"]
github_lines.append(">") # Spacer line

for line in content_lines:
github_lines.append(f"> {line}" if line else ">")

return "\n".join(github_lines) + "\n"

return re.sub(MKDOCS_PATTERN, mkdocs_replacer, content)

def process_file(path, mode):
mode_map = {
"github-to-mkdocs": to_mkdocs,
"mkdocs-to-github": to_github
}
if mode not in mode_map:
raise ValueError(f"Unsupported mode: {mode}. Choose from {list(mode_map.keys())}.")
target_func = mode_map[mode]

with open(path, 'r', encoding='utf-8') as f:
content = f.read()
new_content = target_func(content)
if new_content != content:
with open(path, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f"[{mode.upper()}] Converted: {path}")

def run_conversion(mode):
for root, dirs, files in os.walk('docs'):
if any(x in root for x in ['scripts', 'assets', '__pycache__']):
continue
for file in files:
if file.endswith('.md'):
process_file(os.path.join(root, file), mode)

if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Bidirectional Markdown Admonition Converter")
parser.add_argument("--mode", choices=["github-to-mkdocs", "mkdocs-to-github"], required=True, help="Target format")
args = parser.parse_args()
run_conversion(args.mode)
Loading
Loading