Skip to content

Documentation

Start from the starter

A Next.js project with all of this already wired in: the tag in the layout, a sign-up handler that stores what the person agreed to, and a Stripe webhook. Deploy it as your own in one click, or run one command to add the same wiring to a project you already have.

A public Next.js template with Kicklace already wired in, so a developer clicks one button and has a project on Vercel posting to their workspace. It is built in this repository at templates/nextjs-starter/, and it has to live in a public repository of its own before the button can clone it — which is Michael's step, on his own GitHub account.

Beside it, npx kicklace init does the same wiring in a project somebody already has. It ships in the kicklace package (docs/sdk.md), so it needs a publish too.

What Michael does, in order

1. Push the starter to a repository of its own

cd ~/Developer/kicklace/templates/nextjs-starter
gh repo create kicklace-nextjs-starter --public --source . --remote origin \
  --description "A Next.js app wired to Kicklace: the tag on the site, the SDK in your server."
git init
git add .
git commit -m "A Next.js app wired to Kicklace"
git branch -M main
git push -u origin main

It has to be public: Vercel's Project creation flow clones the repository into the developer's own GitHub, GitLab or Bitbucket account, and it cannot clone one it cannot read.

The folder here stays as it is. It is where the starter is edited and where npm run check proves the Deploy Button's address is the one the README carries; pushing it again is the same three commands with git push at the end.

The address is written into the README already, as https://github.com/fallguy04/kicklace-nextjs-starter. If the repository ends up anywhere else — another account, another name — change it in two places and npm run check will tell you if you missed one:

  • templates/nextjs-starter/README.md, the Deploy Button link;
  • REPO in src/lib/__tests__/starter.test.ts.

Then publish it and set NEXT_PUBLIC_KICKLACE_STARTER_URL to the same address.

2. Publish kicklace@0.2.0 to npm

docs/sdk.md → "0.2.0, the version that carries init" has the commands and the two things to check on the tarball. Nothing else in the package changed, so anything written against 0.1.0 keeps working.

Then, optionally, bump the starter's own kicklace dependency from ^0.1.0 to ^0.2.0 and push it again. It is ^0.1.0 today because that is what is on npm and the starter has to build the day it is published; it only ever uses Kicklace and KicklaceTag, which have not changed.

3. Set the variable, in production and preview

In Vercel → the kicklace project → Settings → Environment Variables:

Name Value Where
NEXT_PUBLIC_KICKLACE_STARTER_URL https://github.com/fallguy04/kicklace-nextjs-starter Production, Preview

Until it is set, /developers says nothing about the starter and nothing about npx kicklace init — the honesty rail: the site never names something that is not on the internet yet. Set it after both of the steps above, because it is the one switch for both.

The site's pages are static, so it takes a redeploy to show, the same way KICKLACE_SIGNUP does.

The Deploy Button's address

Built once, by starterDeployUrl in src/lib/env.ts, and copied into the starter's README as a literal — the starter is a repository of its own and cannot import ours, so src/lib/__tests__/starter.test.ts is what keeps the two the same. This is the whole address:

https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Ffallguy04%2Fkicklace-nextjs-starter&project-name=kicklace-starter&repository-name=kicklace-starter&env=KICKLACE_SECRET_KEY,NEXT_PUBLIC_KICKLACE_KEY,KICKLACE_URL,NEXT_PUBLIC_KICKLACE_URL&envDefaults=%7B%22KICKLACE_URL%22%3A%22https%3A%2F%2Fwww.kicklace.com%22%2C%22NEXT_PUBLIC_KICKLACE_URL%22%3A%22https%3A%2F%2Fwww.kicklace.com%22%7D&envDescription=Your%20Kicklace%20keys%2C%20from%20Settings%20%E2%86%92%20Your%20website%20%E2%86%92%20For%20your%20developers%3A%20the%20public%20key%20for%20the%20tag%2C%20and%20a%20secret%20key%20for%20your%20server.&envLink=https%3A%2F%2Fgithub.com%2Ffallguy04%2Fkicklace-nextjs-starter%23environment-variables

Every parameter, and where it is documented:

Parameter What it does Source
repository-url the template to clone vercel.com/docs/deploy-button/source
project-name, repository-name what the new project and repository are called by default the same page
env a comma-separated list of names the deploy form asks for, and requires vercel.com/docs/deploy-button/environment-variables
envDefaults a URI-encoded JSON object of default values, for names that are not secret the same page
envDescription one sentence shown beside the fields the same page
envLink where to read about them; the docs ask for a specific page, not a top-level one the same page

The four names are the same four the Vercel integration writes into a project (#200, docs/vercel-integration.md), and for the same reason: <KicklaceTag /> reads NEXT_PUBLIC_KICKLACE_URL, and the package's own default is www.kicklace.com, so a project pointed at any other deployment needs both addresses.

Only the two addresses get an envDefaults value. Vercel's own note is that a default is for a feature flag or a public endpoint and never for a key, and that is exactly the line here: nobody's key is ever in a URL, which is also why env cannot carry values at all — the address is in the browser's history.

STRIPE_WEBHOOK_SECRET is deliberately not in env. The starter's Stripe route is optional, and requiring a secret at deploy time for a route somebody may never use would stop the deploy. .env.example names it and the route says what happens without it.

There is no vercel.json in the starter. Vercel detects Next.js on its own, and a config file that only repeated the defaults would be one more thing to keep true.

What is in the starter

File What it shows
app/layout.tsx <KicklaceTag />, reading the two public variables
app/consent.ts the list and the consent sentence, as one constant the form and the handler share
app/signup-form.tsx the form, and the browser id the tag keeps (kl_id) going with the post
app/api/signup/route.ts identify, then subscribe with that sentence
app/api/webhooks/stripe/route.ts the signature by node:crypto, then track("purchase", …) with an idempotency key
app/kicklace.ts one client, built per request so a project with no key still builds

The Stripe route opens by saying that Kicklace takes Stripe's webhook itself (Settings → Integrations → Payments from Stripe), that it is the better path, and that running both would land the purchase twice. A starter that quietly taught the harder way would be teaching the wrong thing.

Proving it still builds

The folder is a whole app, and npm run check in this repository cannot see it — the root tsconfig.json excludes templates, and .gitignore keeps its node_modules, .next and next-env.d.ts out. So it is built by hand, and it has to be built outside this repository: Next finds a project's root by walking up for a lockfile, and inside the monorepo it finds this repository's and then tries to compile src/proxy.ts.

cp -R templates/nextjs-starter /tmp/starter-build
cd /tmp/starter-build
npm install
npm run build          # ✓ Compiled successfully, four routes

No lockfile is committed with the template, which is what Vercel's own examples do: the Deploy Button clones it and npm install resolves the ranges fresh.

This page is still written partly for the people building Kicklace, so parts of it are about work that is not yours to do. It is here because what it describes is real; it is not listed on the documentation index until it has been rewritten.