๐ ๏ธ Development¶
This guide explains how to set up, run, validate, document, and maintain the Jimi application. Jimi is a Streamlit-based AI assistant that integrates Google Gemini workflows, configurable runtime settings, SQLite-backed exception logging, and MkDocs-generated technical documentation.
The development workflow should protect three priorities:
- Keep the Streamlit application stable.
- Keep provider wrappers isolated and testable.
- Keep source comments compatible with MkDocs and mkdocstrings.
๐งญ Development Overview¶
Jimi is organized around a small set of core Python modules:
| File | Purpose |
|---|---|
app.py |
Streamlit application entry point, UI orchestration, session state, and workflow routing. |
gemini.py |
Google Gemini wrapper layer for text, image, embedding, audio, file, and storage workflows. |
config.py |
Runtime settings, paths, constants, environment values, and validation helpers. |
boogr.py |
Shared exception wrapper and SQLite logging implementation. |
requirements.txt |
Python package dependencies. |
mkdocs.yml |
MkDocs Material site configuration. |
docs/ |
Markdown documentation, generated API reference pages, CSS, JavaScript, and images. |
The preferred development model is to keep app.py focused on presentation and workflow routing
while keeping API-specific logic inside wrapper classes.
๐ฆ Project Layout¶
A recommended project structure is:
Jimi/
โโโ app.py
โโโ gemini.py
โโโ boogr.py
โโโ config.py
โโโ requirements.txt
โโโ mkdocs.yml
โโโ README.md
โโโ docs/
โ โโโ index.md
โ โโโ architecture.md
โ โโโ development.md
โ โโโ github-pages.md
โ โโโ api/
โ โ โโโ index.md
โ โ โโโ app.md
โ โ โโโ gemini.md
โ โ โโโ config.md
โ โ โโโ boogr.md
โ โโโ user-guide/
โ โ โโโ index.md
โ โ โโโ text-generation.md
โ โ โโโ document-qna.md
โ โ โโโ semantic-search.md
โ โ โโโ prompt-engineering.md
โ โ โโโ data-management.md
โ โโโ assets/
โ โโโ css/
โ โ โโโ jimi.css
โ โโโ js/
โ โ โโโ jimi.js
โ โโโ images/
โ โโโ jimi-architecture.png
โ โโโ jimi-class-map.png
โโโ logging/
โโโ Exceptions.db
The exact image filenames can be adjusted, but every file referenced in mkdocs.yml or Markdown
pages must exist under docs/.
๐ Python Environment Setup¶
Create and activate a virtual environment from the repository root.
Windows PowerShell¶
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txt
Command Prompt¶
python -m venv .venv
.venv\Scripts\activate.bat
python -m pip install --upgrade pip
pip install -r requirements.txt
macOS / Linux¶
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txt
๐ Environment Configuration¶
Jimi should load credentials and runtime settings from environment variables or local configuration values that are not committed to the repository.
Common environment values include:
$env:GEMINI_API_KEY="your-gemini-api-key"
$env:GOOGLE_API_KEY="your-google-api-key"
$env:GOOGLE_CLOUD_PROJECT_ID="your-google-cloud-project-id"
$env:GOOGLE_CLOUD_LOCATION="us-central1"
Do not commit secrets, .env files, local database files, generated cache files, or provider
credentials.
Recommended .gitignore entries include:
.venv/
__pycache__/
*.pyc
.env
.env.*
logging/*.db
logging/*.sqlite
site/
.cache/
.mypy_cache/
.pytest_cache/
.DS_Store
โถ๏ธ Running the Streamlit App¶
Run the application from the repository root:
The default Streamlit URL is usually:
During local development, use a clean terminal session with the virtual environment activated. This
reduces path issues and ensures the application uses the packages from .venv.
๐งฑ Development Responsibilities by Module¶
app.py¶
app.py is responsible for the Streamlit runtime and should remain focused on the user interface.
Keep these responsibilities in app.py:
- Page configuration.
- Sidebar controls.
- Session-state initialization.
- User input widgets.
- Uploaded-file handling.
- Workflow routing.
- Result rendering.
- Streamlit status messages.
- UI fallback behavior.
Avoid placing provider-specific SDK logic directly in app.py. If a workflow requires new Gemini
behavior, add that behavior to gemini.py first and call the wrapper method from app.py.
gemini.py¶
gemini.py is responsible for Google Gemini provider integration.
Keep these responsibilities in gemini.py:
- GenAI client creation.
- Gemini model configuration.
- Request payload construction.
- Tool configuration.
- Safety configuration.
- Response parsing.
- File upload and retrieval.
- Image extraction.
- Embedding generation.
- TTS audio conversion.
- Transcription and translation prompt construction.
- Google Cloud Storage interaction.
Each wrapper should expose high-level methods that app.py can call without knowing the internal
GenAI request schema.
config.py¶
config.py is responsible for centralizing runtime settings.
Keep these responsibilities in config.py:
- API key lookup.
- Runtime path definitions.
- Logging path definitions.
- Default model names.
- Application constants.
- Common validation helpers.
Avoid scattering hard-coded paths, API keys, database names, or model defaults across the codebase.
boogr.py¶
boogr.py is responsible for exception metadata and persistent logging.
Keep these responsibilities in boogr.py:
- Wrapping exceptions in
Error. - Capturing traceback details.
- Storing module, cause, method, message, and info fields.
- Creating the logging table when needed.
- Writing exception records to SQLite.
Do not duplicate logger implementation code in app.py or gemini.py. Use the shared Error and
Logger classes.
๐งพ Required Exception Logging Pattern¶
Every except Exception as e: block should use the shared logging pattern.
For hard failures, use:
except Exception as e:
ex = Error( e )
ex.module = 'module_name'
ex.cause = 'ClassOrWorkflowName'
ex.method = 'method_name( self, arg1, arg2 )'
Logger( ).write( ex )
raise ex
For recoverable UI fallbacks, log the exception but preserve the original fallback behavior:
except Exception as e:
ex = Error( e )
ex.module = 'app'
ex.cause = 'WorkflowName'
ex.method = 'render_workflow_panel( )'
Logger( ).write( ex )
st.warning( str( ex ) )
return None
For non-critical loop operations, preserve the original control flow:
except Exception as e:
ex = Error( e )
ex.module = 'app'
ex.cause = 'TableRendering'
ex.method = 'render_results_table( records )'
Logger( ).write( ex )
continue
Do not create duplicate wrapper objects in the same handler.
Correct:
except Exception as e:
ex = Error( e )
ex.module = 'gemini'
ex.cause = 'VectorStores'
ex.method = 'delete( self, bucket, name )'
Logger( ).write( ex )
raise ex
Incorrect:
The correct pattern creates one Error object, writes that same object once, and raises or returns
according to the original method behavior.
๐ง Google-Style Docstring Standard¶
Jimi source files should use Google-style docstrings that are compatible with MkDocs, mkdocstrings, and griffe.
Use these section names:
Purpose:Args:Attributes:Returns:Raises:Notes:Examples:
Do not use:
Parameters:Return:Purposewith underline separators.Args:entries for parameters that do not exist.Returns:in constructors that returnNone.selforclsinArgs:sections.
๐ Function Docstring Template¶
Use this template for normal functions and methods:
def generate_text( self, prompt: str, model: str = 'gemini-2.5-flash-lite' ) -> str | None:
"""
Purpose:
Generates a Gemini text response from validated user input and normalized
model configuration.
Args:
prompt: User prompt submitted from the application interface.
model: Gemini model identifier used for content generation.
Returns:
Generated response text when the provider returns text content; otherwise None.
Raises:
Error: Wraps and logs provider, validation, or response parsing failures.
"""
Use concise, accurate descriptions. The Purpose: section should describe what the method does, not
narrate how the developer wrote it.
๐งฑ Class Docstring Template¶
Use this template for classes:
class Chat( Gemini ):
"""
Purpose:
Provides text, multimodal, and tool-grounded Gemini content generation
operations for Streamlit application workflows.
Attributes:
client: Google GenAI client used to submit provider requests.
contents: Request content payload built from prompts, context, and files.
content_config: Gemini generation configuration for the current request.
content_response: Raw Gemini response returned by the provider.
"""
Class docstrings should document durable class responsibilities and meaningful instance attributes. Avoid listing temporary loop variables unless they are intentionally part of the object state.
๐ซ Constructor Docstring Rule¶
Constructors should document initialization behavior and attributes, but they should not include
Returns: when the return value is None.
Correct:
def __init__( self, model: str = 'gemini-2.5-flash-lite' ):
"""
Purpose:
Initializes the chat wrapper with default Gemini model settings, empty
request state, and response placeholders.
Args:
model: Default Gemini model identifier assigned to the wrapper.
Attributes:
model: Active Gemini model identifier.
client: Google GenAI client placeholder.
content_response: Provider response placeholder.
"""
Incorrect:
MkDocs and griffe can warn about constructor return documentation when it is unnecessary or inconsistent with annotations.
๐ Docstring Review Checklist¶
Before accepting a regenerated source file, inspect it for these issues:
Select-String -Path .\app.py -Pattern "Parameters:|Return:|Purpose\s*$|_{3,}|-{3,}"
Select-String -Path .\gemini.py -Pattern "Parameters:|Return:|Purpose\s*$|_{3,}|-{3,}"
Also inspect constructor return sections:
Select-String -Path .\app.py -Pattern "def __init__|Returns:" -Context 0,8
Select-String -Path .\gemini.py -Pattern "def __init__|Returns:" -Context 0,8
These checks are not replacements for a real build, but they quickly catch common documentation formatting failures.
โ Source Validation¶
Run syntax checks after every generated source replacement.
python -m py_compile .\app.py
python -m py_compile .\gemini.py
python -m py_compile .\config.py
python -m py_compile .\boogr.py
Then run a broader compilation pass:
A clean py_compile result confirms Python syntax only. It does not confirm provider credentials,
API availability, Streamlit runtime behavior, or MkDocs rendering.
๐งช Logging Validation¶
Use targeted searches to confirm every broad exception handler logs exactly once.
Select-String -Path .\app.py -Pattern "except Exception as e:|Error\( e \)|Logger\( \)\.write"
Select-String -Path .\gemini.py -Pattern "except Exception as e:|Error\( e \)|Logger\( \)\.write"
For a stronger validation, inspect each handler manually or use a short script that checks every
except Exception block for one Error( e ) wrapper and one Logger( ).write(...) call.
The expected rule is:
Every except Exception handler:
- creates one Error object
- assigns module/cause/method metadata
- writes that same object with Logger
- preserves the original raise, return, continue, pass, or fallback behavior
๐ MkDocs Setup¶
Install documentation dependencies from requirements.txt or explicitly install the required
packages:
The documentation build depends on:
mkdocs.yml- Markdown files under
docs/ - CSS and JavaScript assets under
docs/assets/ - API reference pages that use mkdocstrings directives
- Google-style docstrings in the Python source files
๐งพ API Reference Pages¶
A typical API page should use mkdocstrings:
Recommended API pages:
Each source module must be importable from the project root when mkdocs build runs. If MkDocs
cannot import a module, verify the paths: setting in mkdocs.yml.
๐๏ธ Building Documentation¶
Run:
For local preview:
Open the local site at:
If a page exists under docs/ but is not included in the nav: section of mkdocs.yml, MkDocs may
warn that the page is not included in navigation. Add the page to nav: or remove the unused file.
๐งฐ Common MkDocs Fixes¶
Missing site_name¶
If MkDocs reports:
Ensure the top of mkdocs.yml includes:
API reference only shows one file¶
Confirm each API page exists and is listed in nav::
nav:
- API Reference:
- Overview: api/index.md
- App: api/app.md
- Gemini: api/gemini.md
- Configuration: api/config.md
- Logging: api/boogr.md
Confirm each API page has the correct directive:
CSS or JavaScript not loading¶
Confirm paths are relative to the docs/ directory:
The files should be located at:
Image link not found¶
If Markdown references this:
The image must exist at:
If the image is in docs/assets/images/, reference it as:
๐ GitHub Pages Workflow¶
The recommended GitHub Pages workflow is to publish the generated documentation site from MkDocs.
Build locally first:
Then deploy with:
This pushes the generated site/ output to the gh-pages branch.
In GitHub repository settings:
- Open the repository.
- Go to Settings.
- Select Pages.
- Set the source to the
gh-pagesbranch. - Save the configuration.
The documentation site should become available at the configured GitHub Pages URL.
๐งช Pre-Commit Checklist¶
Before committing changes, run:
python -m py_compile .\app.py
python -m py_compile .\gemini.py
python -m py_compile .\config.py
python -m py_compile .\boogr.py
python -m compileall .
mkdocs build
Then verify:
No syntax errors.
No missing imports.
No MkDocs nav warnings that matter.
No griffe warnings from malformed docstrings.
No missing CSS or JavaScript assets.
No broken image paths.
No missing logging in exception handlers.
No duplicate Error wrappers in exception handlers.
๐งน Development Hygiene¶
Follow these rules while editing the codebase:
- Keep UI orchestration in
app.py. - Keep Gemini SDK calls in
gemini.py. - Keep configuration in
config.py. - Keep logging infrastructure in
boogr.py. - Do not hard-code credentials.
- Do not commit local databases.
- Do not commit generated
site/output unless the project intentionally tracks it. - Do not introduce undocumented public functions.
- Do not use non-Google docstring headings.
- Do not add new exception handlers without logging.
- Do not change fallback behavior unless intentionally refactoring the workflow.
๐งญ Recommended Development Sequence¶
When making significant changes, use this sequence:
- Update or add the wrapper method in
gemini.py. - Validate the method signature and docstring.
- Add exception logging with the required pattern.
- Add or update UI routing in
app.py. - Preserve Streamlit session-state keys.
- Compile all Python files.
- Update Markdown documentation.
- Run
mkdocs build. - Test the Streamlit workflow manually.
- Commit only after validation passes.
๐ Release Checklist¶
Before publishing a release or pushing documentation to GitHub Pages:
Source files compile.
Streamlit app starts.
Primary workflows run.
Exception logging writes to SQLite.
Documentation builds.
API reference renders all expected modules.
Dark theme CSS loads.
JavaScript enhancements load.
Images and icons resolve.
GitHub Pages points to the MkDocs site.
README links point to the documentation site.
A release should not be considered complete until both the application and documentation build successfully.
๐งญ Summary¶
The Jimi development workflow is built around controlled source changes, strict docstring formatting, consistent exception logging, and repeatable documentation builds. The project remains maintainable when the Streamlit interface, provider wrappers, configuration layer, and logging layer stay separated.
The core development rule is simple: