Brand-first slide deck library. Full creative control, zero abstraction tax.
Project description
openslides
Brand-first Python slide deck generator. Create pitch decks, investor presentations, and sales slides with full creative control. Extract brand colors and fonts from any website, write HTML/CSS slides, export to PNG or PDF.
Generate professional slide decks programmatically. No templates, no themes, no fighting the framework.
from openslides import Brand, export, base_html
brand = Brand.from_domain("scaile.tech") # Auto-extract colors, fonts, logo
def slide_hero():
return f'''
{base_html(brand)}
<body style="background:{brand.background}; padding:80px;">
<h1 style="font-family:'{brand.font_headline}'; font-size:72px; color:{brand.text};">
Get into <span style="color:{brand.primary};">ChatGPT</span> answers.
</h1>
</body></html>
'''
export([slide_hero()], "/tmp/my-deck/") # → PNG files
Why openslides?
Most slide libraries force you into preset themes that never match your brand. You end up fighting the abstraction.
openslides is different:
- Brand-first: Extract colors/fonts from any website, or define manually
- Full control: You write HTML/CSS, the library just helps with boilerplate
- No magic: Brand values are explicit in your code, not hidden in themes
- ~300 lines: Simple enough to understand in 10 minutes
Install
pip install openslides
playwright install chromium
# Optional: for brand extraction from URLs
pip install aiohttp
Quick Start
Option 1: Extract brand from website
from openslides import Brand, export, base_html
# Auto-extract colors, fonts, logo from website
brand = Brand.from_domain("stripe.com")
print(brand.primary) # "#635bff"
print(brand.font_headline) # "Inter"
Option 2: Define brand manually
brand = Brand(
primary="#054dfe", # Main accent (CTAs, highlights)
secondary="#15aebf", # Secondary accent
background="#fdfbf5", # Slide background
surface="#ffffff", # Cards, elevated surfaces
text="#191919", # Primary text
muted="#6b6b6b", # Secondary text
font_headline="Syne", # Headlines
font_body="Inter", # Body text
)
Create slides
Each slide is a function returning HTML. Use f-strings to inject brand values:
def slide_hero():
return f'''
{base_html(brand)}
<body style="background:{brand.background}; padding:80px;">
<div style="font-size:12px; color:{brand.primary}; text-transform:uppercase; letter-spacing:2px;">
The Problem
</div>
<h1 style="font-family:'{brand.font_headline}'; font-size:64px; color:{brand.text}; margin-top:20px;">
Your buyers don't Google anymore.
<span style="color:{brand.muted};">They ask ChatGPT.</span>
</h1>
</body></html>
'''
def slide_solution():
return f'''
{base_html(brand)}
<body style="background:{brand.surface}; padding:80px;">
<h1 style="font-family:'{brand.font_headline}'; font-size:64px;">
We make AI recommend <span style="color:{brand.primary};">your brand.</span>
</h1>
</body></html>
'''
Export to PNG/PDF
slides = [slide_hero(), slide_solution()]
# Export to PNG (default)
paths = export(slides, "/tmp/my-deck/")
# Creates: /tmp/my-deck/slide-01.png, slide-02.png, ...
# Export to PDF
paths = export(slides, "/tmp/my-deck/", format="pdf")
# Or use convenience function:
paths = export_pdf(slides, "/tmp/my-deck/")
CLI
Build decks from the command line:
# Build to PNG
openslides build examples/scaile.py -o /tmp/scaile-deck/
# Build to PDF
openslides build examples/scaile.py -o /tmp/scaile-deck/ -f pdf
# List slides in a deck file
openslides list examples/scaile.py
# Custom dimensions
openslides build examples/scaile.py -W 1280 -H 720
API Reference
Brand
Dataclass holding brand assets.
Attributes:
primary- Main accent color (hex)secondary- Secondary accent colorbackground- Slide background colorsurface- Card/surface backgroundtext- Primary text colormuted- Secondary/muted text colorfont_headline- Headline font familyfont_body- Body text font familylogo_svg- Logo as inline SVG (optional)logo_url- Logo URL (optional)name- Brand namedomain- Source domain
Validation:
- Color fields must be valid hex colors (e.g.,
#054dfeor#fff) - Invalid colors raise
ValueError
Methods:
Brand.from_domain(url)- Extract brand from website (requires aiohttp)brand.google_fonts_url- Google Fonts URL for brand fonts
base_html(brand)
Generate HTML boilerplate with brand fonts loaded. Returns everything up to <body>.
base_html(brand)
# Returns: <!DOCTYPE html><html>...<head>...<link href="fonts.googleapis.com/...">...</head>
base_styles(brand)
Generate common CSS classes using brand values. Use inside a <style> tag.
f'<style>{base_styles(brand)}</style>'
# Provides: .headline, .body-text, .muted, .accent, .card, .label, .btn
export(slides, output_dir, format="png")
Export slides to PNG or PDF files.
paths = export(slides, "/tmp/deck/", width=1920, height=1080)
paths = export(slides, "/tmp/deck/", format="pdf")
export_pdf(slides, output_dir)
Convenience wrapper for PDF export.
paths = export_pdf(slides, "/tmp/deck/")
export_async(slides, output_dir, format="png")
Async version of export. Use if already in async context.
Logo Helpers
clearbit_logo(domain, size=40) - Get logo img tag via Clearbit (free, no auth):
from openslides import clearbit_logo
logo = clearbit_logo("stripe.com", size=40)
# Returns: <img src="https://logo.clearbit.com/stripe.com" alt="logo" style="height:40px;" />
brand.logo_img(size=40) - Get logo from Brand (uses logo_svg, logo_url, or Clearbit fallback):
logo = brand.logo_img(size=48)
# Uses: brand.logo_svg if set, else brand.logo_url, else Clearbit
brand.clearbit_logo_url - Direct Clearbit URL:
url = brand.clearbit_logo_url
# Returns: "https://logo.clearbit.com/{domain}"
Philosophy
The best slide decks are brand-specific, not generic. openslides gives you:
- Brand extraction - Get colors/fonts from any website
- Explicit values - Brand values visible in your code
- Full control - Write whatever HTML/CSS you want
- Simple export - Playwright renders to PNG
No themes. No components. No fighting the framework.
License
MIT
Project details
Release history Release notifications | RSS feed
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 openslides_ai-1.0.0.tar.gz.
File metadata
- Download URL: openslides_ai-1.0.0.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19caa09a50c38fcdf34529ce87d90561e42827ba74b7ead5ce5833f5a886dae2
|
|
| MD5 |
1f0b9d981dd31a92f676e7e7fd3c8460
|
|
| BLAKE2b-256 |
ab693c4da85a69f6549b2b2f24cbfc05f4d0f2b9bf8722a44849745d0fa98ee9
|
File details
Details for the file openslides_ai-1.0.0-py3-none-any.whl.
File metadata
- Download URL: openslides_ai-1.0.0-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
698d4453333b80da330882b13a67fdeb6e3926014b2a6876b33af9e151ff4e82
|
|
| MD5 |
e568adcf8d3c35d8c4354c3f4e795d25
|
|
| BLAKE2b-256 |
1b000f16f7aa93e5b406de2a4684571df600faeef66250766e257a05b6c9e241
|