lunx.docs
DocsQuick Start

Quick Start Guide

Bootstrap a new application from zero to running dev server in under 2 minutes. This guide walks through project setup, directory structure, and the full dev-to-production workflow.

1. Bootstrap with lunx create

lunx createwrites a ready-to-install project from one of 26 templates: React, Vue, Svelte, Solid, Preact, Lit, Alpine, Angular, Qwik and vanilla apps, the meta-frameworks (Next.js, Nuxt, SvelteKit, Astro, React Router, TanStack Start, SolidStart, Qwik City, VitePress, Waku, Analog, Remix, Docusaurus, Marko Run), a library and an edge function. Each template is installed, built and opened in a browser by lunx's template test (npm run test:templates).

bash
# Interactive: pick a template, TypeScript or JavaScript, Tailwind
npx lunx-dev@latest create my-app

# Non-interactive for React + TypeScript + Tailwind
npx lunx-dev@latest create my-app --template react --ts --tailwind

cd my-app && npm install
Minimal scaffolding
Lunx generates only what you need. A React + TypeScript project produces 6 files. No 200-file boilerplate. The lunx.config.ts is typically 3–5 lines.

2. Project structure

A fresh Lunx project is intentionally minimal. All framework-specific wiring is handled inside the adapter — not inside your project files.

textfile tree
my-app/
├── src/
│   ├── main.tsx          # Application entry point
│   ├── App.tsx           # Root component
│   └── index.css         # Global styles / Tailwind input
├── index.html            # HTML entry template
├── lunx.config.ts       # Minimal Lunx configuration
├── tsconfig.json         # TypeScript config (auto-generated)
├── package.json
└── .gitignore

3. Understanding lunx.config.ts

The config uses defineConfig for full TypeScript autocomplete. Most fields have sensible defaults — you only declare what differs from the standard behavior.

typescriptlunx.config.ts
import { defineConfig } from 'lunx-dev'

export default defineConfig({
  // Required: which framework adapter to use
  framework: 'react',

  // Optional overrides (all have sensible defaults)
  server: {
    port: 5173,         // default dev port
    host: true,         // expose to local network
    open: true,         // open browser on start
  },
  build: {
    outDir: 'dist',     // output directory
    minify: true,       // Oxc + LightningCSS minification
    sourcemap: false,   // enable for debugging production
  },
  security: {
    scanSecrets: true,  // scan before every build
    checkCVEs: true,    // query OSV database for vulnerabilities
    generateSBOM: true, // CycloneDX 1.5 JSON/XML output
    sri: true,          // inject SHA-384 hashes into index.html
  },
})

4. Development workflow

01
Start the dev server

Boots in about 300 ms, Node startup included. A saved file reaches the browser in about 50 ms on a small app, with component state preserved across module updates.

bash
npm run dev

⚡ lunx v1.0.0  adapter: react  port: 5173
   Local:   http://localhost:5173
   Network: http://192.168.1.100:5173
   ✓ ready in 36ms
02
Make a change — HMR in action

Edit any source file. Lunx detects the change, recompiles only the changed module with Oxc, and pushes the delta to your browser over WebSocket. No full page reload.

bash
# After editing src/App.tsx:
  [hmr] module updated: src/App.tsx (18ms)
  [hmr] 1 component reloaded — state preserved
03
Build for production

Lunx runs the 8-stage security pipeline before bundling. Any violation aborts the build. Output is minified, content-hashed, and SRI-protected.

bash
npm run build

🔍 Security scan...
  ✓ Secrets: 0 found across 84 files
  ✓ CVEs:    0 critical, 0 high in 312 packages
  ✓ SBOM:    dist/bom.json written (CycloneDX 1.5)
  ✓ SRI:     SHA-384 hashes injected into index.html

📦 dist/
  assets/main-cf861a.js     94.2 kB │ gzip: 30.1 kB
  assets/style-d31e9a.css   12.4 kB │ gzip:  3.6 kB
  index.html                 0.9 kB
  ✓ built in 512ms
04
Preview before deploy

Run a local preview of your production build to verify asset paths, service worker behavior, and confirm SRI hashes before pushing to production.

bash
npm run preview
  ⚡ serving dist/ → http://localhost:4173

5. Adding your first component

Lunx supports all standard React patterns — no special wrappers required. Create a component, import it, and HMR updates it instantly with state preserved.

typescriptsrc/components/Counter.tsx
import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div className="flex flex-col items-center gap-4 p-8">
      <h2 className="text-2xl font-bold tabular-nums">Count: {count}</h2>
      <div className="flex gap-3">
        <button
          onClick={() => setCount(c => c - 1)}
          className="px-4 py-2 rounded-lg border border-zinc-700 hover:bg-zinc-800"
        >
          Decrement
        </button>
        <button
          onClick={() => setCount(c => c + 1)}
          className="px-4 py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700"
        >
          Increment
        </button>
      </div>
    </div>
  )
}
Path aliases built-in
Lunx automatically resolves @/ as an alias to your src/ directory. Import using import { Counter } from '@/components/Counter' anywhere in your project.

6. Environment variables

Lunx uses .env files following the Vite convention. Only variables prefixed with LUNX_PUBLIC_ are exposed to the browser bundle — all others remain server-side only, preventing accidental secret leaks.

bash.env
# Browser-safe (exposed to client bundle)
LUNX_PUBLIC_API_URL=https://api.example.com
LUNX_PUBLIC_APP_NAME=My App

# Server-only (never exposed to client)
DATABASE_URL=postgres://user:pass@localhost/db
STRIPE_SECRET_KEY=sk_live_...
typescript
// Access in your components
const apiUrl = import.meta.env.LUNX_PUBLIC_API_URL