Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mofa-frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
dist/
.env
.DS_Store
*.log
37 changes: 37 additions & 0 deletions mofa-frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# MoFA FM

MoFA FM is a local AI podcast studio. It turns any article into a high-quality podcast script and synthesizes it into natural-sounding audio — running entirely on your machine. No cloud, no API keys, full privacy.

## Features

- **Offline-First**: Operates seamlessly against a local inference engine.
- **Visual Intelligence**: Real-time observability into the model's inner workings via the Theater view and Engine Monitor.
- **Design Excellence**: Highly polished interface with considered motion, sound design, and typography.
- **Robust Pipeline**: Hardened against intermittent network failures with intelligent retries.
- **Accessibility**: Full keyboard and screen reader support, honoring reduced-motion preferences.

## Quick Start

\`\`\`bash
npm install
npm run dev
\`\`\`

## Architecture

- **React + Vite**: Fast, modern frontend build.
- **Tailwind CSS**: Utility-first styling tied to a strict design token system.
- **Framer Motion**: Smooth, intentional animations and state transitions.

### Mock vs. Real Engine

MoFA FM is designed to run against the **MoFA Core Engine** (at `127.0.0.1:8420`).
However, for development and demonstration without the heavy backend, the app can run against a simulated local mock engine.

To use the mock engine, create a `.env` file or set the environment variable:
\`\`\`env
VITE_USE_MOCK=true
VITE_ENGINE_URL=http://localhost:8420
\`\`\`

If `VITE_USE_MOCK=false`, the application will make real HTTP and SSE connections to your local Engine.
27 changes: 27 additions & 0 deletions mofa-frontend/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';

export default tseslint.config({
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }]
},
});
15 changes: 15 additions & 0 deletions mofa-frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0a0e17" />
<meta name="description" content="MoFA Engine — Local AI Orchestration" />
<title>MoFA Engine</title>
<link rel="icon" type="image/png" href="/mofa-logo.png" />
</head>
<body style="background-color: #0a0e17; color: #f0f4f8; margin: 0;">
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading
Loading