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

code2app

v0.1.24

Published

Tauri scaffold that packages a website or a bundled CLI as a native desktop + mobile app, configured from a single JSON profile

Readme

🤖 Agent skillnpx skills@latest add https://github.com/OpenSourceAGI/dev-tools-starter-agent --skill native-app-wrapper (what it covers)

native-app-wrapper

A Tauri shell that turns one JSON profile into a native desktop (Windows/macOS/Linux) and mobile (Android/iOS) app. It packages one of two things:

  • A website ("mode": "remote") — a titled window that loads the site directly, plus the OS-level plumbing a plain webview doesn't get for free: a real app icon on every platform, a Google-OAuth-compatible login handoff, and a fullscreen toggle.
  • A command-line tool ("mode": "local") — a bundled HTML frontend backed by the CLI itself, shipped alongside the app binary as a Tauri sidecar, so the app runs with no Node, Python, or other runtime installed on the user's machine. See docs/LOCAL_APPS.md.

packages/about-system-info/native is a working example of the second kind — the about-system CLI shipped as an installable desktop app for all three desktop OSes.

What this is not

Not a place for app-specific UI or logic. In remote mode the wrapped site provides all of that; in local mode the app's own dist/ and its sidecar do. This package's job stops at: open a window, register the app's identity (icon, name, bundle id) with each OS, hand a browser-based OAuth login back to that window, and expose the bundled CLI's output to the bundled frontend. Anything more belongs in the app being wrapped.

Quick start

Scaffold a copy of the wrapper for your own app:

cd packages/native-app-wrapper
node bin/cli.js init ../../apps/my-app/native --profile-file ./my-app.json
cd ../../apps/my-app/native
npm install
npm run dev

init copies the wrapper's sources into the target directory, gives that copy your profile as its only identity, regenerates the Tauri config and Rust constants from it, renames the crate, and draws a placeholder icon set so the copy builds immediately. It also leaves out what the profile doesn't use: a desktop-only profile gets no android:build script, an offline CLI app gets no guide to browser OAuth handoffs. Nothing links back to this package afterward — the copy is a standalone app you can commit next to the thing it wraps, and updating it later means copying the changed scripts across, not re-running init over your own dist/.

To work on this package itself instead, npm run dev here opens a window on the untouched profiles/example.json (https://example.com), which is what the checked-in src-tauri/tauri.conf.json is generated from.

Layout

native-app-wrapper/
├── bin/cli.js             # init / configure / icons
├── profiles/              # one JSON file = one app identity (see profiles/README.md)
│   └── example.json        #   the template, and this package's own default
├── scripts/
│   ├── profile.mjs                   # loads + validates a profile; one definition of the schema
│   ├── configure.mjs                 # profile -> tauri.conf.json, generated_config.rs, remote.json
│   ├── build-sidecar.mjs             # profile's sidecar.build -> src-tauri/binaries/<name>-<triple>
│   ├── generate-icons.mjs            # profile's iconSource -> full src-tauri/icons/ set (Tauri CLI)
│   ├── generate-placeholder-icons.mjs # draws a buildable icon set with no artwork and no deps
│   └── lib/png.mjs                   # the PNG/ICO/ICNS writers that make the above possible
├── src-tauri/
│   ├── src/lib.rs          # window setup, deep-link OAuth handoff, sidecar bridge, fullscreen toggle
│   ├── capabilities/       # Tauri's permission grants (default.json + a generated remote.json)
│   ├── icons/              # generated; checked in so a fresh clone builds
│   └── tauri.conf.json     # generated by configure
├── assets/icon-source.png # the 1024px master `iconSource` points at by default
├── dist/                  # the bundled frontend (a placeholder in remote mode; the app in local mode)
└── docs/
    ├── BUILDING.md         # local dev/build commands and release builds
    ├── LOCAL_APPS.md       # packaging a CLI: the sidecar bridge and the bundled frontend
    ├── OAUTH.md            # why login needs a system browser + deep link, and how it works here
    ├── MOBILE.md           # Android/iOS host requirements and gen/android, gen/apple
    └── APP_STORES.md       # Microsoft Store, Mac App Store, iOS App Store, Google Play

Why generated config instead of a hand-edited tauri.conf.json

An app's identity shows up in five places that must agree: the Tauri config, the Rust deep-link scheme, the Rust sidecar name, the remote capability's origin scope, and the icon set. Hand-editing means five chances to drift. scripts/configure.mjs writes all of them from the profile, so the profile is the only file anyone edits, and CI can assert the generated files still match it.

Why a window, not a bundled copy of a remote site

In remote mode, tauri.conf.json's main window points its url straight at the profile's site over HTTPS — there's no local copy of the app's UI to keep in sync with the real site (build.frontendDist still points at dist/, an unused placeholder Tauri's bundler requires to exist). The tradeoff: the app needs network access to be useful, same as opening the site in a browser tab would. Local mode is the opposite tradeoff — everything is bundled, nothing is fetched.