This is an example app demonstrating how to use Schematic in a Next.js app with Clerk authentication. This app uses schematic-react for usage tracking and entitlement management via feature flags, and uses schematic-components for an embedded customer portal experience.
In order to use this example app, you'll need:
- A Schematic account
- A Clerk account
In order to make full use of the capabilities of Schematic components, you'll also need:
- A Stripe account
- Stripe customer IDs stored in private metadata on your Clerk companies
-
Set up your Schematic account; add features for "Weather Search", "Humidity", and "Wind Speed", create some plans and entitlements for these features, connect your Stripe account, and connect your Clerk account.
-
Set up your
.env
file:
cp .env.example .env
- In the Schematic app, create a component and store its component ID in your
.env
file:
NEXT_PUBLIC_SCHEMATIC_COMPONENT_ID="your-component-id"
- In the Schematic app, create a new API key and store both the publishable key and secret in your
.env
file:
NEXT_PUBLIC_SCHEMATIC_PUBLISHABLE_KEY="api_"
SCHEMATIC_SECRET_KEY="sch_dev_"
- Store your Clerk secret and publishable keys in your .env file:
CLERK_SECRET_KEY="sk_test_"
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_"
- Install dependencies:
npm install
# or
yarn
# or
pnpm install
- Run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
- Open http://localhost:3000 with your browser to see the result.
- First, we wrap our client-side code with the
<SchematicProvider>
provider:
<SchematicProvider publishableKey={schematicPubKey}></SchematicProvider>
- Then, we set a user context with the
identify
function from theuseSchematicEvents
hook; this is called in theClientWrapper
component, which wraps all client-side code.
const { identify } = useSchematicEvents();
const authContext = useAuthContext();
useEffect(() => {
const { company, user } = authContext ?? {};
if (company && user) {
void identify({
company: {
keys: company.keys,
name: company.name,
},
keys: user.keys,
name: user.name,
traits: user.traits,
});
}
}, [authContext, identify]);
- When we complete a weather search, we log that usage to Schematic using the
track
function from theuseSchematicEvents
hook:
track({ event: "weather-search" });
- To enforce entitlements, we use the
useSchematicFlag
hook in various locations:
const humidityFlag = useSchematicFlag("humidity");
{
humidityFlag && <p>Humidity: {weatherData?.humidity}%</p>;
}
- To display our customer portal, we use the
SchematicEmbed
component:
<SchematicEmbed accessToken={accessToken} id={componentId} />
- To provide a temporary access token for our embedded component, we implement a backend route to exchange a secret access token for a temporary, company-scoped access token:
const schematicClient = new SchematicClient({ apiKey });
const resp = await schematicClient.accesstokens.issueTemporaryAccessToken({
resourceType: "company",
lookup: {
clerkId: orgId,
},
});
const accessToken = resp.data?.token;
return NextResponse.json({ accessToken });