Allow shipping that is calculated using a base rate plus a rate per item? I figured this would be built in, but it seems it is not. See here:

I have two options:

Flat rate: I can make it 9.99 USD, but then if it's 100 items, it's still 9.99 USD.
I can make it 1 USD per item, but I als don't want that.

What I want is a base rate of 10 USD, and then 1 USD per item after that. Anyone know how to do that?
UPDATE
There is some information available for Commerce 1.0 here, but hardly any information on Commerce 2. This is basically all there is.
Can it be that Commerce 2 doesn't support this? I mean, nowhere can I see &quot;shipping rules&quot; or anything related to that that allows me to set up these rules?
(I miss UberCart)
Programmatically create your own custom shipping method in a custom module.
Example, custom module called &quot;mymodule&quot;:
/modules/custom/mymodule/src/Plugin/Commerce/ShippingMethod/CustomRate.php
&lt;?php

namespace Drupal\mymodule\Plugin\Commerce\ShippingMethod;

use Drupal\commerce_shipping\Plugin\Commerce\ShippingMethod\ShippingMethodBase;
use Drupal\commerce_price\Price;
use Drupal\commerce_shipping\Entity\ShipmentInterface;
use Drupal\commerce_shipping\PackageTypeManagerInterface;
use Drupal\commerce_shipping\ShippingRate;
use Drupal\commerce_shipping\ShippingService;
use Drupal\Core\Form\FormStateInterface;
use Drupal\state_machine\WorkflowManagerInterface;

/**
 * Provides the FlatRatePerItem shipping method.
 *
 * @CommerceShippingMethod(
 *   id = &quot;custom_rate&quot;,
 *   label = @Translation(&quot;Custom Rate&quot;),
 * )
 */
class CustomRate extends ShippingMethodBase {

  /**
   * Constructs a new FlatRate object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\commerce_shipping\PackageTypeManagerInterface $package_type_manager
   *   The package type manager.
   * @param \Drupal\state_machine\WorkflowManagerInterface $workflow_manager
   *   The workflow manager.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, PackageTypeManagerInterface $package_type_manager, WorkflowManagerInterface $workflow_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $package_type_manager, $workflow_manager);

    $this-&gt;services['default'] = new ShippingService('default', $this-&gt;configuration['rate_label']);
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
        'rate_label' =&gt; '',
        'rate_description' =&gt; '',
        'rate_amount' =&gt; NULL,
        'services' =&gt; ['default'],
      ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildConfigurationForm($form, $form_state);

    $amount = $this-&gt;configuration['rate_amount'];
    // A bug in the plugin_select form element causes $amount to be incomplete.
    if (isset($amount) &amp;&amp; !isset($amount['number'], $amount['currency_code'])) {
      $amount = NULL;
    }
    // A bug in the plugin_select form element causes $base_amount to be undefined.
    if (!empty($this-&gt;configuration['base_amount'])) {
      $base_amount = $this-&gt;configuration['base_amount'];
    }
    else {
      $base_amount = null;
    }

    $form['rate_label'] = [
      '#type' =&gt; 'textfield',
      '#title' =&gt; t('Rate label'),
      '#description' =&gt; t('Shown to customers when selecting the rate.'),
      '#default_value' =&gt; $this-&gt;configuration['rate_label'],
      '#required' =&gt; TRUE,
    ];
    $form['rate_description'] = [
      '#type' =&gt; 'textfield',
      '#title' =&gt; t('Rate description'),
      '#description' =&gt; t('Provides additional details about the rate to the customer.'),
      '#default_value' =&gt; $this-&gt;configuration['rate_description'],
    ];
    $form['base_amount'] = [
      '#type' =&gt; 'commerce_price',
      '#title' =&gt; t('Base amount'),
      '#default_value' =&gt; $base_amount,
      '#required' =&gt; TRUE,
      '#description' =&gt; t('Charged once.'),
    ];
    $form['rate_amount'] = [
      '#type' =&gt; 'commerce_price',
      '#title' =&gt; t('Rate amount'),
      '#default_value' =&gt; $amount,
      '#required' =&gt; TRUE,
      '#description' =&gt; t('Charged for each quantity of each shipment item.'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &amp;$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);

    if (!$form_state-&gt;getErrors()) {
      $values = $form_state-&gt;getValue($form['#parents']);
      $this-&gt;configuration['rate_label'] = $values['rate_label'];
      $this-&gt;configuration['rate_description'] = $values['rate_description'];
      $this-&gt;configuration['base_amount'] = $values['base_amount'];
      $this-&gt;configuration['rate_amount'] = $values['rate_amount'];
    }
  }

  /**
   * {@inheritdoc}
   */
  public function calculateRates(ShipmentInterface $shipment) {
    $base_amount = Price::fromArray($this-&gt;configuration['base_amount']); // create base price
    $amount = Price::fromArray($this-&gt;configuration['rate_amount']);
    $quantity = $shipment-&gt;getTotalQuantity();
    $ship_price = $amount-&gt;multiply($quantity);
    $ship_price = $ship_price-&gt;add($base_amount); // add base
    $rates = [];
    $rates[] = new ShippingRate([
      'shipping_method_id' =&gt; $this-&gt;parentEntity-&gt;id(),
      'service' =&gt; $this-&gt;services['default'],
      'amount' =&gt; $ship_price,
    ]);

    return $rates;
  }

}

Result