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

@epicabdou/create-linkrjs-app

v0.2.0

Published

Scaffold a new linkr.js app (Vite + React + React Router + file-based routing)

Readme

@epicabdou/create-linkrjs-app

Scaffold a new linkr.js app with Vite, React, React Router v7, file-based routing (@epicabdou/linkr), Tailwind CSS v4, and the linkr-design-system.

You can choose between two templates:

| Template | Description | |----------------|-------------| | empty | Minimal app: Home, About, 404, one layout. No authentication or backend. Best for static sites or when you want to add your own auth/API later. | | clerk-convex | Full-stack starter with Clerk (authentication) and Convex (backend). Includes protected dashboard, sign-in/sign-up pages, and a sample tasks API. |


Usage

Create an app

npx @epicabdou/create-linkrjs-app my-app

Or with the shorthand name:

npx create-linkrjs-app my-app

To install in the current folder instead of creating a new one, use .:

npx create-linkrjs-app .

Replace my-app with your project name (or use . for the current directory). The CLI creates a folder with that name in the current directory, or writes into the current directory when you use ..

Choose a template

  • Interactive: When you run the command in a terminal (TTY), you’ll see a prompt to pick empty or clerk-convex. Press Enter for the default (empty).
  • Non-interactive / CI: If no template is selected (e.g. piped input), the default is empty.
  • Explicit flag: Pass the template with --template or -t:
# Minimal app (no auth, no backend)
npx create-linkrjs-app my-app --template empty

# Clerk + Convex (auth + backend + protected dashboard)
npx create-linkrjs-app my-app --template clerk-convex

# In current folder
npx create-linkrjs-app . --template clerk-convex

Dev server: Both templates use Vite and run at http://localhost:8000 by default.


Setup guide: Empty template

The empty template is a minimal Vite + React + TypeScript app with file-based routing and the linkr design system. No accounts, no backend—ideal for landing pages, docs, or when you plan to add your own auth/API.

Step 1: Create the app

npx create-linkrjs-app my-app --template empty

When prompted, you can also choose empty interactively.

Step 2: Install dependencies

cd my-app
pnpm install

You can use npm or yarn instead of pnpm if you prefer.

Step 3: Start the dev server

pnpm dev

Vite will start and open (or show) http://localhost:8000. You should see the linkr.js welcome page with Home and About links.

Step 4: What you have

  • Routes: File-based routing from src/pages/:
    • src/pages/index.tsx/
    • src/pages/about.tsx/about
    • src/pages/404.tsx → catch-all not-found page
  • Layout: One layout in src/layouts/Layout.tsx (nav + main content). It’s applied to all routes via layoutMap in src/main.tsx.
  • Styling: Tailwind v4 + linkr-design-system (tokens and base styles) in src/index.css.
  • Config: vite.config.ts (React + Tailwind plugins, port 8000), tsconfig.json, index.html.

No environment variables or external services are required. You can start adding new pages under src/pages/ and new layouts under src/layouts/ and wire them in createRoutes in src/main.tsx.

Build and preview

pnpm build
pnpm preview

pnpm build runs tsc -b and vite build. pnpm preview serves the built app locally.


Setup guide: Clerk + Convex template

The clerk-convex template adds Clerk for authentication and Convex for the backend. You get sign-in/sign-up, a protected dashboard, and a sample Convex API (tasks). Setup requires free accounts and a few configuration steps.

Step 1: Create the app

npx create-linkrjs-app my-app --template clerk-convex
cd my-app
pnpm install

Step 2: Set up Clerk

  1. Sign up / log in
    Go to clerk.com and create an account (or sign in).

  2. Create an application
    In the Clerk Dashboard, create a new application. Choose sign-in options (e.g. Email, Google, GitHub) and finish the wizard.

  3. Get the Publishable Key
    In the dashboard, open Configure → API Keys. Copy the Publishable key (starts with pk_test_ for development). You’ll add it to .env.local in a later step.

  4. Create a JWT template for Convex

    • In the Clerk Dashboard, go to Configure → JWT Templates.
    • Click New template and choose Convex.
    • The template name must be exactly convex (do not rename it).
    • Open the template and copy the Issuer URL (e.g. https://your-app.clerk.accounts.dev). You’ll add this to the Convex Dashboard in the next section.

Step 3: Set up Convex

  1. Start Convex and link a project
    In your app directory run:

    npx convex dev
    • If prompted, sign in to Convex (e.g. with GitHub).
    • Create a new project or select an existing one.
    • Convex will create a convex/_generated folder and sync your backend. Leave this command running in a separate terminal while developing (or use the combined pnpm dev from Step 5).
  2. Get your Convex URL
    After npx convex dev has run successfully, the Convex Dashboard will show your deployment URL (e.g. https://your-project.convex.cloud). Copy it—you’ll add it as VITE_CONVEX_URL in .env.local.

  3. Add Clerk’s Issuer URL in Convex

    • Open the Convex Dashboard and select your project.
    • Go to Settings → Environment Variables (or DeveloperEnvironment Variables).
    • Add a variable:
      • Name: CLERK_JWT_ISSUER_DOMAIN
      • Value: the Clerk Issuer URL you copied from the JWT template (e.g. https://your-app.clerk.accounts.dev).
    • Save. This lets Convex validate Clerk’s JWTs.

Step 4: Configure environment variables

In your app root, create a local env file and add the keys from Clerk and Convex:

  1. Copy the example file

    cp .env.local.example .env.local
  2. Edit .env.local and set:

    • VITE_CLERK_PUBLISHABLE_KEY — The Clerk Publishable key from Step 2 (e.g. pk_test_...).
    • VITE_CONVEX_URL — The Convex deployment URL from Step 3 (e.g. https://....convex.cloud).

    Example:

    VITE_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxx
    VITE_CONVEX_URL=https://your-project-123.convex.cloud

    Do not commit .env.local (it’s in .gitignore). The VITE_ prefix is required so Vite exposes these variables to the client.

Step 5: Run the app

From the app root:

pnpm dev

This runs both the Vite dev server and the Convex backend (via the template’s dev script). Open http://localhost:8000. You should see:

  • Home and About (public).
  • Sign in in the nav; clicking it opens Clerk’s sign-in.
  • After signing in, Dashboard is available and shows the protected tasks example.

If you see “Missing VITE_CLERK_PUBLISHABLE_KEY” or similar, double-check .env.local and that variable names match exactly (including VITE_).

Step 6: What you have (Clerk + Convex)

  • Auth: Clerk handles sign-in/sign-up. The app uses ClerkProvider and ConvexProviderWithClerk so Convex receives Clerk’s JWT.
  • Pages:
    • / — Home
    • /about — About
    • /sign-in — Clerk sign-in
    • /sign-up — Clerk sign-up
    • /dashboard — Protected; uses Convex’s <Authenticated>; redirects to /sign-in when not logged in
    • 404 — Not found
  • Backend: Convex convex/ folder:
    • auth.config.ts — Configures Convex to trust Clerk’s JWT (using CLERK_JWT_ISSUER_DOMAIN).
    • schema.ts — Defines the tasks table.
    • tasks.ts — Queries and mutations for the current user’s tasks (list, add, toggle).
  • Layouts: Layout.tsx (nav with Clerk SignInButton / UserButton) and ProtectedLayout.tsx (wraps dashboard with Convex <Authenticated>).

For production, use separate Clerk and Convex production instances and set production env vars (e.g. pk_live_... and the production Convex URL). See Clerk and Convex auth with Clerk for more.


What gets created (reference)

Empty template

| Path | Description | |------|-------------| | package.json | App name, scripts (dev, build, preview), deps: @epicabdou/linkr, linkr-design-system, react, react-router, Tailwind, Vite, TypeScript. | | vite.config.ts | React plugin, Tailwind v4 (@tailwindcss/vite), dev server port 8000. | | index.html | Root HTML; script entry /src/main.tsx. | | tsconfig.json | TypeScript for src/. | | src/main.tsx | Entry: CSS, createRoutes with import.meta.glob for pages and layouts, layoutMap, RouterProvider. | | src/index.css | @import "tailwindcss", design-system theme and base. | | src/layouts/Layout.tsx | Nav (Home, About) + <Outlet />. | | src/pages/index.tsx | Home at /. | | src/pages/about.tsx | About at /about. | | src/pages/404.tsx | Catch-all not-found. | | src/vite-env.d.ts | Vite client types. |

Clerk + Convex template

Includes everything from the empty template, plus:

| Path | Description | |------|-------------| | package.json | Extra deps: @clerk/clerk-react, convex, npm-run-all. Scripts: dev (parallel Vite + Convex), dev:frontend, dev:backend. | | .env.local.example | Example env vars: VITE_CLERK_PUBLISHABLE_KEY, VITE_CONVEX_URL. | | .gitignore | Convex output (e.g. .convex/), .env.local. | | convex/auth.config.ts | Clerk JWT issuer config for Convex (CLERK_JWT_ISSUER_DOMAIN). | | convex/schema.ts | Convex schema (e.g. tasks table). | | convex/tasks.ts | Convex queries/mutations for tasks (auth-aware). | | src/main.tsx | ClerkProvider, ConvexProviderWithClerk, useAuth, Convex client from VITE_CONVEX_URL. | | src/layouts/Layout.tsx | Nav with Clerk SignInButton / UserButton. | | src/layouts/ProtectedLayout.tsx | Convex <Authenticated> / <Unauthenticated> / <AuthLoading>; redirect to /sign-in when not authenticated. | | src/pages/sign-in.tsx | Clerk <SignIn /> page. | | src/pages/sign-up.tsx | Clerk <SignUp /> page. | | src/pages/dashboard/index.tsx | Protected dashboard; uses Convex api.tasks (list, add, toggle). | | src/vite-env.d.ts | Types for VITE_CLERK_PUBLISHABLE_KEY, VITE_CONVEX_URL. |


Next steps

  1. Add routes — Add files under src/pages/ (e.g. blog/index.tsx/blog, blog/[id].tsx/blog/:id). See linkr routing docs.
  2. Add layouts — Add components in src/layouts/ and register them in createRoutes’s layoutMap in src/main.tsx.
  3. Protect routesEmpty: use <Protect> from @epicabdou/linkr with a custom config. Clerk + Convex: use Convex’s <Authenticated> and Clerk’s components (as in ProtectedLayout.tsx).
  4. Styling — Use Tailwind and design-system tokens (e.g. bg-primary-500, rounded-lg). See the design-system README.

Requirements

  • Node.js 18+
  • pnpm, npm, or yarn

Generated apps use Vite 5, React 18, React Router 7, and Tailwind CSS 4. The Clerk + Convex template also requires a Clerk account and a Convex account (both have free tiers).