Pulsar

Sponsor Pulsar

pub package pub points likes

Pulsar Web Framework

Pulsar is a simple Dart-first web framework focused on clarity, explicit behavior, and long-term maintainability.

It combines the simplicity of the web platform with the strengths of Dart, without hidden magic or unnecessary abstractions.

🌐 Website: https://pulsar-web.netlify.app


Getting Started

Installation

Pulsar projects are created and served using the official CLI.

Activate the CLI globally:

dart pub global activate pulsar_cli

Create a new project:

pulsar create hello
cd hello

Run the development server:

pulsar serve

Note: The app will be available in your browser with live reload enabled if you use the --watch option.

Project Structure

A typical Pulsar project looks like this:

lib/
 β”œβ”€ app.dart
 └─ components/
     └─ hello.dart

web/
 β”œβ”€ index.html
 β”œβ”€ main.dart
 └─ styles/
     └─ hello.css
  • lib/ contains all Dart components and layouts
  • web/ contains the entry point, HTML, and CSS assets

Pulsar intentionally avoids placing components inside web/ to prevent fragile relative imports and keep Dart code clean and package-based.

Basic Usage

Creating a Component

Components are plain Dart classes that extend Component.

import 'package:pulsar_web/pulsar.dart';

class Counter extends Component {
  int count = 0;

  void increment(Event event) => setState(() => count++);
  void decrement(Event event) => setState(() => count--);

  @override
  PulsarNode render() {
    return div(
      children: [
        h2(children: [text('$count')]),
        button(onClick: decrement, children: [text('-')]),
        button(onClick: increment, children: [text('+')]),
      ],
    );
  }
}

State is managed directly in Dart. Calling setState triggers a re-render of the component.

Styling Components

Components can define their own stylesheets:

@override
List<Stylesheet> get styles => [
  css('components/counter/counter.css'),
];

Note: The css() path is always relative to the web/ directory.

Routing & Layouts

Pulsar includes a simple router with layout support.

Defining a Layout

class App extends Component {
  final Component child;

  App(this.child);

  @override
  PulsarNode render() {
    return div(
      children: [
        h1(children: [text('Persistent Header')]),
        ComponentNode(component: child),
      ],
    );
  }
}

Configuring Routes

void main() {
  mountApp(
    RouterComponent(
      router: Router(
        routes: [
          Route(path: '/', builder: () => HomePage()),
          Route(path: '/counter', builder: () => Counter()),
        ],
        notFound: () => NotFoundPage(),
      ),
      layout: (page) => App(page),
    ),
  );
}

Navigate programmatically using:

navigateTo('/counter');

Core Philosophy

Pulsar is built around one simple idea: clarity over cleverness.

It embraces Dart as it is, without fighting the language or hiding behavior behind magic. The framework favors explicit code, predictable behavior, and direct use of the web platform.

Pulsar grows through reflection, not constant iteration. Every feature exists for a reason, and unnecessary abstractions are intentionally avoided.

The goal is not to be the most powerful framework, but the one that stays understandable, maintainable, and honest over time.

Principles

Pulsar is guided by a small set of principles that shape every design decision.

  • Clarity over cleverness
    If something feels smart but unclear, it does not belong in Pulsar.

  • Dart first, always
    Pulsar embraces Dart’s type system, null safety, and tooling.

  • Explicit by design
    What you write is what runs.

  • Minimal abstraction
    Abstractions must earn their place.

  • Respect the web platform
    Pulsar works with HTML, CSS, and browser semantics.

  • Reflection over iteration
    Design decisions are deliberate, not trend-driven.

Golden Rules

These rules act as guardrails for Pulsar’s development.

  • If a feature requires magic, it should be reconsidered.

  • If Dart already solves the problem, Pulsar must not reimplement it.

  • If an abstraction obscures behavior, it is not acceptable.

  • If something cannot be explained simply, it is probably wrong.

  • If a feature exists only for convenience, it must justify its cost.

  • If removing a feature improves clarity, it should be removed.

Pulsar values long-term clarity over short-term convenience.

Status & Stability

Pulsar is actively developed. Version 0.4.x is considered stable and suitable for real projects.

Feedback, issues, and discussions are welcome:
πŸ‘‰ https://github.com/IgnacioFernandez1311/pulsar_web

Support Pulsar

Pulsar is free and open-source.

If it helps you build better software, consider supporting its development through GitHub Sponsors.

Your support helps keep Pulsar independent, focused, and thoughtfully evolving.

❀️ https://github.com/sponsors/IgnacioFernandez1311