In this post, I’ll walk you through how I built a Go Playground REPL clone from scratch — powered by a Go backend that compiles user-submitted code securely in Docker, deployed with GitHub Actions to AWS Elastic Beanstalk, and paired with a beautiful frontend using Vue.js, Pinia, Tailwind CSS, and Monaco Editor.
Tech Stack
- Backend: Go (Golang), Docker, Gin, os/exec
- Frontend: Vue 3, Pinia, Tailwind CSS, Monaco Editor
- DevOps: GitHub Actions, DockerHub, AWS Elastic Beanstalk
What I Built
- An interactive code editor for writing and executing Go programs.
- A secure backend that:
- Runs code inside a Docker container
- Enforces timeouts to prevent infinite loops
- Handles malicious input gracefully
- A responsive frontend with live theme switching, program examples, and output panels.
Backend Setup
I used the os/exec package in Go to compile and run user code inside a Docker container, isolated from the host.
Sample Go run handler:
func RunCode(c *gin.Context) {
var payload struct {
Code string `json:"code"`
}
if err := c.ShouldBindJSON(&payload); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
return
}
output, err := runInDocker(payload.Code)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"output": output, "error": ""})
}
Sample Dockerfile:
FROM golang:1.24-alpine
WORKDIR /app
COPY . .
RUN go build -o repl-server ./cmd
CMD [ "./repl-server" ]
GitHub Actions Deployment
I set up GitHub Actions to automatically build our Docker image, push to ECR, and deploy to AWS Elastic Beanstalk.
Key CI/CD steps:
- name: Build Docker Image
run: docker build -t repl-api .
- name: Push to ECR
run: |
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin ${{ secrets.ECR_URL }}
docker tag repl-api:latest ${{ secrets.ECR_URL }}/repl-api:latest
docker push ${{ secrets.ECR_URL }}/repl-api:latest
- name: Deploy to EBS
run: |
eb init -p docker go-repl --region us-west-2
eb deploy
Frontend Setup
Used Vue 3 with Pinia to manage state and Monaco Editor for code editing.
Vue + Monaco Editor integration (sample):
import MonacoEditor from '@monaco-editor/vue'
const code = ref(`package main\n\nimport "fmt"\n\nfunc main() {\n fmt.Println("Hello, world!")\n}`)
Sample UI with Tailwind CSS:
Go Playground REPL
Program Examples Dropdown
Added dropdown support with built-in Go examples like
- Fibonacci
- Peano Integers
- Prime Checker
- Bubble Sort
- Pi Calculation
Securing Execution
Used these techniques to sandbox the code:
- Timeout using context.WithTimeout
- Docker resource constraints (--memory, --cpus)
- Output/error size limits
- Validated JSON input structure
Future Improvements
This setup is built with extensibility in mind.
- Add support for JavaScript, Java, Python, etc.
- Enable stdin support in Docker for user input
- Add user accounts and save session history
- Use WebSocket for real-time compile streams
🌐 Live Demo
📝 Final Thoughts
This project was a fun blend of backend performance, frontend UX, and DevOps automation. It’s a perfect playground for experimenting with Go and building a polished, full-stack developer tool.
Feel free to fork and extend it further. Hope this helps you in your learning journey!
Repo
Github Repo