Add an image field, required for WordPress posts

Posts get a nullable image_url. WordPressPublisher now downloads it
and uploads it to WordPress's media endpoint before creating the
post, setting it as featured_media — and rejects publishing (without
touching status) if a blog post has no image set, mirroring the
existing title requirement. Every other network treats it as optional.

Not enforced at save time, same as title — you can still draft an
incomplete WordPress post, it just can't be published until an image
is set. Exposed through the UI form (with a thumbnail/""missing""
indicator in the table), the JSON API, and the Python CLI wrapper.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
m105
2026-07-21 20:03:25 +03:00
co-authored by Claude Sonnet 5
parent fd185ab813
commit 42abc658f2
14 changed files with 259 additions and 28 deletions
@@ -11,6 +11,7 @@
<table class="w-full bg-white border border-gray-200 rounded">
<thead>
<tr class="text-left border-b border-gray-200">
<th class="p-3">Image</th>
<th class="p-3">Site</th>
<th class="p-3">Type</th>
<th class="p-3">Title</th>
@@ -23,6 +24,15 @@
<tbody>
@foreach ($posts as $post)
<tr wire:key="post-{{ $post->id }}" class="border-b border-gray-100">
<td class="p-3">
@if ($post->image_url)
<img src="{{ $post->image_url }}" alt="" class="w-10 h-10 object-cover rounded">
@elseif ($post->type === 'blog')
<span class="text-xs text-amber-600">missing</span>
@else
<span class="text-gray-400">—</span>
@endif
</td>
<td class="p-3">{{ $post->site->name }}</td>
<td class="p-3">{{ ucfirst($post->type) }}</td>
<td class="p-3">{{ $post->title ?: \Illuminate\Support\Str::limit($post->body, 40) }}</td>
@@ -106,6 +116,14 @@
@error('target') <span class="text-red-600 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label class="block text-sm font-medium">
Image URL {{ $type === 'blog' ? '(required to publish to WordPress)' : '(optional)' }}
</label>
<input type="url" wire:model="imageUrl" placeholder="https://..." class="w-full border rounded p-2">
@error('imageUrl') <span class="text-red-600 text-sm">{{ $message }}</span> @enderror
</div>
<div>
<label class="block text-sm font-medium">Status</label>
<select wire:model="status" class="w-full border rounded p-2">