# Markdown Viewer
Read-only Markdown renderer — fetches a `.md` file by URL (public web or SGApps `fs://`), renders it inline with navigation on in-page links to other `.md` files and a "Go Home" bar.
Internally this is the **Code Editor** webapp launched with a chrome-less preset: no sidebar, no top toolbars, no tab bar, light theme, and the markdown tab type pre-selected (not Monaco source — the rendered HTML view).
For an **editable** Markdown surface with WYSIWYG, DOCX/ODF import/export, and both source and preview modes, use [Writer](/apps/writer.md) instead.
## Live Demo
## Embed
```html
```
### Open with a Markdown URL
Encode the Markdown URL in base64 and append it as `/url/`:
```js
var mdUrl = "https://sgapps.io/webapp-docs/README.md";
var src = "https://sgapps.io/online/webapp/markdown-browser/url/" + btoa(mdUrl);
```
Default (no arg) opens the Code Editor welcome page.
## Navigation
Links inside the rendered Markdown behave contextually:
- Links to `.md` / `.markdown` files are rewritten and opened in the same viewer (full navigation stack with a "Go Home" button to return to the originally loaded doc).
- `http(s)://` and `ftp(s)://` links and in-page anchors (`#section`) open as normal external links (new tab).
- Other relative paths open through [xdg-open](https://sgapps.io/online/webapp/xdg-open) — routed to the matching registered app for that mimetype.
Relative image / asset URLs are resolved against the current `.md` file's folder.
## API Events
Markdown Viewer inherits the full [Code Editor](/apps/code-editor.md) API. The active tab is a markdown-render tab (not a Monaco text buffer), so these behave specifically:
- `active-file:codeEditor:value`, `:syntax`, `:markers` → return "No active editor" (no Monaco for this tab type).
- `files:open`, `files:list`, `files:active:set`, `files:close:all` → work normally.
- `fs:*` (read, write, exists, stats, …) → work normally through the shared fs instance.
### `files:open` -- Open a `.md` File in a New Tab
```js
socket.fire("webapp::instance::request", "files:open",
"/files/README.md", "markdown",
function (err, tabId) { /* ... */ }
);
```
### `fs:write` + `files:open` -- Render In-Memory Markdown
```js
var md = "# Hello\n\nThis Markdown was written from the embedder.";
socket.fire("webapp::instance::request", "fs:write",
"input://memory/doc.md", md,
function (err) {
if (err) return console.error(err);
socket.fire("webapp::instance::request", "files:open",
"input://memory/doc.md", "markdown");
}
);
```
### `files:list` -- List Open Tabs
```js
socket.fire("webapp::instance::request", "files:list",
function (err, tabs) { console.log(tabs); }
);
```
## Window Chrome Controls
Fullscreen (hide header + footer):
```js
socket.fire("webapp::instance::embed-mode", true);
```
Granular controls — see [Embedding](/embedding.md).
## Supported Mime Types
Registered for: `text/x-markdown`, `text/markdown`.
Opens from the SGApps window manager when a `.md` is double-clicked in File Manager. Also auto-selected for directory paths matching `/public/documentation/`, `/public/share/*/`, `/apps/*/public/` via the `readme-preview` handler (renders the folder's `README.md` as the entry point).
## Features
- Inline Markdown rendering (not Monaco source view) with navigation
- Click-through on `.md` / `.markdown` links keeps you inside the viewer
- Relative images resolve against the current file's folder
- "Go Home" bar on secondary files to return to the first-loaded doc
- Default welcome content when no URL is passed
- Full inherited `files:*` and `fs:*` API from Code Editor
- For **editing**: use [Writer](/apps/writer.md) (WYSIWYG + markdown source + DOCX/ODF import)