AI-powered AWS architecture designer built with LangGraph
Describe your application in natural language and Scaffold AI designs the AWS serverless architecture, runs a security review against AWS Well-Architected principles, and generates deployment-ready infrastructure-as-code -- all through a visual canvas and chat interface.
After building Resume Tailor AI with AWS Step Functions, I wanted to explore modern AI orchestration beyond AWS-native tooling. I picked up LangGraph -- a framework I had no prior experience with -- and built this full-stack multi-agent platform in a single day.
The goal was to demonstrate:
- Learning velocity -- Shipping production-quality code in unfamiliar frameworks, fast
- Architectural judgment -- Knowing when LangGraph fits better than Step Functions (and vice versa), rather than defaulting to one tool
- Production mindset -- Security gates, rate limiting, input validation, and testing from the start, not bolted on later
| Resume Tailor AI | Scaffold AI | Career Path Architect | |
|---|---|---|---|
| Purpose | Resume optimization | AWS architecture design | Career planning |
| Orchestration | AWS Step Functions | LangGraph | LangGraph |
| Agents | Step Functions workflow | 4 LangGraph agents | 6 LangGraph agents |
| Development | 3 days | 1 day | 2 hours |
| Tests | 212 tests, 98% | 126 tests, 67%* | 142 tests, 99% |
| Features | Resume tailoring | Architecture generation | Roadmap + Critical Review |
*Scaffold AI's 67% coverage focuses on core business logic (LangGraph workflow, security review, IaC generation). Missing coverage is in deployment infrastructure (CDK synthesis, AWS deployment) which was out of scope for the initial build.
All three projects share the same production patterns (validation, error handling, pre-commit hooks, CI/CD, rate limiting, testing) -- the difference is the orchestration approach chosen to match the problem. See LangGraph vs Step Functions for a detailed technical comparison.
| Blank canvas | Architecture generated from prompt |
|---|---|
![]() |
![]() |
| Security review (failed -- score 62/100) | Architecture updated with security fixes |
|---|---|
![]() |
![]() |
| Generated CDK code | Export and deploy options |
|---|---|
![]() |
![]() |
User Input --> Interpreter --> Architect --> Security Specialist --> Code Generator
| | | |
Intent class Graph nodes Security score CDK / Terraform / CF
- Interpreter Agent -- Classifies user intent (new feature, modify, explain, deploy)
- Architect Agent -- Designs AWS serverless architecture with 12 service types
- Security Specialist -- Validates against AWS Well-Architected principles; blocks insecure designs (score < 70/100)
- Code Generators -- Multi-format IaC output (CDK TypeScript, CDK Python, CloudFormation, Terraform)
- React Specialist -- Generates AWS Cloudscape UI components
- Visual Canvas -- React Flow node graph editor with drag-and-drop AWS service nodes
- AI Chat -- Natural language architecture design powered by AWS Bedrock (Claude)
- Security Gate -- Automated scoring blocks code generation for insecure architectures
- Security Badges -- Visual indicators on each node showing active security configs (encryption, WAF, auth)
- Security Auto-Fix -- One-click security remediation with fail banner (Auto-Fix / Mark Resolved)
- Multi-Format IaC -- Generate CDK TypeScript, CDK Python, CloudFormation, or Terraform
- Code Viewer -- Tabbed modal for browsing generated infrastructure code
- Export & Deploy -- Download as ZIP or deploy directly to AWS with CDK
- Project Planner Integration -- Structured API integration with session-based storage
- Shared Types Package -- Type-safe data transfer with Project Planner AI
- Rate Limiting -- 10 req/min chat, 3 req/hr deployment, 20 req/min plan import
- Dark Mode -- Persistent theme preference
- Pre-commit Hooks -- TruffleHog secrets detection, AWS credentials scanning
Scaffold AI receives project plans from Project Planner AI via structured API:
- REST API endpoints -
POST /api/import/planandGET /api/import/plan/{session_id} - Session-based storage - Plans stored with unique session IDs
- Type-safe - Shared TypeScript types ensure data consistency
- Backward compatible - Falls back to URL parameter parsing if needed
- Auto-populated chat - Project context pre-filled from plan data
- 7 comprehensive tests - Full test coverage for import functionality
The integration enables a seamless workflow: Plan β Build β Deploy.
| Layer | Technology |
|---|---|
| AI Orchestration | LangGraph |
| LLM | AWS Bedrock (Claude) |
| Backend | FastAPI |
| Frontend | Next.js 15 + React 19 |
| UI Library | AWS Cloudscape Design System |
| State | Zustand |
| Canvas | React Flow |
| Testing | pytest + Vitest |
| Tooling | pnpm + Turborepo + uv |
- Python 3.12+
- Node.js 22+
- pnpm 10+
- AWS CLI configured with Bedrock access
- uv (Python package manager)
# Clone repository
git clone https://github.com/jfowler-cloud/scaffold-ai.git
cd scaffold-ai
# Install frontend dependencies
pnpm install
# Backend setup
cd apps/backend
uv sync
cp .env.example .env
# Edit .env with your AWS credentials# Terminal 1: Backend (port 8000)
cd apps/backend
uv run uvicorn scaffold_ai.main:app --reload
# Terminal 2: Frontend (port 3000)
cd apps/web
pnpm devWhen running alongside Project Planner AI (via the planner's dev.sh), Scaffold AI uses port 8001 (backend) and 3001 (frontend) to avoid conflicts.
Backend (apps/backend/.env):
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
BACKEND_URL=http://localhost:8000Frontend (apps/web/.env.local):
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000scaffold-ai/
βββ apps/
β βββ backend/ # FastAPI + LangGraph
β β βββ src/scaffold_ai/
β β β βββ main.py # FastAPI app
β β β βββ graph/ # LangGraph workflow (DAG, nodes, state)
β β β βββ agents/ # Specialist agents
β β β βββ services/ # Business services
β β β βββ tools/ # Git, CDK synthesis
β β βββ tests/
β β
β βββ web/ # Next.js 15 frontend
β βββ app/ # App router
β βββ components/ # Cloudscape components, Canvas, Chat
β βββ lib/ # Zustand stores
β
βββ packages/
β βββ generated/ # IaC output
β βββ ui/ # Shared components
β
βββ docs/
βββ steering/ # Cloudscape UI patterns
# Backend tests
cd apps/backend
uv run pytest -v
# Frontend tests
cd apps/web
pnpm test
# All tests (from root)
pnpm test:allTests cover agents, services, LangGraph workflow integration, API endpoints, input validation, rate limiting, and frontend components/stores.
| Resume Tailor AI | Scaffold AI | Career Path Architect | |
|---|---|---|---|
| Orchestration | AWS Step Functions | LangGraph | LangGraph |
| Use case | Deterministic resume tailoring | Dynamic AI multi-agent conversations | Career planning & roadmaps |
| State management | S3 + DynamoDB | LangGraph built-in memory | LangGraph built-in memory |
| Deployment | AWS-native (Lambda, Step Functions) | Framework-agnostic | Framework-agnostic |
| Best for | Predictable workflows, AWS-integrated | Dynamic routing, conversational AI | Skill gap analysis, learning paths |
All three projects share production patterns: input validation, error handling, pre-commit hooks, CI/CD with security scanning, rate limiting, and comprehensive testing.
- LangGraph vs Step Functions -- Technical comparison with cost analysis
- Development Journey -- Build timeline and key decisions
- Multi-Format IaC -- IaC generation patterns
- Contributing -- Development setup and guidelines
- Testing Summary -- Test coverage and strategy
- Security Audit -- Security review and improvements
- Critical Review -- Self-assessment and roadmap
Honest assessment of the codebase as of Feb 2026, based on a full source review. See also CRITICAL_REVIEW.md for the detailed 44-item audit.
The Project Planner AI integration (usePlannerImport.ts) receives a URL-encoded prompt parameter, but discards all structured fields. The resulting PlannerImport object has empty architecture, techStack, and requirements -- only description (the raw text prompt) is populated. This means the Chat component receives an unstructured text blob rather than parsed project metadata.
Recommendation: Parse the prompt text to extract structured fields (project name, architecture, tech stack entries, user count, uptime). Alternatively, coordinate with Project Planner AI to pass a JSON payload via postMessage or a shared backend key instead of a URL parameter. This would allow the architect agent to receive typed inputs and produce better initial designs.
All endpoints are public. All state (architectures, chat history, sharing links, security scores) is stored in memory and lost on restart. The deploy endpoint runs cdk deploy with full system access and no user validation.
Recommendation (short-term): Add API key validation middleware for the deploy endpoint. Add a projects dict keyed by session ID so architectures survive page refreshes. Recommendation (medium-term): Add Cognito auth + DynamoDB persistence as outlined in CRITICAL_REVIEW.md Phase 1.
cdk_deployment.py executes npm install and npx cdk deploy via subprocess.run with no container isolation, no disk space checks, and no cleanup on failure. A malicious or buggy CDK template could write anywhere on the filesystem.
Recommendation: Run CDK synthesis and deployment inside a Docker container with a read-only root filesystem and a tmpfs work directory. Add explicit timeouts and cleanup logic in finally blocks.
15+ except Exception as e blocks across the codebase catch everything and return generic "An internal error occurred" messages. This makes debugging difficult and hides transient vs. permanent failures.
Recommendation: Create a custom exception hierarchy (ScaffoldError, LLMError, DeploymentError, etc.). Catch specific exceptions, log with request context, and return structured error responses with error codes.
Correction: user_input: str has no max length constraint.ChatRequest does validate user_input with a 5000-char limit and non-empty check via field_validator. However, graph_json: dict | None is still unvalidated -- there is no schema check, no node count limit, and no max depth. A crafted graph payload could cause the architect prompt to exceed the LLM context window or produce excessive token costs.
Recommendation: Add a Pydantic validator for graph_json that rejects graphs with more than 50 nodes. Validate that node IDs and types match expected formats.
The frontend references the backend URL in multiple places with different fallback chains (NEXT_PUBLIC_BACKEND_URL || NEXT_PUBLIC_API_URL || "http://localhost:8001"). The port 8001 default is correct -- when launched via the planner's dev.sh, Scaffold AI's backend is bumped to 8001 (and frontend to 3001) so both projects run side-by-side.
Recommendation: Centralize the URL logic into a single lib/config.ts exporting BACKEND_URL and import it everywhere, rather than repeating the fallback chain in each component.
The agents/ directory contains class-based agents (ArchitectAgent, InterpreterAgent) with placeholder methods that are never called. The real logic lives in graph/nodes.py as standalone async functions. This is confusing -- two implementations of the same concept.
Recommendation: Either remove the unused agent classes or refactor nodes.py to delegate to them. The SecuritySpecialistAgent is the one agent class that is actually used (as a fallback); keep that pattern and extend it.
The /api/deploy endpoint accepts raw cdk_code and app_code strings from the client and writes them to disk before executing cdk deploy. While stack_name is validated against a regex to prevent command injection, the code content itself is not inspected. An attacker could submit CDK code containing child_process.exec() or filesystem operations. The deployment runs with the server's full AWS credentials.
Recommendation: At minimum, validate that the CDK code only imports from aws-cdk-lib and constructs. Better: run synthesis in a Docker container with restricted network access and no AWS credentials, then deploy the synthesized CloudFormation template directly.
PlannerNotification.tsx renders plannerData.projectName (always "Imported Project") and plannerData.architecture (always ""). The notification reads: "Imported Project - . Ready to generate code and infrastructure." -- note the dangling hyphen-period from the empty architecture field.
Recommendation: Conditionally render the architecture field. Parse the project name from the prompt text (it's on the Project: line) instead of hardcoding "Imported Project".
Chat.tsx uses two different patterns to reach the backend:
handleSubmitandhandleGenerateCodecall/api/chat(relative URL, routed through Next.js API proxy)handleDeploy,handleSecurityFix, andhandleDownloadZipcallprocess.env.NEXT_PUBLIC_BACKEND_URL || ...(direct, bypasses Next.js)
This means CORS, authentication, and error handling behave differently depending on the action. If a proxy middleware is added later (for auth tokens, logging, etc.), it will only apply to some requests.
Recommendation: Route all backend calls through the Next.js API proxy for consistency, or call the backend directly everywhere. Don't mix both.
_write_generated_file in nodes.py walks up 8 parent directories looking for package.json to find the repo root. If the backend is run from an unexpected working directory or the file structure changes, generated files may be written to the wrong location or silently fail.
Recommendation: Resolve the repo root once at startup via an environment variable or by walking from __file__ with a known anchor (e.g., apps/backend). Cache the result instead of re-walking on every write.
The planner-to-scaffold handoff works end-to-end: the planner's ScaffoldIntegration.tsx opens Scaffold AI with ?from=planner&prompt=..., and usePlannerImport.ts populates the Chat textarea. The notification banner appears via PlannerNotification.tsx. The main gaps are:
- Data fidelity -- structured plan fields are lost (see P0 above)
- Notification content -- project name and architecture display incorrectly (see P2 above)
- URL length -- long plans may be truncated by browsers/proxies at ~2000 chars
Contributions welcome! See CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make changes and add tests
- Run tests:
pnpm test:all - Commit:
git commit -m 'feat: add amazing feature' - Push and open a Pull Request
- β¨ Added SecurityBadge component to all 11 node types β shows active security configs (encryption, WAF, auth, etc.)
- β¨ Security fix visualization β auto-fix normalizes node types for React Flow rendering
- β¨ Security review fail banner with Auto-Fix and Mark Resolved actions
- β¨ Deploy to AWS modal with "coming soon" notice and manual deployment instructions
- β¨ Centralized BACKEND_URL config (
lib/config.ts) β single source of truth for backend URL - β¨ Added
skip_securityflag to workflow state for bypassing security gate - π Fixed all 11 node files β removed duplicate JSX bodies
- π Fixed security gate test assertions and added missing GraphState fields
- β 126 tests passing (up from 116)
- β¨ Upgraded to Claude Opus 4.5 with cross-region inference profile
- β¨ Added portfolio context and capability badges to README
- π Fixed hydration mismatch with loading state
- π Resolved jszip module not found error
- π Polished README for public release
- π§ Made type check and security scan non-blocking in CI
- π¦ Dependency Updates:
- @cloudscape-design/components and chat-components to latest
- @eslint/js from 9.39.2 to 10.0.1
- Bumped actions/checkout from 4 to 6, actions/setup-node from 4 to 6, actions/setup-python from 5 to 6
- β¨ Added dark mode toggle with enhanced CSS patterns
- β¨ Added Scaffold AI logo
- β¨ Added Download ZIP button for generated files
- β¨ Styled Select dropdowns for dark mode
- π Fixed canvas toolbar container in dark mode
- π Fixed Deploy button for CloudFormation with manual instructions
- π Used dynamic timestamps in sharing and history services
- π§ Added GitHub Actions CI workflow
- β¨ Added rate limiting, request timeout, and security hardening
- β¨ Added security history tracking
- β¨ Added architecture sharing and collaboration
- β¨ Added multi-stack architecture support
- β¨ Added Python CDK support
- β¨ Added architecture templates library
- β¨ Added security auto-fix capabilities
- β¨ Added cost estimation feature
- π Critical security fixes and hardening
- π Updated roadmap β 7/9 medium-term items complete
- β¨ Added frontend unit test suite with Vitest
- β¨ Added SecuritySpecialistAgent unit tests (19 tests)
- β¨ Added configurable CORS and CDK CloudFront support
- β¨ Added security gate and multi-format IaC generation
- π Fixed CF/TF node type mismatch
- π Resolved all test failures β mock paths, key names, and missing labels
- π Added comprehensive CLAUDE.md for AI assistant onboarding
- π Serverless-first architecture with 12 node types
- π LangGraph multi-agent workflow with security specialist
- π Interactive drag-and-drop architecture canvas
- π CloudFormation and Terraform IaC generation
- π Real-time AI chat for architecture guidance
MIT License -- see LICENSE for details.
- Project Planner AI - AI-powered project planning β generates architecture plans that hand off directly to Scaffold AI
- Resume Tailor AI - AI-powered resume optimization with Claude Opus 4.5 (3 days, 212 tests, 98% coverage)
- Career Path Architect - AI-powered career planning with LangGraph (2 hours, 142 tests, 99% coverage)
Together, these projects form a complete AI-powered career development platform.
James Fowler
- GitHub: @jfowler-cloud
- LinkedIn: James Fowler - AWS Cloud Architect & DevOps Professional





