FAQ & Troubleshooting
Real solutions for real problems you'll encounter with Skier.
Build Issues
My build is slow
Symptoms: Build takes 10+ seconds for a small site.
Common causes:
- Large static assets — Use
copyStaticTaskfor big files, not template processing - Too many partials — Each partial is re-read per page; consolidate if possible
- Expensive
additionalVarsFn— Avoid file I/O or computation inside these functions
Debug: Run with --debug to see per-task timing:
npx skier --debug"require() of ES Module not supported"
Symptoms: Build fails with this error when using v3+.
Cause: A dependency (often chalk, feed, or others) has migrated to ESM-only.
Fix: Convert your config to ESM:
# Rename your config
mv skier.tasks.cjs skier.tasks.mjsThen update the syntax:
// Before
const { generatePagesTask } = require('skier');
module.exports = [/* ... */];
// After
import { generatePagesTask } from 'skier';
export default [/* ... */];See the Migration Guide for full details.
"Cannot find module" errors
Symptoms: Imports fail despite the file existing.
Cause: ESM requires file extensions in relative imports.
Fix:
// Wrong
import { helper } from './utils';
// Correct
import { helper } from './utils.js';Template Issues
Variable not found / undefined in template
Symptoms: {{myVar}} renders as empty or undefined.
Debug steps:
Check task order — Is the task that sets the variable running before the task that uses it?
// Wrong order generatePagesTask({ /* uses posts */ }), generateItemsTask({ outputVar: 'posts' }), // Too late! // Correct order generateItemsTask({ outputVar: 'posts' }), generatePagesTask({ /* uses posts */ }),Check the variable name — Is it
postsorallPosts? Check youroutputVarsetting.Check globals — Run with
--debugto see the globals object at each step.
Markdown not rendering as HTML
Symptoms: Raw Markdown appears in the page instead of formatted HTML.
Cause: You're using double braces which HTML-escape the content.
Fix: Use triple braces for raw HTML:
<!-- Wrong: escapes HTML -->
{{content}}
<!-- Correct: renders HTML -->
{{{content}}}Partial not found
Symptoms: {{> myPartial}} throws an error.
Checklist:
- Does the file exist at
partialsDir/myPartial.html? - Is
partialsDircorrectly configured in your task? - Does the file extension match
partialExtension(default:.html)?
Pagination Issues
Pagination URLs are wrong
Symptoms: Links go to /undefined/page/2 or similar.
Cause: basePath is misconfigured.
Fix: basePath should be the URL path, not the output directory:
generatePaginatedItemsTask({
outDir: 'public', // Filesystem path
basePath: '/blog', // URL path (what appears in links)
// ...
})Page 1 URL is different from other pages
Expected behavior! Page 1 is at the base path (/blog), subsequent pages at /blog/page/N.
If you need consistent URLs, handle it in your template:
{{#if (eq pagination.currentPage 1)}}
<link rel="canonical" href="/blog">
{{else}}
<link rel="canonical" href="/blog/page/{{pagination.currentPage}}">
{{/if}}Feed Issues
Dates in feed are invalid
Symptoms: Feed validators complain about date format.
Cause: Dates must be ISO 8601 format or JavaScript Date objects.
Fix: Ensure your frontmatter dates are properly formatted:
# In your Markdown frontmatter
date: 2024-01-15T10:00:00Z # ISO 8601generateItemsTask automatically creates a dateObj field (a JavaScript Date object) from frontmatter dates, which generateFeedTask uses for feed entries.
Feed URLs are relative
Symptoms: Feed readers show broken links.
Cause: site.link must be an absolute URL.
Fix:
generateFeedTask({
site: {
link: 'https://example.com', // Include protocol!
// ...
}
})CSS Issues
CSS order is wrong
Symptoms: Later CSS rules don't override earlier ones as expected.
Cause: bundleCssTask concatenates files in alphabetic order.
Fix: Prefix filenames to control order:
src/styles/
01-reset.css
02-variables.css
03-components.css
99-overrides.cssCustom Task Issues
Custom task not running
Symptoms: Your task appears to do nothing.
Checklist:
- Is the task in the exported array?
- Is
runan async function that's actually called? - Check for silent errors — wrap in try/catch:
run: async (config, ctx) => { try { // Your code } catch (err) { ctx.logger.error('Task failed:', err); throw err; } }
Globals from custom task not available
Symptoms: You return data but it's not in globals.
Cause: You must return a plain object, not assign to ctx.globals.
// Wrong — direct assignment doesn't persist
run: async (config, ctx) => {
ctx.globals.myData = computeData();
}
// Correct — return triggers a merge
run: async (config, ctx) => {
return { myData: computeData() };
}Getting Help
Still stuck?
- Check debug output:
npx skier --debug - Read the source: Skier is small and readable
- Open an issue: GitHub Issues