
Use this script if you want to display all your blog posts grouped by month.
Step 1: Create a new page
- Go to your Bear Blog dashboard
- Navigate to Pages → New Page
- Set the page slug to something like
archiveorblog(if blog is not your reserved blog path on bear)
Step 2: Add the post embed code
In the editor, add the post embed code:
<h2 class="archive">Loading posts...</h2>
{{posts}}
Why the placeholder header? The
<h2 class="archive">placeholder prevents layout shift (CLS) when the JavaScript runs.
Step 3: Add the JavaScript
You have two options:
Option 1: Inline minified script (easiest)
Add the JavaScript directly:
<h2 class="archive">Loading posts...</h2>
{{posts}}
<script>
(function(){'use strict';function groupPostsByMonth(){const postsList=document.querySelector('ul.embedded.blog-posts');if(!postsList)return;const listItems=Array.from(postsList.querySelectorAll('li'));if(listItems.length===0)return;const totalPosts=listItems.length;let lastUpdatedDate=null;let lastUpdatedDateString=null;const groupedPosts={};listItems.forEach(li=>{const timeElement=li.querySelector('time[datetime]');if(!timeElement)return;const dateString=timeElement.getAttribute('datetime');if(!dateString)return;const date=new Date(dateString);if(isNaN(date.getTime()))return;if(!lastUpdatedDate||date>lastUpdatedDate){lastUpdatedDate=date;lastUpdatedDateString=dateString}
const monthYear=date.toLocaleDateString('en-US',{month:'long',year:'numeric'});if(!groupedPosts[monthYear]){groupedPosts[monthYear]=[]}
groupedPosts[monthYear].push(li)});const monthDates={};Object.keys(groupedPosts).forEach(monthYear=>{const firstPost=groupedPosts[monthYear][0];const timeElement=firstPost.querySelector('time[datetime]');if(timeElement){const dateString=timeElement.getAttribute('datetime');const date=new Date(dateString);monthDates[monthYear]=date}});const sortedMonths=Object.keys(groupedPosts).sort((a,b)=>{const dateA=monthDates[a]||new Date(0);const dateB=monthDates[b]||new Date(0);return dateB-dateA});if(lastUpdatedDate&&lastUpdatedDateString){let header=postsList.parentNode.querySelector('h2.archive');if(!header){header=document.createElement('h2');header.className='archive';postsList.parentNode.insertBefore(header,postsList)}
const formattedDate=lastUpdatedDate.toLocaleDateString('en-US',{month:'long',day:'numeric',year:'numeric'});const span=document.createElement('span');span.id='last-updated';span.setAttribute('data-date',lastUpdatedDateString);span.textContent=formattedDate;header.textContent=`${totalPosts} entries. Last updated on `;header.appendChild(span);header.appendChild(document.createTextNode('.'))}
postsList.innerHTML='';sortedMonths.forEach(monthYear=>{const monthHeader=document.createElement('h3');monthHeader.className='archive-h3';monthHeader.textContent=monthYear;postsList.parentNode.insertBefore(monthHeader,postsList);const monthList=document.createElement('ul');monthList.className='blog-posts';groupedPosts[monthYear].forEach(li=>{monthList.appendChild(li)});postsList.parentNode.insertBefore(monthList,postsList)});if(postsList.parentNode&&postsList.children.length===0){postsList.remove()}}
if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',groupPostsByMonth)}else{groupPostsByMonth()}})()
</script>
Option 2: External script (better for reusability)
If you want to host the script elsewhere and load it:
- Upload the sort-posts-by-month.js to a CDN or your own hosting
- Replace the inline script with:
<h2 class="archive">Loading posts...</h2>
{{posts}}
<script src="https://your-domain.com/path/to/archive-sort.js"></script>
How it works
- Initial Load: Bear Blog renders all your posts using the
{{posts}}embed code - JavaScript Execution: When the page loads, the script:
- Finds all post list items
- Groups them by month and year
- Finds the most recent post date
- Creates a header showing total count and last updated date
- Reorganizes posts under month headers (newest months first)
- Removes the original flat list
The result
Your archive page will display like this:
{n} entries. Last updated on {lastUpdatedDate}.
November, 2025
- Post title 1
- Post title 2
October, 2025
- Post title 3
...
Customization
You can customize the styling by targeting .archive:
.archive {
margin-bottom: 2rem;
}
.archive-h3 {
margin-top: 2rem;
margin-bottom: 1rem;
}
.blog-posts {
list-style: none;
padding-left: 0;
}