# Mishka Blog v0.0.1 - API Reference

## Modules

- [MishkaBlog](MishkaBlog.md): The blog's Ash domain: posts, collections, tags, bloggers and teams with their followers, comments,
ratings, bookmarks and views, and auto posting, and the JSON:API routes that serve them to a
master, to a site's admin and to a visitor.
- [MishkaBlog.Application](MishkaBlog.Application.md): The blog's OTP application. It supervises the task supervisor that highlights a post's code blocks
and every mishka_installer plugin the extension ships (`plugins/0`): the dashboard widgets, the
notification producers, the settings, sidebar, install, SEO, share card, stylesheet and page
plugins. A plugin registers on the event it listens on once it is supervised here.

- [MishkaBlog.AutoPosting](MishkaBlog.AutoPosting.md): Manages auto-posting configurations in the MishkaBlog plugin with full versioning support.
- [MishkaBlog.AutoPosting.Version](MishkaBlog.AutoPosting.Version.md): 
- [MishkaBlog.BlogPost](MishkaBlog.BlogPost.md): Manages blog posts in the MishkaBlog plugin with full versioning and translation support.
- [MishkaBlog.BlogPost.Version](MishkaBlog.BlogPost.Version.md): 
- [MishkaBlog.Blogger](MishkaBlog.Blogger.md): Manages blogger profiles in the MishkaBlog plugin with full versioning support.
- [MishkaBlog.Blogger.Version](MishkaBlog.Blogger.Version.md): 
- [MishkaBlog.BloggerFollower](MishkaBlog.BloggerFollower.md): Manages user follows for bloggers.
- [MishkaBlog.Collection](MishkaBlog.Collection.md): Manages blog post collections in the MishkaBlog plugin with full versioning support.
- [MishkaBlog.Collection.Version](MishkaBlog.Collection.Version.md): 
- [MishkaBlog.Comment](MishkaBlog.Comment.md): Manages blog post comments in the MishkaBlog plugin with full versioning support.
- [MishkaBlog.CommentVote](MishkaBlog.CommentVote.md): Manages user votes (upvote/downvote) on comments.
- [MishkaBlog.Dashboard.Analytics](MishkaBlog.Dashboard.Analytics.md): Every number on the blog analytics page (`/admin/dashboard/blog/analytics`), read from the database.
- [MishkaBlog.Dashboard.Overview](MishkaBlog.Dashboard.Overview.md): Every number on the blog admin overview page (`/admin/dashboard/blog`), read from the database.
- [MishkaBlog.Dashboard.Scope](MishkaBlog.Dashboard.Scope.md): Every read of the blog dashboard — `MishkaBlog.Dashboard.Overview`,
`MishkaBlog.Dashboard.Analytics` and the widgets under `MishkaBlog.Dashboard.Widgets` — as the
user viewing it, through the resource's own policies.
- [MishkaBlog.Dashboard.WidgetSettings](MishkaBlog.Dashboard.WidgetSettings.md): Registers every mishka_blog dashboard widget's own settings with the Settings page through the
`settings:register` mishka_installer hook — so "Posts to show" is documented under the **Blog** tab
(`category: "blog"`, group **Dashboard widgets**) alongside the rest of the blog's settings,
instead of hiding inside the dashboard's per-user layout where nothing else could see it.
- [MishkaBlog.Dashboard.Widgets.Bloggers](MishkaBlog.Dashboard.Widgets.Bloggers.md): Dashboard widget (a `dashboard:widgets` plugin): the top bloggers leaderboard — a podium of the
three most-published profiles plus the runners-up, each with their post tally and publish role
(`Blogger` + the `post_count` aggregate), read as the viewer through `MishkaBlog.Dashboard.Scope`:
a master ranks bloggers across every site, a site's admin only their own site's, and a viewer
without `admin:dashboard:blog:post` none.
- [MishkaBlog.Dashboard.Widgets.CommentsModeration](MishkaBlog.Dashboard.Widgets.CommentsModeration.md): Dashboard widget (a `dashboard:widgets` plugin): comments awaiting moderation — a pending count
plus the latest few with an excerpt of their content (`Comment`), read as the viewer through
`MishkaBlog.Dashboard.Scope`: a master moderates across every site, a site's admin only their own
site's, and a viewer without `admin:dashboard:blog:comment` none. Each author is named as the
comments page names them (`MishkaBlogWeb.Templates.CommentCard.author/1`), from what the viewer
may read of the account.
- [MishkaBlog.Dashboard.Widgets.DraftsScheduled](MishkaBlog.Dashboard.Widgets.DraftsScheduled.md): Dashboard widget (a `dashboard:widgets` plugin): draft vs scheduled post counts plus the latest
unpublished posts — drafts with their age, scheduled posts with their publish time (`BlogPost`),
read as the viewer through `MishkaBlog.Dashboard.Scope`: a master sees every site's pipeline, a
site's admin only their own site's, and a viewer without `admin:dashboard:blog:post` none.
- [MishkaBlog.Dashboard.Widgets.RecentPosts](MishkaBlog.Dashboard.Widgets.RecentPosts.md): Dashboard widget (a `dashboard:widgets` plugin): the latest blog posts with their status, read as
the viewer through `MishkaBlog.Dashboard.Scope`: a master sees every site's posts, a site's admin
only their own site's, and a viewer without `admin:dashboard:blog:post` none.
- [MishkaBlog.Dashboard.Widgets.TopPosts](MishkaBlog.Dashboard.Widgets.TopPosts.md): Dashboard widget (a `dashboard:widgets` plugin): the most-viewed published posts with their view
tally (`BlogPost` + the `view_count` aggregate), read as the viewer through
`MishkaBlog.Dashboard.Scope`: a master ranks posts across every site, a site's admin only their
own site's, and a viewer without `admin:dashboard:blog:post` none.
- [MishkaBlog.Dev.Generator](MishkaBlog.Dev.Generator.md): Generator for MishkaBlog resources.
- Test functions (no prefix): simple, deterministic — used by factory and tests.
- Dev functions (dev_ prefix): realistic, rich data — used by dev seeds.

- [MishkaBlog.Dev.Seeds](MishkaBlog.Dev.Seeds.md): Dev and stress seeds for MishkaBlog resources.
- [MishkaBlog.Kit](MishkaBlog.Kit.md): Where this extension's UI kit bundle is, and how to install it.
- [MishkaBlog.Notifiers.NotifySettings](MishkaBlog.Notifiers.NotifySettings.md): Registers mishka_blog's notification toggles with the Settings page through the `settings:register`
mishka_installer hook. Each toggle is a boolean (default on) under the **Blog** tab (`category: "blog"`)
in a **Notifications** group (`group:`), with `scope: :both` — a global default (shown in the master's
Global view) that any site may override. Every mishka_blog setting lives under the Blog tab; `group`
separates concerns within it (Notifications, and e.g. AI later).
Delivery honours it: the engine gates every notification on
`Settings.get(Notify.setting_key(type), true, site_id)` (site → global → default) before fanning it out.
- [MishkaBlog.Notifiers.PostMasterPublished](MishkaBlog.Notifiers.PostMasterPublished.md): The master half of `MishkaBlog.Notifiers.PostPublished`. A master publishes through
`:master_publish`, which fires `blog:blog_post:after_master_publish` — not the tenant action's
event — so without a plugin here a post a master published would tell nobody. It delivers exactly
what a tenant publish delivers, to the same audience. Registered in `MishkaBlog.Application`.

- [MishkaBlog.Notifiers.PostPublished](MishkaBlog.Notifiers.PostPublished.md): A plain mishka_installer plugin: when a tenant publishes a blog post
(`blog:blog_post:after_publish`), notify the tenant's blog admins AND master admins — in one
`Notify.deliver/3` call — except the publisher themselves (the notifier's `meta.actor`, passed as
`except:`), so no one is told about their own post.
- [MishkaBlog.PageSource](MishkaBlog.PageSource.md): The rows a page of the blog is made of, read once for the request and handed to everything that
draws them: the head (`MishkaBlog.Plugins.PageSeo`), the frame (`MishkaBlog.Plugins.PageFrame`)
and the page's blocks.
- [MishkaBlog.Plugins.BloggerShareCard](MishkaBlog.Plugins.BloggerShareCard.md): A plain mishka_installer plugin: after a blogger is saved (`blog:blogger:after_save` — created, updated or
published, a master's twin alike), its share card is looked at in the background and drawn when
what it shows changed (`MishkaCmsCore.Runtime.ShareCard.refresh/3`), so it is ready before the
first visitor. Only while it is not archived (`MishkaBlog.ShareCards.target/1`). Registered in
`MishkaBlog.Application`.

- [MishkaBlog.Plugins.CollectionShareCard](MishkaBlog.Plugins.CollectionShareCard.md): A plain mishka_installer plugin: after a category is saved (`blog:collection:after_save` — created, updated or
published, a master's twin alike), its share card is looked at in the background and drawn when
what it shows changed (`MishkaCmsCore.Runtime.ShareCard.refresh/3`), so it is ready before the
first visitor. Only while it is active (`MishkaBlog.ShareCards.target/1`). Registered in
`MishkaBlog.Application`.

- [MishkaBlog.Plugins.ContentComponents](MishkaBlog.Plugins.ContentComponents.md): Tells a site's stylesheet which components its posts draw, which icons they name and which
classes they write, through the `runtime:compile:content_components` hook
`MishkaCmsCore.Runtime.Compilers.TailwindCompiler.content_components/1` fires while it builds a
site's stylesheet: the names the site's published posts list in `content_components`, the icon
classes they list in `content_icons` and the classes they list in `content_classes`, which
`MishkaBlog.Resources.Changes.ContentFacts` stores when a post is written. A template that draws a
post's body — the kit's `blog-post-detail` — then reaches those components and no others
(`MishkaCmsCore.Runtime.Compilers.CssClosure`), the stylesheet carries a rule for each icon, and
it is built with each class.
- [MishkaBlog.Plugins.Installer](MishkaBlog.Plugins.Installer.md): Installs the blog onto one site, when asked.
- [MishkaBlog.Plugins.PageFrame](MishkaBlog.Plugins.PageFrame.md): What the blog tells the site's layout about each of its pages, through the `runtime:page:frame`
mishka_installer hook `MishkaCmsCore.Runtime.SiteLayout` fires in `handle_params/3`: the bar under
the header, and the languages the record a page shows is written in. The layout draws both, so no
page of the blog draws a bar or a language switcher of its own.
- [MishkaBlog.Plugins.PageRecords](MishkaBlog.Plugins.PageRecords.md): Names the kinds of record the blog's pages show — a post, a collection, a tag, a blogger, a team —
on the `runtime:page:records` mishka_installer hook, for a page's "This page shows each" choice
(see `MishkaCmsCore.Runtime.Seo.record_types/1`), each with a few of the site's own to preview a
page with. Each is labelled as the blog's admin names it, where its Permissions and SEO Tags are set.
`MishkaBlog.Plugins.PageSeo` answers for the same kinds.
- [MishkaBlog.Plugins.PageSeo](MishkaBlog.Plugins.PageSeo.md): Gives each post, category, tag, blogger and team its own head on the blog page that serves it,
through the
`runtime:page:seo` mishka_installer hook `MishkaCmsWeb.RuntimeLive` fires in
`handle_params/3` (see `MishkaCmsCore.Runtime.Seo` for the map it is handed and what the head
builds from it).
- [MishkaBlog.Plugins.PageSource](MishkaBlog.Plugins.PageSource.md): Reads the rows a page of the blog shows, once, through the `runtime:page:source` mishka_installer
hook `MishkaCmsWeb.RuntimeLive` fires in `handle_params/3` before the frame and the head
(`MishkaCmsCore.Runtime.PageSource` is the contract: the map it is handed and where what it reads
goes).
- [MishkaBlog.Plugins.PostShareCard](MishkaBlog.Plugins.PostShareCard.md): A plain mishka_installer plugin: after a post is saved (`blog:blog_post:after_save` — created, updated or
published, a master's twin alike), its share card is looked at in the background and drawn when
what it shows changed (`MishkaCmsCore.Runtime.ShareCard.refresh/3`), so it is ready before the
first visitor. Only while it is published (`MishkaBlog.ShareCards.target/1`). Registered in
`MishkaBlog.Application`.

- [MishkaBlog.Plugins.ShareCardTargets](MishkaBlog.Plugins.ShareCardTargets.md): A plain mishka_installer plugin: answers `MishkaCmsCore.Runtime.ShareCard.targets_event/0` with
the blog's share cards on the site asked, under `"mishka_blog"` (`MishkaBlog.ShareCards.targets/1`),
so a redraw of every card of a site — and the blog's own Redraw button in its check-and-repair
modal — reaches its posts, categories, tags, bloggers and teams. Registered in
`MishkaBlog.Application`.

- [MishkaBlog.Plugins.SitemapUrls](MishkaBlog.Plugins.SitemapUrls.md): Adds the blog's posts, categories, bloggers, teams and the tags that ask to be indexed to a
site's `/sitemap.xml`, through the
`seo:sitemap:urls` mishka_installer hook `MishkaCmsCore.Runtime.Compilers.SitemapCompiler` fires
when it builds a site's sitemap. A post, a category, a tag, a blogger or a team written rebuilds its
site's sitemap, because those resources list
`MishkaCmsCore.Runtime.Resources.Notifiers.SitemapRefresh`.
- [MishkaBlog.Plugins.TagShareCard](MishkaBlog.Plugins.TagShareCard.md): A plain mishka_installer plugin: after a tag is saved (`blog:tag:after_save` — created, updated or
published, a master's twin alike), its share card is looked at in the background and drawn when
what it shows changed (`MishkaCmsCore.Runtime.ShareCard.refresh/3`), so it is ready before the
first visitor. Only while it is not archived (`MishkaBlog.ShareCards.target/1`). Registered in
`MishkaBlog.Application`.

- [MishkaBlog.Plugins.TeamShareCard](MishkaBlog.Plugins.TeamShareCard.md): A plain mishka_installer plugin: after a team is saved (`blog:team:after_save` — created, updated or
published, a master's twin alike), its share card is looked at in the background and drawn when
what it shows changed (`MishkaCmsCore.Runtime.ShareCard.refresh/3`), so it is ready before the
first visitor. Only while it is active (`MishkaBlog.ShareCards.target/1`). Registered in
`MishkaBlog.Application`.

- [MishkaBlog.Plugins.TranslationKeys](MishkaBlog.Plugins.TranslationKeys.md): Names the words the blog's bar looks up (`MishkaBlog.Plugins.PageFrame.words/0`) on the
`runtime:translations:used_keys` mishka_installer hook `MishkaCmsCore.Runtime.Translations` fires
when it works out which keys a site still uses.
- [MishkaBlog.PostBlogger](MishkaBlog.PostBlogger.md): Manages the many-to-many relationship between blog posts and bloggers with full version control.
- [MishkaBlog.PostBookmark](MishkaBlog.PostBookmark.md): Manages user bookmarks for blog posts.
- [MishkaBlog.PostCollection](MishkaBlog.PostCollection.md): Manages the many-to-many relationship between blog posts and collections with full version control.
- [MishkaBlog.PostRating](MishkaBlog.PostRating.md): Manages user ratings for blog posts.
- [MishkaBlog.PostTag](MishkaBlog.PostTag.md): Manages the many-to-many relationship between blog posts and tags with full version control.
- [MishkaBlog.PostView](MishkaBlog.PostView.md): Tracks unique page views for blog posts using upsert.
- [MishkaBlog.Provision](MishkaBlog.Provision.md): What a site needs before anybody can look at its blog: this extension's live components, nine
sample pages built out of them, and the sidebar saved as a snippet an author can drop anywhere.
- [MishkaBlog.Repo](MishkaBlog.Repo.md)
- [MishkaBlog.Resources.Actions.PreviewVersion](MishkaBlog.Resources.Actions.PreviewVersion.md): Previews a record as it was in one of its own versions, without restoring it: the generic action
takes the record's id and a `:version_id` argument and returns the record with the version's
values over it.
- [MishkaBlog.Resources.Calculations.EffectivePermissions](MishkaBlog.Resources.Calculations.EffectivePermissions.md): The permissions a post or a category opens with on its blog page, in its sitemap entry and
wherever else a reader is let in, and those a comment is reached with
- [MishkaBlog.Resources.Changes.ContentFacts](MishkaBlog.Resources.Changes.ContentFacts.md): What a post's `content` says about it, worked out once, when the content is written — reading a
post works out neither
- [MishkaBlog.Resources.Changes.HighlightCode](MishkaBlog.Resources.Changes.HighlightCode.md): Highlights the code blocks of a post's `content` with Makeup, once, when the post is written.
- [MishkaBlog.Resources.Changes.PublishLifecycle](MishkaBlog.Resources.Changes.PublishLifecycle.md): Keeps a post's publish times in step with its `:status`.
- [MishkaBlog.Resources.Changes.RestoreVersion](MishkaBlog.Resources.Changes.RestoreVersion.md): Restores a record to one of its own versions, named by the action's `:version_id` argument.
- [MishkaBlog.Resources.Mixins.PaperTrailMixin](MishkaBlog.Resources.Mixins.PaperTrailMixin.md): The version resource a PaperTrail-tracked blog resource keeps its history in: the table, its
foreign key to the record, and the actions and policies that read the history.
- [MishkaBlog.Resources.Preparations.OpenToActor](MishkaBlog.Resources.Preparations.OpenToActor.md): Keeps a public read to the records its reader may open, by the rule the record's page keeps: a
record whose lock names permissions opens only for a reader holding one of them
(`AccessPermissions.match?/3`), and never for a visitor who is not signed in. A list leaves out,
in its own query, every record the reader may not open, so its pages and its count are of what
the reader sees; asking for one of them by itself finds nothing, as an id nothing is stored at
does.
- [MishkaBlog.Resources.Preparations.PreviewVersion](MishkaBlog.Resources.Preparations.PreviewVersion.md): Turns a read of one record into a preview of it as it was in one of its own versions, named by the
read's `:version_id` argument. Nothing is saved.
- [MishkaBlog.Resources.Preparations.ReaderLocks](MishkaBlog.Resources.Preparations.ReaderLocks.md): What a reader may open, as the filter of the read that fetches the records: the answer
`MishkaCmsCore.Accounts.Checks.AccessPermissions` gives for a record's lock, worked out by the
database in the statement that reads the rows, so that no lock is read beforehand.
- [MishkaBlog.Resources.Preparations.SiteAskedOn](MishkaBlog.Resources.Preparations.SiteAskedOn.md): Keeps a public list to the site it is asked on: only the rows whose `:through` record belongs to
the tenant.
- [MishkaBlog.Resources.Validations.NotItsOwnParent](MishkaBlog.Resources.Validations.NotItsOwnParent.md): Refuses an update that makes a record its own parent: the attribute `:field` may not hold the
record's own id. Any other record, or none, is let through. The refusal is `:message` on `:field`.
- [MishkaBlog.Resources.Validations.OpenToActor](MishkaBlog.Resources.Validations.OpenToActor.md): Refuses a write onto a record its actor may not open — a comment, a rating or a bookmark on a
locked post, a vote on a comment of one — with the message the action gives for a record that is
not there, so the refusal tells nothing a reader may not know. Who may open it is what its page
asks (`MishkaBlog.Resources.Preparations.OpenToActor.opens?/2`).
- [MishkaBlog.ShareCards](MishkaBlog.ShareCards.md): Which share card (`MishkaCmsCore.Runtime.ShareCard`) a blog record shows: the kind of record its
page shows (`MishkaBlog.Plugins.PageRecords`) and the captures that name it — what a page of that
kind answers for (`MishkaBlog.Plugins.PageSeo`).
- [MishkaBlog.Tag](MishkaBlog.Tag.md): Manages blog post tags in the MishkaBlog plugin with full versioning support.
- [MishkaBlog.Tag.Version](MishkaBlog.Tag.Version.md): 
- [MishkaBlog.Team](MishkaBlog.Team.md): Manages team structures in the MishkaBlog plugin with full versioning support.
- [MishkaBlog.Team.Version](MishkaBlog.Team.Version.md): 
- [MishkaBlog.TeamFollower](MishkaBlog.TeamFollower.md): Manages user follows for teams.
- [MishkaBlog.TeamMember](MishkaBlog.TeamMember.md): Manages the many-to-many relationship between teams and bloggers with full version control.
- [MishkaBlog.TeamPermission](MishkaBlog.TeamPermission.md): Manages the many-to-many relationship between teams and permissions.
- [MishkaBlogWeb.AshJsonApiRouter](MishkaBlogWeb.AshJsonApiRouter.md): The router the blog's JSON:API is served through, with its OpenAPI document at `/open_api`. The
domains it routes are set by the host application's config.

- [MishkaBlogWeb.Live.Admin.Dashboard.Analytics.Index](MishkaBlogWeb.Live.Admin.Dashboard.Analytics.Index.md): The blog analytics page: five KPI tiles, a daily views chart, the most-read posts, where their
readers came from and whether they were signed in — every figure read from the view log by
`MishkaBlog.Dashboard.Analytics`.
- [MishkaBlogWeb.Live.Admin.Dashboard.AutoPosting.Index](MishkaBlogWeb.Live.Admin.Dashboard.AutoPosting.Index.md): The auto posting list: a Gervaz table of the site's auto posting configurations. The page decodes
the URL state and, once connected, forwards the PubSub broadcasts of its site (every site for a
master) into the table component.
- [MishkaBlogWeb.Live.Admin.Dashboard.Blogger.Index](MishkaBlogWeb.Live.Admin.Dashboard.Blogger.Index.md): The bloggers grid: a Gervaz table drawn as `MishkaBlogWeb.Templates.BloggerCard`, its create/edit
form, and the version history of one blogger.
- [MishkaBlogWeb.Live.Admin.Dashboard.Collection.Index](MishkaBlogWeb.Live.Admin.Dashboard.Collection.Index.md): The collections grid: a Gervaz table drawn as `MishkaBlogWeb.Templates.CollectionCard`, its
create/edit form, a modal that edits one language edition of a collection, and the version history
of one collection, which switches between its language editions.
- [MishkaBlogWeb.Live.Admin.Dashboard.Comment.Index](MishkaBlogWeb.Live.Admin.Dashboard.Comment.Index.md): The comments list: a Gervaz table drawn as `MishkaBlogWeb.Templates.CommentCard`, with a create /
edit / reply form.
- [MishkaBlogWeb.Live.Admin.Dashboard.Home.Index](MishkaBlogWeb.Live.Admin.Dashboard.Home.Index.md): The blog admin overview: five KPI cards, eight section cards, an editorial calendar and three
summary panels, every number read from the database by `MishkaBlog.Dashboard.Overview`.
- [MishkaBlogWeb.Live.Admin.Dashboard.Post.Index](MishkaBlogWeb.Live.Admin.Dashboard.Post.Index.md): The blog posts list: a Gervaz table drawn as `MishkaBlogWeb.Templates.PostCard`, its create/edit
form, and the version history of one post.
- [MishkaBlogWeb.Live.Admin.Dashboard.Tag.Index](MishkaBlogWeb.Live.Admin.Dashboard.Tag.Index.md): The tags grid: a Gervaz table drawn as `MishkaBlogWeb.Templates.TagCard`, its create/edit
form, and the version history of one tag.
- [MishkaBlogWeb.Live.Admin.Dashboard.Team.Index](MishkaBlogWeb.Live.Admin.Dashboard.Team.Index.md): The teams grid: a Gervaz table drawn as `MishkaBlogWeb.Templates.TeamCard`, its create/edit
form, and the version history of one team.
- [MishkaBlogWeb.Live.Admin.Dashboard.VersionsModal](MishkaBlogWeb.Live.Admin.Dashboard.VersionsModal.md): The version history of a dashboard list page: a modal that lists one record's versions a page at a
time, previews one of them, and restores one. The page keeps the template, its `:versions_modal`
and the one-line event handlers; everything they do is here.
- [MishkaBlogWeb.Routes](MishkaBlogWeb.Routes.md): Extension routes for MishkaBlog.

- [MishkaBlogWeb.SidebarMenu](MishkaBlogWeb.SidebarMenu.md): The blog's admin pages and the one sidebar entry that links to them — a `"sidebar:menus"` plugin
(`MishkaCmsCore.Sidebar`).
- [MishkaBlogWeb.Templates.BloggerCard](MishkaBlogWeb.Templates.BloggerCard.md): The bloggers grid: one card per blogger, in as many columns as fit the screen.
- [MishkaBlogWeb.Templates.CollectionCard](MishkaBlogWeb.Templates.CollectionCard.md): The collections grid: one card per collection, in as many columns as fit the screen.
- [MishkaBlogWeb.Templates.CommentCard](MishkaBlogWeb.Templates.CommentCard.md): The comments list: one full-width row per comment, stacked.
- [MishkaBlogWeb.Templates.EditionChips](MishkaBlogWeb.Templates.EditionChips.md): The language chips of a translated blog record: one per edition, the record's own first, each
opening that edition.
- [MishkaBlogWeb.Templates.PostCard](MishkaBlogWeb.Templates.PostCard.md): The blog posts list: one full-width row per post, stacked.
- [MishkaBlogWeb.Templates.TagCard](MishkaBlogWeb.Templates.TagCard.md): The tags grid: one compact chip per tag, packed several to a row.
- [MishkaBlogWeb.Templates.TeamCard](MishkaBlogWeb.Templates.TeamCard.md): The teams grid: one card per editorial team, in as many columns as fit the screen.

