diff --git a/AI_API.md b/AI_API.md index d5e9295..7458b16 100644 --- a/AI_API.md +++ b/AI_API.md @@ -82,12 +82,21 @@ Response shape: "cms_type": "wordpress", "wp_username": "admin", "wp_app_password": "abcd 1234 efgh 5678", + "api_instructions": null, "created_at": "2026-07-19T12:00:00.000000Z", "updated_at": "2026-07-19T12:00:00.000000Z" } } ``` +`api_instructions` is a free-text field (nullable) for `cms_type=custom`/`other` +sites — there's no built-in publisher for these yet, so this is where the +user documents how to actually post there: auth method, endpoints, payload +shape, whatever's needed. **Read it before improvising** when you're about +to publish to a site with no wired-in publisher (see "Any other +network/CMS" below) — it's the site owner telling you directly how their +API works, rather than you having to guess or ask. + `cms_type` is one of `wordpress`, `custom`, `other`. `wp_username`/ `wp_app_password` are only meaningful (non-null) when `cms_type` is `wordpress` — they're a WordPress **Application Password** pair (see @@ -269,11 +278,12 @@ integration yet) There is no built-in publishing path. Do it however is appropriate for that platform (its own API, its own automation), using the credentials -from `GET /api/sites` / `GET /api/accounts`, then report back via -`PATCH /api/posts/{id}` exactly as described above. This is the general -fallback contract: **whatever publishes a post, always ends with either -the `posts:publish` command's automatic bookkeeping, or a manual `PATCH` -setting `status` and, if applicable, `published_url`.** +from `GET /api/sites` / `GET /api/accounts` — check the site's +`api_instructions` first, that's exactly what it's there for — then report +back via `PATCH /api/posts/{id}` exactly as described above. This is the +general fallback contract: **whatever publishes a post, always ends with +either the `posts:publish` command's automatic bookkeeping, or a manual +`PATCH` setting `status` and, if applicable, `published_url`.** ## Quick reference diff --git a/app/Http/Resources/SiteResource.php b/app/Http/Resources/SiteResource.php index 049823e..cce5877 100644 --- a/app/Http/Resources/SiteResource.php +++ b/app/Http/Resources/SiteResource.php @@ -17,6 +17,7 @@ class SiteResource extends JsonResource 'cms_type' => $this->cms_type, 'wp_username' => $this->wp_username, 'wp_app_password' => $this->wp_app_password, + 'api_instructions' => $this->api_instructions, 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; diff --git a/app/Livewire/Sites/Index.php b/app/Livewire/Sites/Index.php index b29b8e8..80dcaf5 100644 --- a/app/Livewire/Sites/Index.php +++ b/app/Livewire/Sites/Index.php @@ -27,6 +27,8 @@ class Index extends Component public string $wpAppPassword = ''; + public ?string $apiInstructions = null; + public function render() { return view('livewire.sites.index', [ @@ -51,6 +53,7 @@ class Index extends Component $this->cmsType = $site->cms_type; $this->wpUsername = $site->wp_username ?? ''; $this->wpAppPassword = $site->wp_app_password ?? ''; + $this->apiInstructions = $site->api_instructions; $this->showForm = true; } @@ -63,6 +66,7 @@ class Index extends Component 'cmsType' => ['required', 'string', 'in:' . implode(',', Site::CMS_TYPES)], 'wpUsername' => ['required_if:cmsType,wordpress', 'nullable', 'string', 'max:255'], 'wpAppPassword' => ['required_if:cmsType,wordpress', 'nullable', 'string', 'max:255'], + 'apiInstructions' => ['nullable', 'string'], ]); Site::updateOrCreate(['id' => $this->editingId], [ @@ -72,6 +76,7 @@ class Index extends Component 'cms_type' => $validated['cmsType'], 'wp_username' => $validated['cmsType'] === 'wordpress' ? $validated['wpUsername'] : null, 'wp_app_password' => $validated['cmsType'] === 'wordpress' ? $validated['wpAppPassword'] : null, + 'api_instructions' => $validated['apiInstructions'], ]); $this->resetForm(); @@ -97,6 +102,7 @@ class Index extends Component $this->cmsType = 'custom'; $this->wpUsername = ''; $this->wpAppPassword = ''; + $this->apiInstructions = null; $this->resetValidation(); } } diff --git a/app/Models/Site.php b/app/Models/Site.php index c26a0c6..a852374 100644 --- a/app/Models/Site.php +++ b/app/Models/Site.php @@ -18,5 +18,6 @@ class Site extends Model 'cms_type', 'wp_username', 'wp_app_password', + 'api_instructions', ]; } diff --git a/database/migrations/2026_07_22_140106_add_api_instructions_to_sites_table.php b/database/migrations/2026_07_22_140106_add_api_instructions_to_sites_table.php new file mode 100644 index 0000000..f9e5ec3 --- /dev/null +++ b/database/migrations/2026_07_22_140106_add_api_instructions_to_sites_table.php @@ -0,0 +1,28 @@ +text('api_instructions')->nullable()->after('wp_app_password'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('sites', function (Blueprint $table) { + $table->dropColumn('api_instructions'); + }); + } +}; diff --git a/resources/views/livewire/sites/index.blade.php b/resources/views/livewire/sites/index.blade.php index c21f917..3d07897 100644 --- a/resources/views/livewire/sites/index.blade.php +++ b/resources/views/livewire/sites/index.blade.php @@ -34,6 +34,8 @@ {{ $revealedId === $site->id ? 'Hide' : 'Show' }} + @elseif ($site->api_instructions) +
Notes for posting here via this site's own API — auth method, endpoints, payload shape, etc. Read by whoever (agent or you) ends up publishing to it.
+ + @error('apiInstructions') {{ $message }} @enderror +