Skip to content

fardinhakimi/funrang

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Funrang

Funrang is a social content engine for small teams. It discovers stories, ranks what matters, generates posts and images, and helps operators review, schedule, and publish them.

This codebase is 100% generated by Codex, guided by the author Fardin Hakimi. It is a learning side-project focused on learning AI engineering through building a real evolving product.

Today the product is centered around:

  • source ingestion from RSS and scraping
  • clustering and ranking of candidate stories
  • AI-assisted post generation
  • AI story generation from free-form prompts
  • image generation through the Python media service
  • review, moderation, scheduling, and publishing
  • Facebook publishing today, with broader channel support evolving

Current Product Shape

Funrang now has two main creation paths:

  1. Real-story content creation

    • ingest sources
    • extract articles
    • cluster and rank stories
    • generate fact-based posts
  2. AI story generation

    • start from a user prompt
    • generate a short social story
    • generate a matching image prompt
    • translate, hashtag, store, and draft the result

Both paths now run through the internal agent-system, which contains:

  • agents
  • workflows
  • runtime
  • memory
  • tools
  • guardrails

This is the current agentic backend layer used for research/selection and generation workflows.

Repository Layout

Main areas you will touch most often:

  • src/server.ts
    • Express app and UI/API boot
  • src/runner.ts
    • scheduled/headless runner entrypoint
  • src/application/
    • application services that orchestrate creation flows
  • src/agent-system/
    • agent runtime, memory, tools, guardrails, agents, workflows
  • src/ui/
    • Vue UI
  • media_service/
    • Python media generation service

Runtime Model

The current default local stack is:

  • Node/TypeScript app
  • Postgres
  • Redis
  • LM Studio for text generation and embeddings
  • Python media service for image/video/media jobs

OpenAI is still supported by parts of the codebase, but the current local-first setup uses LM Studio by default.

Environment Files

This part is important because the repo now uses multiple env files for different runtimes.

Node app

  • .env.dev
    • local development server
  • .env.test
    • tests
  • .env
    • local production-style runner usage outside Docker
  • .env.docker
    • app container used by docker-compose.prod.yml

Python media service

  • media_service/.env
    • media server runtime configuration

Local Development

Prereqs

  • Node.js 20+ recommended
  • Docker + Docker Compose plugin
  • Python 3
  • ffmpeg and ffprobe on PATH
  • LM Studio running locally if you want the default local LLM path

1) Install dependencies

npm i
cp .env.example .env
cp .env.example .env.dev
cp .env.example .env.test

Then update the copied env files to match the current local-first defaults before you start the app:

LLM_PROVIDER=lmstudio
LLM_BASE_URL=http://127.0.0.1:1234/v1
LLM_MODEL=qwen3-8b
AI_EMBEDDING_MODEL=text-embedding-nomic-embed-text-v1.5
AI_EMBEDDING_DIMENSIONS=192
WEB_SEARCH_PROVIDER=duckduckgo
WEB_SEARCH_TIMEOUT_MS=10000
MEDIA_SERVICE_URL=http://127.0.0.1:8091
MEDIA_CALLBACK_BASE_URL=http://127.0.0.1:3333

2) Start infrastructure

docker compose up -d

This starts the local development infra stack:

  • Postgres
  • Redis
  • pgAdmin

3) Prepare the Python media service

npm run media:venv
npm run media:install

4) Run database migrations

npm run migrate:dev

5) Start the app

If you want the Node app and media service together:

npm run dev

If you want to run only the Node app:

npm run ui

Default local URLs:

  • app: http://localhost:3333
  • media service: http://localhost:8091
  • pgAdmin: http://localhost:5050

6) Run tests

npm test

Useful checks:

npm run typecheck
npm run check
npm run eval:ai-story
docker compose ps
ffmpeg -version
ffprobe -version

Local LLM Setup

The current local default is LM Studio.

Typical local settings:

LLM_PROVIDER=lmstudio
LLM_BASE_URL=http://127.0.0.1:1234/v1
LLM_MODEL=qwen3-8b
AI_EMBEDDING_MODEL=text-embedding-nomic-embed-text-v1.5
AI_EMBEDDING_DIMENSIONS=192

Recommended local workflow:

  1. Start LM Studio server
  2. Load your chat model
  3. Load your embedding model
  4. Start the Node app

The current local setup expects:

  • a chat model such as qwen3-8b
  • an embedding model such as text-embedding-nomic-embed-text-v1.5

The current codebase supports:

  • chat/text generation
  • embeddings
  • agent-loop execution through the agent-system

Web Search Tooling

The researcher agent can now use a web search tool.

Current search config:

WEB_SEARCH_PROVIDER=duckduckgo
WEB_SEARCH_TIMEOUT_MS=10000
WEB_SEARCH_BRAVE_API_KEY=

Behavior:

  • default: DuckDuckGo
  • optional: Brave Search when WEB_SEARCH_PROVIDER=brave and WEB_SEARCH_BRAVE_API_KEY is set

Media Service

Image and media generation are handled by the Python service in media_service/.

Node delegates media jobs to that service rather than trying to run those pipelines in-process.

Important local Node-side settings:

MEDIA_SERVICE_URL=http://127.0.0.1:8091
MEDIA_CALLBACK_BASE_URL=http://127.0.0.1:3333
IMAGE_PROVIDER=local

The detailed model/runtime settings for image and video generation live primarily in:

  • media_service/.env

Production-Style Docker Setup

The production-style compose stack is available in:

  • docker-compose.prod.yml

Important

This stack does not use .env as the main app env file.

It currently uses:

  • .env.docker for the app container
  • media_service/.env for the media service container

Start

docker compose -f docker-compose.prod.yml up --build -d

Stop

docker compose -f docker-compose.prod.yml down

Ops profile

docker compose -f docker-compose.prod.yml --profile ops up -d

What prod compose starts

  • app
  • media server
  • Postgres
  • Redis
  • optional pgAdmin via profile

Notes

  • the app container reads .env.docker
  • the media server reads media_service/.env
  • compose overrides internal service URLs for Postgres/Redis/media callbacks
  • the media server expects access to host AI model files at /mnt/storage/ai
  • GPU access is expected for the media server

Current Creation Pipeline

At a high level:

  1. ingest sources
  2. extract documents
  3. cluster and rank candidate stories
  4. select stories
  5. generate post draft
  6. judge/retry if needed
  7. generate media
  8. save drafts
  9. publish or schedule

The agent-based parts currently include:

  • research selection
  • AI story writing
  • AI/story judging
  • post generation and judging

Operationally, generation also runs through:

  • BullMQ-backed AI generation tasks
  • the Node application layer in src/application/
  • the Python media service for image output

Running the Headless Runner

To run the runner outside Docker using .env:

npm run prod

This is the scheduled/headless path for ingestion and post generation.

Authentication and Admin

The app currently includes:

  • local auth
  • Facebook auth/connect
  • YouTube auth/connect
  • super-admin/internal admin endpoints

The UI and APIs are served from the same Node app.

Notes on Drift and Defaults

If you are reading older discussions or docs, these are the current realities:

  • agent-system is now the canonical home for the agentic backend
  • LM Studio is the default local LLM path
  • embeddings are configured for dimension 192
  • web search exists and is configurable
  • media generation is delegated to media_service
  • Docker production-style setup uses .env.docker, not .env, for the app container

Recommended Next Docs Cleanup

The README is now aligned with the current codebase at a high level, but two adjacent docs/config surfaces are still worth keeping in sync over time:

  • .env.example
  • media_service/README.md

Secure Env Sharing

If you need to share env files safely, age is a simple option.

Install:

# Ubuntu/Debian
sudo apt-get install -y age

# macOS
brew install age

Encrypt:

age -p -o .env.age .env

Decrypt:

age -d -o .env .env.age

Good practice:

  • send encrypted env and passphrase in different channels
  • use a one-time strong passphrase
  • never commit decrypted secrets

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors