stave.dev

The lines upon which you compose Two minimal frameworks for building fast, dependency-free web applications. Zero Framework handles the backend. ShadowComponent handles the frontend. No build step. No bloat. code Zero Framework web ShadowComponent

Two Frameworks. One Stack.

Everything you need to build complete web applications, with nothing you don't.

terminal Zero Framework A minimal PHP MVC framework with automatic URL-to-class routing. Create a class, give it a method, and it's an endpoint. The framework resolves the rest.
  • Automatic URL → class routing
  • PHP 8 attributes for security & validation
  • Dual HTML/JSON response system
  • Auto-loading CSS, JS, and components
  • Plugin system with lifecycle hooks
  • Explore Zero Framework
    web ShadowComponent A custom Web Components framework for building encapsulated UI with Shadow DOM. No virtual DOM, no build step, no dependencies — just the web platform.
  • Shadow DOM encapsulation
  • Observable properties with auto-sync slots
  • Template-based rendering
  • 25+ ready-made components
  • Works with any backend or none
  • Explore ShadowComponent

    Why Stave?

    speed

    Zero Bloat

    No dependency tree to audit. No node_modules. No build pipeline. The entire framework is a handful of PHP files you can read in an afternoon.

    visibility

    Own Your Stack

    Every line is readable. Every decision is traceable. When something breaks, you'll know where to look — because there's nowhere to hide.

    music_note

    Compose, Don't Configure

    URL maps to class. File maps to asset. Name maps to component. Convention over configuration means you spend time building, not wiring.

    Up and Running in Seconds

    See how little it takes to create something real.

    A Zero Module

    <?php
    namespace Zero\Module;
    
    class Hello extends \Zero\Core\Module {
    
        public function index() {
            $this->respond($this->viewPath . 'index.php');
        }
    
        public function greet($name = 'world') {
            $this->data = ['name' => $name];
            $this->respond($this->viewPath . 'greet.php');
        }
    }
    • Visit /hello and the index renders
    • Visit /hello/greet/claude and it greets Claude
    • Send Accept: application/json and it returns JSON

    A ShadowComponent

    <template id="my-greeting">
      <style>
        :host { display: block; }
        .greeting { color: var(--accent-primary); }
      </style>
      <p class="greeting">
        Hello, <slot name="name">World</slot>!
      </p>
    </template>
    
    <script>
    class MyGreeting extends ShadowComponent {
      static observables = ["name"];
      connectedCallback() {
        super.connectedCallback();
      }
    }
    customElements.define("my-greeting", MyGreeting);
    <\/script>
    • Shadow DOM encapsulates styles automatically
    • Observable properties sync to slots
    • No build step — just include and use