I've used Dancer quite a bit. Some for larger apps (30+ pages)
This is how I typically lay out a Dancer app. Starting with a top level directory of application name, say "MyApp", I put the routes in different directories instead of jumble them all up in one file. As an example, lets use an app that handles and tracks customers and orders. So something like this:
MyApp/
└── Routes
├── API
│ ├── Component
│ │ ├── Customer.pm
│ │ └── Order.pm
│ ├── Customer.pm
│ └── Order.pm
├── API.pm
├── Customer.pm
└── Order.pm
(templates should have a similar layout in a separate 'Views' directory)Routes/Customer.pm would handle basic requests like GET /Customer/list and POST or GET Customer/1
While routes handling json/ajax only requests (from jquery ect) would be in Routes/API/Customer.pm. Routes/API.pm would be an api for stuff that doesn't directly involve a Customer or Order object (perhaps returning json from an inventory table or something)
And if you get tired of requesting json just to convert it into html with javascript and you want the power of a template (without a SPA); I fetch that stuff with jquery .load() using the 'Component' routes (dynamic parts of a webpage). For example, perhaps when making a new quote, you select a specific customer and you want open orders to be displayed in a popup or inline div somewhere. Using jquery .load(), you would just easily fetch /API/Component/Customer/Open-Orders/<cust id#>, ect and then just inline the returned html. If you stick to a rule of "components can only return html and not cause a page refresh", you will keep from getting too big of mess with them.
This is just sorta a method I made from various best practices from other frameworks. Perhaps its barftastic, but I haven't been complaining about it.