Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/.gitignore export-ignore
/build.sh export-ignore
/builds/ export-ignore
/.github/ export-ignore
38 changes: 38 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Lint

on:
push:
branches: [main]
pull_request:

jobs:
php:
runs-on: ubuntu-latest
strategy:
matrix:
# Oldest supported (README: PHP 7.0+) and current.
php: ['7.0', '8.4']
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: none
- name: Syntax check
run: find . -name '*.php' -not -path './vendor/*' -print0 | xargs -0 -n1 php -l

js:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Syntax check
run: for f in admin/js/*.js; do node --check "$f"; done

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build ZIP (checks versions match and bundles the update checker)
run: ./build.sh
- name: Confirm update checker is bundled
run: unzip -l builds/everyalt-*.zip | grep -q 'everyalt/vendor/plugin-update-checker/plugin-update-checker.php'
83 changes: 71 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
# 🖼️ EveryAlt — Alt text for every image. **Zero limits. Totally free.**

<p align="center">
<strong>🆓 100% free</strong> · <strong>♾️ No limits from us</strong> · <strong>🔑 Your OpenAI key</strong>
<strong>🆓 100% free</strong> · <strong>♾️ No limits from us</strong> · <strong>🔑 Your AI key: OpenAI, Gemini, or DeepInfra</strong>
</p>

> **EveryAlt 1.0 is 100% free.** Bring your own [OpenAI API key](https://platform.openai.com/api-keys), and generate as much alt text as you want. We don’t meter you, cap you, or bill you. **Ever.**
> **EveryAlt 1.0 is 100% free.** Bring your own API key from **OpenAI**, **Google Gemini**, or **DeepInfra**, and generate as much alt text as you want. We don’t meter you, cap you, or bill you. **Ever.**

---

Expand All @@ -28,10 +28,10 @@ No more blank alt fields. No more guessing. **You upload. EveryAlt writes.**
| Before | **EveryAlt 1.0** |
|--------|------------------|
| Limits, tiers, or paywalls | **Unlimited** — your key, your usage |
| Extra service to sign up for | **Just OpenAI** — one key, one place |
| Opaque pricing | **Transparent** — you pay OpenAI only |
| Extra service to sign up for | **Your choice of provider** — one key, no EveryAlt account |
| Opaque pricing | **Transparent** — you pay your AI provider only |

We don’t charge. We don’t sit in the middle. You use **your** OpenAI key. EveryAlt stays **free**, and you have **no limits** from us.
We don’t charge. We don’t sit in the middle. You use **your** own key. EveryAlt stays **free**, and you have **no limits** from us.

---

Expand All @@ -55,27 +55,69 @@ Works on localhost, behind HTTP auth, and with your existing workflow.

1. **Upload** the plugin to `wp-content/plugins/everyalt` (or install via WordPress admin).
2. **Activate** the plugin (Plugins → EveryAlt → Activate).
3. **Open Media → EveryAlt** and add your [OpenAI API key](https://platform.openai.com/api-keys) in **Settings**.
3. **Open Media → EveryAlt → Settings**, pick an **AI model**, and paste the API key for that provider (see [Models & keys](#-models--keys)).
4. Turn on **Auto-generate on upload** if you want, or use **Bulk** / **Review** to handle existing images.

That’s it. No account with us. No caps. No “upgrade to unlock more.”

---

## 🔑 Your key, your usage
## 🤖 Models & keys

- Alt text is generated by **OpenAI** (image is sent as base64; works on localhost and behind HTTP auth).
- Your API key is **stored encrypted** in your WordPress database.
- **You** are billed by OpenAI for your usage; EveryAlt does not charge you.
- We use a small, efficient model so cost per image stays low.
Choose a model in **Settings**. Every model reads the image itself and writes the alt text (and titles). You only need a key for the provider you pick, and you can store keys for several providers and switch any time.

| Model | Provider | Input / 1M tokens | Output / 1M tokens |
|-------|----------|------------------:|-------------------:|
| **GPT-5.4 nano** (default) | OpenAI | $0.20 | $1.25 |
| **Gemini 3.1 Flash-Lite** | Google Gemini | $0.25 | $1.50 |
| **DeepSeek V4.1 Flash** | DeepInfra | $0.20 | $0.60 |
| **GLM-5.3-Flash** | DeepInfra | $0.15 | $0.50 |

Prices are each provider’s published regular rates as of September 2026 and can change: [OpenAI pricing](https://openai.com/api/pricing/) · [Gemini pricing](https://ai.google.dev/gemini-api/docs/pricing) · [DeepInfra pricing](https://deepinfra.com/pricing). The actual cost of every image is recorded on the **Logs** tab.

> **Upgrading from 1.0.x?** Earlier versions used `gpt-5-nano`, which OpenAI is retiring. Existing installs switch to **GPT-5.4 nano** automatically. Your OpenAI key keeps working.

### Getting a key

**OpenAI**
1. Sign in at [platform.openai.com/api-keys](https://platform.openai.com/api-keys).
2. Click **Create new secret key**, name it (e.g. “EveryAlt”), and copy it. It is only shown once.
3. Add a payment method or prepaid credits under billing; generation fails until the account has credit.

OpenAI does not train on API data by default ([details](https://openai.com/enterprise-privacy/)).

**Google Gemini**
1. Sign in to Google AI Studio at [aistudio.google.com/apikey](https://aistudio.google.com/apikey).
2. Click **Create API key**, pick or create a Google Cloud project, and copy the key.
3. Optional: enable billing on the project to use the paid tier.

Gemini has a free tier, but Google may use free-tier content to improve its products; paid-tier content is not used that way ([Gemini API terms](https://ai.google.dev/gemini-api/terms)).

**DeepInfra** (one key covers both DeepSeek V4.1 Flash and GLM-5.3-Flash)
1. Sign in or sign up at [deepinfra.com/dash/api_keys](https://deepinfra.com/dash/api_keys).
2. Click **New API key**, name it, and copy it.
3. Add a payment method or credits in your DeepInfra billing settings.

🔒 **Your images stay private with DeepInfra.** DeepInfra runs these models on its own infrastructure in data centers in the **US and Canada**, with **zero data retention**: images and generated text are processed in memory and not stored, request content is not logged, and your data is never used for training. See [DeepInfra data privacy](https://docs.deepinfra.com/account/data-privacy), the [privacy policy](https://deepinfra.com/privacy), and the [trust center](https://trust.deepinfra.com/) (SOC 2 and ISO 27001).

### Your key, your usage

- The image is sent to your chosen provider as base64, so it works on localhost and behind HTTP auth.
- API keys are **stored encrypted** in your WordPress database.
- **You** are billed by your provider for usage; EveryAlt does not charge you.

### For developers

- `everyalt_model` filters the model ID sent to the provider: `( string $model_id, string $model_slug )`. This replaces `everyalt_openai_model`.
- `everyalt_input_token_price_per_million` / `everyalt_output_token_price_per_million` override the prices used for cost estimates: `( float $price, string $model_slug )`.

---

## 📋 Requirements

- WordPress 5.5+
- PHP 7.0+
- An [OpenAI API key](https://platform.openai.com/api-keys) with API access
- An API key from [OpenAI](https://platform.openai.com/api-keys), [Google Gemini](https://aistudio.google.com/apikey), or [DeepInfra](https://deepinfra.com/dash/api_keys)

---

Expand All @@ -99,6 +141,23 @@ The plugin uses the `everyalt` text domain and ships with a `.pot` in `languages

## 📝 Changelog

### Unreleased
- **New: choose your AI model.** Pick from **GPT-5.4 nano** (OpenAI), **Gemini 3.1 Flash-Lite** (Google), or **DeepSeek V4.1 Flash** / **GLM-5.3-Flash** (DeepInfra) in Settings. Keys are stored per provider, so you can switch without re-entering them. Settings shows each model's published pricing, step-by-step key instructions, and privacy details, including DeepInfra's US/Canada hosting and zero data retention.
- **Changed** OpenAI requests now use **GPT-5.4 nano**; `gpt-5-nano` is being retired. Existing installs switch automatically.
- **Added** a Model column to the Logs tab and CSV export.
- **Developer:** the `everyalt_openai_model` filter is replaced by `everyalt_model`; the price filters now also receive the model slug.
- **Fixed** automatic updates: release ZIPs now bundle the update checker library (it was missing from ZIPs built with `build.sh`).
- **Fixed** deactivating the plugin no longer deletes your API key and settings. Uninstalling now removes all EveryAlt data (settings, key, logs) instead of leaving it behind.
- **Fixed** "Auto-generate on upload" now starts checked on fresh installs, as intended.
- **Fixed** Editors and Authors can now use the block-editor and media-screen "Generate alt text" buttons on images they can edit, and failures now show a message instead of doing nothing.
- **Fixed** auto-generation on upload now runs exactly once per image, after all image sizes exist (it could previously retry once per image size after a failure).
- **Fixed** the 4MB limit now applies to the resized image actually sent to OpenAI, not the original upload, so large phone photos are no longer skipped.
- **Improved** the Bulk and Review tabs are paginated and much faster on large media libraries.
- **Improved** block-editor and media-screen button text is now translatable.
- **Added** a warning when the saved API key can no longer be decrypted (e.g. after the security keys in `wp-config.php` change).
- **Security** CSV log exports are protected against spreadsheet formula injection; the unused HTTP-auth username/password settings (the password was stored in plain text) have been removed and are deleted on update.
- **Removed** the unused `every_alt_logs` database table (dropped on uninstall) and the legacy `/get_tokens` REST endpoint.

### 1.0.2
- **New — AI image titles.** EveryAlt now writes descriptive WordPress image **titles**, not just alt text:
- Optional **Automatically generate image titles when images are uploaded** toggle in Settings.
Expand Down
Loading
Loading