a typical project might look like:
/fpga/
/fpga/src/
/fpga/<ip>/src/
/fpga/<ip>/bld/
/fpga/<ip>/bin/
/fpga/<ip>/doc/
/fpga/<ip>/sim/
/fpga/bld/
/fpga/bin/
/fpga/doc/
/fpga/sim/
But developers will have slightly different opinions. In this case, doc = documentation, sim = simulation, bld = constraints and build scripts, bin = any scripts or programs related to this ip.
This is for a pure HW, single fpga structure. for mixed hw/sw and multi-fpga systems, there may be more folders.
Likewise, there are several things that can get left out. For example, leaving out /src or /<ip>/src. There shouldn't be any IP named "sim" or "doc", so there shouldn't be much confusion in leaving out the "src" name.
Similarly, /fpga/src is intended to be the top level design. This could also be in a "top" library instead.
/fpga/<ip>/bld might not be applicable, or the code might be placed in /fpga/bld. This can be based on the build system as well as how the repository is structured. At some companies, each fpga design will be in a self-contained repository. At others, ip will be in repositories and references to a branch/version will be included in the main project repository instead.
having a separate package folder doesn't offer as much benefit, and _pkg.vhd can be used to denote a package. Packages are less needed with VHDL as you can use "entity work.my_instance" to avoid component declarations (either locally or in a package). The only time you need "component" is for things like coregen -- black-boxes. As a result, you really only need packages for 3rd party IP, types, functions, and procedures.
In the end, there is a wide variety of structures and they are often imperfect and influenced by the requirements of the tools used by the company.