Skip to main content

Generates daily AI art from Hacker News headlines using local Apple Silicon

Project description

HN Local Image

Generates a daily AI art piece based on the top stories currently on Hacker News, using 100% local Apple Silicon hardware.

This is a local-first reimagining of the original concept, allowing you to generate "front page" artwork without relying on external cloud APIs (except for fetching the headlines themselves).

Releases

See RELEASE_NOTES.md for version history and detailed release information.

Inspiration & Credits

This project was heavily inspired by and built upon the concepts of three fantastic projects:

  1. hn_dailyimage: The original Go-based project that conceived the idea of turning Hacker News headlines into art using Gemini, including the clever post-processing for e-ink displays.
  2. MFlux: A stellar line-by-line MLX port of generative image models. MFlux provides the high-performance local image generation engine that makes running this entirely on a Mac possible.
  3. mlx-vlm: Prince Canuma's MLX-based vision-language model package. mlx-vlm powers the local text model that analyzes the headlines and crafts the image prompts.

Features

  • 100% Local Inference: Uses MLX to run both the text model (for prompt analysis) and the image model (for generation) directly on your Mac.
  • Multiple Image Models: Supports z-image-turbo (default), FLUX.2 Klein, Ernie Image Turbo, and Ideogram 4 FP8. Ideogram 4 uses its native JSON-caption format and preset sampler for better quality.
  • Multiple Styles: Choose from various artistic directions (e.g., editorial, story_scene, story_blueprint, story_desk, story_frontpage, original).
  • Target Profiles: Output full-color, high-resolution PNGs for the web, or heavily processed, dithered 1-bit monochrome images optimized for eink displays.
  • Terminal Preview: Automatically previews the generated image directly in your terminal if you are using Kitty or Ghostty.

Styles Gallery

All of the examples below are generated with --target eink: a 1-bit, dithered 800×480 monochrome image optimized for e-ink displays.

Style E-ink Example
Editorial
--style editorial
Editorial Style
Story Scene
--style story_scene
Story Scene Style
Story Blueprint
--style story_blueprint
Story Blueprint Style
Story Desk
--style story_desk
Story Desk Style
Story Frontpage
--style story_frontpage
Story Frontpage Style
Original
--style original
Original Style

Model Comparison

Different models interpret prompts in unique ways. Below are examples of how each available model visualizes the same Hacker News headlines (using the --watermark flag to identify models):

Model Example (with watermark)
Z-Image Turbo (fastest, ~9 steps) Z-Image Turbo
FLUX.2 Klein 4B (balanced, ~4 steps) FLUX2 Klein 4B
FLUX.2 Klein 9B (higher quality, ~4 steps) FLUX2 Klein 9B
Ernie Image Turbo (fast, ~4 steps) Ernie Image Turbo
Ideogram 4 FP8 (high quality, ~20 steps) Ideogram 4 FP8

Use the --watermark flag to add model identification when comparing outputs:

hn-local-image compare --watermark --style editorial

High-Resolution Color Output

The default target is web, which produces full-color, high-resolution 1280×768 PNGs. The same six styles, generated with the default z-image-turbo model:

Style Color Example
Editorial
--style editorial
Editorial Color
Story Scene
--style story_scene
Story Scene Color
Story Blueprint
--style story_blueprint
Story Blueprint Color
Story Desk
--style story_desk
Story Desk Color
Story Frontpage
--style story_frontpage
Story Frontpage Color
Original
--style original
Original Color

Requirements

  • An Apple Silicon Mac (M1/M2/M3/M4)
  • Python 3.12+

Installation

Recommended: Install via PyPI with uv

uv is the fastest Python package installer and highly recommended for running this tool.

Run directly without installing:

uvx hn-local-image

Install for persistent use:

uv tool install hn-local-image
hn-local-image

Alternative: Install from source

Clone the repository and run the application using uv:

git clone https://github.com/ivanfioravanti/hn_local_image.git
cd hn_local_image

uv run will automatically manage the virtual environment and dependencies for you.

Alternative: Install with pip

pip install hn-local-image
hn-local-image

Usage

If installed via PyPI, run the command directly:

hn-local-image [OPTIONS]

If running from source, use uv run:

uv run main.py [OPTIONS]

Examples

Default (Editorial style, Web output, Z-Image Turbo):

uv run main.py

Generate an e-ink optimized image:

uv run main.py --target eink

Use a different style and the FLUX.2 Klein 9B image model:

uv run main.py --style story_blueprint --image-model flux2-klein-9b

Use a different local text model for prompt generation:

uv run main.py --model-name "mlx-community/Llama-3.2-8B-Instruct-4bit"

Options

  • --style: The artistic style to use (e.g., editorial, story_scene, story_blueprint, story_desk, story_frontpage, original). Default is editorial.
  • --target: The output processing mode (web or eink). Default is web.
  • --image-model: The image generation model to use (z-image-turbo, flux2-klein-4b, flux2-klein-9b, ernie-image-turbo, or ideogram-4-fp8). Default is z-image-turbo.
  • --watermark: Add a model name watermark to the bottom-right corner of the generated image for easy identification when comparing models.
  • --model-name: The Hugging Face repo ID of the MLX text model to use for prompt generation. Default is mlx-community/gemma-4-e4b-it-8bit.
  • --output-dir: Directory to save the generated images and JSON sidecars. Default is generated/.
  • --headless: Run without interaction.
  • --headless-upload: Automatically upload the generated image as a binary payload to a URL. Requires configuring the WEBHOOK_URL variable in a .env or .env.example file.

Environment Variables

You can configure the application's default behavior without passing CLI flags by setting the following environment variables in a .env file in the project root:

# Example .env.example file format:
WEBHOOK_URL=https://your-webhook-endpoint.com/upload

# Optional Overrides
PROMPT_MODE=editorial         # Equivalent to --style
TARGET_MODE=eink              # Equivalent to --target
OUTPUT_DIR=generated          # Equivalent to --output-dir
HN_URL=https://news.ycombinator.com/ # Override the default HN url

Comparing Image Models

The compare command generates images with all available image models using the same prompt and seed, making it easy to compare quality and speed side by side.

Compare a single style:

uv run main.py compare --style editorial

Compare a selected subset of image models:

uv run main.py compare --style editorial --image-model z-image-turbo --image-model ideogram-4-fp8

Compare all styles in one run (shared headlines and seed):

uv run main.py compare --all-styles

Compare with e-ink target:

uv run main.py compare --all-styles --target eink

This produces a generated/compare/<timestamp>/ directory with one subfolder per style, each containing:

  • One .png per image model (z-image-turbo.png, flux2-klein-4b.png, flux2-klein-9b.png, ernie-image-turbo.png, ideogram-4-fp8.png)
  • A comparison.json sidecar with prompt details, seed, and per-model timing
  • A root comparison.json aggregating all styles (when using --all-styles)

Webhooks / Headless Uploads

If you pass the --headless-upload flag, the application will automatically read the WEBHOOK_URL environment variable and perform an HTTP POST request sending the raw PNG bytes of the generated image (with Content-Type: image/png).

uv run main.py --target eink --headless-upload

This is heavily modeled after the original hn_dailyimage application to make pushing images to devices like e-ink displays seamless via Cron jobs.

Output

The script will save two files in the output directory (default: generated/):

  1. The generated .png image.
  2. A .json sidecar file containing metadata about the generation, including the time, models used, headlines parsed, and the specific prompt used to generate the image.

License

MIT License. See LICENSE for more 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

hn_local_image-0.2.0.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hn_local_image-0.2.0-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file hn_local_image-0.2.0.tar.gz.

File metadata

  • Download URL: hn_local_image-0.2.0.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hn_local_image-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4a1a2f8c7e95f6f3bf9ba6db359f633fcf7a2cc9764e5a39a533343be1749a9c
MD5 ae75d0a5f1f792f5a7fc3b7f39e2f773
BLAKE2b-256 3044029ce280677ff05b7bd7a66ef53dac0b46c0c809ea350a40be30c199c047

See more details on using hashes here.

Provenance

The following attestation bundles were made for hn_local_image-0.2.0.tar.gz:

Publisher: release.yml on ivanfioravanti/hn_local_image

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hn_local_image-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: hn_local_image-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 19.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hn_local_image-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ededb0da9e14682e83df0fa5cff5fbf0b3f06573217a35019bd53478eb51b7e0
MD5 768fe10c48d0570e763e7ddf1c28d08b
BLAKE2b-256 fcac581597e6d6af80addcb6ad7b901abe813eb4bcf66169a35621ed9be3e768

See more details on using hashes here.

Provenance

The following attestation bundles were made for hn_local_image-0.2.0-py3-none-any.whl:

Publisher: release.yml on ivanfioravanti/hn_local_image

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page