惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
博客园 - 聂微东
有赞技术团队
有赞技术团队
The Cloudflare Blog
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
T
The Blog of Author Tim Ferriss
D
Docker
L
LangChain Blog
Vercel News
Vercel News
C
Check Point Blog
博客园 - Franky
博客园 - 三生石上(FineUI控件)
Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
量子位
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
人人都是产品经理
人人都是产品经理

Sanity.io

A Board Game agent built using Sanity Context and Vercel's AI SDK | Sanity Build a prototype with Claude Code that your whole team can edit | Sanity What’s New - May 2026 | Sanity I built a London pub guide with v0 and the Sanity MCP in six hours. Here's what I learned. | Sanity Build a conference concierge with Agent Context and Anthropic | Sanity Build a content-aware Telegram agent with Vercel AI SDK and Chat SDK | Sanity How I used Agent API to generate photos for my family’s recipes | Sanity What’s New April - 2026 | Sanity Better context, better matches: An AI love story (for dogs) | Sanity How to write for an agent | Sanity Content Agent, meet Slack: AI content operations in your workflow | Sanity Structure powers intelligence | Sanity Your agent needs better content. Here's how to give it. | Sanity How to serve content to agents (a field guide) | Sanity Sanity TypeGen GA: Automatic TypeScript types for content and GROQ | Sanity Sanity is now available on the Vercel Marketplace | Sanity The logo soup problem (and how to solve it) | Sanity Content Releases: From scattered updates to coordinated publishing | Sanity What's New - February 2026 | Sanity How we solved the agent memory problem | Sanity v0 Builder Challenge: The winners | Sanity Introducing: Sanity Agent Skills | Sanity Content Agent: Days of work in one conversation | Sanity Our Sanity Values | Sanity Open Source Pledge 2025: Stepping up when it matters | Sanity v0 builder challenge: $3000 in prizes | Sanity Why AI Breaks Without Structured Content Operations | Sanity What’s New January - 2026 | Sanity BFCM 2025: What teams built when infrastructure stopped being the problem | Sanity How AI shaped holiday shopping and what it means for content in 2026 | Sanity
Migrating the Netlify Blog from Hugo to Eleventy using Sa...
Sam Tancharoensuksavai · 2022-05-19 · via Sanity.io

Over the last year, Netlify has been migrating our codebase from Hugo to Eleventy to streamline our development process and reduce client-side JavaScript. One of the last steps left was to migrate more than 700 markdown files, each representing a blog post, over to our internal Sanity instance. Luckily Sanity’s markdown-to-sanity tool made this process simple.

In this post, I’ll cover:

  • using the markdown-to-sanity tool
  • importing the .ndjson that's generated to our Sanity dataset
  • how we're using Eleventy to render our blog posts
  • any small gotchas I came across

Using markdown-to-sanity

Sanity offers a concise CLI tool to help with the importing and exporting of datasets. The CLI tool requires that the file be a newline-delimited JSON (NDJSON) file. Basically, each line in a file is a valid JSON-object containing a document you want to import. Now, I needed a way to parse all 700 markdown files and convert them into a single .ndjson file. Sanity to the rescue! Their markdown-to-sanity repo did the job beautifully.

After following the README.md you should have the CLI tool installed on your machine. For organizational purposes, I created a new directory called /blog at the root of the repository and dropped all of my markdown files in there. I also needed to bring over all of the static assets – such as images, gifs, and videos – that each blog post was referencing.

Referencing Existing Sanity Data

For each blog post, there is an author. Luckily, we already had these authors stored in our Sanity dataset. Essentially, we want to pass the author’s reference ID that Sanity has set when we create the JSON object of the blog post. Sanity provides a helpful client that you can use to fetch whatever data you need. All you need to do is pass a valid GROQ query into the fetch function.

Here’s a basic example of using the Sanity Client to fetch an author’s ID:

Let’s break a couple of things down:

  • name refers to the author’s name we are retrieving
  • { "ref": _id } represents what we are returning back from the API call. We only want the _id of the author to use as a reference ID
  • !(_id in path("drafts.*")) ensures that we do not retrieve any documents that are currently in a draft state
  • We are returning an object with "_type": "reference to signify to Sanity that this is a reference and we set the _ref to the ID of the author we just fetched

Then, I needed to modify the Sanity document, representing a blog post, before it got created and added to the .ndjson file. Taking a look at the ./src/convertToSanityDocument.js file, you'll notice that this is where we create the Sanity Document. I made a number of edits to the final object to ensure there was parity in the data between the markdown file and what was stored in Sanity.

Importing your NDJSON into Sanity

After successfully running the markdown-to-sanity tool, you should have a .ndjson file where each new line is a single blog post. Now you want to import this data into your dataset stored in Sanity. You can reference the Importing Data article for more details.

With my newly generated .ndjson file, I ran the Sanity CLI to import this file into our dataset. It should look something like this:

I also added the --replace and --allow-failing-assets flags to the end of my command, both of which are explained in the Importing Data document.

Tying Sanity and Eleventy together

If you’re looking for more granular detail into how we’re using Eleventy and Vue together, I’ll point you to Zach Leatherman’s post. In this section, I’ll talk about how we are calling Sanity, storing the response, and building templates around our data.

Eleventy Global Data

Just like in our example when we fetched the authors from our Sanity, we will be doing the same thing, but this time we will store the response within a global data file. Leveraging Eleventy’s global data gives us the ability to grab the data we need within a template file.

For instance, if we wanted to query for all the blog posts we might have code that looks something like this:

Using the Data

Now that we have all our blog posts within Eleventy’s Global datastore, we can expect our posts to be available at data.blogPosts . I’d like to create a static HTML file for each blog post. Eleventy’s Pagination feature makes this extremely easy, as the first line states, “pagination allows you to iterate over a data set and create multiple files from a single template.”

Let’s create a Vue template file that will serve as the template for our blog posts.

The following is happening in the code above:

  • data: "blogPosts" inside the pagination object is referencing the blogPosts data object that we set in our global data store.
  • size: 1 means that we want to chunk the array of all posts into single chunks where each chunk represents a single blog post.
  • alias: "post" is the variable you can use within this template file to refer to the chunk of data returned from paginating.
  • We are directly referencing the post object, set by the pagination alias, within the permalink, by grabbing the slug for the blog post and using it to create the blog’s permalink.
  • Within our <template> we are again referencing the post object to render the title of the blog post.

Rendering Markdown

First, we had Markdown files, then imported the Markdown content of those files into Sanity, and now we want to render out that Markdown into something browsers can understand: HTML. Traditionally, Eleventy leverages Liquid or Nunjucks to process Markdown into HTML, but remember we are using Vue.

Luckily, we knew someone who could help us patch that gap. Thus, Eleventy’s Render Plugin was born! Using this plugin we could feed the markdown string into the renderTemplate function that this plugin makes available globally, and directly injects the output into our template file.

Syntax Highlighter

What’s a developer-focused blog without pretty code blocks?

Eleventy offers another great plugin to take care of processing code blocks within a markdown file. Using the @11ty/eleventy-plugin-syntaxhighlight plugin whenever we run our markdown through the renderTemplate() function, the highlighter plugin will use PrismJS to process the block according to the language specified in the code fence.

Conclusion

What sounded like a daunting task, migrating over 700 markdown files into Sanity and pulling those blog posts into our Eleventy codebase, turned out to be a fairly straightforward process thanks to the great foresight and care the Sanity team brings to their product.

There are moments as a developer when you feel like you have a special set of superpowers, and being able to process so many files at one time and import that data into our internal Sanity just by executing a single command was a special moment for me. Thanks again to the great folks at Sanity, as well as Zach Leatherman for letting me nerd-snipe you for a couple of awesome features to the Eleventy ecosystem!