Metadata-Version: 2.5
Name: wagtail-roost
Version: 0.3.5
Summary: News/blog app for Wagtail: sections, articles, authors, tags and RSS feeds.
Project-URL: Repository, https://codeberg.org/Lupus/wagtail-roost
Author-email: Stjepan Zlodi <lupus@lupus.hr>
License: BSD-3-Clause
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Wagtail
Classifier: Framework :: Wagtail :: 7
Classifier: Framework :: Wagtail :: 8
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Requires-Dist: django>=5.0
Requires-Dist: wagtail>=7.0
Description-Content-Type: text/markdown

# wagtail-roost

News and blog publishing for [Wagtail](https://wagtail.org): sections,
articles, authors, tags and RSS feeds.

## Features

- **Sections and subsections** — organise your news into sections,
  nested as deep as you like. Each section has its own landing page
  and a browsable date archive (daily, weekly or monthly — your
  choice per section).
- **Articles** — rich article pages with authors, tags and
  hand-picked related articles.
- **Author profiles** — every author gets a profile page with their
  articles.
- **Tag pages** — every tag gets its own landing page with a
  description and image.
- **RSS feeds** — for all articles, per section, per tag and per
  author, with an on/off switch on each section, tag and author.
- **Navigation menus** — build multi-level menus in the admin and
  render them anywhere with a template tag.
- **Search-engine and social ready** — articles and author profiles
  include structured data (JSON-LD) for Google News and rich search
  results, and every page carries Open Graph and Twitter card tags so
  shared links unfurl with title, description and image.
- **Bring your own design** — the bundled templates are minimal
  semantic HTML, meant to be overridden to match your site.

## Install

```bash
# from PyPi
uv add wagtail-roost   # or: pip install wagtail-roost 

# or straight from the repository:
uv add git+https://codeberg.org/Lupus/wagtail-roost.git
```

Add to `INSTALLED_APPS`:

```python
INSTALLED_APPS = [
    "roost",
    "wagtail.contrib.redirects",
    "wagtail.contrib.routable_page",
    "wagtail.contrib.table_block",
    "wagtail.embeds",
    "wagtail.sites",
    "wagtail.users",
    "wagtail.snippets",
    "wagtail.documents",
    "wagtail.images",
    "wagtail.admin",
    "wagtail",
    "modelcluster",
    "taggit",
    # ... plus the django.contrib apps every Django project has ...
]
```

On top of a standard Wagtail install, roost needs
`wagtail.contrib.routable_page` (section, tag and author URLs),
`wagtail.contrib.table_block` and `wagtail.embeds` (article body
blocks) and `wagtail.snippets` (authors, tags and navigations).

Wire up Wagtail's URLs in your project's `urls.py`:

```python
from django.urls import include, path

from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.documents import urls as wagtaildocs_urls

urlpatterns = [
    ...
    path("admin/", admin.site.urls),  # existing
    path("cms/", include(wagtailadmin_urls)),
    path("documents/", include(wagtaildocs_urls)),
    path("", include(wagtail_urls)),  # must be LAST — catch-all
]
```

Also make sure these standard Wagtail settings are set:

```python
WAGTAIL_SITE_NAME = "My News Site"
WAGTAILADMIN_BASE_URL = "https://www.example.com"
```

`WAGTAIL_SITE_NAME` is the default publisher name in structured data,
and `WAGTAILADMIN_BASE_URL` is needed to build absolute URLs.

Run `python manage.py migrate`.

> **Note: `treebeard.E001` warning.** You may see a `treebeard.E001`
> system check warning. This is a known false positive from the
> Wagtail 7.x + django-treebeard 5.x combination — django-treebeard
> added this check, and Wagtail's own Page/Collection managers
> trigger it even though Wagtail handles it correctly internally.
> It's noise coming from library code, not yours. Wagtail's
> recommended workaround is to silence it:
>
> ```python
> SILENCED_SYSTEM_CHECKS = ["treebeard.E001"]
> ```

Then, in the Wagtail admin: create a **News index** page (the home of
all news, tag pages and the global feed), add **Section** pages under
it, and write **Article** pages inside sections. Add an **Author
index** page to publish author profiles.

Tip: to get URLs that start with the section slug (`/politics/…`
rather than `/news/politics/…`), make the News index your site's
root page (Settings → Sites). The root page's own slug never appears
in URLs.

## Navigation

Create a **Navigation** snippet in the admin and give it a code.
Menus can have as many levels as you need — links to pages or
external URLs, grouped under dropdowns, with whole navigations
nestable inside each other.

Render a navigation by its code:

```html
{% load roost_tags %}
{% navigation "main" %}
```

## Sitemap

Sitemap includes: news index, section, and article pages (via
`wagtail.contrib.sitemaps.Sitemap`); tag pages (`roost.sitemaps.TagSitemap`);
author profile pages (`roost.sitemaps.AuthorSitemap`).

Wire them together in your `urls.py`:

```python
from wagtail.contrib.sitemaps import views as sitemap_views
from wagtail.contrib.sitemaps.sitemap_generator import Sitemap as WagtailPageSitemap

from roost.sitemaps import AuthorSitemap, TagSitemap

sitemaps = {
    "pages": WagtailPageSitemap,
    "tags": TagSitemap,
    "authors": AuthorSitemap,
}

urlpatterns += [
    path("sitemap.xml", sitemap_views.sitemap, {"sitemaps": sitemaps}, name="sitemap"),
]
```

Requires `wagtail.contrib.sitemaps` and `django.contrib.sitemaps` in
`INSTALLED_APPS`.

Archive bucket pages are intentionally left out of the sitemap — they
are non-canonical listing views of articles that are already covered
by their own entries.

## Settings

All optional, set in your Django settings:

| Setting | Default | Purpose |
|---|---|---|
| `ROOST_TAG_RSS_DEFAULT` | `True` | whether new tags start with their feed enabled |
| `ROOST_ARCHIVE_GRANULARITY_DEFAULT` | `"month"` | default archive period for new sections |
| `ROOST_FEED_LIMIT` | `10` | max items per feed |
| `ROOST_LATEST_COUNT` | `10` | articles shown on landing pages |
| `ROOST_PUBLISHER_NAME` | Wagtail site name | publisher name in structured data |
| `ROOST_PUBLISHER_LOGO` | `None` | publisher logo URL in structured data (required for Google News rich results) |
| `ROOST_SOCIAL_NETWORKS` | built-in list | networks offered for author social links (default: Bluesky, Facebook, Instagram, LinkedIn, Mastodon, Website, X, YouTube) |

## Templates

Templates extend `base.html` from your project and expect `title`,
`meta`, `extra_head` and `content` blocks. Override any of them under
`roost/` in your own templates directory.

When starting a new project, the best practice is to copy the roost
templates into that project and adapt them there — they're meant as
a starting point for your own design, and having them in your project
makes them easy to edit and keeps your markup under version control.

Because the markup is plain semantic HTML, a lightweight stylesheet
is enough for a decent default look — the bundled demo project simply
links [Pico CSS](https://picocss.com) in its `base.html`.

## Development

Uses [uv](https://docs.astral.sh/uv/) — no manual venv or activation
needed:

```bash
uv sync                                    # create .venv, install everything
uv run pytest                              # run the test suite
uv run testproject/manage.py migrate       # set up the demo project
uv run testproject/manage.py runserver
uv build                                   # build sdist + wheel
uv publish                                 # release to PyPI
```
