Skip to main content
The Flask starter template is a lightweight Python application with a Preact frontend. Perfect for developers who prefer Python and want a simple, no-build-tools approach.

Quick Start

1

Clone the template

npx degit tough-tongue/docs/flask-minimal my-ttai-app
cd my-ttai-app
2

Create virtual environment

python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
3

Install dependencies

pip install -r requirements.txt
4

Configure environment

Create a .env file:
.env
TTAI_TOKEN=your_api_key_here
API_BASE_URL=https://api.toughtongueai.com/api/public
PORT=8008
Get your API key from the Developer Portal.
5

Update scenario ID

Edit www/config.js:
www/config.js
export const toughTongueConfig = {
  baseUrl: "https://app.toughtongueai.com",
  scenarioId: "YOUR_SCENARIO_ID_HERE",
  defaultStyles: {
    name: "Assessment",
    color: "indigo-500",
    background: "white",
  },
};
6

Run the app

python app.py
Visit http://localhost:8008

What’s Included

Flask Backend

Secure API proxy routes to protect your API key

Preact Frontend

Lightweight React alternative, no build tools needed

Iframe Integration

Ready-to-use ToughTongue embed with event handling

Session Analysis

Built-in analysis endpoint integration

Project Structure

flask-minimal/
├── app.py                 # Main Flask app (static file server)
├── api/
│   └── index.py           # API routes for ToughTongue integration
├── www/                   # Frontend assets
│   ├── index.html         # Main HTML page
│   ├── app.js             # Main application logic (Preact)
│   ├── assessment.js      # Assessment page with iframe handling
│   ├── config.js          # Configuration (scenario ID, styles)
│   ├── styles.css         # Application styling
│   └── components/
│       └── results.js     # Results display component
├── requirements.txt       # Python dependencies
└── vercel.json            # Vercel deployment config

Core Integration Patterns

1. Embedding the Iframe

The iframe is embedded in www/assessment.js:
const buildIframeUrl = () => {
  let baseUrl = `${toughTongueConfig.baseUrl}/embed/${toughTongueConfig.scenarioId}`;
  const params = new URLSearchParams();
  params.append("name", toughTongueConfig.defaultStyles.name);
  params.append("color", toughTongueConfig.defaultStyles.color);
  params.append("bg", toughTongueConfig.defaultStyles.background);
  params.append("pulse", "true");
  params.append("transcribe", "true");
  return `${baseUrl}?${params.toString()}`;
};

2. Listening for Events

Handle iframe events in www/assessment.js:
useEffect(() => {
  const handleMessage = async (event) => {
    const data = event.data;
    if (data && data.event) {
      switch (data.event) {
        case "onStart":
          // Session started - store session ID
          setSessionData({
            sessionId: data.sessionId,
            status: "started",
            timestamp: data.timestamp,
          });
          break;
        case "onStop":
          // Session completed - ready for analysis
          setSessionData((prev) => ({
            ...prev,
            status: "completed",
            timestamp: data.timestamp,
          }));
          break;
      }
    }
  };
  window.addEventListener("message", handleMessage);
  return () => window.removeEventListener("message", handleMessage);
}, []);

3. Analyzing Sessions

After a session completes, analyze it via the backend API: Frontend (www/assessment.js):
const analyzeSession = async (sessionId) => {
  const response = await fetch("/api/analyze", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ session_id: sessionId }),
  });
  return await response.json();
};
Backend (api/index.py):
@app.route("/api/analyze", methods=["POST"])
def analyze():
    data = request.json
    response = requests.post(
        f"{API_BASE_URL}/sessions/analyze",
        json=data,
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {TTAI_TOKEN}",
        },
    )
    return jsonify(response.json()), response.status_code

API Endpoints

The Flask backend provides these API proxy routes:

POST /api/analyze

Analyzes a completed session:
// Request
{ "session_id": "SESSION_ID" }

// Response
{
  "session_id": "SESSION_ID",
  "analysis": {
    "overall_score": 85,
    "strengths": ["Clear communication"],
    "areas_for_improvement": ["Response time"]
  }
}

GET /api/sessions/<session_id>

Retrieves session details:
{
  "id": "session_id",
  "scenario_id": "scenario_id",
  "transcript": "...",
  "duration": 300,
  "created_at": "2024-01-01T00:00:00Z"
}

Customization

Changing the Scenario

Update the scenario ID in www/config.js:
export const toughTongueConfig = {
  scenarioId: "YOUR_NEW_SCENARIO_ID",
  // ...
};

Styling

Modify www/styles.css to customize appearance. The starter includes:
  • Responsive layout
  • Card-based UI components
  • Smooth transitions
  • CSS variables for theming

Adding New API Endpoints

Add routes in api/index.py:
@app.route("/api/your-endpoint", methods=["POST"])
def your_endpoint():
    data = request.json
    # Your logic here
    return jsonify({"result": "success"})

Adding New Components

Create files in www/components/:
// www/components/my-component.js
import { h } from "https://unpkg.com/preact?module";

export function MyComponent({ prop }) {
  return h("div", { class: "my-component" }, prop);
}

Environment Variables

VariableRequiredDefaultDescription
TTAI_TOKENYes-Your ToughTongue AI API token
API_BASE_URLNohttps://api.toughtongueai.com/api/publicAPI base URL
PORTNo8008Server port

Deployment

The project includes vercel.json for serverless deployment:
1

Install Vercel CLI

npm install -g vercel
2

Deploy

cd flask-minimal
vercel
3

Add environment variables

In Vercel dashboard, add TTAI_TOKEN to your project’s environment variables.
4

Deploy to production

vercel --prod

Other Platforms

For other platforms (Heroku, Railway, etc.):
  1. Ensure Python 3.9+ is available
  2. Set environment variables
  3. Configure start command: python app.py
  4. Ensure port is configurable via PORT environment variable
For production, consider using gunicorn:
pip install gunicorn
gunicorn app:app

Troubleshooting

Check:
  • Verify TTAI_TOKEN is set correctly in .env
  • Check token hasn’t expired
  • Ensure token has necessary permissions
Check: - Verify scenario ID is correct in www/config.js - Check scenario is set to is_public: true in ToughTongue AI dashboard - Review browser console for errors - Ensure HTTPS is used in production (required for microphone access)
Check: - Check WWW_DIR path in app.py is correct - Verify files exist in www/ directory
  • Check file permissions
Flask-CORS is already configured in api/index.py. If issues persist, check API base URL is correct.

Dependencies

  • Flask 2.0+: Web framework
  • requests: HTTP library for API calls
  • flask-cors: CORS support
  • python-dotenv: Environment variable management
  • gunicorn: Production WSGI server (optional)

Learn More

API Reference

ToughTongue AI API documentation

Iframe Events

Complete iframe integration guide

Troubleshooting

Common issues and solutions