The approach I took was to split away the common stuff i use into plugins. Most of the sites I build are 80% the same same in terms of data i need to collect. Essentially all these hang of a tab for each kind of information. For example, I have and SEO tab, a publishing tab, Social Media tab for open graph etc… You get the idea.
This means my site & page blue prints are pretty light and I build most of the site from existing tabs and blue prints. I use extends and field groups a lot too,
I also built a hero image system in its own plugin that be dropped into any site. It makes heavy use of conditional fields in order to generate fancy hero areas using slides, videos, images and text.
I use my site.yml to store things like global SEO data, the branding for the site like logo image files, and its here that I list out the sites content but I tailor this part to the needs of the current site, rather then just simply list out pages.
Just to illustrate what I mean, heres how the hero plugin is setup:
'snippets' => [
// HERO TYPES
'herocontent' => __DIR__ . '/snippets/herocontent.php',
'heroimage' => __DIR__ . '/snippets/heroimage.php',
'heroslides' => __DIR__ . '/snippets/heroslides.php',
'herovideo' => __DIR__ . '/snippets/herovideo.php',
'hero' => __DIR__ . '/snippets/hero.php',
'blueprints' => [
// HERO FIELDS
'image' => __DIR__ . '/blueprints/fields/image.yml',
'slides' => __DIR__ . '/blueprints/fields/slides.yml',
'video' => __DIR__ . '/blueprints/fields/video.yml',
'split' => __DIR__ . '/blueprints/fields/split.yml',
'tabs/hero' => __DIR__ . '/blueprints/tabs/hero.yml',
Hope that helps.