Drop-in blog integration for Django & Flask — powered by EarlySEO. Articles are served from EarlySEO's CDN. Just add your site ID and go.
Project description
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:
- Detects whether you're using Django or Flask
- Asks for your Site ID (from Dashboard → Integrations → SDK)
- Generates starter templates, URL config, and a
.envfile
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
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"
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://example.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.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file earlyseo_blog-1.0.5.tar.gz.
File metadata
- Download URL: earlyseo_blog-1.0.5.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using 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
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70d2c7c4ce29465441df788f0a99f4f3535e9b7659add92b2d7e645eeb725a51
|
|
| MD5 |
1e037ffd3a80f139a11c2af0e8f51f23
|
|
| BLAKE2b-256 |
86d0d41301486ff21c05277cabede9e5299838b4bacb1f4aae88204a01cfa4dc
|
File details
Details for the file earlyseo_blog-1.0.5-py3-none-any.whl.
File metadata
- Download URL: earlyseo_blog-1.0.5-py3-none-any.whl
- Upload date:
- Size: 22.1 kB
- Tags: Python 3
- Uploaded using 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
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
899c51d5d8e5cbb40f1bda30c1826fbb94b5bdcb7c4201b4cb3b45332170fc2b
|
|
| MD5 |
c9845d70e338d1479baad40958335dd9
|
|
| BLAKE2b-256 |
cf4f8d80233fd7803018fdcfb6c6a14626471186f54ab5ad77f48c4dc5cf57fd
|