Skip to main content

earlyseo-blog

Drop-in blog integration for Django and Flask — powered by EarlySEO. Articles are authored in the EarlySEO dashboard and rendered in your Python web app.

Quick Start (Recommended)

The fastest way to get started — run the CLI from your project root:

pip install earlyseo-blog
earlyseo-blog

The CLI automatically:

  1. Detects whether you're using Django or Flask
  2. Asks for your Site ID (from Dashboard → Integrations → SDK)
  3. Generates starter templates, URL config, and a .env file

Run your dev server and visit /blog — your articles are live.


Manual Setup

If you prefer to configure things yourself:

Django

pip install "earlyseo-blog[django]"

settings.py

INSTALLED_APPS = [
    # …
    "earlyseo_blog.django",
]

EARLYSEO_SITE_ID = "your-site-id"   # from Dashboard → Integrations → SDK
# Optional: set your real domain only when you need absolute back links
# EARLYSEO_BASE_URL = "https://your-domain.com"

By default, /blog links back to the same-domain site root and /blog/<slug>/ links back to same-domain /blog. Set EARLYSEO_BASE_URL to force those links to an absolute real domain. Placeholder example.com values are ignored.

urls.py

from django.urls import include, path

urlpatterns = [
    path("blog/", include("earlyseo_blog.django.urls")),
]

Visit /blog to see your articles.

Template tags

Override the built-in HTML by creating your own templates:

<!-- templates/earlyseo/blog_list.html -->
{% extends "base.html" %}
{% load earlyseo %}

{% block extra_head %}{% earlyseo_styles %}{% endblock %}

{% block content %}
  {% for article in articles %}
    <h2><a href="{% url 'earlyseo_blog:blog_detail' slug=article.slug %}">{{ article.title }}</a></h2>
    <p>{{ article.meta_description }}</p>
  {% endfor %}
{% endblock %}

Available template tags: {% earlyseo_styles %}, {% earlyseo_article_css %}, {% earlyseo_article article %}.

Flask

pip install "earlyseo-blog[flask]"

app.py

from flask import Flask
from earlyseo_blog.flask.views import create_blog_blueprint

app = Flask(__name__)
app.config["EARLYSEO_SITE_ID"] = "your-site-id"
# Optional: set your real domain only when you need absolute back links/sitemaps
# app.config["EARLYSEO_BASE_URL"] = "https://your-domain.com"

app.register_blueprint(create_blog_blueprint(), url_prefix="/blog")

Override the built-in HTML by placing templates/earlyseo/blog_list.html and templates/earlyseo/blog_detail.html in your templates folder.


Sitemap

Django

Plug into Django's built-in sitemaps framework:

# settings.py
INSTALLED_APPS = [
    # …
    "django.contrib.sitemaps",
    "earlyseo_blog.django",
]
# urls.py
from django.contrib.sitemaps.views import sitemap
from earlyseo_blog.django.sitemap import EarlySeoBlogSitemap

sitemaps = { "blog": EarlySeoBlogSitemap }

urlpatterns = [
    path("blog/", include("earlyseo_blog.django.urls")),
    path("sitemap.xml", sitemap, {"sitemaps": sitemaps}, name="sitemap"),
]

Flask

Register a /blog/sitemap.xml route automatically:

from earlyseo_blog.flask.sitemap import register_blog_sitemap

app.config["EARLYSEO_BASE_URL"] = "https://your-domain.com"
register_blog_sitemap(app, url_prefix="/blog")

Or get entries for a custom sitemap:

from earlyseo_blog.flask.sitemap import create_blog_sitemap_entries

entries = create_blog_sitemap_entries(base_url="https://example.com")

Python Client

Use the client directly in any Python app:

from earlyseo_blog import EarlySeoClient

client = EarlySeoClient(site_id="your-site-id")

# List articles (page 1)
page = client.get_list_page(1)
for article in page.articles:
    print(article.title, article.slug)

# Get a single article
article = client.get_article("my-article-slug")
print(article.title)
print(article.content_html)

Async Client

from earlyseo_blog import AsyncEarlySeoClient

async def main():
    async with AsyncEarlySeoClient(site_id="your-site-id") as client:
        page = await client.get_list_page(1)
        article = await client.get_article("my-article-slug")

Install the async extra for HTTP/2 support:

pip install "earlyseo-blog[async]"

Models

All responses are validated with Pydantic v2:

Model Description
Manifest Site manifest with total pages/articles
ArticleListItem Summary for list views
ArticleListPage Paginated list of ArticleListItem
Article Full article with content_html
from earlyseo_blog.models import Article, Manifest

CSS

Built-in styles for article content and blog layout:

from earlyseo_blog.css import ARTICLE_CSS, BLOG_CSS

Include them in your <style> tag or template to get default styling.


Configuration

Setting Description Default
site_id Your EarlySEO site ID (required) —

Django: Set EARLYSEO_SITE_ID in settings.py.

Flask: Set in app.config["EARLYSEO_SITE_ID"].


Requirements

  • Python ≥ 3.9
  • httpx ≥ 0.24
  • pydantic ≥ 2.0
  • Django ≥ 4.2 (for Django integration)
  • Flask ≥ 2.3 (for Flask integration)

License

Proprietary — see LICENSE for details.

Metadata

Release files for earlyseo-blog 1.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for earlyseo-blog 1.0.7
File Size Uploaded
earlyseo_blog-1.0.7.tar.gz 17.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for earlyseo-blog 1.0.7
File Interpreter ABI Platform
earlyseo_blog-1.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 40.8 kB

Release files / earlyseo_blog-1.0.7.tar.gz

Download URL earlyseo_blog-1.0.7.tar.gz
Size 17.6 kB
Tags Source
SHA-256 checksum
How to use checksums
db989be239930d485fec20115ddcf1347a832bd2913fb498c45898149b8cd85b
BLAKE2b-256 checksum
How to use checksums
ab2a08d92eebd6aa5135e5f2763e8004d4097f81c1ba76efc299ac392e007e1f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.8.0 pkginfo/1.12.1.2 readme-renderer/42.0 requests/2.33.1 requests-toolbelt/1.0.0 urllib3/2.6.3 tqdm/4.67.3 importlib-metadata/9.0.0 keyring/25.7.0 rfc3986/2.0.0 colorama/0.4.6 CPython/3.11.10

Release files / earlyseo_blog-1.0.7-py3-none-any.whl

Download URL earlyseo_blog-1.0.7-py3-none-any.whl
Size 23.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d1151ecdb14a3fc278f8d78c42afa165975098d4901472022d2a19c80c53ea18
BLAKE2b-256 checksum
How to use checksums
e20f5b5030ca8c09d9236cb5d71bbb95e9a3fc859ddf6767dd21bf9b6df09acd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.8.0 pkginfo/1.12.1.2 readme-renderer/42.0 requests/2.33.1 requests-toolbelt/1.0.0 urllib3/2.6.3 tqdm/4.67.3 importlib-metadata/9.0.0 keyring/25.7.0 rfc3986/2.0.0 colorama/0.4.6 CPython/3.11.10

Release history Release notifications | RSS feed

This release

1.0.7 This release

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page