# Spiderpup A lightweight web framework with reactive components, written in Perl and JavaScript. Author components in YAML or single-file `.pup` format. ## Features - **Declarative components** - Define UI with YAML or single-file `.pup` syntax - **Reactive data binding** - Computed properties with automatic updates - **Shorthand syntax** - `$var` for getters/setters, `@click` for events, implicit `this` - **LESS compiler** - Variables, nesting, mixins, color functions, math (via CSS::LESSp) - **Component composition** - Imports, slots, broadcast/receive, event bubbling - **SPA routing** - Client-side navigation with route parameters - **Transitions** - Animated conditional rendering (fade, slide) - **Developer experience** - Error overlays, HTML caching, base path support ## Architecture Spiderpup uses a two-part architecture: 1. **pupserver** - A Perl HTTP server that: - Loads YAML and `.pup` page definitions - Compiles LESS to CSS - Transforms shorthand syntax (`$var`, `@click`, implicit `this`) - Parses HTML templates into JSON structures - Generates JavaScript class definitions - Caches compiled HTML for performance - Serves static files (JS, CSS, raw YAML) 2. **www/webroot/js/spiderpup.js** - A client-side JavaScript runtime that: - Provides the `Recipe` base class for components - Handles reactive rendering and updates - Manages component lifecycle (mount/destroy) - Implements control flow (`if`/`elseif`/`else`, `for` loops) - Supports slots for component composition - Provides broadcast/receive messaging between components - Handles event bubbling via `emit`/`on` ## Getting Started ### Running the Server ```bash pupserver ``` The server runs on `http://localhost:5000` by default. ### Project Structure ``` spiderpup/ ├── bin/ │ └── pupserver # Perl web server ├── lib/ │ └── Yote/Spiderpup/ # Server-side modules │ ├── SFC.pm # Single-file component (.pup) parser │ └── Transform.pm # Expression transformer └── www/ # Web root directory ├── webroot/ # Static assets (servable by any webserver) │ ├── js/ # JavaScript │ │ └── spiderpup.js # Client-side runtime │ ├── css/ # CSS stylesheets │ └── *.html # Compiled page files ├── pages/ # Page definitions (YAML or .pup) │ ├── index.yaml # Served at / │ ├── about.yaml # Served at /about │ └── mydir/ # Subdirectory │ └── index.yaml # Served at /mydir └── recipes/ # Reusable components ├── card.yaml # Imported as /recipes/card ├── clicker.pup # .pup format also works └── ... ``` ### URL Routing URLs map to pages as follows: | URL | Page File | |-----|-----------| | `/` | `www/pages/index.yaml` (or `index.pup`) | | `/about` | `www/pages/about.yaml` (or `about.pup`) | | `/mydir` | `www/pages/mydir/index.yaml` (or `index.pup`) | | `/mydir/dashboard` | `www/pages/mydir/dashboard.yaml` (or `dashboard.pup`) | Both `.yaml` and `.pup` files are supported. When both exist, `.yaml` takes precedence. Recipes in `www/recipes/` are not directly accessible via URL. They are only available for import by pages and other recipes. ## Single-File Components (.pup) As an alternative to YAML, you can author pages and recipes using the `.pup` single-file component format. This uses ` ``` ### Block Reference | Block | Maps to | Notes | |-------|---------|-------| | ` ``` Comments (`//` and `/* */`) and trailing commas are supported. ### Sub-Recipes Define sub-recipes using `recipe="name"` on script and template blocks: ```html ``` ### YAML vs .pup Both formats produce identical compiled output. Choose based on preference: | | YAML | .pup | |---|------|------| | Syntax | Indentation-based | Block-based (`` tags (files loaded separately) - **`include-js`**: Reads file contents and embeds them inline in a `