Redirect Management System
This project uses Sanity CMS to manage URL redirects for the First15 website. Redirects are automatically deployed via Netlify on every build.
Overview
Redirects are managed in Sanity Studio and automatically fetched during the Eleventy build process to generate Netlify's _redirects file.
How It Works
- Sanity CMS - Content editors manage redirects through the Sanity Studio UI
- Eleventy Build - Fetches published redirects from Sanity and filters by go-live date
- Netlify - Uses the generated
_redirects file to handle URL redirections
Deployment Triggers
Redirects are deployed automatically when:
- Code is pushed to the
main branch
- Content is published in Sanity (via webhook)
- Scheduled builds run (3x daily: 2:15am, 3:15am, 4:15am Central)
Managing Redirects in Sanity
Accessing Redirects
- Navigate to Website > Redirects in Sanity Studio
- Choose from:
- Import Redirects - Bulk import from existing
_redirects file
- _redirects File Preview - View the current active redirects
- Redirect History & Audit Log - See all redirects and recent changes
- All Redirects - Browse/edit individual redirects
Creating a New Redirect
-
Go to Website > Redirects > All Redirects
-
Click Create
-
Fill in the required fields:
- Source Path - The URL path to redirect FROM (e.g.
/old-page)
- Destination Path - The URL to redirect TO (e.g.
/new-page or full URL)
- Redirect Type - Choose 302 (Temporary) or 301 (Permanent)
- Go Live Date (optional) - When the redirect should become active
- Notes (optional) - Internal documentation
-
Click Publish
Field Details
Source Path
- Must start with
/
- Cannot contain spaces
- Cannot contain
# or ? characters
- Supports Netlify patterns like
* and :splat
- Conflict Warning: You'll see a warning if another redirect uses the same source path
Destination Path
- Can be a relative path (e.g.
/new-page) or full URL (e.g. https://example.com)
- Relative paths must start with
/
- Supports Netlify placeholders like
:splat, :topic
Redirect Type
- 302 - Temporary (default) - For short-term redirects, seasonal campaigns
- 301 - Permanent - For permanently moved content, SEO preservation
Go Live Date
- Optional field - leave empty for immediate activation
- Redirects with future dates won't be included in builds
- Will automatically activate during the next scheduled build after the date passes
Importing Existing Redirects
- Go to Website > Redirects > Import Redirects
- Paste the contents of your existing
_redirects file
- Click Parse Redirects to preview
- Review the parsed redirects
- Click Import to Sanity to create all redirect documents
Viewing Active Redirects
Go to Website > Redirects > _redirects File Preview to see:
- The exact contents of the
_redirects file that will be deployed
- Active redirect count
- Copy button for the file contents
Viewing Redirect History
Go to Website > Redirects > Redirect History & Audit Log to see:
- All redirects with their status (Active/Scheduled/Draft)
- Creation and update timestamps
- Notes and metadata
Technical Implementation
File Structure
first15web/
├── _data/
│ └── redirects.js # Fetches redirects from Sanity with date filtering
├── redirects.liquid # Template that generates _redirects file
└── _site/
└── _redirects # Generated file (deployed to Netlify)
Data Fetching (_data/redirects.js)
// Fetches published redirects from Sanity
const query = `*[_type == "redirect" && !(_id in path("drafts.**"))] | order(source_path asc)`;
// Filters by go_live_date
const activeRedirects = data.filter((redirect) => {
if (!redirect.go_live_date) return true; // Active immediately
return new Date(redirect.go_live_date) <= today;
});
Caching
- Production: 1 hour cache
- Development: 5 minute cache
- Uses
@11ty/eleventy-fetch for caching
Template (redirects.liquid)
Generates the _redirects file in Netlify format:
[source] [destination] [status_code]
Example output:
/old-page /new-page 301
/store https://store.example.com 302
/blog/* /articles/:splat 301
Netlify Redirect Format
The generated _redirects file follows Netlify's redirect syntax:
Basic Redirect
/old-path /new-path 301
Splat (Wildcard)
/old-section/* /new-section/:splat 301
Placeholders
/blog/:slug /articles/:slug 301
Domain Redirects
https://olddomain.com/* https://newdomain.com/:splat 301
Query Parameters
/search /results?q=:query 302
Development
Local Development
The system pulls from the production Sanity dataset by default. Changes published in Sanity will appear in local builds after the cache expires (5 minutes).
To rebuild and see updated redirects:
cd first15web
npx @11ty/eleventy
cat _site/_redirects # View generated file
Testing Redirects Locally
- Create/edit a redirect in Sanity Studio
- Publish the redirect
- Wait 5 minutes for cache to expire (or delete
.cache folder)
- Rebuild:
npx @11ty/eleventy
- Check
_site/_redirects for your changes
Removing Old Static File
The old static _redirects file is no longer used. The Eleventy config previously had:
eleventyConfig.addPassthroughCopy('./_redirects'); // ❌ REMOVED
This line was removed because redirects are now dynamically generated from Sanity.
Troubleshooting
Redirect Not Working
- Check if published: Drafts are not included in builds
- Check go-live date: Future-dated redirects won't be active yet
- Check the preview: Use "_redirects File Preview" in Sanity to confirm it's included
- Clear cache: Delete
.cache folder in first15web and rebuild
- Verify deployment: Check that Netlify deployed the updated
_redirects file
Duplicate Redirects
If you see a conflict warning in Sanity:
- The warning shows which existing redirect has the same source path
- Publishing will replace the existing redirect
- Both redirects cannot be active simultaneously
Redirect Not Appearing
Redirects won't appear in builds if:
- They're still in draft state (not published)
- The go-live date is in the future
- The cache hasn't expired yet (wait 5 min in dev, 1 hour in production)
Build Errors
If Eleventy build fails:
- Check that
@sanity/client is installed: npm list @sanity/client
- Verify Sanity credentials in
utils/sanityClient.js
- Check console for GROQ query errors
- Test the query in Sanity Vision: https://first15.sanity.studio/vision
Best Practices
Choosing Redirect Type
- 301 Permanent: Use for content that has permanently moved, old URLs you want search engines to forget
- 302 Temporary: Use for seasonal campaigns, temporary maintenance redirects, A/B testing
Go-Live Dates
- Use for scheduled campaigns and time-sensitive redirects
- Redirects activate during the next scheduled build (2:15am, 3:15am, or 4:15am Central)
- Leave empty for immediate activation after publishing
Source Paths
- Always use lowercase
- Use hyphens, not underscores (
/my-page not /my_page)
- Be specific - more specific paths should come before wildcards
- Test in a non-production environment first
Notes Field
Use the notes field to document:
- Why the redirect exists
- When it can be removed
- Related tickets or requests
- Original requester
Additional Resources