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

@latchprotocol/create-app

v0.1.1

Published

The Latch app template: scaffold a DEX, a Launchpad or both on LatchProtocol's shared core. npm create @latchprotocol/app. MIT, one config file, no core deployment.

Readme

@latchprotocol/create-app

The Latch app template: scaffold a DEX, a Launchpad or both on LatchProtocol's shared core. You get a Vite + React front end, one config file (latch.config.ts: chain, fee wallet, branding, features) and a verify script. You deploy no core contracts: your pools live in the Vault and pool managers Latch already runs on the chain you pick. Set the fee wallet, restyle if you want, ship. MIT, and so is everything it emits.

npm create @latchprotocol/app my-app -- \
  --chain base \
  --fee-wallet 0xYourTreasury \
  --fee-bps 25 \
  --features both          # dex | launchpad | both

cd my-app
npm install
npm run latch:verify     # read every configured address back off chain
npm run dev

npx @latchprotocol/create-app my-app … does the same thing. The -- after the directory is npm's: it passes the flags through npm create to the scaffolder.

Run it with no flags and it prompts. Add --yes and it never will: every option has a flag, and anything with no safe default is an error rather than a guess.

The same scaffolder runs as latch init in @latchprotocol/cli, and it is also importable: import { runCreate } from "@latchprotocol/create-app", then await runCreate(["my-app", "--chain", "base", "--yes"]) returns the exit code.


What it produces

A Vite + React app, one config file, and two scripts. No contracts.

my-app/
  latch.config.ts        chain · fee wallet · branding · feature flags · tokens
  src/
    config/              the config's shape, Latch's address book, validation
    lib/                 chain reads: pools, tokens, launches, fees
    components/          the shell and the four data states
    routes/              Swap · Pools · Launch · Launch wizard · Fees
    theme.ts             config colours -> CSS custom properties
  scripts/
    latch-verify.mjs     turn every configured address into a fact or a failure
    latch-deploy.mjs     resolve and write addresses. Sends no transaction, ever.

Everything a tenant changes to go to market is in latch.config.ts. Restyling is a colour edit there — no stylesheet in the template hardcodes a colour.


Shared core, not a full fork

The tenant does not deploy Vault, CLPoolManager or BinPoolManager. Their pools live in the core Latch already has deployed and verified on the chosen chain.

That is cheaper and faster for them — no nineteen-contract deployment, no verification, no audit question — and it is the only model in which Latch's protocol fee is enforceable, because protocolFeeController on a shared pool manager belongs to Latch governance and is capped at MAX_PROTOCOL_FEE = 4000 pips (0.4%) by core.

A full fork is permitted by the GPL, owes nothing, and gets no shared registry. It is supported here only in the sense that chain.contracts lets a tenant point the front end at their own addresses. The generated README says so plainly rather than pretending the choice does not exist.

Between the two: chain.router. A tenant on the shared core can point every swap — the DEX surfaces and a launch's buy path, which share one widget adapter — at their OWN router while the Vault, the pool managers, the kits, the lockers and the registry stay Latch's. Absent or null (the default, and what the scaffolder writes) means Latch's router from the SDK address book, with no configuration at all. It is a first-class option rather than the contracts escape hatch on purpose: wanting your own router is not the same claim as wanting your own core, and a tenant should not have to use the full-fork mechanism to say the smaller thing. Setting both to different addresses is a blocking config error — one of them would otherwise lose silently. The router must still be Latch's UniversalRouter ABI wired to the same Vault and Permit2, because the widgets encode that command set; latch:verify checks the code, the router's vault(), paused() and owner(), and says whose router is in use. Latch's routed-fill fee travels with Latch's router, so a tenant on their own neither pays nor collects it — the generated README states that rather than leaving it to be discovered.

Nothing to deploy, and that is deliberate

Both launch kits take every launch parameter as a call argument, so one instance serves every tenant: launches differ by their arguments, not by their bytecode. LaunchpadKitV2 (locked launches) additionally keeps a per-tenant config the tenant writes itself — the integrator wallet, its share of locked-LP fees and its launch fee — and refuses a launch that restates it differently; the kit's owner cannot touch a tenant's config. LaunchGuardHook's only authority is a per-pool launchOwner, and RevShareHook is configured entirely per pool. So latch:deploy resolves and verifies rather than deploying, latch:tenant prints the one transaction that stores a tenant's terms (LatchPad.configure from the pad's owner when chain.launchTenant is a LatchPad — the recommended, transferable form with an on-chain brand — or setTenantConfig from the wallet otherwise), and --own-kit prints a forge command for a tenant who wants their own instance anyway.

Where the SDK address book records no shared kit for a chain, chain.launchpadKitV2 and chain.launchpadKit start null and the launch screens say so plainly instead of rendering an example. The generated README documents the options.

Latch utilities, on by default

The emitted app also ships Team splits (/splits, and a "pay the creator share to a split" option in the launch wizard), locks (/locks, lock badges on pools and launched tokens) and airdrops (/airdrops: multisend and claimable Merkle drops from a CSV, and a claim page that verifies the claims file against the drop's root). Each is a flag in features; addresses come from the SDK address book per chain, and a contract recorded null renders "coming soon on ". The contracts charge their own flat fees, read live and shown before signing; the template adds no fee of its own to any of them. The template carries its own tests (npm test), run in a generated project.


Licensing — the rule this package exists under

This package and everything it emits are MIT, and a tenant may close-source their fork. That holds for exactly one reason: the emitted app reaches the protocol through the MIT @latchprotocol/sdk and through ABIs, never through GPL Solidity. An ABI call is not linking and does not create a derivative work.

| Layer | Licence | |---|---| | This scaffolder and its template | MIT | | @latchprotocol/sdk, /widgets, /connect | MIT, independently authored | | Latch core, periphery, router, Latch's hooks | GPL-2.0-or-later |

Never import GPL Solidity, or anything generated from it, into template/. Not sources, not build artifacts, not a hex bytecode string.

test/scaffold.test.ts enforces this: it greps every emitted source file for an import reaching into packages/core, packages/periphery, packages/router, a GPL hook package, or any .sol path, and fails the build if it finds one. The rule is a test, not a paragraph.

The same rule is why latch:deploy --own-kit prints a command instead of running one. Shipping the kit's bytecode would put GPL code inside an MIT distribution.


The template is a real app

Every file under template/ typechecks and builds exactly as it sits on disk, against defaults pointing at a chain Latch is deployed on. Substitution replaces valid values with other valid values, in two shapes:

name: '__LATCH_APP_NAME__',              // placeholder inside a string literal
id: 4663 /* __LATCH_CHAIN_ID__ */,       // real literal, tagged by a comment

The tagged form is what lets the template compile before substitution — and a template nobody can build is a template nobody reviews. After substitution the marker comment is gone, and scaffold() fails loudly if any marker survives.


Flags

| Flag | Meaning | |---|---| | --chain <name\|id> | robinhood / 4663, base / 8453, or sepolia / 11155111. Required. hyperevm / 999 is accepted too: the app renders one "Coming soon on HyperEVM" page until the SDK address book records the chain. | | --fee-wallet <address> | Where the front end's swap fee is paid. Required when --fee-bps > 0. | | --fee-bps <n> | Fee in basis points of the swap output, 0..100. Default 0. | | --features <set> | dex (swap, pools, locks, airdrops), launchpad (launchpad, splits, locks, airdrops), both (everything), or a comma list of swap,pools,launchpad,splits,locks,airdrops. | | --name <string> | Product name. Defaults from the directory name. | | --package-manager <pm> | npm / pnpm / yarn / bun. Only changes the printed next steps. | | --yes | Never prompt. |

The fee ceiling of 100 bps mirrors MAX_INTEGRATOR_FEE_BPS in @latchprotocol/widgets, which is what actually builds the calldata. If the two ever disagree, the widget is authoritative.


Other Latch packages

  • @latchprotocol/sdk — TypeScript SDK: pool keys and ids, the hook permission bitmap, typed events, the address book, market reads and the Launchpad builders
  • @latchprotocol/connect — the wallet layer: a Latch-themed wrapper over RainbowKit and wagmi, with the Latch chain list
  • @latchprotocol/widgets — embeddable swap, liquidity and launch widgets with integrator fee attribution
  • @latchprotocol/cli — the latch command: launches, hosted Launchpad and DEX sites, airdrops, splits, locks and latch doctor
  • @latchprotocol/create-hook — the hook starter: npx @latchprotocol/create-hook my-latch --template dynamic-fee

Website: latches.fun · X: @Latchesdotfun


No invented data

The template inherits the rule the Latch dapp runs under: every figure is read from chain, and what cannot be read is named rather than filled in. Four visually distinct states — loading, error, empty, not-configured — live in src/components/States.tsx, and there is no fifth state where a screen shows an example.

Two consequences worth knowing before extending the template:

  • @latchprotocol/widgets exports a LaunchWidget that this template does not use. It is bound to a proposed token-sale interface that no deployed Latch contract implements. The launch screens here are written against the real LAUNCHPAD_KIT_ABI instead, and they render a fee schedule rather than a sale progress bar, because a Latch launch is a pool with a decaying fee and has no cap to progress toward.
  • The pool table discloses capability, never safety. It says what a hook is able to do, from its permission bitmap. A registry listing is not an audit and a bitmap is not a review.