npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mintiljs

v0.1.5

Published

Minimal SSR web framework for Bun — React pages rendered on the server, zero client JS unless you ask for it

Readme

MintilJS

Minimal SSR web framework for Bun — React pages rendered on the server, zero client JavaScript unless you ask for it.

MintilJS is a full-stack framework built on Bun, Hono, and React 19. Drop files in pages/ and they become SSR routes. Add api/ files for JSON endpoints. Throw in islands/ for partial hydration. All with zero configuration.

bun create mintil my-app
cd my-app
bun install
bun run mintil dev

Features

  • File-based routingpages/ → SSR routes, api/ → JSON endpoints
  • SSR by default — zero JS in the browser unless you opt in
  • useClient — per-page hydration bundles via Bun.build
  • Islands — independent interactive components, no full-page re-render
  • getServerSideProps — per-request data fetching
  • Hierarchical middleware — global, API-wide, directory-scoped
  • Layouts — root layout (components/layouts/base.tsx) + per-directory overrides
  • Tailwind v4 — automatic CSS processing via PostCSS
  • Streaming SSRrenderToReadableStream for pages without client bundles
  • Auth modulemintiljs/auth (JWT, sessions, middleware)
  • i18n modulemintiljs/i18n (auto-detected messages, placeholders, CSR fetcher)
  • Plugin system — extend the app at startup
  • Auto-reload — file watcher in development

Install

bun create mintil my-app                     # showcase (default)
bun create mintil my-app -t minimal          # minimal template
bun create mintil my-app -t blank            # blank template
bun create mintil my-app -i                  # + install deps
cd my-app
bun run mintil dev

Or add to an existing project:

bun add mintiljs

Quick Start

my-app/
  pages/                → SSR routes
    index.tsx             /
    blog/
      (:slug).tsx         /blog/:slug
      layout.tsx          layout scoped to /blog/*
  api/                  → JSON endpoints
    hello.ts              /api/hello
    middleware.ts         applies to all /api/*
  islands/              → auto-registered hydratable components
    Counter.tsx
  components/
    layouts/
      base.tsx            root layout
  i18n/                 → auto-detected messages
    messages/
      en/0.json
      pt-BR.json
  mintil.config.ts      → project config (optional)
  middleware.ts         → root middleware (every request)

Create a page

// pages/index.tsx → /
export default function Home() {
  return <h1 className="text-3xl font-bold">Home</h1>;
}

Add an API endpoint

// api/hello.ts → GET /api/hello
import type { ApiHandler } from "mintiljs";

export default (c) => c.json({ message: "Hello" });

Make a page interactive

// pages/counter.tsx
import React from "react";

export const useClient = true;

export default function Counter() {
  const [count, setCount] = React.useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Fetch data on every request

import type { GetServerSideProps } from "mintiljs";

export const getServerSideProps: GetServerSideProps = async ({ params, searchParams }) => {
  const data = await db.find(params.id);
  return { props: { data } };
};

export default function Page({ data }: { data: any }) {
  return <div>{data.name}</div>;
}

Configuration

Export a MintilConfig default from mintil.config.ts:

import type { MintilConfig } from "mintiljs";

export default {
  port: 3456,
  host: false,            // true = bind to 0.0.0.0
  mode: "development",    // "development" | "production"
  assetsPath: "/assets",  // prefix for public/ files; "/" to serve at root
  plugins: [],
} satisfies MintilConfig;

CLI

| Command | Description | |---|---| | mintil init <name> | Scaffold a new project (-t template, -i install deps) | | mintil dev | Dev mode with auto-reload | | mintil start | Production mode | | mintil g page <n> | Scaffold a page | | mintil g api <n> | Scaffold an API route | | mintil g island <n> | Scaffold an island |

Modules

Auth (mintiljs/auth)

// api/login.ts
import { createAuthMiddleware, InMemorySessionStore } from "mintiljs/auth";

const JWT_SECRET = process.env.JWT_SECRET || "dev-secret";
const store = new InMemorySessionStore();

export const auth = createAuthMiddleware({
  jwt: { secret: JWT_SECRET, expiresIn: "1h" },
  session: { store, maxAge: 86400, cookieName: "session", cookiePath: "/" },
});

// POST /api/login — sign JWT and return it
import type { ApiMethodHandler } from "mintiljs";

export const POST: ApiMethodHandler = async (request, response) => {
  const { username, password } = await request.json();
  if (username !== "admin" || password !== "123456") {
    return response.json({ error: "Invalid credentials" }, 401);
  }
  const token = await auth.signJWT({ sub: username, userId: username, role: "admin" });
  return response.json({ token });
};
// api/admin/middleware.ts — protect all /api/admin/* routes
import { auth } from "../login";

export default auth.requireAuth;
// api/me.ts — use the verified token
import type { ApiMethodHandler } from "mintiljs";
import { auth } from "./login";

export const GET: ApiMethodHandler = async (request, response) => {
  const token = request.header("Authorization")?.slice(7);
  const payload = token ? await auth.verifyJWT(token) : null;
  return payload
    ? response.json({ user: { id: payload.userId, name: payload.sub } })
    : response.json({ error: "Unauthorized" }, 401);
};

i18n (mintiljs/i18n)

i18n/messages/en/0.json   → { "greeting": "Hello" }
i18n/messages/en/1.json   → { "welcome": "Welcome to {site}!" }
i18n/messages/pt-BR.json  → { "greeting": "Olá" }
import { getMessages, t, format } from "mintiljs/i18n";

const msgs = await getMessages("en");
t(msgs, "greeting")                              // "Hello"
t(msgs, "welcome", { site: "MintilJS" })         // "Welcome to MintilJS!"
format("Hello {name}!", { name: "John" })        // "Hello John!"

The framework auto-registers /_mintil/i18n/:locale for CSR usage.

Plugin System

import type { MintilPlugin } from "mintiljs";

const health: MintilPlugin = {
  name: "health",
  setup(app) { app.get("/health", (c) => c.json({ ok: true })); },
};

export default { plugins: [health] } satisfies MintilConfig;

API Reference

Full TypeDoc-generated documentation at docs/api/:

bun run docs

License

MIT