Third-party packages

A Pyxle project has two dependency sets: Python packages (used by your @server loaders, @action mutations, and pages/api/*.py endpoints) and Node packages (used by your React/JSX components). Add to whichever side you need.

Python packages (pip)

Add the package to requirements.txt and install:

echo "pydantic>=2" >> requirements.txt
pip install -r requirements.txt

Import it in the Python section of a .pyxl file (above the first JS import) or in a pages/api/*.py module:

from pydantic import BaseModel

Node packages (npm)

Install with npm and import it in the JSX section of a .pyxl file:

npm install zustand
import { create } from 'zustand';

Vite bundles it for the browser and Pyxle's SSR runtime bundles it for the server, so most packages "just work" on both. Prefer packages with SSR support (they render the same markup on the server and client) — a browser-only package should be used inside a useEffect, an event handler, or a <ClientOnly> boundary. See Client Components.

Run both installers at once with pyxle install.

CommonJS packages and SSR

The server render bundles your page as an ES module, with React provided by the runtime rather than bundled in. Pyxle resolves dependencies ESM-first (it prefers a package's module/ESM entry over its CommonJS main), so libraries that ship both — including lucide-react and most of the shadcn/ui ecosystem — render on the server with no extra configuration.

A package that ships only CommonJS and calls require('react') internally can't be linked into the ES-module server bundle. If one does, the server render fails with an actionable error that names the package's require(...) and your page file, and suggests the fix: use a version that ships an ES module, or render that part of the page client-only with <ClientOnly> so it never runs during the server render.

The import alias

pyxle init sets up an import alias (default @/*) in jsconfig.json, and Pyxle wires the same alias into the Vite config and the SSR runtime. So @/lib/format resolves to lib/format.js from anywhere, on both server and client:

import { formatDate } from '@/lib/format';

shadcn/ui

shadcn/ui is a collection of components you copy into your project (not an installed dependency). Enable it when you scaffold:

pyxle init my-app --shadcn        # implies Tailwind
# or answer "y" to the shadcn prompt in interactive init

The scaffold pre-configures everything shadcn needs — components.json, jsconfig.json (the @ alias), lib/utils.js, and a Tailwind v4 stylesheet with the shadcn theme tokens — so you don't need to run shadcn init. Add components directly:

cd my-app
npm install
npx shadcn@latest add button

This drops components/ui/button.jsx into your project (JavaScript, not TypeScript). Import it via the alias and use it in any page:

// pages/index.pyxl (JSX section)
import { Button } from '@/components/ui/button';

export default function Home() {
  return <Button>Click me</Button>;
}

pyxle build bundles it for production and it renders server-side like any other component.

Verified flow. The steps above were verified end to end on Node 22 with shadcn@latest: scaffold with --shadcnnpm installnpx shadcn@latest add button → import via @/components/ui/buttonpyxle build + pyxle serve. Because the scaffold ships a ready components.json, running shadcn init is unnecessary — it would only offer to overwrite the config the scaffold already wrote.

Adding shadcn to an existing project

If you scaffolded without it, enable Tailwind first (see Styling), then create a components.json at your project root (npx shadcn@latest init can generate it in JavaScript mode — answer no to TypeScript), pointing its tailwind.css at your CSS entry (pages/styles/app.css) and its aliases at your import alias.

Next steps