import streamlit as st import requests import json import streamlit.components.v1 as components import os # Import templates and icons from separate files from templates import ARCHITECTURE_TEMPLATES, get_all_providers, get_template from service_icons import SERVICE_ICONS, get_icon_url, map_service_to_icon # Page Configuration st.set_page_config( page_title="ArchViz AI Pro - Draw.io Style Icons", page_icon="🏗️", layout="wide" ) # API Configuration OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY") # UI Styling st.markdown("""

🏗️ ArchViz AI Pro Pro EditionDraw.io Icons

Enterprise Architecture Visualization with Official Cloud Service Icons

""", unsafe_allow_html=True) # Sidebar Configuration st.sidebar.title("📚 Cloud Architecture Library") st.sidebar.markdown("Select from professional architecture templates:") selected_provider = st.sidebar.selectbox( "Cloud Provider:", ["None"] + get_all_providers() ) if selected_provider != "None": templates = ARCHITECTURE_TEMPLATES[selected_provider] selected_template = st.sidebar.selectbox( f"{selected_provider} Templates:", list(templates.keys()) ) if st.sidebar.button("Load Template", use_container_width=True): template_data = templates[selected_template] st.session_state['template_text'] = template_data["description"] st.session_state['template_services'] = template_data.get("services", []) st.sidebar.markdown("---") st.sidebar.markdown(f"**Template: {selected_template}**") template_info = templates[selected_template] st.sidebar.info(template_info["description"][:200] + "...") st.sidebar.markdown(f"**Use Case:** {template_info['use_case']}") if "services" in template_info: st.sidebar.markdown(f"**Services:** {', '.join(template_info['services'])}") st.sidebar.markdown("---") st.sidebar.markdown("### ✨ Pro Features") st.sidebar.markdown(""" **🎨 Draw.io-Style Icons:** - ✅ Official AWS Architecture Icons - ✅ Official GCP Service Icons - ✅ Official Azure Service Icons - ✅ 100+ Service-Specific Icons **💼 Enterprise Features:** - ✅ Edit Generated Diagrams - ✅ High-Quality PNG Export - ✅ Fullscreen Presentation Mode - ✅ Professional Templates **Perfect for:** - Solution Architecture - RFP Responses - Client Presentations - Technical Documentation """) # Main Layout col1, col2 = st.columns([1, 1.5]) with col1: st.subheader("📝 Architecture Description") default_text = st.session_state.get('template_text', '') prompt_text = st.text_area( "Describe your cloud architecture:", value=default_text, height=200, placeholder="Example: Mobile app connects to AWS API Gateway, which routes to Lambda functions..." ) st.info("💡 **Pro Tip:** Mention specific service names (Lambda, Cloud Run, Functions App) to get official cloud icons!") col_gen, col_edit = st.columns(2) with col_gen: generate_btn = st.button("✨ Generate Diagram", type="primary", use_container_width=True) with col_edit: if 'mermaid_code' in st.session_state: edit_mode = st.button("✏️ Edit Code", use_container_width=True) if edit_mode: st.session_state['show_editor'] = not st.session_state.get('show_editor', False) # Show editor if requested if st.session_state.get('show_editor', False) and 'mermaid_code' in st.session_state: st.markdown("---") st.subheader("🛠️ Edit Diagram Code") edited_code = st.text_area( "Modify the Mermaid code:", value=st.session_state['mermaid_code'], height=250, key="editor", help="Edit the diagram structure, labels, or styling" ) col_apply, col_cancel = st.columns(2) with col_apply: if st.button("✅ Apply Changes", use_container_width=True): st.session_state['mermaid_code'] = edited_code st.session_state['show_editor'] = False st.rerun() with col_cancel: if st.button("❌ Cancel", use_container_width=True): st.session_state['show_editor'] = False st.rerun() # Display detected services if 'template_services' in st.session_state and st.session_state['template_services']: st.markdown("---") st.markdown("**📦 Template Services:**") services_html = "" for service in st.session_state['template_services']: provider, icon_url = map_service_to_icon(service) if icon_url: services_html += f' ' st.markdown(services_html, unsafe_allow_html=True) # API Call Logic if generate_btn and prompt_text: if not OPENROUTER_API_KEY: st.error("⚠️ OPENROUTER_API_KEY not found in environment variables!") else: with st.spinner("🎨 Creating your architecture diagram with official cloud icons..."): try: # Build enhanced prompt with icon information icon_guidance = """ IMPORTANT - Use service-specific names for proper icons: AWS: Lambda, API Gateway, DynamoDB, S3, CloudWatch, EC2, RDS, ECS, SQS, SNS, ALB, CloudFront GCP: Cloud Functions, Cloud Run, Firestore, Cloud SQL, BigQuery, Pub/Sub, GKE, Cloud Storage Azure: Functions, App Service, Cosmos DB, SQL Database, Application Insights, AKS, Storage Keep node labels SHORT (max 15 chars) - use abbreviations: - "API GW" not "API Gateway" - "Lambda" not "AWS Lambda Functions" - "DDB" not "DynamoDB Database" """ response = requests.post( url="https://openrouter.ai/api/v1/chat/completions", headers={ "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json", "HTTP-Referer": "http://localhost:8501", "X-Title": "ArchViz AI Pro", }, data=json.dumps({ "model": "arcee-ai/trinity-large-preview:free", "messages": [ { "role": "user", "content": f"""You are a cloud architecture diagram expert. Create a professional Mermaid diagram. {icon_guidance} REQUIREMENTS: 1. Use flowchart TB (top to bottom) or LR (left to right) 2. Keep ALL labels SHORT (under 15 characters) 3. Use exact service names from the list above 4. Style nodes with colors: compute (lightgreen), database (lightblue), storage (lightyellow), API (lightcoral), monitoring (lightgray) 5. Use arrows: --> for data flow, -.-> for async, ==> for main flow 6. Group services in subgraphs 7. Add clear flow labels EXAMPLE: graph TB subgraph "Client" A[Mobile App] end subgraph "API Layer" B[API Gateway] C[Lambda] end subgraph "Data" D[(DynamoDB)] end subgraph "Logs" E[CloudWatch] end A -->|"HTTPS"| B B -->|"Invoke"| C C -->|"Store"| D C -.->|"Logs"| E style B fill:#ffe1e1,stroke:#d32f2f,stroke-width:2px style C fill:#e1ffe1,stroke:#388e3c,stroke-width:2px style D fill:#e1e1ff,stroke:#303f9f,stroke-width:2px Convert this to a diagram: {prompt_text} Output ONLY Mermaid code. No explanations.""" } ] }) ) result = response.json() if "choices" in result: raw_mermaid = result['choices'][0]['message']['content'].strip() clean_mermaid = raw_mermaid.replace("```mermaid", "").replace("```", "").strip() # Extract service names from the generated diagram st.session_state['mermaid_code'] = clean_mermaid st.session_state['show_editor'] = False st.success("✅ Diagram generated with official cloud service icons!") st.rerun() else: st.error(f"API Error: {result.get('error', 'Unknown error')}") except Exception as e: st.error(f"Connection Error: {e}") # Diagram Rendering with col2: st.subheader("📊 Visual Diagram") # Icon legend st.markdown("""
🎨 Official Cloud Icons: AWS GCP Azure | API Compute Database
""", unsafe_allow_html=True) if 'mermaid_code' in st.session_state: mermaid_code = st.session_state['mermaid_code'] # Build comprehensive icon mapping for JavaScript with PROVIDER-SPECIFIC matching icon_map_items = [] # Create provider-specific service mappings with exact matches provider_services = {} # AWS services with their specific identifiers aws_services = { "lambda": ["lambda", "λ"], "api gateway": ["apigateway", "apigw", "apigateway", "api_gateway"], "dynamodb": ["dynamodb", "ddb"], "s3": ["s3"], "cloudwatch": ["cloudwatch", "cw"], "ec2": ["ec2"], "rds": ["rds"], "ecs": ["ecs"], "sqs": ["sqs"], "sns": ["sns"], "alb": ["alb", "applicationloadbalancer"], "elb": ["elb", "loadbalancer"], "cloudfront": ["cloudfront", "cf"], "vpc": ["vpc"], "route53": ["route53", "dns"], "cognito": ["cognito"], "kinesis": ["kinesis"], "step functions": ["stepfunctions", "stepfunction"], "eks": ["eks"], "fargate": ["fargate"], "elasticache": ["elasticache"], "aurora": ["aurora"] } # GCP services with their specific identifiers gcp_services = { "cloud functions": ["cloudfunctions", "gcf"], "cloud run": ["cloudrun"], "firestore": ["firestore"], "cloud sql": ["cloudsql"], "bigquery": ["bigquery", "bq"], "pub/sub": ["pubsub", "pubsub"], "gke": ["gke"], "cloud storage": ["cloudstorage", "gcs"], "cloud spanner": ["spanner"], "cloud tasks": ["cloudtasks"], "cloud scheduler": ["cloudscheduler"], "dataflow": ["dataflow"], "dataproc": ["dataproc"], "compute engine": ["computeengine", "gce"] } # Azure services with their specific identifiers azure_services = { "functions": ["azurefunctions"], "app service": ["appservice", "webapp"], "cosmos db": ["cosmosdb", "cosmos"], "sql database": ["sqldatabase", "azuresql"], "application insights": ["applicationinsights", "appinsights"], "aks": ["aks"], "storage": ["azurestorage", "blobstorage"], "logic apps": ["logicapps"], "service bus": ["servicebus"], "event hubs": ["eventhubs"], "key vault": ["keyvault"], "api management": ["apimanagement", "apim"], "virtual machines": ["virtualmachines", "azurevm"] } # Build the icon mapping with provider prefixes for disambiguation for service, url in SERVICE_ICONS.get("aws", {}).items(): service_lower = service.lower() # Add with AWS prefix for precise matching icon_map_items.append(f'"aws_{service_lower.replace(" ", "").replace("-", "")}": "{url}"') # Add common variations if service_lower in aws_services: for variant in aws_services[service_lower]: icon_map_items.append(f'"aws_{variant}": "{url}"') for service, url in SERVICE_ICONS.get("gcp", {}).items(): service_lower = service.lower() # Add with GCP prefix for precise matching icon_map_items.append(f'"gcp_{service_lower.replace(" ", "").replace("-", "")}": "{url}"') # Add common variations if service_lower in gcp_services: for variant in gcp_services[service_lower]: icon_map_items.append(f'"gcp_{variant}": "{url}"') for service, url in SERVICE_ICONS.get("azure", {}).items(): service_lower = service.lower() # Add with Azure prefix for precise matching icon_map_items.append(f'"azure_{service_lower.replace(" ", "").replace("-", "")}": "{url}"') # Add common variations if service_lower in azure_services: for variant in azure_services[service_lower]: icon_map_items.append(f'"azure_{variant}": "{url}"') # Generic icons (no provider prefix) for service, url in SERVICE_ICONS.get("generic", {}).items(): key = service.lower().replace(" ", "").replace("-", "") icon_map_items.append(f'"{key}": "{url}"') icon_mapping_json = "{" + ",".join(icon_map_items) + "}" html_content = f"""
100%
{mermaid_code}
100%
""" components.html(html_content, height=700, scrolling=True) with st.expander("📄 View/Download Source Code"): st.code(mermaid_code, language="text") col_down1, col_down2, col_down3 = st.columns(3) with col_down1: st.download_button( label="⬇️ Mermaid (.mmd)", data=mermaid_code, file_name="architecture-diagram.mmd", mime="text/plain", use_container_width=True ) with col_down2: st.download_button( label="⬇️ Text (.txt)", data=mermaid_code, file_name="architecture-diagram.txt", mime="text/plain", use_container_width=True ) with col_down3: markdown_content = f"# Architecture Diagram\n\n```mermaid\n{mermaid_code}\n```" st.download_button( label="⬇️ Markdown (.md)", data=markdown_content, file_name="architecture-diagram.md", mime="text/markdown", use_container_width=True ) st.caption("💡 Import into: Mermaid Live • GitHub • Confluence • Notion • Draw.io") else: st.info("👈 Describe your architecture and click 'Generate Diagram' to see it with official cloud service icons!") st.markdown("### 🎨 Available Service Icons") tab_aws, tab_gcp, tab_azure = st.tabs(["AWS", "GCP", "Azure"]) with tab_aws: st.markdown("**AWS Architecture Icons (Sample)**") sample_aws = ["Lambda", "API Gateway", "DynamoDB", "S3", "CloudWatch", "EC2", "RDS", "ECS"] icons_html = "" for service in sample_aws: icon_url = get_icon_url(service.lower(), "aws") if icon_url: icons_html += f'

{service}
' st.markdown(icons_html, unsafe_allow_html=True) with tab_gcp: st.markdown("**Google Cloud Icons (Sample)**") sample_gcp = ["Cloud Functions", "Cloud Run", "Firestore", "Cloud SQL", "BigQuery", "Pub/Sub", "GKE", "Cloud Storage"] icons_html = "" for service in sample_gcp: icon_url = get_icon_url(service.lower(), "gcp") if icon_url: icons_html += f'

{service}
' st.markdown(icons_html, unsafe_allow_html=True) with tab_azure: st.markdown("**Azure Service Icons (Sample)**") sample_azure = ["Functions", "App Service", "Cosmos DB", "SQL Database", "Application Insights", "AKS", "Storage", "Logic Apps"] icons_html = "" for service in sample_azure: icon_url = get_icon_url(service.lower(), "azure") if icon_url: icons_html += f'

{service}
' st.markdown(icons_html, unsafe_allow_html=True) st.markdown("---") st.caption("© 2026 ArchViz AI Pro")