diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..3f72fcf
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:3.11-slim
+
+WORKDIR /app
+
+COPY requirements.txt .
+COPY secrets.toml /app/.streamlit/secrets.toml
+RUN pip install -r requirements.txt
+
+COPY . .
+
+CMD ["streamlit", "run", "graph_data_generator_streamlit/app.py", "--server.enableCORS", "false", "--browser.serverAddress", "0.0.0.0", "--browser.gatherUsageStats", "false", "--server.port", "8080"]
\ No newline at end of file
diff --git a/README.md b/README.md
index a6736f1..2f56d86 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
 # MOCK GRAPH DATA GENERATOR
-Applet using [Streamlit](https://streamlit.io) to conveniently design and generate interwoven mock data.
+Applet using [Streamlit](https://streamlit.io) to conveniently design and generate interwoven mock data. A running cloud instance of this can be found [here](https://dev.neo4j.com/mock-graph-data-generator)
 
 ## Install Poetry
 This applet uses [Poetry](https://python-poetry.org) for dependency management.
@@ -9,7 +9,7 @@ This applet uses several packages that will auto-install if you use either the p
 1. [graph-data-generator](https://pypi.org/project/graph-data-generator/) for generating the actual mock data from a .json configuration
 2. [neo4j-uploader](https://pypi.org/project/neo4j-uploader/) for uploading generated .json output to a [Neo4j](https://neo4j.com/developer/) graph database instance
 
-## Running
+## Local Running
 ```
 poetry update
 poetry run streamlit run graph_data_generator_streamlit/app.py
@@ -17,3 +17,17 @@ poetry run streamlit run graph_data_generator_streamlit/app.py
 
 ## Testing with local packages
 `poetry add --editable /path/to/package`
+
+## Running in Google Cloud
+- Set up a [Google Cloud account](https://cloud.google.com)
+- Create a [Google Cloud Project](https://developers.google.com/workspace/guides/create-project)
+- [Enable billing](https://cloud.google.com/billing/docs/how-to/modify-project) for that project
+- Temporarily move any .streamlit/secret.toml file to the root folder director (same level as Dockerfile)
+- Install [glcoud cli](https://cloud.google.com/sdk/docs/install)
+- Run the following commands from the terminal of your local dev machine:
+```
+gcloud builds submit --tag gcr.io/<google_cloud_project_id>/mock-graph-generator
+gcloud run deploy --image gcr.io/<google_cloud_project_id>/mock-graph-generator --platform managed --allow-unauthenticated
+
+When completed, can move secrets.toml file back to .streamlit/ - that or maintain a separate external secrets.toml file just for Google Cloud
+```
\ No newline at end of file
diff --git a/app.yaml b/app.yaml
new file mode 100644
index 0000000..3c2d3f9
--- /dev/null
+++ b/app.yaml
@@ -0,0 +1,3 @@
+runtime: python311
+
+entrypoint: streamlit run graph_data_generator_streamlit/app.py --server.enableCORS false --browser.serverAddress 0.0.0.0 --browser.gatherUsageStats false --server.port $PORT
\ No newline at end of file
diff --git a/graph_data_generator_streamlit/app.py b/graph_data_generator_streamlit/app.py
index c838017..6c351ea 100644
--- a/graph_data_generator_streamlit/app.py
+++ b/graph_data_generator_streamlit/app.py
@@ -1,12 +1,10 @@
 import streamlit as st
 from ui.instructions_ui import instructions_ui
 from ui.generate_ui import generate_ui
-from ui.config_ui import config_ui
 from ui.design_ui import arrows_ui, generators_ui
 from ui.ideate_ui import ideate_ui
 from ui.export_ui import export_ui
 from ui.samples_ui import samples_list
-from graph_data_generator import start_logging
 import logging
 
 # SETUP
@@ -17,17 +15,25 @@
 # Uncomment to start graph_data_generator logging
 # start_logging()
 
-# LOAD any env
-neo4j_uri = st.secrets.get("NEO4J_URI", None)
+# LOAD optional env data
+try:
+    neo4j_uri = st.secrets.get("NEO4J_URI", None)
+    neo4j_user = st.secrets.get("NEO4J_USER", None)
+    open_ai_key = st.secrets.get("OPENAI_API_KEY", None)
+    neo4j_pass = st.secrets.get("NEO4J_PASSWORD", None)
+except:
+    neo4j_uri = None
+    neo4j_user = None
+    neo4j_pass = None
+    open_ai_key = None
+    pass
+
 if "NEO4J_URI" not in st.session_state:
     st.session_state["NEO4J_URI"] = neo4j_uri
-neo4j_user = st.secrets.get("NEO4J_USER", None)
 if "NEO4J_USER" not in st.session_state:
     st.session_state["NEO4J_USER"] = neo4j_user
-password = st.secrets.get("NEO4J_PASSWORD", None)
 if "NEO4J_PASSWORD" not in st.session_state:
-    st.session_state["NEO4J_PASSWORD"] = password
-open_ai_key = st.secrets.get("OPENAI_API_KEY", None)
+    st.session_state["NEO4J_PASSWORD"] = neo4j_pass
 if "OPENAI_API_KEY" not in st.session_state:
     st.session_state["OPENAI_API_KEY"] = open_ai_key
 
diff --git a/graph_data_generator_streamlit/ui/export_ui.py b/graph_data_generator_streamlit/ui/export_ui.py
index e897bd4..4609c88 100644
--- a/graph_data_generator_streamlit/ui/export_ui.py
+++ b/graph_data_generator_streamlit/ui/export_ui.py
@@ -1,9 +1,8 @@
 
 
 import streamlit as st
-from graph_data_generator import generators
 import graph_data_generator as gdg
-from neo4j_uploader import upload, start_logging, stop_logging, UploadResult
+from neo4j_uploader import upload, start_logging 
 import json
 
 def export_ui():
diff --git a/graph_data_generator_streamlit/ui/ideate_ui.py b/graph_data_generator_streamlit/ui/ideate_ui.py
index 5e39808..510c4a7 100644
--- a/graph_data_generator_streamlit/ui/ideate_ui.py
+++ b/graph_data_generator_streamlit/ui/ideate_ui.py
@@ -2,13 +2,13 @@
 
 import streamlit as st
 from streamlit_agraph import agraph, Node, Edge, Config
-import streamlit.components.v1 as components
 import logging
 import openai
 import json
 import random
 import base64
 import ast
+import os
 
 # Yes yes - move all the non-ui stuff into a controller or something already
 
@@ -330,22 +330,19 @@ def ideate_ui():
     # OPENAI TEXTFIELD
     new_open_ai_key = st.text_input(f'OpenAI KEY', type="password", value=st.session_state["OPENAI_API_KEY"])
 
+    if new_open_ai_key is None or new_open_ai_key == "":
+        st.warning(f'OpenAI API Key required to use this feature')
+        return
+    
     # Set openAI key
-    openai.api_key = new_open_ai_key
+    openai.api_key = new_open_ai_key # This doesn't work in a Google Cloud Run instance
+    os.environ["OPENAI_API_KEY"] = new_open_ai_key
 
     # Display prompt for user input
     sample_prompt = "Sharks eat big fish. Big fish eat small fish. Small fish eat bugs."
-    run_openai = True
 
-    b1, b2 = st.columns(2)
-    with b1:
-        if st.button('Load Sample', key="graphgpt_sample"):
-            st.session_state["SAMPLE_PROMPT"] = sample_prompt
-    
-    with b2:
-        if st.button('Load Sample without OpenAI', key="graphgpt_sample_no_key"):
-            st.session_state["SAMPLE_PROMPT"] = sample_prompt
-            run_openai = False
+    if st.button('Load Sample', key="graphgpt_sample"):
+        st.session_state["SAMPLE_PROMPT"] = sample_prompt
 
     prompt = st.text_area("Prompt", value=st.session_state["SAMPLE_PROMPT"])
     if prompt is None or prompt == "":
@@ -354,13 +351,9 @@ def ideate_ui():
     nodes = None
     edges = None
 
-    if run_openai == False:
-        # Load vetted response to save on hitting openai for the same thing
-        response = [["Sharks", "eat", "big fish"], ["Big fish", "eat", "small fish"], ["Small fish", "eat", "bugs"]]
-    else: 
-        # Send completion request to openAI
-        full_prompt = triples_prompt(prompt)
-        response = generate_openai_response(full_prompt) 
+    # Send completion request to openAI
+    full_prompt = triples_prompt(prompt)
+    response = generate_openai_response(full_prompt)
 
     # Convert response to agraph nodes and edges
     try:
@@ -376,8 +369,8 @@ def ideate_ui():
     
     # Display data
     st.write('Graph Viewer')
-    agraph(nodes=nodes,  
-        edges=edges, 
+    agraph(nodes=nodes,
+        edges=edges,
         config=config)
     
     # For displaying JSON schema. This can be quite long though
@@ -399,4 +392,4 @@ def ideate_ui():
             st.session_state["ARROWS_URI"] = uri
     with b2:
         if st.button("Push to Generator"):
-            st.session_state["ARROWS_DICT"] = arrows_dict
\ No newline at end of file
+            st.session_state["ARROWS_DICT"] = arrows_dict
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..3a2ba48
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,71 @@
+altair==5.2.0 ; python_version >= "3.11" and python_version < "4.0"
+annotated-types==0.6.0 ; python_version >= "3.11" and python_version < "4.0"
+anyio==4.2.0 ; python_version >= "3.11" and python_version < "4.0"
+attrs==23.1.0 ; python_version >= "3.11" and python_version < "4.0"
+blinker==1.7.0 ; python_version >= "3.11" and python_version < "4.0"
+cachetools==5.3.2 ; python_version >= "3.11" and python_version < "4.0"
+certifi==2023.11.17 ; python_version >= "3.11" and python_version < "4.0"
+charset-normalizer==3.3.2 ; python_version >= "3.11" and python_version < "4.0"
+click==8.1.7 ; python_version >= "3.11" and python_version < "4.0"
+colorama==0.4.6 ; python_version >= "3.11" and python_version < "4.0" and platform_system == "Windows"
+distro==1.9.0 ; python_version >= "3.11" and python_version < "4.0"
+faker==19.13.0 ; python_version >= "3.11" and python_version < "4.0"
+gitdb==4.0.11 ; python_version >= "3.11" and python_version < "4.0"
+gitpython==3.1.40 ; python_version >= "3.11" and python_version < "4.0"
+graph-data-generator==0.4.1 ; python_version >= "3.11" and python_version < "4.0"
+h11==0.14.0 ; python_version >= "3.11" and python_version < "4.0"
+httpcore==1.0.2 ; python_version >= "3.11" and python_version < "4.0"
+httpx==0.26.0 ; python_version >= "3.11" and python_version < "4.0"
+idna==3.6 ; python_version >= "3.11" and python_version < "4.0"
+importlib-metadata==6.11.0 ; python_version >= "3.11" and python_version < "4.0"
+isodate==0.6.1 ; python_version >= "3.11" and python_version < "4.0"
+jinja2==3.1.2 ; python_version >= "3.11" and python_version < "4.0"
+jsonschema-specifications==2023.12.1 ; python_version >= "3.11" and python_version < "4.0"
+jsonschema==4.20.0 ; python_version >= "3.11" and python_version < "4.0"
+lorem-text==2.1 ; python_version >= "3.11" and python_version < "4.0"
+markdown-it-py==3.0.0 ; python_version >= "3.11" and python_version < "4.0"
+markupsafe==2.1.3 ; python_version >= "3.11" and python_version < "4.0"
+mdurl==0.1.2 ; python_version >= "3.11" and python_version < "4.0"
+neo4j-uploader==0.4.1 ; python_version >= "3.11" and python_version < "4.0"
+neo4j==5.16.0 ; python_version >= "3.11" and python_version < "4.0"
+networkx==3.2.1 ; python_version >= "3.11" and python_version < "4.0"
+numpy==1.26.2 ; python_version >= "3.11" and python_version < "4.0"
+openai==1.6.1 ; python_version >= "3.11" and python_version < "4.0"
+opencv-python==4.8.1.78 ; python_version >= "3.11" and python_version < "4.0"
+packaging==23.2 ; python_version >= "3.11" and python_version < "4.0"
+pandas==2.1.4 ; python_version >= "3.11" and python_version < "4.0"
+pasteboard==0.3.3 ; python_version >= "3.11" and python_version < "4.0" and platform_system == "Darwin"
+pillow==10.1.0 ; python_version >= "3.11" and python_version < "4.0"
+protobuf==4.25.1 ; python_version >= "3.11" and python_version < "4.0"
+pyarrow==14.0.2 ; python_version >= "3.11" and python_version < "4.0"
+pyclip==0.7.0 ; python_version >= "3.11" and python_version < "4.0"
+pydantic-core==2.14.6 ; python_version >= "3.11" and python_version < "4.0"
+pydantic==2.5.3 ; python_version >= "3.11" and python_version < "4.0"
+pydeck==0.8.0 ; python_version >= "3.11" and python_version < "4.0"
+pygments==2.17.2 ; python_version >= "3.11" and python_version < "4.0"
+pyparsing==3.1.1 ; python_version >= "3.11" and python_version < "4.0"
+python-dateutil==2.8.2 ; python_version >= "3.11" and python_version < "4.0"
+pytz==2023.3.post1 ; python_version >= "3.11" and python_version < "4.0"
+pywin32==306 ; python_version >= "3.11" and python_version < "4.0" and platform_system == "Windows"
+rdflib==7.0.0 ; python_version >= "3.11" and python_version < "4.0"
+referencing==0.32.0 ; python_version >= "3.11" and python_version < "4.0"
+requests==2.31.0 ; python_version >= "3.11" and python_version < "4.0"
+rich==13.7.0 ; python_version >= "3.11" and python_version < "4.0"
+rpds-py==0.16.2 ; python_version >= "3.11" and python_version < "4.0"
+six==1.16.0 ; python_version >= "3.11" and python_version < "4.0"
+smmap==5.0.1 ; python_version >= "3.11" and python_version < "4.0"
+sniffio==1.3.0 ; python_version >= "3.11" and python_version < "4.0"
+streamlit-agraph==0.0.45 ; python_version >= "3.11" and python_version < "4.0"
+streamlit==1.29.0 ; python_version >= "3.11" and python_version < "4.0"
+tenacity==8.2.3 ; python_version >= "3.11" and python_version < "4.0"
+toml==0.10.2 ; python_version >= "3.11" and python_version < "4.0"
+toolz==0.12.0 ; python_version >= "3.11" and python_version < "4.0"
+tornado==6.4 ; python_version >= "3.11" and python_version < "4.0"
+tqdm==4.66.1 ; python_version >= "3.11" and python_version < "4.0"
+typing-extensions==4.9.0 ; python_version >= "3.11" and python_version < "4.0"
+tzdata==2023.4 ; python_version >= "3.11" and python_version < "4.0"
+tzlocal==5.2 ; python_version >= "3.11" and python_version < "4.0"
+urllib3==2.1.0 ; python_version >= "3.11" and python_version < "4.0"
+validators==0.22.0 ; python_version >= "3.11" and python_version < "4.0"
+watchdog==3.0.0 ; python_version >= "3.11" and python_version < "4.0" and platform_system != "Darwin"
+zipp==3.17.0 ; python_version >= "3.11" and python_version < "4.0"