Often at work I find myself with a similar set of terminal windows open. I have front-end and back-end project directories open in vim, each being served somehow, with logs and docker ps for good measure. In order to save myself the effort of opening all of these things, I have created workspaces in tmux. I use the somewhat hacky method of writing a tmux source file from my start script, which allows me to keep everything in one file. I can save the below as ~/bin/myproject-workspace and easily edit it if the project structure evolves.

#!/bin/bash

session_name="myproject"
src=$(mktemp)

cat << EOF > $src

# Window 1: run services
rename-window exec

# Pane 1: view back-end logs
send "cd $CODE_HOME/myproject/backend/" C-m
send "tail -f backend.log" C-m

# Pane 2: serve front-end
split-window -h
send "cd $CODE_HOME/myproject/frontend/" C-m
send "./run" C-m

# Pane 3: run server
split-window -v
resize-pane -t 3 -y 35
send "cd $CODE_HOME/myproject/backend/" C-m
send "./run" C-m

# Pane 4: run supplemental containers
split-window -v
resize-pane -t 4 -y 10
send "cd $CODE_HOME/myproject/containers/" C-m
send "./run; watch \"docker ps --format \'{{.Names}} {{.Status}}\'\"; ./die" C-m

# Window 2: back-end code
new-window -n backend
send "cd $CODE_HOME/myproject/backend/" C-m

# Window 3: front-end code
new-window -n frontend
send "cd $CODE_HOME/myproject/frontend/" C-m

# Start on window 1
select-window -t 1

EOF

tmux new-session -d -s "$session_name"
tmux attach-session -t "$session_name" \; source-file "$src" \; detach-client
tmux attach

rm "$src"