Files
nuc/docs/publishing-artifacts.md
Alejandro Gutiérrez f56528ddcd Slim CLAUDE.md from 65K to 21K by splitting app-specific docs
Move OpenClaw, Palmr, MinIO, JSX publishing, MCP configs, and migration
candidates into dedicated docs/ files. Keep only DevOps-essential content
inline (deployment rules, DNS, router, credentials, troubleshooting).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 02:56:08 +00:00

100 lines
3.8 KiB
Markdown

# Publishing JSX/React Artifacts Online
Single-file React components (JSX) can be published as standalone web pages via the NUC's artifacts infrastructure.
## How It Works
```
Public Internet → Tailscale Funnel (:443) → Traefik → artifacts-web (nginx) → /opt/artifacts/
```
- **Funnel URL:** `https://alezmad-nuc.tail58f5ad.ts.net/artifacts/<name>/`
- **LAN URL:** `https://artifacts.nuc.lan/<name>/`
- **Nginx container:** `artifacts-web` (image: `nginx:alpine`, read-only mount of `/opt/artifacts`)
- **Traefik public route:** `Host(alezmad-nuc.tail58f5ad.ts.net) && PathPrefix(/artifacts)` → strips `/artifacts``artifacts-web:80`
- **Config file:** `/traefik/dynamic/nuc-services-public.yaml` (inside `coolify-proxy` container)
## Quick Publish Steps
```bash
# 1. Build self-contained HTML from JSX
# - Replace `import { useState, ... } from "react"` with `const { useState, ... } = React;`
# - Remove `export default ComponentName;`
# - Wrap in HTML with React 18 CDN + Babel standalone
# - Add `ReactDOM.createRoot(root).render(<Component />)` at the end
# 2. Copy to NUC artifacts directory
ssh nuc "echo '7vXHpSTD.' | sudo -S mkdir -p /opt/artifacts/<name>"
scp /tmp/build/index.html nuc:~/tmp-artifact.html
ssh nuc "echo '7vXHpSTD.' | sudo -S mv ~/tmp-artifact.html /opt/artifacts/<name>/index.html"
ssh nuc "echo '7vXHpSTD.' | sudo -S chmod 644 /opt/artifacts/<name>/index.html"
# 3. Done! No server restart needed — nginx serves it immediately.
```
## HTML Template for JSX Files
```html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TITLE</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #08090d; overflow-x: hidden; }
/* Add any @keyframes or global styles here */
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect, useRef, useCallback } = React;
// ... paste JSX component code here (without import/export lines) ...
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(React.createElement(ComponentName));
</script>
</body>
</html>
```
## Build Script (for large JSX files)
```bash
# Automated: strips import/export, wraps in HTML
cat > /tmp/build.html << 'HEADER'
<!DOCTYPE html>
<html><head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head><body><div id="root"></div>
<script type="text/babel">
const { useState, useEffect, useRef, useCallback, useMemo, useReducer } = React;
HEADER
# Strip first line (import) and last line (export), append body
sed -n '2,$p' source.jsx | sed '$d' >> /tmp/build.html
# Add render footer (replace COMPONENT_NAME)
cat >> /tmp/build.html << 'FOOTER'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(React.createElement(COMPONENT_NAME));
</script></body></html>
FOOTER
```
## Currently Published
| Path | Source | Public URL |
|------|--------|------------|
| `/opt/artifacts/checkin/` | `arrio/.scratch/checkin_demo_v1.jsx` | `https://alezmad-nuc.tail58f5ad.ts.net/artifacts/checkin/` |