Skip to content
MatheusBomtempoPublic

About

Open source AI-assisted Instagram publishing for newsrooms - draft, review, and post breaking-news content fast, with a human always in the loop.

Topics

Resources

Contributing

Security policy

Stars

85 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

71 Commits

Folders and files

Repository files navigation

JornAI

From source to Instagram feed in minutes β€” AI writes the copy, a human always approves.

An open-source web tool that lets a newsroom publish breaking-news posts to Instagram with almost no friction: paste a police report, a press release or a link, and get a ready-to-review post with a title, subtitle and caption β€” built on a pipeline designed not to invent facts.

CI License: MIT Next.js TypeScript PostgreSQL


JornAI story feed with posts in review

Every story in one feed: paste a source β†’ AI drafts the post β†’ frame the photo β†’ a human approves and publishes.


See it in action

1 Β· Drop in your source

New story screen with a pasted link, credits and the Generate button

TL;DR: paste a text, an article link or a PDF, optionally credit someone (πŸ“Έ @photographer), and hit Generate. The AI writes the title, subtitle and caption β€” and never touches the photo.

2 Β· Frame the photo, tweak the text

Media step: photo framed on the brand template with editable title and subtitle

TL;DR: drag and zoom the photo, drag the title or subtitle to reposition them, edit the words (69 / 149 character limits). The brand template stays intact; only this post changes. What you see is exactly what the server renders.

Video (Reels) works too. Upload a clip instead of a photo and JornAI handles the boring parts:

  • Normalizes any video to 9:16 β€” already-vertical clips are cropped top and bottom; landscape clips are kept whole over a blurred, mirrored backdrop instead of ugly black bars.
  • Keeps the title card and logo inside Instagram's safe zones, so the profile, caption and buttons never cover them.
  • Burns in an animated title card (slide + fade) in one of three styles, using your brand colors.
  • Fixes phone-recorded videos that arrive rotated.

3 Β· More than one photo? Make it a carousel

Carousel section: the cover, a second photo and the reorder, frame and edit buttons

TL;DR: add up to 10 photos and the post becomes an Instagram carousel. The 1st photo is the cover, with the template, title and subtitle; the others go out as the bare photo, cropped to the same proportion (Instagram requires it). Reorder, swap the cover and frame each slide.

4 Β· Edit the image without leaving the app

Image editor on the blur tab, with a face blurred

TL;DR: every photo β€” cover or slide β€” has an Edit image popup, framed at the real proportion of the art:

  • Blur image β€” tap or drag over the photo to hide faces, plates or anything else (with undo). Handy for accident and police photos.
  • Adjust β€” zoom, straighten, rotate, mirror, and blurred borders: show the whole photo and fill the rest of the frame with a mirrored, blurred copy, the same look as the videos.
  • Color β€” brightness, contrast and saturation.

5 Β· Review, publish β€” and add it to the story

Review step with the carousel preview, the Approve and publish button and the Add to story too checkbox

TL;DR: see the post exactly as it will look on Instagram (carousels can be swiped), then Approve and publish, Request rewrite (the AI writes a new version) or Reject with a reason. Every change is a new version, so the full history is kept.

  • Add to story too β€” a checkbox under the approve button, always unticked by default. When ticked, once the feed post is out the art (carousel: cover only) or the rendered video is also published as an Instagram story.
  • If the story fails, the feed post stays up β€” the failure is recorded and the review screen says why.

Built for newsrooms

Administration panel tabs: Newsroom style, Templates, Users, API keys, Company, Settings, AI balance

TL;DR: the admin area is where a newsroom makes JornAI sound and look like itself.

  • Newsroom style β€” register real posts from your newsroom; the AI learns the tone and format (it never copies the content).
  • Templates β€” build photo templates visually (see below).
  • Users & roles β€” admin, manager and reporter, each company isolated from the others.
  • API keys, Company, Settings, AI balance β€” connect providers, set your logo and brand colors, toggle mandatory review, watch your AI spend.

Make the template yours

Template builder: drag the title and subtitle boxes over the frame, set size, color, weight, alignment and case

TL;DR: the photo template is the heart of JornAI, and it is fully customizable β€” upload your brand frame (a transparent PNG made in Canva or Photoshop), drag the title and subtitle boxes where you want them, and pick the format (4:5 or 1:1), font size, color, weight, alignment and case. Video is simpler on purpose: it ships with 3 ready-made title-card styles (classic, light, bold) that pick up your brand colors.


Why JornAI

Newsrooms often need to get a short, urgent post out β€” an accident, a weather alert, a local event β€” with almost no friction, but still with editorial review and consistent branding. JornAI is not a generic social-media scheduler and not a raw AI text generator with no guardrails:

  • 🧾 Fact-first. Sources are cleaned, redacted and checked before and after the model, so a confident-sounding article doesn't come with invented details.
  • πŸ‘€ Always human-approved. Nothing reaches Instagram without a person approving it.
  • 🎨 Consistent branding. Photo + text are composed on a fixed template, in the browser and on the server, with identical results.
  • 🌍 Works in your language. One environment variable picks the language of the sources and the posts (en and pt included, more welcome).
  • πŸ†“ Runs with no keys. AI_PROVIDER="mock" + local storage lets you try the whole flow without any external service.

How it works

Source (photo, text, link, or PDF)
        β”‚
        β–Ό
AI writes the copy (title, subtitle, caption)
        β”‚
        β–Ό
Reporter frames the photo(s) or video in the brand template
(single photo, carousel of up to 10, or a 9:16 Reels video)
        β”‚
        β–Ό
Editor reviews β†’ approve / reject / regenerate / edit
(optional: "Add to story too")
        β”‚
        β–Ό
Publish to Instagram (feed / carousel / Reels, + story if ticked)
  • AI only writes text β€” it never generates or picks images. Photos are always real and chosen by a person.
  • Every AI generation (or manual edit) creates a new version, so nothing is overwritten and there is a full history.
  • Photo, carousel (up to 10 photos) and video (Reels) posts, with an animated title card for video.
  • Built-in image editor: blur faces, blurred borders, rotate/straighten, color.
  • Optional story share on approval β€” always an explicit, per-post choice.
  • Peer review: a reporter's post can be approved by a manager/admin, or by two colleagues.
  • Multi-tenant: each company has its own feed, templates, style examples and settings.

Fact-accuracy pipeline

Feeding a police report or an official PDF straight into an LLM is a good way to get a confident-sounding article with wrong facts. JornAI's pipeline is built around not letting that happen:

  • Source text is cleaned and compacted deterministically (no AI) before it ever reaches a model β€” official documents/forms get their real fields extracted (who, where, cause, injuries) instead of being blindly truncated.
  • Personal data (names, national IDs, phone numbers, plates) is redacted before the AI ever sees it.
  • The system prompt has explicit, tested rules against inventing details, generic filler, or unsupported claims.
  • Generated content is checked against the source by a deterministic validator after generation (e.g. the weekday must match the source date, no unsupported claims about investigations, road closures or deaths); a violation triggers one corrective regeneration before failing loudly.
  • The weekday is computed by code, never by the model.

Working language

JornAI works in any language β€” one per deployment: the language of the sources and of the generated posts, chosen with the APP_LANGUAGE environment variable. Each language is a small pack with its own rules for source cleanup, personal-data redaction and the fact validator. Two ship today, as examples:

Value Example of what the pack covers
en (default) Posts in English; English rules (SSN, US phone numbers, mm/dd/yyyy dates).
pt Posts in Brazilian Portuguese; Brazilian rules (CPF, plates, police-report forms, dd/mm/yyyy dates).

The prompts themselves are written in English; only the examples and rules the model must reproduce live in the language pack (src/lib/language/<lang>/). To add your language, add a pack there and register it in src/lib/language/index.ts β€” see CONTRIBUTING.md. APP_LANGUAGE also sets the default interface language (each person can still switch it in the UI); the code, comments and logs are always English.

Tech stack

  • Next.js (App Router) + TypeScript, PostgreSQL via Prisma
  • Fabric.js for the in-browser art editor, Sharp for the server-side final render, ffmpeg for video
  • AI: any OpenAI-compatible or Anthropic text provider (OpenRouter, Groq, Gemini, OpenAI, Claude), with automatic fallback across providers
  • Instagram Graph API for publishing (single image, carousel, Reels and stories); S3/R2-compatible storage (or local disk in dev)

Roles

Role Can do
admin Everything β€” users, API keys, templates, style examples, approve/publish
manager Approve/reject/regenerate/edit/publish; manage templates and style examples
staff (reporter) Submit sources, edit own drafts before approval; approve a colleague's post (two approvals publish it)

Getting started

git clone https://github.com/MatheusBomtempo/JornAI.git
cd JornAI
npm install
docker compose up -d       # PostgreSQL that matches .env.example (or bring your own)
cp .env.example .env       # fill in DATABASE_URL and, optionally, an AI provider key
npm run db:migrate
npm run db:seed            # sample company + accounts, dev only
npm run dev

Open http://localhost:3000 and sign in with admin@jornai.local / admin12345 (created by the seed, development only).

No AI key yet? Keep AI_PROVIDER="mock" in .env to run the whole flow with a stub AI response β€” useful for trying the app without any external service.

Setup before your first post

Two kinds of configuration, done once, in this order:

1 Β· Program configuration (for whoever runs it)

Everything technical is configured through environment variables β€” see .env.example, which documents each one. The important ones:

Variable What it does
APP_LANGUAGE Working language (en and pt ship as examples; add your own pack)
DATABASE_URL / DIRECT_URL PostgreSQL connection
AUTH_SECRET Signs the session JWTs
AI_PROVIDER mock, chain (fallback across providers), openrouter, groq, gemini, openai, anthropic
STORAGE_PROVIDER local (dev) or s3 (S3 / Cloudflare R2 / Supabase)
IG_USER_ID / IG_ACCESS_TOKEN Instagram Graph API publishing

2 Β· Style configuration (for the newsroom, in the app)

TL;DR: before the first post, open Admin and make JornAI look and sound like your newsroom. It takes a few minutes and you only do it once.

  • Company β€” your name, logo, Instagram @ and brand colors (the logo and colors show up on the art and on the video title cards). On the very first login the admin is guided through this.
  • Templates β€” build your photo frame with the template builder: 4:5 or 1:1, your overlay PNG, title and subtitle positions and text style.
  • Newsroom style β€” paste a few real posts so the AI learns your tone and format.

You can come back and change any of these later.

Deploying

The project deploys as a regular Next.js app (it is developed against Vercel + Neon + Cloudflare R2). npm run build applies the Prisma migrations, so the build needs the database configured.

Documentation

  • SPEC.md β€” full technical spec: database schema, API endpoints, state machine, Instagram publishing.
  • CONTRIBUTING.md β€” how to contribute and how to add a language.
  • SECURITY.md β€” how to report a vulnerability.

Roadmap ideas

  • More language packs (Spanish, French, …)
  • More official-document profiles (the way police-report forms are cleaned today)
  • Other social networks (deliberately out of scope for now)

Not planned, on purpose: scheduling, AI image generation, and publishing without human approval.

Contributing

Issues and pull requests are welcome β€” read CONTRIBUTING.md first. If JornAI is useful to you, a ⭐ helps other newsrooms find it.

License

MIT β€” see LICENSE.

About

Open source AI-assisted Instagram publishing for newsrooms - draft, review, and post breaking-news content fast, with a human always in the loop.

Topics

Resources

Contributing

Security policy

Stars

85 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages