Fully typed url builder, client and utilities for Blogger feeds
We ❤ Blogger
pnpm i blogger-feeds
<script type="module">
const { make } = await import("https://cdn.jsdelivr.net/npm/blogger-feeds@latest/core")
</script>
You can import just what you need to further tree-shake the package size
// Imports all at once
import * as BF from "blogger-feeds";
import {
make, // just the url builder function
} from "blogger-feeds/core";
import {
client, // just the client async generator
} from 'blogger-feeds/client';
import {
isoDate, // blogger-compatible date formatter
merge, // merges blogger feeds urls or configs
thumb, // remaps a blogger image url to a resized version
ytimg, // remaps a youtube url to its default hq thumbnail
} from "blogger-feeds/helpers";
This library serves a very specific use-case: read-only posts fetching on Blogger blogs, when the excellent Gapi + Blogger v3 api may be "overkill". In example when building a lightweight preact / alpinejs widget.
It's very a simple url builder function:
- builds on top of the native js URL interface
- takes a fully typed config object of blogger params
- validates them against Blogger conventions
- builds a native js URL to the requested resource
- explicits blogger defaults
- normalizes the url for cache consistency
An async function generator that:
- builds on top of the native
fetch()
api - lazily loops over all posts starting from input
- reuses Blogger's own pagination features
- can be used in a handy
for await ... of
loop - returns a fully-typed feed object (caveat)
- or a fully transparent error object
The url builder make()
at the core of the package works by itself, enforcing parameter-level validation and expliciting blogger defaults for url consistency (helping caches work).
You may use the client()
directly on a Blogger page with no additional setup. But in any other environment, since Blogger correctly enforces strict CORS headers, you are most likely to incur into cors issues. To avoid that:
- Blogger must be setup with a custom domain
- that domain should be sending proper CORS headers
To achieve this setup I am using Cloudflare's generous free plan, but any other solution is equally viable as long as it allows to enforce your own cors headers.
-
Please note that the Feed object is not the fetched data, but a simplified representation exposing:
- relevant meta data related to the request itself
- a flattened susbet of relevant resource data
-
Should you need to access raw feeds data, you may prefer to avoid the client and directly fetch the url.
-
No sanitization is applied to any content returned from Blogger feeds. Please make sure to sanitize post.body html output using an html sanitizer library (like dom-purify, sanitize-html, js-xss...)
//----------------------
// import what you need
//----------------------
import { make, client } from "blogger-feeds";
//----------------------
// build an url
//----------------------
const SinglePostUrl = make({
// you may pass "blogger" to get the blogger.com equivalent
blog: new URL("https://www.my-blogger.com"),
postId: "1234567", // at least 7 digits
// postId takes precedence over any other params
// all the rest will be ignored
});
// null if invalid config
console.log(SinglePostUrl?.href);
const PagedPostsUrl = make({
blog: new URL("https://www.my-blogger.com"),
// never pass a valid postId
// when you need a paginated list
// blogger's defaults will be added for consistency
// "max-results": defaults to 25
// "start-index": defaults to 1
// "orderby": defaults to "published"
});
console.log(PagedPostsUrl?.href);
//----------------------
// fetch a resource
//----------------------
// you may abort the client at any moment
const Aborter = new AbortController();
const DefaultClient = client({
make: {
// same config as make()
blog: new URL("https://www.my-blogger.com"),
},
opt: {
// custom fetch options
signal: Aborter.signal,
},
// cherry-pick meta or post props
keep: ["href", "title", "image"],
});
for await (const feed of DefaultClient) {
console.log(feed); // {meta: {...}, data: Array(25)}
// it loops as long as there are still posts to fetch
// take a look at meta.next
}
const PostClient = client({
// reuse this url
from: SinglePostUrl,
make: {
// with new params
postId: '9876543',
}
})
for await (const post of PostClient) {
console.log(post); // {meta: {...}, data: Array(1)}
// always 1 post in data array
}
This library is very opinionated, it was built to consolidate code patterns from custom Blogger widgets currently employed in public-facing production blogs.
I remark that it is not meant to replace GAPI client, but it's just a different approach to fetch published posts in a read-only scenario, heavily inspired by Blogger's own dynamic templates.
The library is neither affiliated or approved by Google Blogger