@epicabdou/create-linkrjs-app
v0.2.0
Published
Scaffold a new linkr.js app (Vite + React + React Router + file-based routing)
Maintainers
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-appOr with the shorthand name:
npx create-linkrjs-app my-appTo 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
--templateor-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-convexDev 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 emptyWhen prompted, you can also choose empty interactively.
Step 2: Install dependencies
cd my-app
pnpm installYou can use npm or yarn instead of pnpm if you prefer.
Step 3: Start the dev server
pnpm devVite 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→/aboutsrc/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 vialayoutMapinsrc/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 previewpnpm 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 installStep 2: Set up Clerk
Sign up / log in
Go to clerk.com and create an account (or sign in).Create an application
In the Clerk Dashboard, create a new application. Choose sign-in options (e.g. Email, Google, GitHub) and finish the wizard.Get the Publishable Key
In the dashboard, open Configure → API Keys. Copy the Publishable key (starts withpk_test_for development). You’ll add it to.env.localin a later step.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
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/_generatedfolder and sync your backend. Leave this command running in a separate terminal while developing (or use the combinedpnpm devfrom Step 5).
Get your Convex URL
Afternpx convex devhas run successfully, the Convex Dashboard will show your deployment URL (e.g.https://your-project.convex.cloud). Copy it—you’ll add it asVITE_CONVEX_URLin.env.local.Add Clerk’s Issuer URL in Convex
- Open the Convex Dashboard and select your project.
- Go to Settings → Environment Variables (or Developer → Environment 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).
- Name:
- 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:
Copy the example file
cp .env.local.example .env.localEdit
.env.localand 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.cloudDo not commit
.env.local(it’s in.gitignore). TheVITE_prefix is required so Vite exposes these variables to the client.
Step 5: Run the app
From the app root:
pnpm devThis 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
ClerkProviderandConvexProviderWithClerkso 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-inwhen not logged in- 404 — Not found
- Backend: Convex
convex/folder:auth.config.ts— Configures Convex to trust Clerk’s JWT (usingCLERK_JWT_ISSUER_DOMAIN).schema.ts— Defines thetaskstable.tasks.ts— Queries and mutations for the current user’s tasks (list, add, toggle).
- Layouts:
Layout.tsx(nav with ClerkSignInButton/UserButton) andProtectedLayout.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
- Add routes — Add files under
src/pages/(e.g.blog/index.tsx→/blog,blog/[id].tsx→/blog/:id). See linkr routing docs. - Add layouts — Add components in
src/layouts/and register them increateRoutes’slayoutMapinsrc/main.tsx. - Protect routes — Empty: use
<Protect>from@epicabdou/linkrwith a custom config. Clerk + Convex: use Convex’s<Authenticated>and Clerk’s components (as inProtectedLayout.tsx). - 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).
