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

create-apollo-suite-monorepo

v1.0.1479

Published

Scaffold a monorepo with a frontend app and Apollo CMS as a git submodule backend (single-origin via Next.js rewrites + assetPrefix)

Readme

create-apollo-suite-monorepo

Scaffold a pnpm monorepo where your custom frontend lives alongside Apollo CMS mounted as a git submodule backend (read-only — pull updates only).

Usage

npx create-apollo-suite-monorepo my-site

With flags:

npx create-apollo-suite-monorepo my-site \
  --frontend-name "@my-site/frontend" \
  --db "postgresql://user:pass@localhost:5432/my-site" \
  --url "http://localhost:3000" \
  --locale th

Result

my-site/
├── apps/
│   ├── frontend/          ← @my-site/frontend (Next.js skeleton)
│   └── backend/           ← git submodule → apollo-cms
├── package.json           ← root workspace
├── pnpm-workspace.yaml
├── .env.local             ← shared dev env
├── .gitmodules            ← submodule config
└── .gitignore

Routing modes

Single-origin (default)

Both apps share one public origin (the frontend). The frontend's next.config.ts rewrites these paths to the backend so /_next/* doesn't collide:

| Browser path | Goes to | | ------------------------------------ | -------------------- | | /, your custom routes | apps/frontend | | /admin/* | apps/backend (admin pages and their JS chunks) | | /api/auth/*, /api/v1/*, /api/admin/*, /api/email/*, /api/health, /api/mcp, /api/editing-presence/* | apps/backend | | /uploads/* | apps/backend (media) |

Apollo CMS reads APOLLO_ASSET_PREFIX (default /admin) and serves its built JS under <prefix>/_next/static/. Because the prefix coincides with the admin path, a single /admin/:path* rewrite covers both pages and chunks — no separate asset rewrite is emitted. The frontend must not define routes at /admin, /api/auth, /api/v1, etc.

You can override the prefix:

npx create-apollo-suite-monorepo my-app --admin-prefix /cms

When the prefix is anything other than /admin, the scaffold also emits a matching <prefix>/:path* rewrite for backend chunks.

Separate origins (fallback)

Pass --admin-prefix none (or off/false/disabled) to skip the rewrite wiring. The backend runs at http://localhost:3000 and the frontend at http://localhost:3001. Useful when you'd rather deploy them on separate subdomains (e.g. cms.example.com + example.com).

Flags

| Flag | Default | Description | | -------------------------- | --------------------------------------- | ------------------------------------ | | --frontend-name <name> | @<dir>/frontend | Frontend package.json name | | --backend-url <url> | https://github.com/5Lab-Group-Co-Ltd/apollo-suite.git | Submodule git URL | | --backend-branch <name> | main | Submodule branch to track | | -d, --db <url> | (prompted) | DATABASE_URL for backend | | -u, --url <url> | :3001 single-origin / :3000 separate | NEXT_PUBLIC_SITE_URL | | -l, --locale <code> | en | NEXT_PUBLIC_DEFAULT_LOCALE | | --admin-prefix <path> | /admin | Single-origin admin/asset namespace; none to disable. Alias: --asset-prefix | | --apps <slug,slug> | (asked) | Suite apps to install besides the mandatory ones; "" for mandatory only. See Suite apps | | --skip-install | off | Don't run pnpm install | | --skip-submodule | off | Don't add the git submodule | | -h, --help | — | Show help |

After install

cd my-site
pnpm backend:setup   # push schema + seed apollo-cms
pnpm dev             # frontend :3001 + backend :3000 in parallel

In single-origin mode open http://localhost:3001/admin (the frontend port); the rewrite proxies to the backend and Better Auth's cookies/origins line up because NEXT_PUBLIC_SITE_URL and the backend's trustedProxyHeaders are wired to the public origin.

Suite apps

The scaffold writes apollo.apps.json at the project root: the suite apps the project installs besides the mandatory ones. An app that is not listed gets no tables, no screens and no jobs.

  • --apps <slug,slug> — written as given, after checking it against the backend that was just cloned: every slug must be an app there, and every app it requires must be listed too. A missing required app is an error, never added for you.
  • No --apps, in a terminal — the installer lists the apps in the cloned backend (read from its apps/*/plugin.json, never a list inside the installer) and asks.
  • No --apps, not a terminal, or --skip-submodule — mandatory apps only.

.env.local gets APOLLO_APPS_FILE=../../apollo.apps.json (resolved against apps/backend), and the root package.json gets an apl script:

pnpm apl apps                  # every app and its state
pnpm apl install <slug...>     # add apps — runs the upgrade that creates their tables
pnpm apl uninstall <slug>      # leave an app out — its tables and data are kept
pnpm apl doctor                # do the file, the apps and the database agree?

Before the database has been set up once, edit the list by hand and run pnpm backend:setup; apl install needs the tables setup creates.

Updating the backend

pnpm backend:update  # git submodule update --remote --merge apps/backend
                     # + node apps/backend/scripts/sync-root-workspace.mjs + pnpm install

Don't edit files inside apps/backend — open issues / PRs against the apollo-cms repository upstream.

Root pnpm-workspace.yaml mirrors the backend's overrides and patches

pnpm reads only the root pnpm-workspace.yaml; the submodule's own copy is ignored once apps/backend is a package of the outer workspace. The scaffold (and pnpm backend:update) therefore run node apps/backend/scripts/sync-root-workspace.mjs, which copies the backend's security overrides and patchedDependencies into the root file (patch paths rewritten to apps/backend/patches/…). Your own root overrides are kept; backend keys win on conflict.

Without the mirror the drizzle-kit patch never applies, and every drizzle-kit push / apl install re-adds each NULLS NOT DISTINCT unique constraint and prompts to truncate any non-empty table that owns one — in CI (no TTY) the push aborts.

It also writes the backend's own next, react and react-dom specifiers into the root overrides, so every workspace package — your frontend and every apps/cms-plugins/* suite app included — resolves the same copy the backend does, and the next pnpm backend:update moves them for you. Suite apps are bundled into the backend's Next build; a second next (or React) makes pnpm install a second next-safe-action, and typecheck fails with TS2345 across every useAction call (apollo-suite #1915, #1916). The cost is that your frontend follows the backend's next/react too.

One-time step for an existing consumer, after the first backend:update that brings this in: commit the rewritten root pnpm-workspace.yaml and pnpm-lock.yaml, and check pnpm why next-safe-action shows ONE copy. Adding node apps/backend/scripts/sync-root-workspace.mjs --check to CI makes a submodule bump that skipped backend:update fail loudly instead.

Scaffolds created before sync-root-workspace

Run it once by hand, then reinstall:

node apps/backend/scripts/sync-root-workspace.mjs && pnpm install

and add node apps/backend/scripts/sync-root-workspace.mjs to your backend:update script between the submodule update and pnpm install.

Scaffolds created before v0.9.991

Two entries were missing from older scaffolds, and pnpm dev fails during plugins:build without them:

error: Could not resolve: "ioredis"
error: Could not resolve: "@opentelemetry/api"

apps/backend/plugins/* has to be listed in the root pnpm-workspace.yaml (apollo-cms's own workspace file is ignored once the submodule is a package of an outer workspace, so the built-in plugins' dependencies never install), and @opentelemetry/api has to be a root devDependency (bun's bundler resolves next's guarded require() of this optional peer, which pnpm — unlike bun — does not install). Patch an existing scaffold with:

# pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'apps/extensions/*'
  - 'apps/backend/plugins/*'   # add this
// package.json
"devDependencies": {
  "concurrently": "^9.0.0",
  "@opentelemetry/api": "^1.9.0"   // add this
}

then re-run pnpm install.

Scaffolds created before --apps

They keep working unchanged: with no apollo.apps.json and no APOLLO_APPS_FILE, the backend installs every app. To choose apps in one of them, after pnpm backend:update has brought in a backend with scripts/apl.ts:

  1. Add the script to the root package.json:

    "apl": "pnpm --filter ./apps/backend exec bun run scripts/apl.ts"
  2. Add apollo.apps.json.apl-tmp to .gitignore.

  3. Run pnpm apl apps. Create apollo.apps.json at the project root listing every app it shows as installed — { "apps": ["<slug>", "<slug>"] } — so nothing changes yet. Leave out the ones marked mandatory.

  4. Add APOLLO_APPS_FILE=../../apollo.apps.json to the root .env.local. ⚠️ Do steps 3 and 4 in this order: without the variable, apl writes to apps/backend/apollo.apps.json, inside the submodule.

  5. pnpm apl doctor should report nothing. Then pnpm apl uninstall <slug> for each app the project does not use — its tables and data are kept.

Deploying to production

The scaffold pins packageManager: "[email protected]" (the version lives in pnpm-policy.mjs), so Corepack or pnpm itself switches to it. If your CI / deploy host installs pnpm separately, make sure it's pnpm 12+ — pnpm sets strictDepBuilds: true by default and reads the allow-list from allowBuilds in pnpm-workspace.yaml; pnpm 10 silently ignores allowBuilds, and pnpm 11+ silently ignores the deprecated onlyBuiltDependencies. Once the version is pinned, pnpm 12 fails (ERR_PNPM_UNRECOGNIZED_WORKSPACE_SETTINGS) on any key in pnpm-workspace.yaml it does not know. No .npmrc is generated: pnpm 11+ reads it only for auth and registry, so the install settings it used to carry (engineStrict, autoInstallPeers, strictPeerDependencies, publicHoistPattern, shellEmulator) live in pnpm-workspace.yaml. ⚠️ pnpm 12 also ignores a registry token written as an environment variable in a project .npmrc. It warns environment variables are not expanded in repository-controlled registry credentials and installs without the token. On a CI or deploy host that installs from a private registry, put the token in the user-level ~/.npmrc or pnpm's global config instead. Mixing up the build allow-list leads to sharp (and esbuild, @swc/core, …) skipping their postinstalls, which surfaces at runtime as:

Failed to load external module sharp-<hash>:
  Error: Cannot find module 'sharp-<hash>'

The scaffold's pnpm-workspace.yaml already lists the binaries Apollo CMS needs in allowBuilds. If you add a new native dep, append it there.

Node.js policy

Use Node 24.22.1 (the latest Node 24 release verified on 2026-10-23). Run nvm install && nvm use from the project root. Later stable 24.x patches are accepted; Node 22, 25, 26 and prereleases are rejected. CI reads the exact version from .nvmrc for reproducibility. Update .nvmrc, .node-version, both package engine ranges and installer-monorepo/node-policy.mjs together when adopting a newer Node 24 release. The installer copies this policy and pins into generated projects. GitHub Actions may use their own bundled Node runtime, separate from project commands.