ghmk's picture
Add security improvements for public deployment
c078ea1
"""
Character Forge - Main Application Entry Point
===============================================
License: GNU AGPL v3.0
Copyright (C) 2025 Gregor Hubert, Max Koch "cronos3k"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Main entry point for the Character Forge Streamlit application.
Run with: streamlit run app.py
"""
import streamlit as st
from pathlib import Path
# Import configuration
from config.settings import Settings
# Import components
from ui.components.backend_selector import render_backend_selector
from ui.components.status_display import render_status_display
def initialize_session_state():
"""
Initialize Streamlit session state with default values.
Session state is Streamlit's way of persisting data across reruns.
This function sets up all the global state our app needs.
"""
# Backend selection
if 'backend' not in st.session_state:
st.session_state.backend = "Gemini API (Cloud)"
# API keys
if 'gemini_api_key' not in st.session_state:
st.session_state.gemini_api_key = Settings.get_gemini_api_key()
# Output directory
if 'output_dir' not in st.session_state:
st.session_state.output_dir = Settings.OUTPUT_DIR
# Generation history
if 'history' not in st.session_state:
st.session_state.history = []
def render_header():
"""Render the application header and global controls."""
st.set_page_config(
page_title="Character Forge - AI Image Generation",
page_icon="πŸ”₯",
layout="wide",
initial_sidebar_state="expanded"
)
st.title("πŸ”₯ Character Forge - AI Image Generation")
st.markdown(
"""
**Professional character sheets and multi-image composition powered by AI**
*Supports Gemini API, OmniGen2, and ComfyUI backends*
"""
)
# Show API key warning if not configured
if not st.session_state.get('gemini_api_key'):
st.warning(
"⚠️ **API Key Required**: Please enter your Gemini API key in the sidebar to start generating. "
"Get a free API key at [Google AI Studio](https://aistudio.google.com/app/apikey).",
icon="πŸ”‘"
)
st.divider()
def render_global_backend_selector():
"""
Render the global backend selector that applies to all pages.
This is one of the key improvements over Gradio - no parameter drilling!
The backend selection is stored in session_state and accessible everywhere.
"""
st.subheader("πŸ”§ Generation Backend")
col1, col2 = st.columns([2, 1])
with col1:
# Render the backend selector component
backend = render_backend_selector()
st.session_state.backend = backend
with col2:
# Render status display
if st.button("πŸ”„ Refresh Status"):
st.rerun()
st.divider()
def render_sidebar():
"""Render the sidebar with navigation and settings."""
with st.sidebar:
st.image("https://via.placeholder.com/150x150.png?text=🍌", width=150)
st.markdown("## Navigation")
st.page_link("pages/01_πŸ”₯_Character_Forge.py", label="πŸ”₯ Character Forge")
st.page_link("pages/02_🎬_Composition_Assistant.py", label="🎬 Composition Assistant")
st.page_link("pages/03_πŸ“Έ_Standard_Interface.py", label="πŸ“Έ Standard Interface")
st.divider()
st.markdown("## Settings")
# API Key input (for Gemini)
st.markdown("### πŸ”‘ API Key")
st.info("Get your FREE API key at [Google AI Studio](https://aistudio.google.com/app/apikey)")
api_key = st.text_input(
"Gemini API Key",
value=st.session_state.gemini_api_key or "",
type="password",
help="Enter your Google Gemini API key. Required for Gemini backend. Your key stays in YOUR session only.",
placeholder="Enter your API key here..."
)
if api_key != st.session_state.gemini_api_key:
st.session_state.gemini_api_key = api_key
# Output directory
st.text_input(
"Output Directory",
value=str(st.session_state.output_dir),
disabled=True,
help="All generated images are saved here"
)
st.divider()
st.markdown("## About")
st.markdown(
"""
**Character Forge** v1.0.0
Multi-backend AI image generation with specialized tools for:
- Character sheet creation
- Multi-image composition
- Text/image-to-image generation
---
**License:**
GNU AGPL v3.0
**Privacy:**
Your API key is stored only in YOUR session.
It is never shared with other users.
**Get Started:**
- [Get API Key](https://aistudio.google.com/app/apikey)
- [HuggingFace Space](https://huggingface.co/spaces/ghmk/character_forge)
"""
)
def main():
"""Main application entry point."""
# Initialize session state
initialize_session_state()
# Render header
render_header()
# Render global backend selector
render_global_backend_selector()
# Render sidebar
render_sidebar()
# Main content area
st.info(
"""
πŸ‘ˆ **Select a tool from the sidebar to get started:**
- **πŸ”₯ Character Forge**: Create multi-angle character sheets automatically
- **🎬 Composition Assistant**: Smart multi-image composition with auto-prompts
- **πŸ“Έ Standard Interface**: Direct text-to-image and image-to-image generation
The backend selector above applies to all tools.
"""
)
# Show recent generations
if st.session_state.history:
st.subheader("πŸ“Έ Recent Generations")
cols = st.columns(4)
for idx, item in enumerate(st.session_state.history[-4:]):
with cols[idx]:
st.image(item['image'], caption=item['name'], use_container_width=True)
if __name__ == "__main__":
main()