# From draft to live in four steps

What happens between an editor's change in Storyblok and the page you are reading.

## The publishing path

1. **Model**
   
   Blocks are defined in one JSON file and pushed to the Storyblok space. TypeScript types are generated from the same file.
   
   [storyblok/components.json](https://github.com/marcop135/nextstory/blob/main/storyblok/components.json)

2. **Preview**
   
   The Visual Editor opens the preview route, which checks the secret and the draft before it turns on Next.js draft mode.
   
   [src/app/api/preview/route.ts](https://github.com/marcop135/nextstory/blob/main/src/app/api/preview/route.ts)

3. **Publish**
   
   Storyblok calls the revalidate route with the story slug. The route validates the payload and expires that story's cache tag.
   
   [src/app/api/revalidate/route.ts](https://github.com/marcop135/nextstory/blob/main/src/app/api/revalidate/route.ts)

4. **Serve**
   
   The next request loads the published story from the Storyblok CDN and renders it as a React Server Component.
   
   [src/lib/fetch-story.ts](https://github.com/marcop135/nextstory/blob/main/src/lib/fetch-story.ts)

## Why the cache tags matter

Published stories are cached per story. A publish expires one story in every language, so the rest of the site stays cached. Drafts are never cached, so the editor always sees the latest change.

The full request path is in [docs/architecture.md](https://github.com/marcop135/nextstory/blob/main/docs/architecture.md).

## The schema names resolve to React components

The server registers the component map before rendering a story. Each block name in the CMS resolves to its implementation.

```TypeScript
export function registerStoryblokComponents(): void {
  setComponents(storyblokComponents);
}
```

The registration function used by the server renderer.

[src/lib/storyblok.ts](https://github.com/marcop135/nextstory/blob/main/src/lib/storyblok.ts)

## See what each block looks like

The block library renders every component once, labelled with its Storyblok name.

[Open the block library](/blocks)

## Learning notes

[Content relationships](/content-relationships)

Reuse one story across pages

[Cache invalidation](/cache-invalidation)

Publish once, refresh dependent pages

Canonical: https://nextstory.marcopontili.com/how-it-works
Content source: storyblok; published representation.
