Skip to main content
This builds, in a Next.js 15 App Router project:
  1. a typed fetch helper, lib/vacademy.ts;
  2. a server-rendered course grid with stream tabs, linking each course to its hosted page;
  3. optionally, your own course page with generateMetadata and schema.org JSON-LD;
  4. app/sitemap.ts.
Every fetch runs on your server, so pages are fully rendered HTML for search engines and the key is never needed in the browser.

1. Add the key

Create a publishable key in the Vacademy dashboard under Settings → Integrations → Catalogue API & websites (details). Put it in .env.local, and in your host’s environment variables (for example Vercel → Project → Settings → Environment Variables):
.env.local
Check it:
Server-side requests (no Origin header) work without verifying a website. You only need a verified website for requests made from browser JavaScript.

2. The fetch helper

lib/vacademy.ts
next: { revalidate: 60 } matches the API’s own 60-second cache: Next.js serves the cached response and refreshes it in the background at most once a minute, whatever your traffic.

3. A course grid

app/courses/page.tsx
Each card links to course.url, the course’s page on the hosted catalogue site, where the visitor picks a version, adds it to the cart and pays.
To use next/image instead of <img>, allow the image host in next.config.ts under images.remotePatterns. Read the host from a real image_url.

4. Choose where course pages live

Your own course page (optional)

app/courses/[id]/page.tsx
  • generateMetadata and the page both call load(id); Next.js runs that fetch once per request.
  • Every *_html field is sanitised by the API (jsoup relaxed safelist; images only from http(s) URLs), so it is safe to render as HTML.
  • generateStaticParams pre-renders every course at build time. Courses published later render on their first visit.
  • structured_data describes the course for search engines. Its offers[].url stays the hosted page, where the course is bought; the snippet sets the top-level url to your page.

5. Sitemap

app/sitemap.ts
If you link to hosted pages instead, drop the loop: course pages belong to the hosted site’s host, not yours.

Next