diff --git a/docs/api/runtime-storage.md b/docs/api/runtime-storage.md
new file mode 100644
index 0000000000000000000000000000000000000000..2d8ab2871d102872d6b3658ec24d1d35fca8b153
--- /dev/null
+++ b/docs/api/runtime-storage.md
@@ -0,0 +1,1235 @@
+# Runtime storage items
+
+There are **138** storage items from **37** pallets.
+
+<ul>
+<li>System - 0
+<ul>
+<li>
+<details>
+<summary>
+<code>Account</code></summary>
+ The full account information for a particular account ID.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ExtrinsicCount</code></summary>
+ Total extrinsics count for the current block.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>BlockWeight</code></summary>
+ The current weight for the block.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>AllExtrinsicsLen</code></summary>
+ Total length (in bytes) for all extrinsics put together, for the current block.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>BlockHash</code></summary>
+ Map of block numbers to block hashes.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ExtrinsicData</code></summary>
+ Extrinsics data for the current block (maps an extrinsic's index to its data).
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Number</code></summary>
+ The current block number being processed. Set by `execute_block`.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ParentHash</code></summary>
+ Hash of the previous block.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Digest</code></summary>
+ Digest of the current block, also part of the block header.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Events</code></summary>
+ Events deposited for the current block.
+
+ NOTE: The item is unbound and should therefore never be read on chain.
+ It could otherwise inflate the PoV size of a block.
+
+ Events have a large in-memory size. Box the events to not go out-of-memory
+ just in case someone still reads them from within the runtime.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>EventCount</code></summary>
+ The number of events in the `Events<T>` list.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>EventTopics</code></summary>
+ Mapping between a topic (represented by T::Hash) and a vector of indexes
+ of events in the `<Events<T>>` list.
+
+ All topic vectors have deterministic storage locations depending on the topic. This
+ allows light-clients to leverage the changes trie storage tracking mechanism and
+ in case of changes fetch the list of events of interest.
+
+ The value has the type `(T::BlockNumber, EventIndex)` because if we used only just
+ the `EventIndex` then in case if the topic has the same contents on the next block
+ no notification will be triggered thus the event might be lost.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>LastRuntimeUpgrade</code></summary>
+ Stores the `spec_version` and `spec_name` of when the last runtime upgrade happened.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>UpgradedToU32RefCount</code></summary>
+ True if we have upgraded so that `type RefCount` is `u32`. False (default) if not.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>UpgradedToTripleRefCount</code></summary>
+ True if we have upgraded so that AccountInfo contains three types of `RefCount`. False
+ (default) if not.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ExecutionPhase</code></summary>
+ The execution phase of the block.
+</details>
+</li>
+</ul>
+</li>
+<li>Account - 1
+<ul>
+<li>
+<details>
+<summary>
+<code>PendingRandomIdAssignments</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingNewAccounts</code></summary>
+
+</details>
+</li>
+</ul>
+</li>
+<li>Scheduler - 2
+<ul>
+<li>
+<details>
+<summary>
+<code>IncompleteSince</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Agenda</code></summary>
+ Items to be executed, indexed by the block number that they should be executed on.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Lookup</code></summary>
+ Lookup from a name to the block number and index of the task.
+
+ For v3 -> v4 the previously unbounded identities are Blake2-256 hashed to form the v4
+ identities.
+</details>
+</li>
+</ul>
+</li>
+<li>Babe - 3
+<ul>
+<li>
+<details>
+<summary>
+<code>EpochIndex</code></summary>
+ Current epoch index.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Authorities</code></summary>
+ Current epoch authorities.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>GenesisSlot</code></summary>
+ The slot at which the first epoch actually started. This is 0
+ until the first block of the chain.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CurrentSlot</code></summary>
+ Current slot number.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Randomness</code></summary>
+ The epoch randomness for the *current* epoch.
+
+ # Security
+
+ This MUST NOT be used for gambling, as it can be influenced by a
+ malicious validator in the short term. It MAY be used in many
+ cryptographic protocols, however, so long as one remembers that this
+ (like everything else on-chain) it is public. For example, it can be
+ used where a number is needed that cannot have been chosen by an
+ adversary, for purposes such as public-coin zero-knowledge proofs.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingEpochConfigChange</code></summary>
+ Pending epoch configuration change that will be applied when the next epoch is enacted.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextRandomness</code></summary>
+ Next epoch randomness.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextAuthorities</code></summary>
+ Next epoch authorities.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SegmentIndex</code></summary>
+ Randomness under construction.
+
+ We make a trade-off between storage accesses and list length.
+ We store the under-construction randomness in segments of up to
+ `UNDER_CONSTRUCTION_SEGMENT_LENGTH`.
+
+ Once a segment reaches this length, we begin the next one.
+ We reset all segments and return to `0` at the beginning of every
+ epoch.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>UnderConstruction</code></summary>
+ TWOX-NOTE: `SegmentIndex` is an increasing integer, so this is okay.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Initialized</code></summary>
+ Temporary value (cleared at block finalization) which is `Some`
+ if per-block initialization has already been called for current block.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>AuthorVrfRandomness</code></summary>
+ This field should always be populated during block processing unless
+ secondary plain slots are enabled (which don't contain a VRF output).
+
+ It is set in `on_finalize`, before it will contain the value from the last block.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>EpochStart</code></summary>
+ The block numbers when the last and current epoch have started, respectively `N-1` and
+ `N`.
+ NOTE: We track this is in order to annotate the block number when a given pool of
+ entropy was fixed (i.e. it was known to chain observers). Since epochs are defined in
+ slots, which may be skipped, the block numbers may not line up with the slot numbers.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Lateness</code></summary>
+ How late the current block is compared to its parent.
+
+ This entry is populated as part of block execution and is cleaned up
+ on block finalization. Querying this storage entry outside of block
+ execution context should always yield zero.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>EpochConfig</code></summary>
+ The configuration for the current epoch. Should never be `None` as it is initialized in
+ genesis.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextEpochConfig</code></summary>
+ The configuration for the next epoch, `None` if the config will not change
+ (you can fallback to `EpochConfig` instead in that case).
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SkippedEpochs</code></summary>
+ A list of the last 100 skipped epochs and the corresponding session index
+ when the epoch was skipped.
+
+ This is only used for validating equivocation proofs. An equivocation proof
+ must contains a key-ownership proof for a given session, therefore we need a
+ way to tie together sessions and epoch indices, i.e. we need to validate that
+ a validator was the owner of a given key on a given session, and what the
+ active epoch index was during that session.
+</details>
+</li>
+</ul>
+</li>
+<li>Timestamp - 4
+<ul>
+<li>
+<details>
+<summary>
+<code>Now</code></summary>
+ Current time for the current block.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>DidUpdate</code></summary>
+ Did the timestamp get updated in this block?
+</details>
+</li>
+</ul>
+</li>
+<li>Parameters - 5
+<ul>
+<li>
+<details>
+<summary>
+<code>ParametersStorage</code></summary>
+
+</details>
+</li>
+</ul>
+</li>
+<li>Balances - 6
+<ul>
+<li>
+<details>
+<summary>
+<code>TotalIssuance</code></summary>
+ The total units issued in the system.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>InactiveIssuance</code></summary>
+ The total units of outstanding deactivated balance in the system.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Account</code></summary>
+ The Balances pallet example of storing the balance of an account.
+
+ # Example
+
+ ```nocompile
+  impl pallet_balances::Config for Runtime {
+    type AccountStore = StorageMapShim<Self::Account<Runtime>, frame_system::Provider<Runtime>, AccountId, Self::AccountData<Balance>>
+  }
+ ```
+
+ You can also store the balance of an account in the `System` pallet.
+
+ # Example
+
+ ```nocompile
+  impl pallet_balances::Config for Runtime {
+   type AccountStore = System
+  }
+ ```
+
+ But this comes with tradeoffs, storing account balances in the system pallet stores
+ `frame_system` data alongside the account data contrary to storing account balances in the
+ `Balances` pallet, which uses a `StorageMap` to store balances data only.
+ NOTE: This is only used in the case that this pallet is used to store balances.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Locks</code></summary>
+ Any liquidity locks on some account balances.
+ NOTE: Should only be accessed when setting, changing and freeing a lock.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Reserves</code></summary>
+ Named reserves on some account balances.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Holds</code></summary>
+ Holds on account balances.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Freezes</code></summary>
+ Freeze locks on account balances.
+</details>
+</li>
+</ul>
+</li>
+<li>TransactionPayment - 32
+<ul>
+<li>
+<details>
+<summary>
+<code>NextFeeMultiplier</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>StorageVersion</code></summary>
+
+</details>
+</li>
+</ul>
+</li>
+<li>OneshotAccount - 7
+<ul>
+<li>
+<details>
+<summary>
+<code>OneshotAccounts</code></summary>
+
+</details>
+</li>
+</ul>
+</li>
+<li>Quota - 66
+<ul>
+<li>
+<details>
+<summary>
+<code>IdtyQuota</code></summary>
+ maps identity index to quota
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RefundQueue</code></summary>
+ fees waiting for refund
+</details>
+</li>
+</ul>
+</li>
+<li>AuthorityMembers - 10
+<ul>
+<li>
+<details>
+<summary>
+<code>AccountIdOf</code></summary>
+ maps member id to account id
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>AuthoritiesCounter</code></summary>
+ count the number of authorities
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IncomingAuthorities</code></summary>
+ list incoming authorities
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>OnlineAuthorities</code></summary>
+ list online authorities
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>OutgoingAuthorities</code></summary>
+ list outgoing authorities
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Members</code></summary>
+ maps member id to member data
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>BlackList</code></summary>
+
+</details>
+</li>
+</ul>
+</li>
+<li>Authorship - 11
+<ul>
+<li>
+<details>
+<summary>
+<code>Author</code></summary>
+ Author of current block.
+</details>
+</li>
+</ul>
+</li>
+<li>Offences - 12
+<ul>
+<li>
+<details>
+<summary>
+<code>Reports</code></summary>
+ The primary structure that holds all offence records keyed by report identifiers.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ConcurrentReportsIndex</code></summary>
+ A vector of reports of the same kind that happened at the same time slot.
+</details>
+</li>
+</ul>
+</li>
+<li>Historical - 13
+<ul>
+</ul>
+</li>
+<li>Session - 14
+<ul>
+<li>
+<details>
+<summary>
+<code>Validators</code></summary>
+ The current set of validators.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CurrentIndex</code></summary>
+ Current index of the session.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>QueuedChanged</code></summary>
+ True if the underlying economic identities or weighting behind the validators
+ has changed in the queued validator set.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>QueuedKeys</code></summary>
+ The queued keys for the next session. When the next session begins, these keys
+ will be used to determine the validator's session keys.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>DisabledValidators</code></summary>
+ Indices of disabled validators.
+
+ The vec is always kept sorted so that we can find whether a given validator is
+ disabled using binary search. It gets cleared when `on_session_ending` returns
+ a new set of identities.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextKeys</code></summary>
+ The next session keys for a validator.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>KeyOwner</code></summary>
+ The owner of a key. The key is the `KeyTypeId` + the encoded key.
+</details>
+</li>
+</ul>
+</li>
+<li>Grandpa - 15
+<ul>
+<li>
+<details>
+<summary>
+<code>State</code></summary>
+ State of the current authority set.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingChange</code></summary>
+ Pending change: (signaled at, scheduled change).
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextForced</code></summary>
+ next block number where we can force a change.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Stalled</code></summary>
+ `true` if we are currently stalled.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CurrentSetId</code></summary>
+ The number of changes (both in terms of keys and underlying economic responsibilities)
+ in the "set" of Grandpa validators from genesis.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SetIdSession</code></summary>
+ A mapping from grandpa set ID to the index of the *most recent* session for which its
+ members were responsible.
+
+ This is only used for validating equivocation proofs. An equivocation proof must
+ contains a key-ownership proof for a given session, therefore we need a way to tie
+ together sessions and GRANDPA set ids, i.e. we need to validate that a validator
+ was the owner of a given key on a given session, and what the active set ID was
+ during that session.
+
+ TWOX-NOTE: `SetId` is not under user control.
+</details>
+</li>
+</ul>
+</li>
+<li>ImOnline - 16
+<ul>
+<li>
+<details>
+<summary>
+<code>HeartbeatAfter</code></summary>
+ The block number after which it's ok to send heartbeats in the current
+ session.
+
+ At the beginning of each session we set this to a value that should fall
+ roughly in the middle of the session duration. The idea is to first wait for
+ the validators to produce a block in the current session, so that the
+ heartbeat later on will not be necessary.
+
+ This value will only be used as a fallback if we fail to get a proper session
+ progress estimate from `NextSessionRotation`, as those estimates should be
+ more accurate then the value we calculate for `HeartbeatAfter`.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Keys</code></summary>
+ The current set of keys that may issue a heartbeat.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ReceivedHeartbeats</code></summary>
+ For each session index, we keep a mapping of `SessionIndex` and `AuthIndex` to
+ `WrapperOpaque<BoundedOpaqueNetworkState>`.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>AuthoredBlocks</code></summary>
+ For each session index, we keep a mapping of `ValidatorId<T>` to the
+ number of blocks authored by the given authority.
+</details>
+</li>
+</ul>
+</li>
+<li>AuthorityDiscovery - 17
+<ul>
+</ul>
+</li>
+<li>Sudo - 20
+<ul>
+<li>
+<details>
+<summary>
+<code>Key</code></summary>
+ The `AccountId` of the sudo key.
+</details>
+</li>
+</ul>
+</li>
+<li>UpgradeOrigin - 21
+<ul>
+</ul>
+</li>
+<li>Preimage - 22
+<ul>
+<li>
+<details>
+<summary>
+<code>StatusFor</code></summary>
+ The request status of a given hash.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PreimageFor</code></summary>
+
+</details>
+</li>
+</ul>
+</li>
+<li>TechnicalCommittee - 23
+<ul>
+<li>
+<details>
+<summary>
+<code>Proposals</code></summary>
+ The hashes of the active proposals.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ProposalOf</code></summary>
+ Actual proposal for a given hash, if it's current.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Voting</code></summary>
+ Votes on a given proposal, if it is ongoing.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ProposalCount</code></summary>
+ Proposals so far.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Members</code></summary>
+ The current members of the collective. This is stored sorted (just by value).
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Prime</code></summary>
+ The prime member that helps determine the default vote behavior in case of absentations.
+</details>
+</li>
+</ul>
+</li>
+<li>UniversalDividend - 30
+<ul>
+<li>
+<details>
+<summary>
+<code>CurrentUd</code></summary>
+ Current UD amount
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CurrentUdIndex</code></summary>
+ Current UD index
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MonetaryMass</code></summary>
+ Total quantity of money created by universal dividend (does not take into account the possible destruction of money)
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextReeval</code></summary>
+ Next UD reevaluation
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextUd</code></summary>
+ Next UD creation
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PastReevals</code></summary>
+ Past UD reevaluations
+</details>
+</li>
+</ul>
+</li>
+<li>Wot - 40
+<ul>
+</ul>
+</li>
+<li>Identity - 41
+<ul>
+<li>
+<details>
+<summary>
+<code>Identities</code></summary>
+ maps identity index to identity value
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CounterForIdentities</code></summary>
+Counter for the related counted storage map
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdentityIndexOf</code></summary>
+ maps account id to identity index
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdentitiesNames</code></summary>
+ maps identity name to identity index (simply a set)
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NextIdtyIndex</code></summary>
+ counter of the identity index to give to the next identity
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdentitiesRemovableOn</code></summary>
+ maps block number to the list of identities set to be removed at this bloc
+</details>
+</li>
+</ul>
+</li>
+<li>Membership - 42
+<ul>
+<li>
+<details>
+<summary>
+<code>Membership</code></summary>
+ maps identity id to membership data
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CounterForMembership</code></summary>
+Counter for the related counted storage map
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipsExpireOn</code></summary>
+ maps block number to the list of identity id set to expire at this block
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingMembership</code></summary>
+ identities with pending membership request
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingMembershipsExpireOn</code></summary>
+ maps block number to the list of memberships set to expire at this block
+</details>
+</li>
+</ul>
+</li>
+<li>Cert - 43
+<ul>
+<li>
+<details>
+<summary>
+<code>StorageIdtyCertMeta</code></summary>
+ Certifications metada by issuer
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CertsByReceiver</code></summary>
+ Certifications by receiver
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>StorageCertsRemovableOn</code></summary>
+ Certifications removable on
+</details>
+</li>
+</ul>
+</li>
+<li>Distance - 44
+<ul>
+<li>
+<details>
+<summary>
+<code>EvaluationPool0</code></summary>
+ Identities queued for distance evaluation
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>EvaluationPool1</code></summary>
+ Identities queued for distance evaluation
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>EvaluationPool2</code></summary>
+ Identities queued for distance evaluation
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>EvaluationBlock</code></summary>
+ Block for which the distance rule must be checked
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdentityDistanceStatus</code></summary>
+ Distance evaluation status by identity
+
+ * `.0` is the account who requested an evaluation and reserved the price,
+   for whom the price will be unreserved or slashed when the evaluation completes.
+ * `.1` is the status of the evaluation.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>DistanceStatusExpireOn</code></summary>
+ Identities by distance status expiration session index
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>DidUpdate</code></summary>
+ Did evaluation get updated in this block?
+</details>
+</li>
+</ul>
+</li>
+<li>SmithSubWot - 50
+<ul>
+</ul>
+</li>
+<li>SmithMembership - 52
+<ul>
+<li>
+<details>
+<summary>
+<code>Membership</code></summary>
+ maps identity id to membership data
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CounterForMembership</code></summary>
+Counter for the related counted storage map
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipsExpireOn</code></summary>
+ maps block number to the list of identity id set to expire at this block
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingMembership</code></summary>
+ identities with pending membership request
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingMembershipsExpireOn</code></summary>
+ maps block number to the list of memberships set to expire at this block
+</details>
+</li>
+</ul>
+</li>
+<li>SmithCert - 53
+<ul>
+<li>
+<details>
+<summary>
+<code>StorageIdtyCertMeta</code></summary>
+ Certifications metada by issuer
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CertsByReceiver</code></summary>
+ Certifications by receiver
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>StorageCertsRemovableOn</code></summary>
+ Certifications removable on
+</details>
+</li>
+</ul>
+</li>
+<li>AtomicSwap - 60
+<ul>
+<li>
+<details>
+<summary>
+<code>PendingSwaps</code></summary>
+
+</details>
+</li>
+</ul>
+</li>
+<li>Multisig - 61
+<ul>
+<li>
+<details>
+<summary>
+<code>Multisigs</code></summary>
+ The set of open multisig operations.
+</details>
+</li>
+</ul>
+</li>
+<li>ProvideRandomness - 62
+<ul>
+<li>
+<details>
+<summary>
+<code>NexEpochHookIn</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RequestIdProvider</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RequestsReadyAtNextBlock</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RequestsReadyAtEpoch</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RequestsIds</code></summary>
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CounterForRequestsIds</code></summary>
+Counter for the related counted storage map
+</details>
+</li>
+</ul>
+</li>
+<li>Proxy - 63
+<ul>
+<li>
+<details>
+<summary>
+<code>Proxies</code></summary>
+ The set of account proxies. Maps the account which has delegated to the accounts
+ which are being delegated to, together with the amount held on deposit.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Announcements</code></summary>
+ The announcements made by the proxy (key).
+</details>
+</li>
+</ul>
+</li>
+<li>Utility - 64
+<ul>
+</ul>
+</li>
+<li>Treasury - 65
+<ul>
+<li>
+<details>
+<summary>
+<code>ProposalCount</code></summary>
+ Number of proposals that have been made.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Proposals</code></summary>
+ Proposals that have been made.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Deactivated</code></summary>
+ The amount which has been reported as inactive to Currency.
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Approvals</code></summary>
+ Proposal indices that have been approved but not yet awarded.
+</details>
+</li>
+</ul>
+</li>
+</ul>
\ No newline at end of file
diff --git a/xtask/res/templates/runtime-storages.md b/xtask/res/templates/runtime-storages.md
new file mode 100644
index 0000000000000000000000000000000000000000..0891e57cda2dbb7a1814625d433d32df8002b04b
--- /dev/null
+++ b/xtask/res/templates/runtime-storages.md
@@ -0,0 +1,21 @@
+# Runtime storage items
+
+There are **{{storage_counter}}** storage items from **{{ pallets | length }}** pallets.
+
+<ul>
+{% for pallet in pallets -%}
+<li>{{ pallet.name }} - {{ pallet.index }}
+<ul>
+{% for storage in pallet.storages -%}
+<li>
+<details>
+<summary>
+<code>{{ storage.name }}{#({{ storage.key }}→{{ storage.value }})#}</code></summary>
+{{ storage.documentation }}
+</details>
+</li>
+{% endfor -%}
+</ul>
+</li>
+{% endfor -%}
+</ul>
\ No newline at end of file
diff --git a/xtask/src/gen_doc.rs b/xtask/src/gen_doc.rs
index cbda42494f57b169e3332ee3d67fd9403fb917c4..4513910abbdc5d3e422b836cc649a3f2defc6b1d 100644
--- a/xtask/src/gen_doc.rs
+++ b/xtask/src/gen_doc.rs
@@ -16,6 +16,7 @@
 
 use anyhow::{bail, Context, Result};
 use codec::Decode;
+use frame_metadata::{StorageEntryMetadata, StorageEntryType};
 use scale_info::form::PortableForm;
 use serde::Serialize;
 use std::{
@@ -29,6 +30,7 @@ use tera::Tera;
 const CALLS_DOC_FILEPATH: &str = "docs/api/runtime-calls.md";
 const EVENTS_DOC_FILEPATH: &str = "docs/api/runtime-events.md";
 const ERRORS_DOC_FILEPATH: &str = "docs/api/runtime-errors.md";
+const STORAGES_DOC_FILEPATH: &str = "docs/api/runtime-storage.md";
 const TEMPLATES_GLOB: &str = "xtask/res/templates/*.md";
 
 // define structs and implementations
@@ -42,6 +44,7 @@ struct Pallet {
     calls: Vec<Call>,
     events: Vec<Event>,
     errors: Vec<ErroR>,
+    storages: Vec<Storage>,
 }
 #[derive(Clone, Serialize)]
 struct Call {
@@ -73,6 +76,18 @@ struct ErroR {
     index: u8,
     name: String,
 }
+#[derive(Clone, Serialize)]
+struct Storage {
+    documentation: String,
+    name: String,
+    key: Option<String>,
+    value: String,
+}
+#[derive(Clone, Serialize)]
+struct StorageMap {
+    name: String,
+    type_name: String,
+}
 
 impl Pallet {
     fn new(
@@ -81,6 +96,7 @@ impl Pallet {
         call_scale_type_def: &Option<scale_info::TypeDef<PortableForm>>,
         event_scale_type_def: &Option<scale_info::TypeDef<PortableForm>>,
         error_scale_type_def: &Option<scale_info::TypeDef<PortableForm>>,
+        storage_entries: &Option<Vec<StorageEntryMetadata<PortableForm>>>,
     ) -> Result<Self> {
         let calls = if let Some(call_scale_type_def) = call_scale_type_def {
             if let scale_info::TypeDef::Variant(calls_enum) = call_scale_type_def {
@@ -109,12 +125,18 @@ impl Pallet {
         } else {
             vec![]
         };
+        let storages = if let Some(storage_entries) = storage_entries {
+            storage_entries.iter().map(Into::into).collect()
+        } else {
+            vec![]
+        };
         Ok(Self {
             index,
             name,
             calls,
             events,
             errors,
+            storages,
         })
     }
 }
@@ -163,6 +185,23 @@ impl From<&scale_info::Field<PortableForm>> for EventParam {
     }
 }
 
+impl From<&StorageEntryMetadata<PortableForm>> for Storage {
+    fn from(entry: &StorageEntryMetadata<PortableForm>) -> Self {
+        let (key, value) = match entry.ty {
+            StorageEntryType::<PortableForm>::Plain(v) => (None, format!("{}", v.id)),
+            StorageEntryType::<PortableForm>::Map { key, value, .. } => {
+                (Some(format!("{}", key.id)), format!("{}", value.id))
+            }
+        };
+        Self {
+            documentation: entry.docs.iter().cloned().collect::<Vec<_>>().join("\n"),
+            name: entry.name.to_owned(),
+            key,
+            value,
+        }
+    }
+}
+
 impl From<&scale_info::Variant<PortableForm>> for ErroR {
     fn from(variant: &scale_info::Variant<PortableForm>) -> Self {
         Self {
@@ -244,7 +283,7 @@ pub(super) fn gen_doc() -> Result<()> {
         bail!("unsuported metadata version")
     };
 
-    let (call_doc, event_doc, error_doc) = print_runtime(runtime);
+    let (call_doc, event_doc, error_doc, storage_doc) = print_runtime(runtime);
 
     let mut file = File::create(CALLS_DOC_FILEPATH)
         .with_context(|| format!("Failed to create file '{}'", CALLS_DOC_FILEPATH))?;
@@ -258,6 +297,10 @@ pub(super) fn gen_doc() -> Result<()> {
         .with_context(|| format!("Failed to create file '{}'", ERRORS_DOC_FILEPATH))?;
     file.write_all(error_doc.as_bytes())
         .with_context(|| format!("Failed to write to file '{}'", ERRORS_DOC_FILEPATH))?;
+    let mut file = File::create(STORAGES_DOC_FILEPATH)
+        .with_context(|| format!("Failed to create file '{}'", STORAGES_DOC_FILEPATH))?;
+    file.write_all(storage_doc.as_bytes())
+        .with_context(|| format!("Failed to write to file '{}'", STORAGES_DOC_FILEPATH))?;
 
     Ok(())
 }
@@ -295,6 +338,12 @@ fn get_from_metadata_v14(
             println!("{}: {} (0 errors)", pallet.index, pallet.name);
             None
         };
+        let storage_entries = if let Some(storages) = pallet.storage {
+            Some(storages.entries)
+        } else {
+            println!("{}: {} (0 storages)", pallet.index, pallet.name);
+            None
+        };
 
         let pallet = Pallet::new(
             pallet.index,
@@ -302,6 +351,7 @@ fn get_from_metadata_v14(
             &calls_type_def,
             &events_type_def,
             &errors_type_def,
+            &storage_entries,
         )?;
 
         println!(
@@ -322,13 +372,19 @@ fn get_from_metadata_v14(
             pallet.name,
             pallet.errors.len()
         );
+        println!(
+            "{}: {} ({} storages)",
+            pallet.index,
+            pallet.name,
+            pallet.storages.len()
+        );
         pallets.push(pallet);
     }
     Ok(pallets)
 }
 
 /// use template to render markdown file with runtime calls documentation
-fn print_runtime(pallets: RuntimePallets) -> (String, String, String) {
+fn print_runtime(pallets: RuntimePallets) -> (String, String, String, String) {
     // init variables
     let mut user_calls_counter = 0;
     let user_calls_pallets: RuntimePallets = pallets
@@ -392,6 +448,11 @@ fn print_runtime(pallets: RuntimePallets) -> (String, String, String) {
         .iter()
         .for_each(|pallet| error_counter += pallet.errors.len());
 
+    let mut storage_counter = 0;
+    pallets
+        .iter()
+        .for_each(|pallet| storage_counter += pallet.storages.len());
+
     // compile template
     let tera = match Tera::new(TEMPLATES_GLOB) {
         Ok(t) => t,
@@ -427,5 +488,11 @@ fn print_runtime(pallets: RuntimePallets) -> (String, String, String) {
         .render("runtime-errors.md", &context)
         .expect("template error");
 
-    (call_doc, event_doc, error_doc)
+    // render storages
+    context.insert("storage_counter", &storage_counter);
+    let storage_doc = tera
+        .render("runtime-storages.md", &context)
+        .expect("template storage");
+
+    (call_doc, event_doc, error_doc, storage_doc)
 }