This is a simplistic MVP for creating data visualizations utilizing descriptions given in a chat.
LangGraph Python server https://github.com/charlesverge/datastories-langgraph
LangGraph Generative UI Node server https://github.com/charlesverge/datastories
The ReAct agent:
- Takes a user query as input
- Reasons about the query and decides on an action
- Executes the chosen action using available tools
- Observes the result of the action
- Repeats steps 2-4 until it can provide a final answer
- Create a
.env
file.
cp .env.example .env
- Define required API keys in your
.env
file.
For a simple setup a local nginx server is use to handle serving of html files. For a production setup typically you would use a content delivery network
- BUCKET_DIR=/opt/homebrew/var/www/graph location to store outputs, needs to be available on BUCKET_URL
- BUCKET_URL=http://localhost:8080/graph/
- OPENAI_API_KEY Your open api key
- WORKING_DIR working directory for executing generated code, for production this would need to be broken out into it's own service with various restrictions to prevent prompt injection attacks
Start the server on port 2025 langgraph dev --port 2025
- Install the Data Stories Node Server, the node server generates the React UI elements
The node server will utilize port 2024
-
Install the LangGraph Chat agent, set the configuration to point to your LanGraph server NEXT_PUBLIC_API_URL=http://localhost:8025 NEXT_PUBLIC_ASSISTANT_ID=gen_graph
-
Install a nginx server to allow serving of the ui elements from the node server and the lang graph server in python on the same host. This forwards the /ui/ directory to the node server and the remainder of the traffic on port 8025 to the python LangGraph server on 2025
# ── server for :8000 → :3000 ─────────────────────────────────────────────
server {
listen 127.0.0.1:8000;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# ── server for :8024 → default :2025, but /ui/... → :2024/ui/... ────────
server {
listen 127.0.0.1:8025;
server_name localhost;
# match /ui/... first
location ^~ /ui/ {
# proxy_pass without a URI means the full original URI is appended,
# so /ui/foo → http://127.0.0.1:2024/ui/foo
proxy_pass http://127.0.0.1:2024;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# all other requests on :8025 → 2025
location / {
proxy_pass http://127.0.0.1:2025;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}