Working with a git-based content workflow can be a powerful way to manage content for a site. But sometimes you need to add an image to a blog post or other content. Managing images in a git-based workflow either means adding another service or needing to be super diligent about managing images in your repository.
#TL;DR
This guide will show you how to add an image uploader to your Astro site to make it easy to manage images in your content. The uploader is only present in local development, and enforces a repeatable structure for storing images in your repository which surfaces when you serve your site in production.
Although this is specific to Astro, the concepts could be applied to other site framework where components are supported within your markdown content.
#JFDI (just deploy it)
If you’d prefer to just clone and deploy an example to explore, click the button below and you’ll very quickly have an example Astro site when an uploader ready to use in local development.
#Set up the project
Let’s create a new Astro project.
Be sure to choose Use blog template when prompted on where to start. The blog template will have what we need to build out the image uploader.
#Configure Astro
This approach uses an API route (server endpoint) to process the uploaded file. For this to work, we have to enable server-side rendering (SSR) in Astro. We can do this by leaving the site as static and enabling SSR only for specific routes.
#Add SSR to Astro
For API endpoints to work, we need to enable SSR in Astro. Many content sites can be built with Astro without server-side rendering, or with minimal server-side rendering. We’re going to assume that is the case for your site and use hybrid
rendering mode.
Hybrid rendering mode defaults to rendering all pages as static. Pages and API endpoints that should be dynamically rendered on the server can be individually configured to do so.
Using server mode
The rest of the guide assumes we’re working in hybrid mode. If you’re using server
mode, you’ll have to adjust
accordingly.
#Add uploader component
Add an uploader component to your Astro project. This will be the upload form that will post to an API endpoint to handle the file upload.
Place this file in your src/components
directory.
There are a few things to note about this component:
- The component is designed to be used as a utility during development and does not function in production. After using it to upload an image, it replaces itself in the content with the appropriate markup. Unused upload components left in the code will fail a production build to prevent the form from being included in the final build and ensure you’ve uploaded all necessary images.
- The form posts to
/actions/upload
, which we’ll set up in the next step. - We include both the
url
(from Astro) andid
(prop) in the form to help the API endpoint know where to save the file and which content to replace. - The form is submitted asynchronously so that the browser will update the content when the image is added without refreshing the page.
#Add component to a blog post
As long as MDX is enabled, you can now add the component to any blog post on your site.
Check import path
Note that the path to the component may need to be adjusted based on your project structure.
View that post in your browser and you should now see the unstyle image upload form.
#Add the API endpoint
Now we need to set up the API endpoint to handle the file upload. This will be a simple function that saves the file to the repository, then replaces the uploader component with the image in the blog post.
Create a new file at src/actions/upload.ts
.
Note that this creates a specific structure for storing your images:
- Images are stored in a folder named for the blog post slug within the
public/images
directory. - The component is replaced in the source content file with the markdown image syntax. This is using a simple regex to find a specific pattern,
<Uploader id="x" />
, wherex
is the ID of the uploader component.
#Upload images!
That’s it! Now you can drop an image into the uploader form. The image will be saved to your repository in the proper directory, and then the uploader component will be replaced with markdown image syntax in your content file.
Where you had the component in your content file:
You’ll now have the markdown image syntax:
And the content will be automatically updated in your browser.
#Next steps
I hope this gave you some inspiration for introducing tools that can augment your content workflow to make it more efficient, enjoyable, and maintainable.
Here are a few ideas for consideration as you bring this functionality into production.
#Add a platform adapter
You’ll also need an adapter when deploying the project. For deploying to Netlify, you can use Astro’s Netify adapter. To install and configure this automatically run the following command:
#Auto-import the component
Pro-tip! You can use astro-auto-import
to avoid having to manually import the component into each blog post. I like doing this to keep my content files clean and focused on the content.
Then add the integration to your astro.config.mjs
file.