34.4 Forestry.io and Its Successor Tina
Right, let’s talk about the great decoupling: getting your content out of your code and into a proper CMS. You’ve built a slick Hugo site, but the thought of your non-technical marketing team trying to git commit is giving you hives. Enter the Headless CMS. And for a long time, the go-to, almost-default choice for Hugo was Forestry.io. It was a beautiful, git-based solution that felt like it was made for Hugo. Then, one day in late 2022, they pulled the plug. Poof. Gone. It was a stark reminder that we build our houses on other people’s land. But from its ashes rose a phoenix, albeit a phoenix that changed its name and a lot of its DNA: TinaCMS.
The Ghost of Forestry.io (And What Made It Great)
First, a moment of silence for Forestry. It was brilliant because it understood Hugo’s content structure intuitively. You connected it to your git repo (GitHub, GitLab, etc.), it would read your config.toml/yaml/json and your content directory, and bam — it would generate a slick, custom admin UI based on your front matter. No need to build an API or define your content models twice. It was git-native, meaning it just made commits and pushes on your behalf. The content lived in your repo, which is exactly where you wanted it.
The magic was in how it parsed your front matter to create a form. A simple about.md with this front matter:
---
title: "About Us"
description: "We are the best company."
team_member:
- name: "Alice"
role: "CEO"
- name: "Bob"
role: "CTO"
---
Would result in a Forestry UI with fields for title (text input), description (textarea), and team_member (a repeatable group of fields for name and role). It just worked. The pitfall? Well, besides its eventual demise, it sometimes struggled with extremely complex or custom front matter structures. But for 90% of Hugo sites, it was perfect.
Enter Tina: The Ambitious Successor
TinaCMS is what the Forestry team built next, and it’s a much more ambitious, developer-centric beast. Calling it just a “headless CMS” is a bit of a misnomer; it’s more of a visual editing framework. The core idea is similar: content lives in git. But the approach is different. Instead of being a separate admin site, Tina is typically embedded into your own site.
This is both its superpower and its main point of friction. You don’t just connect a repo; you integrate Tina by installing it as a package (npm install -g @tinacms/cli) and adding its provider components to your site. This means you get a contextual editing experience — click an “Edit” button, and you can change content right on the page you’re looking at. It’s incredibly powerful for content teams.
Getting Your Hands Dirty with Tina
Setting up Tina is more involved than Forestry was. You’re not just configuring a SaaS admin panel; you’re adding a development framework. First, you define a content schema in your project. This is where you explicitly tell Tina about your content shapes, which is actually a great bit of documentation.
Here’s a basic tina/config.ts example for our earlier front matter:
// tina/config.ts
import { defineConfig } from "@tinacms/cli";
export default defineConfig({
schema: {
collections: [
{
label: "Pages",
name: "pages",
path: "content",
fields: [
{
type: "string",
label: "Title",
name: "title",
},
{
type: "string",
label: "Description",
name: "description",
ui: {
component: "textarea",
},
},
{
label: "Team Members",
name: "team_member",
type: "object",
list: true,
fields: [
{
type: "string",
label: "Name",
name: "name",
},
{
type: "string",
label: "Role",
name: "role",
},
],
},
],
},
],
},
});
See? You’re defining the structure in code. This is more work upfront, but it’s explicit, version-controlled, and prevents the magic-but-sometimes-brittle parsing that Forestry did.
The real “wow” moment comes when you enable visual editing. You’ll wrap your site in Tina’s providers and then use tina-field directives in your templates. When you’re in edit mode, these become clickable fields. It feels like magic, but the code behind it is very deliberate.
The Rough Edges and The Payoff
Let’s be direct: Tina has a higher barrier to entry. You need to be comfortable with React, even if your site is in Hugo (they have a “iframe” mode for non-React sites, but it’s not the flagship experience). The setup involves build processes and a local GraphQL data layer that Tina spins up. It can feel like overkill for a simple blog.
But the payoff is immense. You get a truly custom, foolproof editing experience for your team. You’re not bending your content model to fit a generic CMS’s UI; you’re building the exact UI your content needs. And because it’s all in your codebase, you own it completely. No one can turn it off. The team behind it is clearly all-in on the developer experience, and it shows in the flexibility.
The best practice? Use Tina’s @tinacms/cli to spin up a local editing environment during development. This lets you see your changes in real-time without a full Hugo build. And for heaven’s sake, thoroughly test the editing experience yourself before handing it over to content editors. Walk through every button and field. What’s obvious to you, a developer, might be confusing to someone who just wants to change a headline without breaking the entire website layout. That’s the real trick, and Tina gives you the tools to make it seamless.