When building something from scratch, you need to do a lot of hard things at once, with limited resources. The standard advice is to take an iterative approach, prioritising things and then cycling quickly through them, finding solutions just good enough to move things forwards before moving onto the next thing.
It's good advice, but there are issues with following it in practice. Often when you explore solutions to a problem, even simple ones, the problem reveals itself to be much more complex than you had anticipated. You find new sub-problems, and tangental problems, which all look just as important and necessary to solve as the original. Combined, these issues make it pretty easy to go off track and end up deep into the problem you were supposed to just find a quick solution for. After all, it's just one more thing, you're thinking about it, and you'll have to solve it at some point anyway. Why not now?
I've made this mistake a lot. I'm trying to get better at being strict and saying "not now" to new problems that I discover in the middle of an iteration, and avoid getting sidetracked from shipping by working on things that can be left for later. I'd like to share a tactic I use to do this that has worked well for me. It's to ask a question about the problem itself: "from my perspective right now, is this a nice problem to have?". If yes, I skip it. If no, I work on it immediately.
A couple of examples to illustrate. Let's say I'm building a new product, and signup isn't implemented yet. No signup, obviously, means no users. From my perspective right now, is that a nice problem to have? No - I have zero users right now, and I want some. The only way to move forwards is to build this.
Whilst I'm building signup, however, I realise that the app also needs reset password functionality. If a user signs up then forgets their password, that's a problem. But from my perspective right now, is this a nice problem to have? Yes! I have zero users, and want some. Having this problem means I'll have users, which would be great. Sure, the app will definitely need reset password functionality eventually, but I can do it later. First, I should build and ship anything that's stopping me from getting users.
These simple examples hopefully get the point across. There are always tiers of functionality which build upon one another, and this simple question provides a neat hack to sort things in order of when they'll actually be useful so you can build and ship those tiers in faster iterations, rather than delaying shipping while you build everything up front. Try it out when you next build something.