Next.js + Markdown Lessons:
In this lesson, we'll explore the basics of structured content, while enabling basic content editing in Stackbit's visual editor.
This is a lesson within the Next.js + Markdown tutorial that requires completing all previous steps. If you're looking for more information on content modeling with Stackbit, see the conceptual guide or the file-based modeling reference.
As mentioned while setting up the project, Stackbit's only real requirement is that content must be structured and separated from code. Let's start with a little background on why that is necessary and beneficial . (Or skip it and jump right into the code.)
Stackbit operates in a fully declarative way. The editing experience for any given site is driven by the code and configuration provided by the site's developer(s).
To be able to provide a superior editing experience, Stackbit needs to know where the content from editable elements on the page are stored, which is why we require that you structure your content.
Structured content also provides a great benefit to developers in an enhanced developer experience.
- Components & Reusability: Separating content from code means that you can also abstract your page templates into reusable components using a component framework like React, Vue, or Svelte. This is how most modern websites are built.
- Cleaner Code & Separation of Concerns: Your code then becomes easier to work with by being more modular and reducing the number of responsibilities for each file in your project.
- Confidence & Type-Safety: Content being fed into components is predictable, which means you can introduce TypeScript for type-safety in your code, boosting confidence that your site will work in production.
When using files as the content source, Stackbit does not inherently understand the structure of the content within the files. You can provide this structure through a series of model configurations in the
See the technical reference for an exhaustive list of options when configuring file-based content models.
Content models can be one of three types: page, object, or data. Pages are models that represent a single webpage on your site. The collection of documents (content files) of type
page is what Stackbit uses to populate the sitemap for your site.
We can add our home page to this sitemap by providing a simple model definition for a
page model in
# .stackbit/models/page.yaml type: page name: page hideContent: true fields: - name: title type: string required: true - name: sections type: list items: type: model models: [hero, stats]
This tells Stackbit that we have two fields:
title is just a name for the page, while
sections will contain the content sent to individual components that content editors can use to build pages on your site.
Back in your browser, you should now see the home page in the sitemap.
sections field on the page model, we specified that it was a list that could be of multiple types. If you check your Stackbit dev console, you'll see warnings about
stats models not being found.
Let's create the hero model.
# .stackbit/models/hero.yaml name: hero fields: - name: heading type: string - name: body type: markdown - name: image type: object fields: - name: src type: image - name: alt type: string - name: button type: model models: [button] - name: theme type: enum options: [imgLeft, imgRight]
Notice here that we're linking another level deeper and using a
button model for the
button field here. So let's add that model, too:
# .stackbit/models/button.yaml name: button fields: - name: label type: string - name: url type: string - name: theme type: enum options: [default, outline]
We also have a
# .stackbit/models/stats.yaml name: stats fields: - name: heading type: string - name: body type: markdown - name: stats type: list items: type: object fields: - name: label type: string - name: value type: string - name: theme type: enum options: [primary, dark]
hero model, the
stats model has an embedded structured field called
stats. But unlike the
hero model, the
stats model doesn't define this as another model, but defines the shape of the object directly.
Note: We also took this approach with the
image field in
hero, but only to keep this example simple. You'd likely also want to abstract
image into its own model and component in a real project.
This is to demonstrate the flexibility in structuring content. How exactly you choose to structure your content is entirely up to you. In this example,
button is component that is likely to used by multiple other components, while individual stat cards (called
StatItem in this project) may not be, so we keep it tightly coupled to the
Now we're ready to start editing content!
With all the models properly defined, you can use the page editor to adjust content within sections of the page.
Notice when you do this that the content gets updated in
# content/pages/index.md --- title: Home Page sections: - type: hero # ... heading: Only YOU can make the perfect sandwich!
Stackbit also listens for content changes in the content source. If you change the markdown content directly, notice that the preview in the visual editor reflects those changes. Learn more about automatic content reload.
Next, add a new section to the home page.
And again, check
content/pages/index.md to see how the content changed.
# content/pages/index.md --- title: Home Page sections: # ... - type: hero heading: A New Hero Section body: | With some body content!!! # ...
And last, add a new page.
The page is blank here because we haven't added any sections to it. An upcoming lesson will cover presets, which can make this process much smoother for content editors.
You now have a new file in the
content/pages directory. You can also see the new page in the sitemap.
There's a lot going on in the Stackbit dev server and API to make this all work together. You're welcome to pause and dig into the details on how Stackbit updates and retrieves content.
Otherwise, let's take content editing to the next level by introducing inline editing.