I currently have a Shiny app split into four files: app.R containing the "shinyApp(ui, server)" line of code (42 lines), server.R containing three fairly long reactive expressions (318 lines), ui.R containing about 5 fairly long tabPanels and sidebarPanels (197 lines), and functions.R containing four very long functions I use in server.R (212 lines).
In its current state, my app is just these four files sitting in a single folder. What are the best practices for splitting this up? Is it necessary? This is probably going to be my go-to project to talk about during interviews, so I want to make sure the Github looks nice.
It seems you already made use of most of the available options to split files (separate UI and Server and souring in R functions).
One additional thing you could consider is creating Shiny modules. This would effectively create mini self-containing Shiny pieces that can fit into any Shiny app you like (similar to how a function can be used across different scripts). This is however only possible or useful if you have sections of your app that are modular in nature (e.g. repeated elements or self-contained sub pages).
If your goal is to use this as a demo project, just make sure as well that the code is nicely formatted (you can use styler) and good comments are present to help someone looking through your code understand what is going on. For the R functions, you can consider using roxygen style comments and even generate documentation.
Personally I also like to arrange my server code in the same order as my UI, so that code of UI elements that are close are grouped together on the server side as well.