Designing languages for golfing requires a good amount of exposure to golf problems such that you can create a list of useful structures that you would like to abbreviate. Trivial example constructs are filter, map, zip and reduce operations and various variants of those operations.
The most obvious thing is to pack as much functionality into a single character or single byte (if you don't want to use ASCII). You overload it as much as possible. You can have a character do something for an integer, something else for a double, something else for a list etc. You really want to pack as much functionality into a single character as possible.
The next obvious thing is to have implicit type conversions wherever possible because explicit type conversions would just make a solution one byte longer. Of course, this means you have to trade off between overloading and implicit type conversions. And this is exactly where a lot of experience comes back in such that you know which is going to be used more often.
I'm the person behind Burlesque (the programming language) and it was never designed to be a golfing language but it eventually turned into one over the course and there are a lot of mistakes (some that were fixed, some that can't be fixed by design) when it comes to golfing. (Most obviously Burlesque uses two characters per built-in, you'd automatically make all burlesque programs half as long if you'd map every burlesque built-in to one byte).
One other thing you can do is to use parsing errors to "mean" something. I.e. if the parsing error is at the end of a program you can just ignore it or fix it for example in the case of "m{foobar" which is missing a "}" but since it's at the end of the program you could just insert a "}" and you saved one byte.
If you want to know something or more details you can hit me up in a chat.