Flask Diagrammer v43: From Concept to Canvas with AI-Powered Visualization
by README Architect
Summary
Dive into "Flask Diagrammer v43: From Concept to Canvas with AI-Powered Visualization" and revolutionize how you bring complex ideas to life. This comprehensive guide unveils Flask Diagrammer v43, a cutting-edge tool designed to streamline the creation of intricate diagrams, flowcharts, and system architectures. Whether you're mapping out software designs, visualizing data flows, or documenting complex processes, Flask Diagrammer v43 transforms abstract concepts into clear, actionable visual representations with unparalleled ease, guiding you from initial setup to mastering its core functionalities. Beyond its intuitive UI and robust features for crafting diagrams, this book explores the groundbreaking integration of AI-powered design, leveraging Google Gemini to generate sophisticated diagrams from natural language prompts, dramatically accelerating your workflow. For those curious about the mechanics, it also delves "Under the Hood," exposing the architecture, the powerful BEJSON (Boehnen Elton JSON) schema, and efficient data management strategies that make Flask Diagrammer v43 a truly robust and scalable solution. Get ready to elevate your visualization game, from initial concept to a polished, AI-assisted canvas.
Introduction to Flask Diagrammer v43
Introduction to Flask Diagrammer v43
Welcome to Flask Diagrammer v43: From Concept to Canvas with AI-Powered Visualization. This book delves into the architecture and functionality of the Flask Diagrammer, a powerful web-based tool designed for creating and managing hierarchical node-based diagrams. Version 43 represents a significant evolution, integrating a robust Flask backend with an interactive frontend, and introducing cutting-edge AI capabilities for diagram generation.
What is Flask Diagrammer v43?
At its core, Flask Diagrammer v43 is a Flask-hosted BEJSON Diagrammer. It provides a rich, interactive user interface in the browser, powered by a lightweight yet capable Python Flask server. The application is specifically engineered for visualizing structured data following the BEJSON 104db schema, offering an intuitive way to map out complex relationships and hierarchies.
The Flask server (app.py) is responsible for serving the diagrammer's UI (index.html) and handling critical backend operations, most notably the export of diagrams. One of its standout features is the automatic server-side persistence: every diagram exported by the user is automatically saved to a dedicated diagrams/ subfolder on the server.
Key Features at a Glance
Flask Diagrammer v43 combines several innovative features to deliver a seamless diagramming experience:
- Interactive Canvas: A dynamic drag-and-drop interface for creating, positioning, and connecting nodes and shapes.
- Flask Backend: A Python Flask application serving the UI and managing server-side operations, ensuring data integrity and persistence.
- BEJSON 104db Schema Compliance: Diagrams are structured and exported according to the BEJSON standard, facilitating data interchange and programmatic manipulation.
- Automatic Server-Side Saving: Every diagram exported by the user is automatically saved as a
.jsonfile in thediagrams/directory on the server, in addition to being offered as a client-side download. - AI-Powered Diagram Generation: Integration with the Gemini API allows users to generate complex diagrams from natural language prompts, revolutionizing the initial concept-to-canvas workflow.
- Hierarchical Node Management: Support for parent-child relationships between nodes, enabling the creation of intricate organizational structures with features like node collapsing.
- Customizable Styling: Nodes can be customized with various colors and text styles, and the application supports both light and dark themes.
- Ruler and Grid Snap: Precision tools for aligning and positioning elements on the canvas.
- Import/Export Functionality: Diagrams can be imported from or exported to BEJSON
.jsonfiles, ensuring portability and archival capabilities.
What's New in v43?
Version 43 marks a pivotal shift for the BEJSON Diagrammer, transforming it from a standalone HTML application into a full-fledged Flask-based system. Key changes and improvements include:
- Flask Conversion: The entire application, previously a standalone HTML file, has been re-architected to run as a Flask web application. This brings the benefits of a robust backend, including easier integration with other services and enhanced security.
-
Dedicated Export API: A new
/api/exportendpoint has been introduced inapp.py. This endpoint specifically handles incoming BEJSON data, saves it to the server'sdiagrams/subfolder, and then facilitates the download of the same file to the client. This ensures both local backup and user-initiated downloads.@app.route('/api/export', methods=['POST']) def export_diagram(): data = request.get_json(force=True) name = data.get('Diagram_Name', 'untitled') safe = ''.join(c if c.isalnum() or c in ('_', '-') else '_' for c in name).lower() filename = safe + '.json' # Auto-save to diagrams/ with open(os.path.join(DIAGRAMS_DIR, filename), 'w') as f: json.dump(data, f, indent=2) # Return as download buf = io.BytesIO(json.dumps(data, indent=2).encode('utf-8')) buf.seek(0) return send_file(buf, as_attachment=True, download_name=filename, mimetype='application/json') - Enhanced Data Persistence: The new Flask backend guarantees that all exported diagrams are automatically archived on the server, providing a reliable record of your work.
- AI Integration: While the core diagramming logic was adapted, the UI was extended to include direct integration with Google's Gemini AI models, allowing for diagram generation from text prompts.
-
Minor Fixes and Optimizations: Version 43.1.0 specifically addressed a critical CSS issue (
html{height:100%}) to ensure proper vertical anchoring for the grid layout, enhancing the visual stability and responsiveness of the application.
This book will guide you through setting up, using, and extending Flask Diagrammer v43, exploring its code, design principles, and the powerful combination of Flask and AI for visualization.
Getting Started: Installation and First Run
Getting Started: Installation and First Run
Flask Diagrammer v43 is a powerful, AI-powered visualization tool designed to help you construct and manage complex node diagrams using the BEJSON 104db schema. This chapter will guide you through setting up and running the application on your local machine, ensuring you have everything you need to start visualizing your data.
Prerequisites
Before you begin, ensure you have the following installed on your system:
- Python 3.x: Flask Diagrammer v43 requires Python. You can download it from the official Python website.
- pip: Python's package installer, usually bundled with Python 3.4 or later.
Installation
Follow these steps to set up the Flask Diagrammer project:
- Create Project Structure: Create a new directory for your project and set up the basic file structure as follows:
flask-diagrammer-v43/ ├── app.py └── templates/ └── index.html - Place Source Files:
- Save the provided `app.py` content into `flask-diagrammer-v43/app.py`.
- Save the provided `index.html` content into `flask-diagrammer-v43/templates/index.html`.
- Create a Virtual Environment (Recommended):
It's good practice to use a virtual environment to manage project dependencies. Navigate to your project directory in the terminal and run:
cd flask-diagrammer-v43 python3 -m venv venv - Activate the Virtual Environment:
- macOS/Linux:
source venv/bin/activate - Windows:
venv\Scripts\activate
- macOS/Linux:
- Install Flask: With your virtual environment activated, install Flask using pip:
pip install Flask
First Run
Once Flask is installed, you can launch the application:
- Run the Flask Application: From your activated virtual environment in the `flask-diagrammer-v43` directory, execute `app.py`:
python app.pyYou should see output indicating that the Flask development server is running, typically on port 5000:
* Serving Flask app 'app' * Debug mode: on * Running on http://127.0.0.1:5000The application will automatically create a `diagrams/` subfolder in your project root if it doesn't already exist. This folder will be used for auto-saving your exported BEJSON diagrams.
- Access in Browser: Open your web browser and navigate to the address provided in the terminal, usually:
Your First Diagram
Upon opening the application, you will be greeted by the BEJSON Diagrammer interface. A default "Elton Boehnen" node will be present. You can start interacting immediately:
- Click the
+button (Floating Action Button) in the bottom-right to Add Root Node. - Select a node and use the PROPERTIES drawer (accessible via the
☰icon in the top-right) to modify its label, color, or add child nodes. - Explore the Object List (
≡icon in the bottom-left) to view and navigate your nodes. - Try out the Gemini AI Generator in the Properties drawer to create diagrams from natural language prompts (requires an API key).
- Remember, exporting your diagram via the "Export BEJSON" button will automatically save a
.jsonfile to thediagrams/folder on your server, in addition to triggering a download.
You are now ready to start building your own comprehensive BEJSON diagrams!
Crafting Diagrams: UI Features and Core Functionality
Chapter Overview
The Flask Diagrammer v43 presents a sophisticated, yet intuitive, web-based interface for creating and managing BEJSON diagrams. This chapter delves into the core UI features, interaction patterns, and underlying functionalities that empower users to craft complex visual representations with ease. From basic shape manipulation to advanced hierarchy management and AI-powered generation, we will explore the tools that bring your concepts to the canvas.
Core Diagramming Elements
At the heart of any diagramming tool are its fundamental building blocks. Flask Diagrammer v43 provides two primary elements: Shapes (Nodes) and Connectors (Lines).
Shapes (Nodes)
Shapes represent entities or concepts within your diagram. They are rectangular nodes with customizable properties and support hierarchical relationships.
- Adding Shapes:
- Root Nodes: Initiating new, independent nodes can be done via the Floating Action Button (FAB).
<div class="fab-item" onclick="app.addShape()"><span>Add Root Node</span></div> - Child Nodes: To build hierarchical structures, child nodes can be added directly from a selected parent node's properties panel.
<button onclick="app.addChildNode()">+ Add Child Node</button>
- Root Nodes: Initiating new, independent nodes can be done via the Floating Action Button (FAB).
- Properties: Each shape has several editable attributes:
- Label: A prominent title for the node.
- Body Text: Detailed descriptive text, editable in a dedicated text editor (Lightroom).
- Color & Font Color: Visual styling for the node's background and text. Font color can be set to 'auto' for intelligent contrast.
- Dimensions: Predefined size options (Square, Rect, Large, Massive) or custom sizing.
- Hierarchy: Displays parent/child relationships and the node's generation/tier. Nodes can be promoted to root nodes.
- Hierarchy Management:
- Make Root Node: Converts a child node into a top-level parent.
<button id="btn-mkroot" onclick="app.makeRoot()">↑ Make Root Node</button> - Collapse/Expand: Parent nodes with children can be collapsed to hide their descendants, simplifying complex diagrams.
<g onpointerdown="app.toggleCollapse(event,'${s.id}')">...</g>
- Make Root Node: Converts a child node into a top-level parent.
Connectors (Lines)
Connectors define relationships between shapes, visually indicating flow or association.
- Creation: Connectors are drawn by dragging between anchor points located at the corners and midpoints of each shape's edges. A "pending" state assists in linking.
<circle cx="${p.x}" cy="${p.y}" class="anc-hit" onpointerdown="app.anchorDown(event,'${s.id}',${i})"/> - Flow Direction: Connectors can display directional arrows (forward, backward, bidirectional) or none, providing semantic meaning to the connection.
<select id="inp-flow" onchange="app.upConn('flow',this.value)">...</select>
User Interface (UI) Overview
The diagrammer's UI is designed for efficiency and clarity, segmenting controls into logical panels and interactive areas.
Viewport and Canvas
The central interactive area where diagrams are built.
- Canvas (`#canvas-container`): The drawable area, featuring a customizable grid for alignment.
#canvas-container { background-image: linear-gradient(var(--grid) 1px, transparent 1px), linear-gradient(90deg, var(--grid) 1px, transparent 1px); background-size: 50px 50px; } - Viewport (`#viewport`): The scrollable and zoomable window into the canvas.
<div id="viewport"> <div id="canvas-container"> <svg id="canvas"></svg> </div> </div> - Zoom: Controls are available in the FAB to adjust the canvas zoom level, impacting the visibility of rulers and elements.
<div class="fab-item" onclick="app.zoom(.1)"><span>Zoom In</span></div> - Grid Snap: Toggles snapping of shapes to a 50px grid, aiding in precise alignment.
<input type="checkbox" id="chk-snap" checked onchange="app.setSnap(this.checked)"> <span><span class="snap-dot" id="snap-dot"></span>Grid Snap (50px)</span>
Rulers
Positioned along the top and left edges of the viewport, rulers provide visual coordinates for elements on the canvas, scaling with the zoom level.
<div class="ruler-h" id="ruler-top"></div>
<div class="ruler-v" id="ruler-left"></div>
Main Controls (Top-Right)
- Menu Toggle (☰): Opens/closes the Properties Drawer.
<div class="menu-toggle btn-icon pa" onclick="app.toggleDrawer()">☰</div> - Multi-Select Toggle (Sel): Activates multi-selection mode, allowing users to select multiple shapes for bulk actions.
<div class="multi-toggle btn-icon pa" id="btn-multi" onclick="app.toggleMulti()">Sel</div>
Floating Action Button (FAB - Bottom-Right)
A context-sensitive button that expands to reveal quick actions.
- Actions: Add Root Node, Open Live Schema, Zoom In, Zoom Out.
<div class="fab-main" onclick="app.toggleFab()">+</div>
Object Panel (Bottom-Left)
Provides a list-based view of all diagram objects, aiding in navigation and selection, especially for complex diagrams.
- Toggle: Activated by the Object FAB (≡).
<div class="obj-fab pa" id="obj-fab" onclick="app.toggleObjPanel()" title="Object List">≡</div> - Features:
- Lists all shapes with their labels and hierarchy tiers.
- Allows direct selection of shapes, instantly moving the viewport to the selected item.
- Indicates collapsed nodes and their hidden descendants.
- The panel header is draggable, allowing users to reposition it on the screen.
Properties Drawer (Right)
The primary control panel for editing selected diagram elements and system settings.
- Contextual Display: The content of the drawer dynamically changes based on whether a single shape, multiple shapes, a connector, or nothing is selected.
- Diagram Name: Edit the overall diagram title.
- Content (for Shapes): Update label, access the body text editor.
- Hierarchy (for Shapes): View parent/child info, add child nodes, make root.
- Style (for Shapes): Adjust color and font color.
- Dimensions (for Shapes): Resize shapes with predefined buttons.
- Line Flow (for Connectors): Set arrow directions.
- Gemini AI Generator: A powerful section allowing users to generate or augment diagrams using AI, providing an API key, selecting a model, defining a prompt, and choosing between append/replace modes.
<textarea id="ai-prompt" placeholder="Describe the diagram you want to build..."></textarea> <button onclick="app.generateDiagram()" class="red">GENERATE DIAGRAM</button> - System Controls: Toggle grid snap, Export/Import BEJSON, Toggle Theme, Delete Selected, About dialog.
Status Bar (Bottom)
Displays real-time information such as "Ready" status, operation feedback, and current zoom level.
<div class="status-bar">
<span id="st-l">Ready</span>
<span id="st-r">75%</span>
</div>
Lightroom
A full-screen overlay for focused editing tasks.
- Edit Body Text: Provides ample space for writing detailed descriptions for a selected shape.
<button onclick="app.openTextEditor()">Edit Body Text</button> - Live Schema (BEJSON): Displays the diagram's entire structure in BEJSON format, allowing users to view or even directly edit the underlying data.
<div class="fab-item" onclick="app.openSchemaView()"><span>Live Schema</span></div>
Core Functionality
Beyond the UI, specific functions drive the diagrammer's capabilities.
Selection and Manipulation
- Single & Multi-Selection: Users can select individual shapes or connectors, or enter multi-selection mode to select several shapes for group operations like deletion or moving.
function sel(ids) { ... } // Handles single/multi selection logic function onShapeDown(e, id) { ... } // Initiates shape selection and drag - Dragging & Panning: Shapes can be dragged around the canvas. The viewport itself can be panned to navigate large diagrams.
window.addEventListener('pointermove', onMove, { passive: false }); window.addEventListener('pointerup', onUp); - Deletion: Selected shapes or connectors can be removed from the diagram. If a parent is deleted, its children are re-parented to the deleted parent's parent.
<button id="btn-del" class="red" onclick="app.deleteSel()">Delete Selected</button> - Theme Toggling: Switches between light and dark modes for user preference.
<button onclick="app.toggleTheme()">Toggle Theme</button>
Data Input and Output (BEJSON)
The Flask Diagrammer leverages the BEJSON 104db schema for its data model, enabling robust import and export capabilities.
- Export BEJSON: Diagrams can be exported as a
.jsonfile, adhering to the BEJSON standard.Crucially, Flask Diagrammer v43 integrates a backend Flask server (`app.py`) to manage exports:
@app.route('/api/export', methods=['POST']) def export_diagram(): data = request.get_json(force=True) name = data.get('Diagram_Name', 'untitled') filename = safe + '.json' # Auto-save to diagrams/ with open(os.path.join(DIAGRAMS_DIR, filename), 'w') as f: json.dump(data, f, indent=2) # Return as download ... return send_file(buf, as_attachment=True, download_name=filename, mimetype='application/json')This means every export automatically saves a copy to the server's local
diagrams/subfolder, providing an automatic backup and history, in addition to the client-side download.<button onclick="app.exportData()">Export BEJSON</button> - Import BEJSON: Users can import existing BEJSON
.jsonfiles, loading diagrams directly into the canvas.<input type="file" accept=".json" onchange="app.importData(this)"> - Internal BEJSON Conversion: The frontend JavaScript (`index.html`) includes functions to serialize (`toBEJSON()`) and deserialize (`fromBEJSON()`) the diagram state to and from the BEJSON format, ensuring data integrity and interoperability.
AI-Powered Diagram Generation
A standout feature of v43 is its integration with the Gemini AI model, allowing users to generate complex diagrams from natural language prompts.
- API Key & Model Selection: Users provide their Gemini API key and select from various available Gemini models (e.g., Flash, Pro).
- Prompting: A text area allows users to describe the diagram they wish to create, including its structure, content, and relationships.
- Generation Mode: Users can choose to "Append" new AI-generated elements to the existing diagram or "Overwrite" the current diagram entirely.
- System Instructions: The AI is guided by a strict system instruction to ensure it generates BEJSON 104db compliant data, including rules for unique IDs, spacing, and attribute adherence.
const systemInstruction = `You are the BEJSON Diagrammer AI. Your core mission is to generate complex node diagrams following the strict BEJSON 104db tabular standard. ...`; // ... fetch call to Gemini API async function generateDiagram() { ... }
AI-Powered Design: Leveraging Gemini for Diagram Generation
AI-Powered Design: Leveraging Gemini for Diagram Generation
Flask Diagrammer v43 introduces a powerful integration with Google's Gemini AI, transforming how diagrams are created and iterated upon. This feature allows users to describe their desired diagram in natural language, and Gemini, guided by a strict schema, will generate the corresponding BEJSON structure, which Flask Diagrammer then visualizes instantly on the canvas. This significantly reduces the manual effort in diagram construction, enabling rapid prototyping and exploration of complex ideas.
The Gemini AI Generator Interface
The AI Generator is accessible within the main properties drawer of the Flask Diagrammer. When the drawer is opened (via the '☰' button in the top-right corner), a dedicated section titled "Gemini AI Generator" provides all the necessary controls:
- Gemini API Key: A required input field where you must provide your personal Gemini API key. This key authenticates your requests to Google's generative AI services.
- AI Model: A dropdown list allowing you to select from various Gemini models. Options include:
- Gemini 3 Flash (Preview)
- Gemini 3.1 Pro (Preview)
- Gemini 3.1 Flash-Lite (Preview)
- Gemini Flash-Lite (Latest)
- Gemini 2.5 Flash (Selected by default)
Choosing different models can influence the speed, cost, and quality of the generated diagrams.
- Generation Mode: Two radio buttons dictate how the AI's output is applied to your current diagram:
- Append: (Default) Adds the newly generated shapes and connectors to your existing diagram without modifying or deleting current elements. This is ideal for expanding a diagram or combining AI-generated sections.
- Overwrite: Replaces the entire current diagram with the AI-generated content. Use this mode when you want a completely new diagram based on your prompt.
- AI Prompt: A large textarea where you articulate your diagram concept. This is where you describe the nodes, their relationships, and any specific styling or hierarchical requirements. For example, "Create a diagram of a microservices architecture with three services: User, Product, Order. User connects to Product. Order connects to Product. Product connects to User."
- GENERATE DIAGRAM Button: Initiates the AI generation process.
- AI Status: A small status indicator that shows the current state of the AI operation (e.g., "AI Ready", "Generating...", "Success!", "Error: ...").
How Flask Diagrammer Guides Gemini
The core of this AI integration lies in the detailed system_instruction provided to the Gemini model.
This instruction rigorously defines the expected BEJSON 104db tabular format, ensuring that Gemini produces structured and
parsable output suitable for diagram rendering. The system instruction acts as a highly specific guide, transforming
Gemini from a general-purpose language model into an expert BEJSON diagram generator.
The system instruction includes the following key directives:
You are the BEJSON Diagrammer AI. Your core mission is to generate complex node diagrams
following the strict BEJSON 104db tabular standard.
### DATA STRUCTURES (STRICT):
1. Shapes (Entity: 'Shape'):
- id: unique string starting with 's' (e.g. s1, s2)
- x, y: numbers (MUST be multiples of 50)
- w, h: numbers (width/height, e.g. 200, 120)
- color, fontColor: hex strings
- label: Title string
- text: Body string (use \n for line breaks)
- parentId: id of parent shape or null
- collapsed: boolean
2. Connectors (Entity: 'Connector'):
- id: unique string starting with 'c' (e.g. c1, c2)
- from, to: { shapeId: string, anchorIndex: number }
- anchorIndex: 0=Top, 1=Right, 2=Bottom, 3=Left.
- flow: 'none', 'forward', 'backward', 'bidirectional'
### RULES:
- Respond ONLY with a clean JSON object: { "shapes": [...], "connectors": [...] }.
- Mode: [OVERWRITE or APPEND, depending on user selection]. Create a completely new diagram.
- Spacing: Ensure nodes are at least 200px apart.
Understanding the BEJSON Output
Gemini is specifically instructed to output a JSON object containing two arrays: "shapes" and "connectors".
Each element in these arrays strictly adheres to the BEJSON 104db schema for diagrammatic elements.
Shapes (Entity: 'Shape')
These represent the nodes or boxes in your diagram:
id: A unique string identifier for the shape, always starting with 's' (e.g.,"s1","s2").x, y: Numerical coordinates for the top-left corner of the shape. Crucially, these values must be multiples of 50 to align with the grid snapping.w, h: Numerical width and height of the shape (e.g.,200,120).color: A hexadecimal string representing the background color of the shape (e.g.,"#334").fontColor: A hexadecimal string for the text color, or"auto"for automatic dark/light detection.label: The main title or label displayed on the shape.text: The body text content within the shape. Use\nfor line breaks.parentId: Theidof the parent shape in a hierarchical structure, ornullif it's a root node.collapsed: A boolean value (trueorfalse) indicating if child nodes should be hidden.
Connectors (Entity: 'Connector')
These define the lines or arrows that link shapes:
id: A unique string identifier for the connector, always starting with 'c' (e.g.,"c1","c2").from, to: Objects specifying the start and end points of the connector.shapeId: Theidof the source or target shape.anchorIndex: An integer (0-7) indicating which anchor point on the shape the connector attaches to.0: Top-Left1: Top-Middle2: Top-Right3: Middle-Right4: Bottom-Right5: Bottom-Middle6: Bottom-Left7: Middle-Left
flow: A string indicating the directionality of the connector:"none","forward"(arrow at end),"backward"(arrow at start), or"bidirectional"(arrows at both ends).
Integrating AI-Generated Content
Once Gemini returns the JSON, Flask Diagrammer's generateDiagram() function takes over. It parses this JSON,
and based on the selected "Generation Mode" (Append or Overwrite), it either clears the current canvas or adds the new
shapes and connectors to the existing ones. Unique IDs are maintained to prevent conflicts. The diagram is then
re-rendered, displaying the AI-generated visualization immediately.
Key Considerations for AI Generation
- API Key Security: Treat your Gemini API key like a password. It is stored locally in the browser for the current session and not transmitted to the Flask server. However, always be mindful of where you enter it.
- Prompt Engineering: The quality and specificity of your prompt directly impact the AI's output. Experiment with different phrasing, break down complex diagrams into simpler parts, and explicitly mention desired shapes, connections, and even relative positioning.
- Iterative Design: The AI generator is a powerful assistant, not a replacement for human design. Use the "Append" mode to gradually build up complex diagrams, generating parts with AI and then refining them manually.
- Model Choice: Different Gemini models offer varying capabilities. If you encounter issues or want faster responses, try switching to a 'Flash' model. For more nuanced understanding of complex prompts, a 'Pro' model might be beneficial.
The Gemini AI integration in Flask Diagrammer v43 streamlines the initial conceptualization and layout phase of diagramming, allowing users to focus more on the logical structure and less on the manual drawing process.
Under the Hood: Architecture, BEJSON Schema, and Data Management
Under the Hood: Architecture, BEJSON Schema, and Data Management
Delving deeper into Flask Diagrammer v43 reveals a well-structured architecture designed for both user-friendliness and robust data handling. This chapter explores the core components that make the application tick: its Flask-based backend, the precise BEJSON data schema it employs, and the sophisticated mechanisms for managing diagram data, including its innovative AI integration.
Architectural Overview: Flask and the Single-Page Application
Flask Diagrammer v43 adopts a classic client-server model, with a lightweight Python Flask backend serving a rich JavaScript frontend. This architecture ensures a smooth, interactive user experience while offloading data persistence and certain server-side operations to Python.
-
Flask Backend (
app.py): The Python fileapp.pyserves as the application's minimalist server. Its primary responsibilities include:- Serving the main diagrammer interface (
index.html) as a single-page application (SPA). - Providing an API endpoint (
/api/export) for handling diagram exports. This endpoint not only facilitates client-side download but also performs an automatic server-side save of the diagram. - Ensuring the necessary `diagrams/` directory exists for persistent storage.
The backend is intentionally lean, focusing on foundational tasks, allowing the frontend to manage the majority of the application's complexity.
# File: app.py import json import io import os from flask import Flask, render_template, request, send_file app = Flask(__name__) DIAGRAMS_DIR = os.path.join(os.path.dirname(__file__), 'diagrams') os.makedirs(DIAGRAMS_DIR, exist_ok=True) @app.route('/') def index(): return render_template('index.html') @app.route('/api/export', methods=['POST']) def export_diagram(): data = request.get_json(force=True) name = data.get('Diagram_Name', 'untitled') safe = ''.join(c if c.isalnum() or c in ('_', '-') else '_' for c in name).lower() filename = safe + '.json' # Auto-save to diagrams/ with open(os.path.join(DIAGRAMS_DIR, filename), 'w') as f: json.dump(data, f, indent=2) # Return as download buf = io.BytesIO(json.dumps(data, indent=2).encode('utf-8')) buf.seek(0) return send_file(buf, as_attachment=True, download_name=filename, mimetype='application/json') if __name__ == '__main__': app.run(debug=True, port=5000) - Serving the main diagrammer interface (
-
Frontend (
index.html): The bulk of the application's logic resides within `index.html`. It's a self-contained Single-Page Application (SPA) leveraging HTML, CSS, and a substantial JavaScript codebase encapsulated within an `app` IIFE (Immediately Invoked Function Expression). This JavaScript orchestrates:- Rendering the interactive diagram canvas, shapes, and connectors using SVG.
- Handling user interactions (dragging, selecting, adding/deleting elements).
- Managing the application's state (
Sobject). - Interfacing with the Flask backend for data export and the Gemini AI API for diagram generation.
- Providing the entire user interface, including rulers, property drawers, and the object panel.
-
Communication: The frontend communicates with the backend via standard HTTP requests. Specifically, diagram export is handled by a `POST` request to the `/api/export` endpoint, sending the current diagram state as a JSON payload.
The BEJSON Standard: A Tabular Approach to Diagram Data
Flask Diagrammer v43 utilizes a custom data format called BEJSON (presumably "Boehnen's Export JSON") version 104db for representing diagrams. This standard employs a tabular structure, defining fields and then listing values in corresponding arrays. This approach can be efficient for storing structured data and is explicitly designed for hierarchical diagrams.
The toBEJSON() function in index.html is responsible for serializing the current diagram state into this format. Here's a breakdown of the schema:
{
"Format": "BEJSON",
"Format_Version": "104db",
"Format_Creator": "Elton Boehnen",
"Diagram_Name": "Your Diagram Name",
"Records_Type": ["Shape", "Connector"],
"Fields": [
// Fields for Shape records
{ "name": "Record_Type_Parent", "type": "string" }, // "Shape" or "Connector"
{ "name": "id", "type": "string", "Record_Type_Parent": "Shape" },
{ "name": "x", "type": "number", "Record_Type_Parent": "Shape" },
{ "name": "y", "type": "number", "Record_Type_Parent": "Shape" },
{ "name": "w", "type": "number", "Record_Type_Parent": "Shape" },
{ "name": "h", "type": "number", "Record_Type_Parent": "Shape" },
{ "name": "label", "type": "string", "Record_Type_Parent": "Shape" },
{ "name": "color", "type": "string", "Record_Type_Parent": "Shape" },
{ "name": "fontColor", "type": "string", "Record_Type_Parent": "Shape" },
{ "name": "text", "type": "string", "Record_Type_Parent": "Shape" },
{ "name": "parentId", "type": "string", "Record_Type_Parent": "Shape" },
{ "name": "generation", "type": "integer", "Record_Type_Parent": "Shape" },
{ "name": "collapsed", "type": "boolean", "Record_Type_Parent": "Shape" },
// Fields for Connector records
{ "name": "id", "type": "string", "Record_Type_Parent": "Connector" },
{ "name": "from", "type": "string", "Record_Type_Parent": "Connector" }, // shapeId
{ "name": "fromIdx", "type": "integer", "Record_Type_Parent": "Connector" }, // Anchor index (0-7)
{ "name": "to", "type": "string", "Record_Type_Parent": "Connector" }, // shapeId
{ "name": "toIdx", "type": "integer", "Record_Type_Parent": "Connector" }, // Anchor index (0-7)
{ "name": "flow", "type": "string", "Record_Type_Parent": "Connector" } // 'none', 'forward', 'backward', 'bidirectional'
],
"Values": [
// Each inner array corresponds to a Shape or Connector record,
// with values ordered according to the "Fields" array.
// Example Shape record:
["Shape", "s1", 100, 100, 200, 120, "Root Node", "#334", "auto", "Some description", null, 0, false, null, null, null, null, null, null],
// Example Connector record:
[ "Connector", null, null, null, null, null, null, null, null, null, null, null, null, "c1", "s1", 5, "s2", 1, "forward"]
]
}
Key Elements of the BEJSON Schema:
-
Format,Format_Version,Format_Creator,Diagram_Name: Standard metadata for identification and naming. -
Records_Type: Declares the types of records present in the `Values` array (e.g., "Shape", "Connector"). -
Fields: An array of objects defining the properties for each record type. Each field specifies its `name`, `type`, and the `Record_Type_Parent` it belongs to.-
Shape Fields:
id(string): Unique identifier for the shape (e.g., "s1").x,y(number): Coordinates on the canvas.w,h(number): Width and height of the shape.label(string): Primary text label for the shape.color(string): Background color (hex code).fontColor(string): Text color (hex code or "auto").text(string): Detailed body text (supports `\n` for line breaks).parentId(string): ID of the parent shape, establishing hierarchy.generation(integer): The hierarchical level of the shape (calculated dynamically).collapsed(boolean): Indicates if child nodes are hidden.
-
Connector Fields:
id(string): Unique identifier for the connector (e.g., "c1").from,to(string): TheshapeIds of the start and end shapes.fromIdx,toIdx(integer): The anchor index (0-7) on the respective shapes, determining the connection point.flow(string): Directionality of the connector ('none','forward','backward','bidirectional').
-
Shape Fields:
-
Values: A 2D array where each inner array represents a single record. The first element of each inner array (`v[0]`) indicates its `Record_Type_Parent` (e.g., "Shape" or "Connector"), and subsequent elements correspond to the `Fields` defined for that type, filling in `null` for irrelevant fields.
Data Management Lifecycle
Efficient data management is crucial for any diagramming tool. Flask Diagrammer v43 provides comprehensive features for saving, loading, and managing diagram data.
-
Frontend State Management:
The entire active diagram is managed in the frontend JavaScript `S` (State) object, which holds arrays of `shapes` and `connectors`, along with other operational parameters like zoom level, selection, and the diagram name. All user interactions directly modify this `S` object, and the `render()` function translates this state into SVG elements on the canvas.
-
Exporting Diagrams (
exportData()):When a user chooses to export a diagram:
- The `toBEJSON()` function converts the current frontend `S` state into the BEJSON format.
- This JSON data is sent via a `POST` request to the Flask backend's `/api/export` endpoint.
- The Flask server receives the data. It sanitizes the `Diagram_Name` to create a filename and automatically saves the BEJSON file into the `diagrams/` subfolder relative to `app.py`. This provides an inherent server-side backup mechanism for all exported diagrams.
- Concurrently, the Flask server sends the same JSON data back to the client as a downloadable file, allowing the user to save a local copy of their diagram.
This dual-save mechanism ensures both local and server-side persistence of the diagram data.
-
Importing Diagrams (
importData()):Diagrams can be loaded from local BEJSON files. The user selects a `.json` file via a file input, and JavaScript's `FileReader` asynchronously reads its content. The `fromBEJSON()` function then parses this JSON, validates it against the schema, and reconstructs the diagram by updating the frontend `S` state, which is then rendered on the canvas.
AI-Powered Generation: From Prompt to Diagram
A standout feature of v43 is its integration with the Gemini AI API, enabling users to generate complex diagrams from natural language prompts.
-
User Input: Users provide their Gemini API key, select an AI model, specify an generation mode (append or replace), and type a natural language prompt describing the desired diagram.
-
Prompting the AI: The
generateDiagram()function constructs a request to the Google Generative Language API. Crucially, it includes a detailedsystem_instruction. This instruction acts as a strict guide for the AI, informing it that it is the "BEJSON Diagrammer AI" and providing the exact `DATA STRUCTURES (STRICT)` for both `Shape` and `Connector` entities, including their fields, types, and specific rules (e.g., "x, y: numbers (MUST be multiples of 50)"). It also clarifies the generation mode (append or overwrite) and spacing rules.const systemInstruction = `You are the BEJSON Diagrammer AI. Your core mission is to generate complex node diagrams following the strict BEJSON 104db tabular standard. ### DATA STRUCTURES (STRICT): 1. Shapes (Entity: 'Shape'): - id: unique string starting with 's' (e.g. s1, s2) - x, y: numbers (MUST be multiples of 50) // ... other shape fields ... 2. Connectors (Entity: 'Connector'): - id: unique string starting with 'c' (e.g. c1, c2) - from, to: { shapeId: string, anchorIndex: number } - anchorIndex: 0=Top, 1=Right, 2=Bottom, 3=Left. // ... other connector fields ... ### RULES: - Respond ONLY with a clean JSON object: { "shapes": [...], "connectors": [...] }. - ${mode === 'replace' ? 'Mode: OVERWRITE. Create a completely new diagram.' : 'Mode: APPEND. Add to existing with unique IDs.'} - Spacing: Ensure nodes are at least 200px apart.`; -
Response Handling: Upon receiving a response from the Gemini API, the JavaScript code extracts the raw text, parses the embedded JSON object (which the AI is instructed to provide), and then integrates the generated `shapes` and `connectors` into the existing diagram state (`S.shapes`, `S.connectors`). Depending on the selected mode, it either replaces the current diagram or appends new elements, ensuring unique IDs.
This AI integration transforms the Diagrammer into a powerful ideation and rapid prototyping tool, allowing users to go "From Concept to Canvas" with unprecedented speed.