Reduce the size of config file (yaml) - many repeats

I think the best way to condense or optimize this configuration is to combine the packages: mapping with the !include using substitutions. The repeated code seems to have 3 unique items, the id, input pin, and output pin. This allows all of the related entities needed for each instance to be consolidated into one file. The packages: mapping takes care of merging all of the similar configurations together. Using the substitution feature of the !include statement allows the single file to implement 8 nearly identical instances of the related entities.

substitutions:
  device_name: kitchen-buttons
  friendly_name: Bedlamp
  ip_node: '222'


esphome:
  name: ${device_name}

esp32:
  board: node32s
  framework:
    type: arduino

packages:
  base: !include .base.yaml
  button1: !include { file: .button.yaml, vars: { id : '1' , gpio_in: '23' , gpio_out: '16'} }
  button2: !include { file: .button.yaml, vars: { id : '2', gpio_in: '22', gpio_out: '27' } }
  button3: !include { file: .button.yaml, vars: { id : '3', gpio_in: '4', gpio_out: '14' } }
  button4: !include { file: .button.yaml, vars: { id : '4', gpio_in: '3', gpio_out: '26' } }
  button5: !include { file: .button.yaml, vars: { id : '5', gpio_in: '19', gpio_out: '25' } }
  button6: !include { file: .button.yaml, vars: { id : '6', gpio_in: '18', gpio_out: '13' } }
  button7: !include { file: .button.yaml, vars: { id : '7', gpio_in: '5', gpio_out: '33' } }
  button8: !include { file: .button.yaml, vars: { id : '8', gpio_in: '17', gpio_out: '32' } }
    

output:
  - platform: ledc
    pin: 2
    id: rtttl_out


rtttl:
  output: rtttl_out
  on_finished_playback:
    - logger.log: 'Song ended!'

api:
  services:
    - service: play_rtttl
      variables:
        song_str: string
      then:
        - rtttl.play:
            rtttl: !lambda 'return song_str;'    


############################################################################
#.button.yaml file contents

#Expected ${id} to substitute for index number
#Expected ${gpio_in} to substitute for the gpio button pin
#Expected ${gpio_out} to substitute for the gpio button pin

switch:
  - platform: template
    name: "Toggle ${id} single"
    id: switch_${id}_single
    optimistic: true
    icon: mdi:numeric-1-box
    on_turn_on:
    - light.turn_on: 
        id: button_led_${id}
        effect: "single"
        brightness: 50%
    on_turn_off:
    - light.turn_off: button_led_${id}

  - platform: template
    name: "Toggle ${id} double"
    id: switch_${id}_double
    optimistic: true
    icon: mdi:numeric-1-box-multiple
    on_turn_on:
    - light.turn_on: 
        id: button_led_${id}
        effect: "double"
        brightness: 50%
    on_turn_off:
    - light.turn_off: button_led_${id}

  - platform: template
    name: "Toggle ${id} long"
    id: switch_${id}_long
    internal: true
    optimistic: true
    icon: mdi:chat-sleep
    on_turn_on:
    - light.turn_on: 
        id: button_led_${id}
        effect: "hold"
        brightness: 50%
    on_turn_off:
    - light.turn_off: button_led_${id}


binary_sensor:
  - name: "Button ${id}"
    id: button_${id}
    internal: true
    platform: gpio
    pin:
      number: ${gpio_in}
      mode:
        input: true
        pullup: true
      inverted: true

    on_multi_click:
      - timing:
          - ON for at most 1s
          - OFF for at most 0.3s
          - ON for at most 1s
          - OFF for at least 0.2s
        then:
          - lambda: !lambda id(switch_${id}_double).toggle();
          - logger.log: "Button ${id} Double"
      - timing:
          - ON for at most 1s
          - OFF for at least 0.5s
        then:
          - lambda: !lambda id(switch_${id}_single).toggle();
          - logger.log: "Button ${id} Single"
      - timing:
          - ON for 1s to 2s
          - OFF for at least 0.5s
        then:
          - lambda: !lambda id(switch_${id}_single).turn_off();
          - lambda: !lambda id(switch_${id}_double).turn_off();
          - logger.log: "Button ${id} Long"
  

output:
  - platform: ledc
    pin:  ${gpio_out}
    id: pin_led_${id}

light:
  - platform: monochromatic
    output: pin_led_${id}
    name: "Button ${id} LED"
    id: button_led_${id}
    internal: true
    effects:
      - pulse:
          name: "single"
          transition_length: 2s
          update_interval: 4s
      - pulse:
          name: "double"
          transition_length: 1s
          update_interval: 2s
      - pulse:
          name: "hold"
          transition_length: 0.5s
          update_interval: 1s