# PicoSPA

PicoSPA - progressive enhancer for your MPA, make it feel PicoSPA.

[![Minified bundle size](https://img.shields.io/bundlephobia/minzip/@pic0/spa.svg)](https://bundlephobia.com/package/@pic0/spa)
[![really open source](https://img.shields.io/badge/really-open_source-red)](https://codeberg.org/wolframkriesing/picospa)
[![License](https://img.shields.io/npm/l/@pic0/spa.svg)](https://codeberg.org/wolframkriesing/picospa/src/branch/main/LICENSE)
[![npm version](https://img.shields.io/npm/v/@pic0/spa.svg)](https://www.npmjs.com/package/@pic0/spa)

**PicoSPA** makes Multi-Page Applications (MPAs) feel a bit more like Single-Page Applications (SPAs) — without changing your architecture.

It's a small, framework-agnostic JavaScript library that allows you to:
- Restore scroll positions across navigations
- Reopen `<details>` elements after reload
- Toggle and restore color schemes
- Add anchors to headings
- Store all state in `sessionStorage`
- It adds no dependencies, weighs ~2KB minified

Use it with a `<script>` tag and enhance your site with just a few lines.

## 💡 Why?

MPAs often lose state (scroll, UI toggles, etc.) between page loads.
SPAs often come with huge frameworks and complexity, size and speed overhead without much gain.  
PicoSPA helps you preserve these micro-interactions without rewriting your site.
See how [kokoanalytics](https://www.kokoanalytics.com/2024/10/30/server-side-rendering-in-koko-analytics-version-1-4/)
uses exactly this same approach.

## 🚀 Getting Started

Include via a script tag at the end of your page, or at least after the
DOM nodes referred to have been rendered.

```html
<script src="https://cdn.jsdelivr.net/npm/@pic0/spa@2026.1.12/_dist/picospa.min.js"></script>
<script>
  // Restore scroll position of the page, useful e.g. when filtering/sorting data, big forms, comments, threads, ...
  picospa.scroll.restore();
  
  // Reopen the <details> on page changes or when coming back to the page.
  picospa.details.reopen();
  
  // Restore the color scheme, e.g. light or dark mode.
  picospa.colorScheme.restoreLast();
  
  // Add anchors to headings, so you can link to them.
  picospa.section.addAnchors();
</script>

<p>Toggle the color scheme.</p>
<button onclick="picospa.colorScheme.toggle();">Toggle Color Scheme</button>
```

## Development

### Setup

- `npx playwright install` to install the browsers needed for the tests

### Run the tests

- `npm run test:serve` (in a console) to start the test server that will be needed for running the playwright tests
- `npm run test` (in another console) to run the playwright tests
Why run it in two consoles? I just do it like that, so I can also open and look at test files directly in the browser, e.g. `http://localhost:3000/test/section.html` to see the section tests.
- `npm run test:fast` to run the tests only in chromium, which reduces the number of tests and browsers to run, to get faster feedback