Skip to content

Overview

Pico-Framework

Pico-Framework brings a modern, expressive architecture to the world of embedded development. Inspired by Express.js and designed specifically for microcontrollers, Pico-Framework makes it easy to build web-connected applications initially on the Raspberry Pi Pico.

With a modular design, a full HTTP server, flexible routing, middleware, JWT authentication, and JSON storage services — all optimized for embedded constraints — Pico-Framework offers a professional, scalable foundation for building robust IoT and control applications.

Pico-Framework brings structure, scalability, and modern design patterns to the embedded world.


Features

Key Features

  • Integrated HTTP Server
    Serve REST APIs or simple web UIs directly from the Pico, with a full-featured request/response lifecycle and persistent connection support.

  • Flexible Express-style Router
    Define routes and HTTP methods with support for path parameters, query strings, forms, middleware chaining, and route-specific logic.

  • Middleware Architecture
    Use reusable middleware to handle authentication, validation, logging, and more. Middleware can be scoped globally or per-route.

  • JWT Authentication
    Optional, built-in JSON Web Token parsing and verification, enabling secure, stateless auth without extra libraries.

  • Http Request Builder Build HTTP client requests using a simple fluent syntax and get complete Http response information.

  • JSON Service with Storage Abstraction
    Easily persist and retrieve configuration data using a built-in JSON serializer, backed by pluggable storage (e.g., SD card or littlefs). The framework supports state persistence providing a framework model based on the JSON Service.

  • Abstract Storage Interface
    Use SD FAT in 4 bit SDIO mode out of the box using the FAT+CLI library (see it on Github)) or use littlefs (see it on Github) flash file support with the same interface.

  • SD File Manager
    Read/write files, serve static assets, and manage configuration files with a simple abstraction over the SD card.

  • littlefs File Manager
    Read/write files, serve static assets, and manage configuration files with a simple abstraction over the littlefs flash file system.

  • Event Manager
    Publish and subscribe to internal system events for decoupled module communication. Supports both task and ISR contexts for both system and user events. Events can have multiple subscribers so an event can be broadcast.

  • Framework Manager The Framework Manager manages startup, bringing up Wi-Fi with resilience. It also uses SNTP to set these system time. Optionally, it can use ip-api and open-meteo to determine the local timezone. These are free to use in development but licenses may be required for commercial use.

  • Scheduler
    Built-in task scheduling system for time-of-day events, interval-based jobs, or event-triggered actions — all tied to FreeRTOS timers.

  • Object-Oriented Task Model and MVC enabled
    Each controller runs in its own task class. Tasks are lightweight, composable, and integrated with the event system. A simple set of Model/Views are provided supporting HTML, templating and JSON.

  • Dependency Injection (WIP)
    Core modules dependencies are directly injected. In addition, a simple service registration capability is provided making it easy to locate desired services. It is designed for extensibility and testability even in constrained environments.


Architecture at a Glance

Pico-Framework is designed from the ground up to feel familiar to web developers, yet optimized for embedded environments:

[Diagram coming]

Simple Application Structure

void App::initRoutes() {
  router.addRoute("GET", "/hello", []
                    (HttpRequest &req, HttpResponse &res, const auto &)
                    { res.send("Welcome to Pico-Framework!"); 
  });    
  // Add more routes ...
}

void App::onStart()
{
  // Create a controller e.g.
  static DashboardController dashboardController(router, pico);
  dashboardController.start();
}

void App::onEvent(const Event &e)
{
   if (e.notification.kind == NotificationKind::System)
    {
        switch (e.notification.system)
        {
            // Wi-Fi starts asynchronously
            case SystemNotification::NetworkReady:
                server.start(); // start the HTML server
                break;

            // ... other events
        }
    }
}

void App::poll()
{
    runEvery(15000, [&]() // run every 15 seconds
    { 
      printf("[App] Running main polling loop...\n"); 
    }, "logLoop"); 
}

Use Cases

  • Embedded Control Panels (e.g., sprinkler systems, lighting controllers, home automation)
  • IoT Gateways & Edge Devices
  • Diagnostics Dashboards
  • Secure Configuration Interfaces
  • Lab Tools & Instrumentation

Getting Started

Visit the GitHub repository (when we go public later this month):
👉 https://github.com/Pico-Framework

You'll find: - Quick start guides - Code examples - Ready-to-run demo projects - Documentation on tasks, routes, events, and configuration


Licensing

Pico-Framework is released under the MIT License to maximize adoption, contributions, and commercial flexibility.


Contribute or Contact

Want to contribute or collaborate? Open an issue or pull request on GitHub, or email us at: 📩 ian@archbell.com

Pico-Framework brings structure, scalability, and modern design patterns to the embedded world.