Librerías externas y otros frameworks
¿Bootstrap, PrimeVue, un gráfico con Chart.js, un juego con Phaser, o convivir con una app entera de Quasar, Vue, React o Angular? Nexa no reemplaza nada de eso — sabe convivir con todo, con un mecanismo distinto según qué tan "viva" sea la librería.
CSS de terceros: un <link> normal
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">Bootstrap, Tailwind por CDN, el CSS de PrimeVue/PrimeReact — Nexa nunca procesa ni entiende ese CSS, así que no hace falta ningún paso especial. Un <link rel="stylesheet"> en src/layout.tsx (para todo el sitio) o en una página puntual alcanza.
JS con build global (UMD): un <script> normal
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
function renderChart() {
new Chart(document.getElementById("grafico"), {
type: "bar",
data: { labels: ["Ene", "Feb"], datasets: [{ data: [10, 20] }] }
});
}Bootstrap JS, Chart.js, y en general cualquier librería que se pueda cargar como <script> clásico (no type="module") deja una variable global (bootstrap, Chart, ...). Como un chunk de Nexa copia el handler tal cual, podés usar esa variable global directo en un onClick — sin declarar nada en nexa.toml.
Librerías ES module puras: el mismo [imports] que platform/stripe
# nexa.toml
[imports]
confetti = "https://esm.sh/canvas-confetti"Si la librería solo se distribuye como módulo ES (sin build global), usá [imports] — el mismo mecanismo que ya usan platform y stripe. El chunk detecta <nombre>. en el handler y antepone el import; el import map del <head> resuelve el specifier a la URL real.
Motores y frameworks completos: como isla
<div data-nexa-island="game" data-nexa-strategy="visible">
<p>Cargando juego…</p>
</div>
// src/islands/game.island.ts — Phaser cargado como <script> global
export default function mount(el) {
const game = new Phaser.Game({ parent: el, width: 800, height: 600 });
return () => game.destroy(true);
}Para algo con ciclo de vida propio — el loop de un juego de Phaser, o un árbol de componentes con estado de Vue/Quasar/React/Angular — la respuesta es una isla, no [imports] suelto en un handler. Tu app de Quasar se compila con SU propio build (Vite, igual que siempre); Nexa nunca lee tus .vue ni tus .tsx de React, solo sirve el bundle final como cualquier otro JS. Importante: aunque la sintaxis de Nexa se parezca a React (JSX, export default function), una página Nexa NO es un componente React — se compila a HTML estático una sola vez, sin VDOM, sin hooks, sin re-render. useState/useEffect no funcionan ahí; si necesitás eso de verdad, va dentro de una isla que use React de verdad.
Vendorizar un paquete de npm real: la guía completa
mkdir vendor-build && cd vendor-build
npm install marked
echo 'export { marked } from "marked";' > entry.js
npx esbuild entry.js --bundle --format=esm --target=es2022 --outfile=marked.js
cp marked.js ../public/vendor/marked.js
# nexa.toml
[imports]
marked = "/vendor/marked.js"Cuando el paquete tiene dependencias propias o viene en CommonJS (el caso más común, no solo ESM puro del punto anterior), hace falta un paso de bundling — instalar el paquete en cualquier lado con npm, un entry.js que re-exporte lo necesario, y esbuild --bundle --format=esm a un único archivo, copiado a public/vendor/. El proceso paso a paso, con dos ejemplos reales ya probados (con envoltorio propio, y sin ninguno), está en docs/VENDORING.md del repo de Nexa.