No description
  • TypeScript 75.6%
  • CSS 14.5%
  • Shell 6.9%
  • HTML 3%
Find a file Use this template
izy 1f05d2a297
Some checks failed
Build / build (push) Failing after 52s
Replace Docker with direct commands in CI
Removes the Docker wrapper from build.sh in favor of running
pnpm and composer natively. The CI workflow now delegates to
build.sh --ci and sets minimumReleaseAge in pnpm config.
2026-05-15 23:24:35 +00:00
.forgejo/workflows Replace Docker with direct commands in CI 2026-05-15 23:24:35 +00:00
plugins Refactor multi-page plugin and remove hardcoded base meta 2026-05-14 18:22:02 +00:00
src Add multi-page Vite plugin for route-based rendering 2026-05-14 15:59:15 +00:00
.gitignore Initial commit 2026-05-12 18:28:32 +00:00
.rules Update project rules and rsync delete flag 2026-05-15 03:38:45 +00:00
build.sh Replace Docker with direct commands in CI 2026-05-15 23:24:35 +00:00
components.json Initial commit 2026-05-12 18:28:32 +00:00
index.html Refactor multi-page plugin and remove hardcoded base meta 2026-05-14 18:22:02 +00:00
LICENSE Initial commit 2026-05-12 18:28:32 +00:00
package.json Move pnpm build allowlist to workspace config 2026-05-13 04:10:24 +00:00
pnpm-lock.yaml Add path-based routing and update docs 2026-05-14 13:08:33 +00:00
pnpm-workspace.yaml Replace Docker with direct commands in CI 2026-05-15 23:24:35 +00:00
README.md Add path-based routing and update docs 2026-05-14 13:08:33 +00:00
tsconfig.json Reset styling and config to defaults; update pnpm 2026-05-12 23:57:20 +00:00
vite.config.ts Add multi-page Vite plugin for route-based rendering 2026-05-14 15:59:15 +00:00

Preact Template

A minimal Preact project template with TypeScript, Tailwind CSS v4, and Vite 7.

Stack

  • Framework: Preact 10 + TypeScript
  • Build Tool: Vite 7
  • Styling: Tailwind CSS v4 (via @tailwindcss/vite)
  • Fonts: JetBrains Mono (bundled via @fontsource)
  • Icons: Lucide (Preact-compatible)
  • UI Components: Minimal shadcn-style components in src/components/ui/

Architecture

src/
├── App.tsx              # Route dispatcher (path-based routing via window.location.pathname)
├── main.tsx             # Preact entry point with ErrorBoundary
├── ErrorFallback.tsx    # Error boundary fallback UI
├── index.css            # Single source of truth for all styles
├── pages/               # Page components (one file per route)
│   └── Home.tsx         # Home page component
├── components/
│   └── ui/              # shadcn-style UI components (Button, Alert)
├── lib/                 # Utility functions
└── assets/              # Images, favicon

Styling System

Single CSS file: src/index.css contains:

  • Tailwind CSS imports
  • Custom CSS variables for the theme (OKLCH color space)
  • Custom @keyframes animations (fade-in)
  • Accessibility support (prefers-reduced-motion)

Custom color palette (OKLCH):

  • --background / --foreground: Base surface and text colors
  • --primary: Brand primary color (indigo)
  • --card: Card surface color
  • --cyan, --magenta, --matrix-green: Extended accent colors

DO NOT create additional CSS files. All styling goes in index.css or inline Tailwind classes.

Build Configuration

Vite config (vite.config.ts):

  • Preact plugin for JSX transformation
  • Tailwind CSS v4 via @tailwindcss/vite
  • Image optimization via vite-plugin-image-optimizer (85% quality)
  • Terser minification (drop console, mangle toplevel, 2-pass)
  • Lightning CSS for CSS minification
  • Path alias: @/src/

TypeScript: --noCheck flag used in build script for faster builds

Build System

CRITICAL: All dependency management happens inside Docker containers via build.sh. Never run pnpm commands directly on the host for production builds.

./build.sh           # Build project (output in dist/)
./build.sh install   # Fresh install + audit + build
./build.sh clean     # Remove node_modules, dist, caches
./build.sh update    # Update dependencies to latest compatible versions
./build.sh audit     # Run security audit

The build.sh script:

  1. Runs all pnpm commands inside ephemeral node:latest Docker containers
  2. Mounts current directory as /app with user permissions
  3. Installs pnpm globally in container's temp directory
  4. Builds from src/ → outputs to dist/

Development

For quick iteration without Docker (not recommended for production builds):

pnpm dev      # Dev server at http://localhost:5173
pnpm build    # Build to dist/
pnpm preview  # Preview production build
pnpm lint     # ESLint check

Making Changes

  1. Edit source files in src/
  2. Test with pnpm dev or ./build.sh
  3. The build output goes to dist/

Dependency Management

To add/remove dependencies:

  1. Edit package.json
  2. Run ./build.sh install to reinstall and rebuild
  3. Test the build works before committing

Conventions

Preact vs React

  • Import from preact and preact/hooks, NOT react
  • Use react-error-boundary for error boundaries (Preact compatibility)
  • Button component uses @radix-ui/react-slot with asChild pattern for polymorphic rendering

Tailwind Configuration

  • CSS variables: Defined in :root and @theme blocks in index.css
  • Components config: components.json defines shadcn paths/aliases

Adding UI Components

Follow shadcn-style patterns:

  1. Components go in src/components/ui/
  2. Use class-variance-authority for variant props
  3. Use tailwind-merge via @/lib/utils for className merging
  4. Export component with TypeScript interface

Adding Pages (Routing)

The app uses path-based routing via window.location.pathname in src/App.tsx — no router library needed.

  1. Create a new page component in src/pages/ (e.g., src/pages/About.tsx)
  2. Add a route condition in src/App.tsx:
    if (path === "/about") return <About />;
    
  3. Server config: Caddy must have try_files {path} /index.html in the site block so unknown paths serve the SPA's index.html. Without this, direct navigation to routes returns 404.

Icon Usage

Icons via lucide-react. Import specific icons to avoid bundle bloat.

Image Optimization

SVG and raster images in src/assets/ are automatically optimized during build via vite-plugin-image-optimizer (uses Sharp for rasters, SVGO for vectors).

What NOT to Do

  • Don't run pnpm commands directly on host for production builds (use ./build.sh)
  • Don't create additional CSS files (index.css is the single source of truth)
  • Don't duplicate color variables or animation definitions
  • Don't add animation libraries (define custom keyframes in index.css instead)
  • Don't add a tailwind.config.js (Tailwind v4 is configured via CSS @theme block)
  • Don't add a router library — use window.location.pathname in App.tsx with page components in src/pages/
  • Don't add generic documentation files that don't reflect actual codebase state