A solution I often see is to write out a config file like this:
cat <<EOF > ~/.app/config
var1=$var1
var2=$var2
EOF
Then, that config file is a proper shell scrip itself, and can be sourced by the shell script at startup, like so:
[ -e ~/.app/config ] && source ~/.app/config
Sourcing it (rather than executing it as a command) ensures that all variables it defines will be visible in the script that sourced it.
Then, of course, you'd want to make user-directed customization after sourcing it, but before writing out the new version.
Caveat Emptor
Using this method is okay for something quick-n-dirty, or something only you will touch. However, sourcing a script runs all of the code in it, in the current session. That means it can rm -rf /
, and it could also redefine functions or variables which you've defined in your main script, overriding them.