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

store-management-tool

v0.1.6

Published

An Authentik-protected Next.js dashboard for managing existing databases, permissions, uploads, and friendly data-entry forms.

Downloads

881

Readme

Store Management Tool

store-management-tool is an Authentik-protected dashboard for Next.js App Router applications. It combines dynamic SQLite administration, a small CMS, table and form permissions, managed uploads, and friendly Google-Forms-style data entry.

The installing application owns all runtime data. Store Management Tool never keeps durable state inside node_modules.

Install

npm install store-management-tool

Store Management Tool needs Node.js 20.9 or newer, Next.js 15.5.20+ or 16.2.10+, React 19.2.6+, and Auth.js 5.

The dashboard uses better-sqlite3, which installs a native binding during a normal npm install. Do not install with --ignore-scripts. If scripts were disabled earlier, repair only that dependency:

npm rebuild better-sqlite3 --ignore-scripts=false

If npm reports that better-sqlite3 is waiting for script approval, approve and rebuild it from the installing project:

npm approve-scripts better-sqlite3
npm rebuild better-sqlite3

Current stable Next.js releases pin an older PostCSS build. Until Next.js updates it, add this to the installing application's root package.json so npm uses the patched PostCSS release:

{
  "overrides": {
    "next": {
      "postcss": "^8.5.10"
    }
  }
}

Mount the dashboard

The UI uses one optional catch-all page. This single page owns /dashboard, its login screen, list editor, form builder, permissions pages, and end-user form routes.

// app/dashboard/[[...path]]/page.tsx
export const dynamic = "force-dynamic";
export const runtime = "nodejs";

export { default } from "store-management-tool/dashboard";

OAuth callbacks and uploads are HTTP route handlers, so Next.js requires one separate API wrapper:

// app/api/store-management-tool/[...path]/route.ts
export const runtime = "nodejs";

export { GET, POST } from "store-management-tool/api";

Import the scoped dashboard stylesheet once from the host root layout:

// app/layout.tsx
import "store-management-tool/styles.css";

Finally, preserve the native SQLite dependency in the server bundle:

// next.config.ts
import { withStoreManagementTool } from "store-management-tool/next-config";

export default withStoreManagementTool({});

Do not also define app/dashboard/page.tsx or other host routes under /dashboard; the package catch-all owns that subtree.

Host environment

Next.js loads the installing application's .env files. Store Management Tool reads process.env at runtime and does not load or publish a package-local .env.

# The host application's existing managed database.
DATABASE_URL=file:./data/app.db

# Store Management Tool's own metadata, kept outside node_modules.
CMS_STATE_DATABASE_URL=file:./.store-management-tool/state.sqlite

# Existing files here are discovered; new uploads are added here.
CMS_UPLOADS_DIR=./uploads

# Optional when process.cwd() is not the host project root.
CMS_PROJECT_ROOT=

AUTH_SECRET=replace-with-a-long-random-secret
AUTH_URL=http://localhost:3000
AUTHENTIK_ISSUER=https://auth.example.com/application/o/store-management-tool/
AUTHENTIK_CLIENT_ID=
AUTHENTIK_CLIENT_SECRET=
AUTHENTIK_REDIRECT_URI=http://localhost:3000/api/auth/callback/authentik
AUTHENTIK_GROUPS_CLAIM=groups
AUTHENTIK_ALLOWED_GROUPS=cms-users
AUTHENTIK_ADMIN_GROUPS=cms-admins

All relative database and upload paths resolve from the installing project's root. Keep AUTH_URL as the public site origin only, without /dashboard or /api appended.

Set AUTHENTIK_REDIRECT_URI to the exact callback URI the installing project must send to Authentik. The package uses its configured base path instead of forcing /api/store-management-tool. Auth.js requires the final /callback/authentik portion; everything before it is selected by the installing project. Register the same complete value on the Authentik OAuth2/OIDC provider as a Strict redirect URI:

https://your-app.example.com/api/auth/callback/authentik

The protocol, hostname, port, path, and absence of a trailing slash must match. The login page validates this contract before it sends a request to Authentik. AUTHENTIK_ISSUER is explicit rather than calculated; copy the provider's per-application issuer from Authentik. Advanced installations may override discovery by configuring all three of AUTHENTIK_AUTHORIZATION_ENDPOINT, AUTHENTIK_TOKEN_ENDPOINT, and AUTHENTIK_USERINFO_ENDPOINT together. AUTHENTIK_ISSUER remains required for OIDC token validation. Authentication settings are environment-only and cannot be changed from the browser.

Data ownership and safety

Store Management Tool uses two separate databases:

  1. The managed database is the installer's existing SQLite database. Its tables, columns, foreign keys, and rows are discovered dynamically. It changes only after an authorized schema command, row action, or form submission.
  2. The state database belongs to Store Management Tool and stores form definitions, grants, migrations, and observed Authentik principals. It defaults to .web-cms/state.sqlite for backward compatibility; set CMS_STATE_DATABASE_URL=file:./.store-management-tool/state.sqlite for new installations.

The state database must not point to the managed database. Removing node_modules does not remove either database or the uploads directory.

Opening the dashboard never silently creates a missing managed SQLite database. An administrator instead sees the configured path and an explicit, confirmed option to create an empty database. Store Management Tool automatically creates and migrates only its own state database.

Existing managed tables, rows, foreign keys, and files are read dynamically. They do not need to have been created by Store Management Tool.

Permissions

Authentik remains mandatory. User grants use the stable OIDC sub; group grants use values from the configured groups claim. Effective permissions are the union of direct user and group grants, while global administrators retain access.

Table permissions cover viewing, adding, editing, and deleting rows; changing schema; managing forms; and managing permissions. Form permissions are separate:

  • use allows opening and submitting a published form without exposing its table.
  • manage allows editing that form and granting its permissions.

Authorization is enforced in pages, server actions, and upload APIs—not only by hiding controls.

Forms and routes

Administrators build forms under /dashboard/forms with a drag-and-drop Form.io visual builder. The builder exposes the selected table's live columns as database Fields, so questions remain mapped to known columns instead of writing unstructured response data. Foreign keys render as friendly choices while submissions store the referenced key. Published user forms open at /dashboard/submit/<slug> and use the same separate Authentik login at /dashboard/login.

Visual definitions are stored in the package-owned state database; submissions continue to be validated and written through Store Management Tool's database provider. File and image questions continue to use CMS_UPLOADS_DIR. Existing forms are converted to visual definitions when first edited, and the state schema migration preserves their fields and permissions.

The client-only builder is pinned to @formio/js 5.4.2 under MIT. This package does not use the Form.io server, hosted API, enterprise modules, accounts, license keys, or response-based services. See THIRD_PARTY_NOTICES.md for the included notice. Future Form.io upgrades must pass npm run check:licenses before release.

Forms can hide technical columns, inject fixed values, show friendly labels and help text, upload files, present fixed choices, and turn single-column SQLite foreign keys into dropdowns. Submission is validated against the current live schema before insertion. The Form editor exposes a provider-reported ID strategy for each primary key: manual input, database-generated, or server-generated UUID. SQLite rowid integer keys and database defaults are omitted for SQLite to generate; UUID/GUID-compatible keys can use crypto.randomUUID() and stay out of the user-facing Form. Composite keys are never silently assigned a package-generated strategy.

Form storage uses a versioned engine envelope and the dashboard calls a form-engine adapter plus generic editor/renderer boundaries. Form.io is the current formio engine, but database mapping, permissions, ID generation, validation, and submission are engine-neutral. A future engine can replace the adapter and UI boundary without changing those layers. The adapter entry point is store-management-tool/form-engine.

Local development

npm install
npm run lint
npm run typecheck
npm run build
npm run package:build
npm pack --dry-run

Current limits

  • SQLite is the implemented managed database provider; the provider contract leaves room for PostgreSQL and MySQL adapters.
  • A form targets one table.
  • Automatic relationship dropdowns support single-column foreign keys and load at most 500 choices.
  • Anonymous forms are not supported; every user signs in through Authentik.

License

MIT