Let me explain myself ahead of time. I’ve been thinking of this problem for some time and here’s how far I’ve come.
How to schedule posting with publish/end date aka automated publishing.
Consider all this for already a little established sites with continuous deployment, CDN, large theme, many images, CSS/JS/HTML processing etc. etc.
Solution #1 - a regular rebuild task
The most common suggested solution is a scheduled task that triggers build and done by
- build environment itself (i.e. Travis-ci, BitBucket Pipelines etc.)
- external build trigger (i.e. Netlify POST build trigger)
The site is rebuilt enough often so that posts appear/are hidden when required.
Summary for this approach
Pros:
- Hugo is amazingly fast to build on even large sites
- Easy to implement on almost any CI/git/hosting scenario
- Running often will ensure always up-to-date content
Cons:
- Build is long on large sites considering other tasks like SASS/LESS, image minify, critical CSS, CSS/JS minify any other pre/post-processing module you might have
- Each build purges CDN (i.e. forcing AWS CloudFront purge too often adds costs)
- The first reload on CDN region after purge is slow
- Build notifications not distinguishable from rebuilds vs real changes
- What if rebuild and content commit triggers to come in at the same moment/in parallel?
Doing this at short intervals is not a sane approach to increase timing precision - daily, hourly, every 10 minutes? Again, consider increased CPU/billing costs (even using “free” Netlify - let’s be nice to them). What if everyone starts to do this (from forums/blogs I see a lot of doing like it)?
Final score: doable, but costly
Solution #2 (not possible) - trigger build at the exact time
Only thing, we need to know WHEN.
When can be defined as:
closest datetime from a merged array of - all published posts expiry dates + all future posts publish dates
.
If this WHEN is written in a public location, then remote trigger could GET it, compare times and if required, do POST trigger for a build.
Getting soonest expiry date is kinda easy by doing range on all posts, some ifs, something like that. Now comes the real problem - getting to loop over future posts publish dates. During a normal build, Hugo excludes the future posts.
I have considered the following workarounds:
-
One could enable --buildFuture
, but then future posts should be hidden, so need to edit the whole theme to exclude them again from every location including sitemaps, tags etc. What if the theme is an external dependency?
-
On CD/CI do a separate build step with --buildFuture
on different destination directory for the sole purpose of getting the future posts publishing dates, output in file. Then copy this info to /public/
-
On CD/CI perform command line hugo list future
which outputs paths to .md files, then read/regex content for expirydate
. Consider different front-matter syntaxes (yaml/toml/json). Again output results in /public/
location.
All of those are tedious, kind of fragile and hard hack-arounds. But if working, then external task could read those public dates (depending on output success/format) and do its logic.
Summary:
Pros:
- Precision possible up to few minutes even with a static generated site
- The low cost to execute
- Can bring the solution on any site/theme without rewriting it
Cons:
- Requires little of code setup for both site build and remote checker
Final score: almost there, if just had future on my hands