@misar/blog (1.4.0)

Published 2026-10-30 10:10:05 +00:00 by misaradmin

Installation

@misar:registry=
npm install @misar/blog@1.4.0
"@misar/blog": "1.4.0"

About this package

@misar/blog

The /blogs list and article pages for any Misar product site, rendered on that site's own domain from api.misar.io/io/blog/*.

Each product shows its own MisarBlog author's articles, and that product's URL is the canonical one:

platform MisarBlog author site
mail @misarmail misarmail.com
reach @misarreach misarreach.com
post @misarpost misarpost.com
seo @misarseo misarseo.com
dev @misar-dev misar.dev
ai @misar-ai misar.ai

misar-io stores them in product_blog_posts (filled hourly by /api/cron/product-blog-sync); misar.io's own /blogs (platform io) keeps reading the @misar company feed in blog_posts. A slug that is not that author's article is a 404 on the product. Publishing a product article means publishing it on misar.blog under the product's author account.

Next.js

// src/lib/blog.ts
import { createNextBlog } from "@misar/blog/next";
export const blog = createNextBlog({
  platform: "mail",
  siteUrl: "https://www.misarmail.com",
  productName: "MisarMail",
});
// src/app/blogs/page.tsx
import { blog } from "@/lib/blog";
export const revalidate = 3600;
export const generateMetadata = blog.generateIndexMetadata;
export default blog.IndexPage;

// src/app/blogs/[slug]/page.tsx
// No generateStaticParams/dynamicParams: if the root layout reads cookies()
// or headers() (most product layouts do), a prerendered route aborts at
// runtime ("changed from static to dynamic") and every article is a 500.
import { blog } from "@/lib/blog";
export const revalidate = 3600;
export const generateMetadata = blog.generatePostMetadata;
export default blog.PostPage;

// src/app/sitemap.ts — spread `await blog.sitemapEntries()` into the result.
/* globals.css, after @misar/ui/theme.css and base.css */
@import "@misar/blog/styles.css";

Other frameworks (TanStack Start)

Use createBlogApi, BlogIndexView / BlogPostView with your router's link as Link, and buildIndexMeta / buildPostMeta + toHeadTags for <head>. Nothing in the root entry imports next/*.

Canonical

canonical: "self" (default) makes each product the canonical home of its copy. canonical: "misar-io" points posts at misar.io and drops them from the product's sitemap.

In-house ads

Since 1.2.0 the index and post views render the Misar/Assisters house-ad network (HouseAdSlot, src/house-ads.ts). Posts get a card after the article body and a sticky card in the right rail; the index gets a card above the grid. Each ad promotes another Misar or Assisters product — never the blog's own (PLATFORM_PRODUCT) — with its exact brand name, its www. domain and a "7 Days Free Trial" CTA to that product's /pricing, tagged utm_source=<platform>_blog&utm_medium=house_ad&utm_campaign=<placement>. The pick is deterministic per page, so markup is stable and cacheable.

createNextBlog({ ...site, ads: false });                       // off
createNextBlog({ ...site, ads: { exclude: ["assisters-dev"] } }); // narrow

The creatives use Tailwind classes from this package: a site that does not already scan it needs @source "<path>/packages/blog/src/**/*.{ts,tsx}" (or the published styles.css, which does it).

Podcast episode embeds (1.4.0)

When api.misar.io/io/blog/posts/<slug> returns podcast_spotify_episode_id, podcast_apple_show_id + podcast_apple_track_id and/or youtube_video_id, the post view renders the episode above the article: the Apple Podcasts player on Apple devices (iPhone, iPad, Mac, iPadOS desktop UA), Spotify elsewhere, with a "Switch to ..." link when both exist; the plain <audio> for podcast_audio_url when there is no platform id; nothing otherwise. The choice is made in the browser (Cloudflare caches the HTML) behind a fixed-height placeholder (152px Spotify, 175px Apple). All new response fields are optional, so older API responses keep rendering as before.

A consuming site's Content-Security-Policy must allow the embeds:

frame-src https://open.spotify.com https://embed.podcasts.apple.com https://www.youtube-nocookie.com;
media-src https://*.misar.io;   # the <audio> fallback (mp3 host)

Dependencies

Dependencies

ID Version
highlight.js ^11.12.0
html-react-parser ^6.1.8
lucide-react ^0.577.0

Development dependencies

ID Version
@misar/ui 1.10.0
@types/react ^19.3.0
next 15.5.28
react ^19.3.1
react-dom ^19.3.1
tsup ^8.5.1
typescript ^5.9.3

Peer dependencies

ID Version
@misar/ui >=1.4.0
next >=15.5.28
react ^18.0.0 || ^19.0.0
Details
npm
2026-10-30 10:10:05 +00:00
74
latest
68 KiB
Assets (1)
Versions (7) View all
1.4.0 2026-10-30
1.3.1 2026-10-22
1.2.0 2026-10-21
1.1.0 2026-10-21
1.0.2 2026-10-17