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>
121 lines
3.5 KiB
Markdown
121 lines
3.5 KiB
Markdown
# Muninn
|
|
|
|
Muninn is a personal content-operations hub. It keeps track of your
|
|
**Sites**, **Social Accounts**, and **Posts**, and exposes them over a
|
|
local JSON API so an AI agent (or you, via the built-in UI) can draft,
|
|
schedule, and publish content across WordPress blogs, Reddit, and other
|
|
platforms.
|
|
|
|
Built with Laravel 13, Livewire, and Tailwind CSS.
|
|
|
|
## What it does
|
|
|
|
- **Sites** — the websites you own (WordPress, custom, or other), with
|
|
optional WordPress Application Password credentials for publishing.
|
|
- **Social Accounts** — logins for social networks (Twitter, Instagram,
|
|
Facebook, Reddit, TikTok, LinkedIn, YouTube, etc.).
|
|
- **Posts** — the actual content, each tied to a Site and optionally a
|
|
Social Account, moving through
|
|
`draft -> scheduled -> publishing -> published/failed`.
|
|
- A **JSON API** (`/api/sites`, `/api/accounts`, `/api/posts`) plus thin
|
|
Python CLI wrappers in `python_scripts/`, so an agent can poll for due
|
|
posts (`?due=1`) and drive the publish lifecycle without hand-rolling
|
|
HTTP requests.
|
|
- A **Publish button** in the UI (Posts page) for any post whose network has
|
|
a publisher wired up — queues a background job so slow, flaky publishers
|
|
(e.g. Reddit's browser automation) don't block the page.
|
|
- Built-in publishers (`app/Support/Publishing/`), one per network, resolved
|
|
by `Post.type`:
|
|
- **WordPress**: posts directly to a site's WordPress REST API, uploading
|
|
`Post.image_url` as the featured image first — required to publish a
|
|
WordPress post, optional for every other post type. Also available
|
|
synchronously from the CLI: `php artisan posts:publish {post_id}`.
|
|
- **Reddit**: drives a standalone Playwright sidecar at
|
|
`sidecars/reddit-post/` that logs in and creates a post.
|
|
- Anything else: no publisher yet — publish however fits, then report
|
|
back via the API.
|
|
|
|
See `AI_API.md` for the full API reference and publishing contract, and
|
|
`python_scripts/README.md` for the CLI wrapper usage.
|
|
|
|
**Note:** the JSON API has no authentication and returns credentials in
|
|
plain text by design — it's meant to run on your local network only, not
|
|
be exposed to the public internet.
|
|
|
|
## Requirements
|
|
|
|
- PHP 8.3+
|
|
- Composer
|
|
- Node.js + npm
|
|
- MySQL (or another Laravel-supported database)
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
composer install
|
|
cp .env.example .env
|
|
php artisan key:generate
|
|
```
|
|
|
|
Edit `.env` and set your database credentials (`DB_DATABASE`,
|
|
`DB_USERNAME`, `DB_PASSWORD`, etc. — defaults assume a local MySQL
|
|
database named `muninn`), then run migrations:
|
|
|
|
```bash
|
|
php artisan migrate
|
|
```
|
|
|
|
Install JS dependencies and build frontend assets:
|
|
|
|
```bash
|
|
npm install
|
|
npm run build
|
|
```
|
|
|
|
Alternatively, run everything in one shot with:
|
|
|
|
```bash
|
|
composer run setup
|
|
```
|
|
|
|
### Running locally
|
|
|
|
```bash
|
|
composer run dev
|
|
```
|
|
|
|
This starts the PHP dev server, queue listener, log viewer (Pail), and
|
|
Vite dev server together. The app is served at `http://localhost:8000` by
|
|
default.
|
|
|
|
Outside of `composer run dev` (e.g. a plain production deploy), the Publish
|
|
button needs its own queue worker running, or queued publishes will just sit
|
|
in the `jobs` table:
|
|
|
|
```bash
|
|
php artisan queue:work
|
|
```
|
|
|
|
### Reddit sidecar (optional)
|
|
|
|
If you plan to publish to Reddit, set up the Playwright sidecar separately:
|
|
|
|
```bash
|
|
cd sidecars/reddit-post
|
|
npm install
|
|
npx playwright install
|
|
```
|
|
|
|
See `sidecars/reddit-post/README.md` for usage.
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
composer test
|
|
```
|
|
|
|
## License
|
|
|
|
The Laravel framework is open-sourced software licensed under the
|
|
[MIT license](https://opensource.org/licenses/MIT).
|