diff --git a/proposals/DOM-Parts-Declarative-Template.md b/proposals/DOM-Parts-Declarative-Template.md
deleted file mode 100644
index 2d6121f0..00000000
--- a/proposals/DOM-Parts-Declarative-Template.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# DOM Parts Declarative Template API
-
-This proposal covers the declarative API for creating a DOM part within a
-`<template>` element.
-
-## Proposal
-
-Double curly braces `{{}}` provide markers for DOM parts.
-
-In the most basic level, this proposal can produce the three DOM parts:
-`NodePart`, `AttributePart`, `ChildNodePart`.
-
-### Basic Examples
-
-Suppose we had the following template in some HTML extension template languages
-where `{name}` and `{email}` indicated locations of dynamic data insertion:
-
-```html
-<section>
-  <h1 id="name">{name}</h1>
-  Email: <a id="link" href="mailto:{email}">{email}</a>
-</section>
-```
-
-And the application has produce a template with the following content:
-
-```html
-<template>
-  <section>
-    <h1 id="name">{{}}</h1>
-    Email: <a id="link" href="{{}}">{{}}</a>
-  </section>
-</template>
-```
-
-This will create a `ChildNodePart` attached to `<h1>` with no content, a
-`NodePart` attached to `<a>`, and an `AttributePart` connected to `href`.
-
-A framework could fetch these parts use either a
-[`DocumentPart`](./DOM-Parts-Imperative.md#option-2-documentpartgroup) on the
-`DocumentFragment` produced by the template.
-
-## `PartialAttributePart`
-
-Allowing `{{}}` inside an attribute with some static content raises the same
-question as a
-[`PartialAttributePart`](./DOM-Parts-Imperative.md#partial-attribute-updates),
-but if the imperative questions are resolved so too could the declarative
-template syntax.
-
-## Metadata
-
-Templating systems may need to serialize data about the nodes they are marking
-into the processing instructions. Or at the very least parts could be named so
-that they are easier to fetch.
-
-```html
-<div>{{email data="foo"}}</div>
-```
-
-This could be exposed on the imperative API to be consumed in JavaScript by
-application logic.
-
-## Choice of marker
-
-The `{{}}` is a reasonable DOM part marker, but it could be something else, or
-it could even be something that is declared as the placeholder.
-
-## Compatability
-
-It may be challenging to implement `<template>` parsing of `{{}}` for
-compatability reasons, so there may need to be restrictions such as only
-allowing this template syntax in a new API like `createTemplateWithParts()`.
diff --git a/proposals/DOM-Parts-Declarative.md b/proposals/DOM-Parts-Declarative.md
new file mode 100644
index 00000000..f9ab5088
--- /dev/null
+++ b/proposals/DOM-Parts-Declarative.md
@@ -0,0 +1,131 @@
+# DOM Parts Declarative API
+
+This proposal covers the declarative API for creating a DOM part within a
+`<template>` element and main document HTML.
+
+## Proposal
+
+Double curly braces `{{}}` provide markers for DOM parts.
+
+In the most basic level, this proposal can produce the three DOM parts:
+`NodePart`, `AttributePart`, `ChildNodePart`.
+
+### Basic Examples
+
+Suppose we had the following template in some HTML extension template languages
+where `{name}` and `{email}` indicated locations of dynamic data insertion:
+
+```html
+<section>
+  <h1 id="name">{name}</h1>
+  Email: <a id="link" href="mailto:{email}">{email}</a>
+</section>
+```
+
+And the application has produced an HTML `<template>` with the following
+content:
+
+```html
+<template>
+  <section>
+    <h1 id="name">{{}}</h1>
+    Email: <a id="link" href="{{}}">{{}}</a>
+  </section>
+</template>
+```
+
+This will create a `ChildNodePart` attached to `<h1>` with no content, an
+`AttributePart` connected to `href`, and a `ChildNodePart` connected to `<a>`
+with no content.
+
+A framework could fetch these parts using the `getPartRoot()` on the
+[`DocumentFragment`](./DOM-Parts-Imperative.md#retrieving-a-documentpartroot)
+and then calling [`getParts()`](./DOM-Parts-Imperative.md#getparts).
+
+## Enablement
+
+For any DOM node, including `<template>`, a new `parseparts` attribute is
+introduced that indicates to the parser it should parse DOM part tags as DOM
+parts.
+
+```html
+<div parseparts></div>
+```
+
+Even for `innerHTML` use cases, only DOM nodes that are wrapped DOM with the
+`parseparts` attribute will use declarative parts.
+
+## Node parts
+
+For node parts, a `{{}}` tag could be provided as an attribute.
+
+```html
+<template>
+  <section {{}}></section>
+</template>
+```
+
+Would create a `NodePart` for `<section>`.
+
+## Partial attributes
+
+Allowing `{{}}` inside an attribute works the same as a
+[partial attribute update](./DOM-Parts-Imperative.md#partial-attribute-updates),
+in that it will create an `AttributePart` for the entire attribute, but it will
+have multi-valued `value` property.
+
+```html
+<template>
+  <section>
+    <h1 id="name">{{}}</h1>
+    Email: <a id="link" href="mailto:{{}}">{{}}</a>
+  </section>
+</template>
+```
+
+The `AttributePart` for `href` would have `statics` equal to `['mailto:', '']`.
+Empty string values are provided for any markers without default content.
+
+## Default Values
+
+To provide default values for any part, a part can be split into a start `{{#}}`
+and finish `{{/}}` indicators.
+
+```html
+<template>
+  <section>
+    <h1 id="name">{{#}}Ryosuke Niwa{{/}}</h1>
+    Email:
+    <a id="link" href="mailto:{{#}}rniwa@apple.com{{/}}">
+      {{#}}rniwa@apple.com{{/}}
+    </a>
+  </section>
+</template>
+```
+
+## Names and Metadata
+
+Templating systems may need to serialize data about the nodes they are marking
+into the processing instructions. Or at the very least parts could be named so
+that they are easier to fetch.
+
+```html
+<div>{{email data="foo"}}</div>
+```
+
+This could be exposed on the imperative API to be consumed in JavaScript by
+application logic.
+
+For parts that are split between opening and closing, it's possible to have
+multiple metadata values which are included as two elements in the `metadata`
+field.
+
+```
+{{# metadata1}}default value{{/ metadata2}}
+```
+
+## Choice of marker
+
+The `{{}}` and `{{#}}{{/}}` are reasonable DOM part markers, but this is open to
+proposals. It's possible to even allow the page to decide ewhat their markers
+should be.
diff --git a/proposals/DOM-Parts-Imperative.md b/proposals/DOM-Parts-Imperative.md
index 8034a6c9..f8aee1c0 100644
--- a/proposals/DOM-Parts-Imperative.md
+++ b/proposals/DOM-Parts-Imperative.md
@@ -8,35 +8,63 @@ A DOM part is represented by the `Part` interface and its sub interfaces.
 
 ```webidl
 interface Part {
-    attribute any value;
-    void commit();
+  attribute any value;
+
+  readonly attribute PartRoot root;
+  readonly attribute FrozenArray<DOMString> metadata;
+  void commit();
+};
+
+dictionary PartInit {
+  FrozenArray<DOMString> metadata;
 };
 
 interface NodePart : Part {
-    constructor(Node node);
-    readonly attribute Node node;
+  constructor(PartRoot root, Node node, optional PartInit init = {});
+
+  readonly attribute Node node;
 };
 
 interface AttributePart : Part {
-    constructor(Element element, DOMString qualifiedName, DOMString? namespace);
-    readonly attribute DOMString prefix;
-    readonly attribute DOMString localName;
-    readonly attribute DOMString namespaceURI;
+  constructor(
+      PartRoot root,
+      Element element,
+      DOMString qualifiedName,
+      optional DOMString? namespace = null,
+      optional Array<DOMString> statics = [],
+      optional PartInit init = {});
+
+  readonly attribute DOMString prefix;
+  readonly attribute DOMString localName;
+  readonly attribute DOMString namespaceURI;
+  readonly attribute DOMString rawName;
+
+  readonly attribute FrozenArray<DOMString> statics;
 };
 
 interface ChildNodePart : Part {
-    constructor(Node node, Node? previousSibling, Node? nextSibling);
-    readonly attribute Node? previousSibling;
-    readonly attribute Node? nextSibling;
+  constructor(
+      PartRoot root,
+      optional Node? previousSibling = null,
+      optional Node? nextSibling = null,
+      optional PartInit init = {});
+
+  readonly attribute Node? previousSibling;
+  readonly attribute Node? nextSibling;
+  readonly attribute FrozenArray<Node> children;
+};
+
+interface DocumentPartRoot {
 };
 ```
 
-The `Part` has one property named "value" of
-[_any_ type](https://heycam.github.io/webidl/#idl-any).
+`Part` points to a specific type of DOM, most commonly a `Node` or collection of
+sibling nodes. Depending on the type of `Part`, it has various properties that
+expose more information.
 
-When a new value is set or assigned to a DOM part, the change does not
-immediately reflect back to the corresponding
-[node](https://dom.spec.whatwg.org/#concept-node), its
+Each `Part` has a `value` that can be updated. When a new value is set or
+assigned to a DOM part, the change does not immediately reflect back to the
+corresponding [node](https://dom.spec.whatwg.org/#concept-node), its
 [attributes](https://dom.spec.whatwg.org/#concept-attribute), or its
 [properties](<(https://tc39.es/ecma262/#sec-object-type)>). Instead, the new
 value is staged to be later committed in a batch. This batching reduces the
@@ -44,7 +72,7 @@ runtime overhead of constantly returning control back from browser's
 implementation to JavaScript between each DOM mutation and allows browser
 engine's to avoid or batch certain sanity checks and housekeeping tasks.
 
-In the most basic level, this proposal consists of three DOM parts:
+In the most basic level, this proposal consists of four DOM parts:
 
 1. `NodePart` represents a single
    [node](https://dom.spec.whatwg.org/#concept-node).
@@ -54,8 +82,11 @@ In the most basic level, this proposal consists of three DOM parts:
    [child](https://dom.spec.whatwg.org/#concept-tree-child)
    [nodes](https://dom.spec.whatwg.org/#concept-node) of a node which can be
    [replaced](https://dom.spec.whatwg.org/#concept-node-replace).
+1. `DocumentPartRoot` represents a
+   [document](https://dom.spec.whatwg.org/#concept-document) or
+   [document fragment](https://dom.spec.whatwg.org/#interface-documentfragment).
 
-### Basic Examples
+### Basic examples
 
 Suppose we had the following template in some HTML extension template languages
 where `{name}` and `{email}` indicated locations of dynamic data insertion:
@@ -87,9 +118,13 @@ as follows:
 ```js
 const name = staticContent.getElementById("name");
 const link = staticContent.getElementById("link");
-const namePart = new ChildNodePart(name);
-const emailPart = new ChildNodePart(link);
-const emailAttributePart = new AttributePart(link, "href");
+const namePart = new ChildNodePart(document.getPartRoot(), name);
+const emailPart = new ChildNodePart(document.getPartRoot(), link);
+const emailAttributePart = new AttributePart(
+  document.getPartRoot(),
+  link,
+  "href"
+);
 ```
 
 Then assigning values as follows will update the DOM:
@@ -112,141 +147,66 @@ The resultant DOM will look like this:
 </section>
 ```
 
-## Part Groups
-
-DOM parts need grouping and ownership to provide batching and to enable parts
-created declaratively to be retrieved and updated by JavaScript.
-
-### Option 1. `PartGroup`
-
-One option is to make the concept of DOM part group a real DOM
-[interface](https://heycam.github.io/webidl/#idl-interfaces):
-
-```webidl
-interface PartGroup {
-    constructor(sequence<Part> parts);
-    readonly attribute FrozenArray<Part> parts;
-    void commit();
-}
-```
-
-Note that if we allow a single `Part` to belong to multiple `PartGroup`s, the
-first `PartGroup` which commits the changes would apply the mutations. In
-effect, this allows
-non-[partitioned](https://en.wikipedia.org/wiki/Partition_of_a_set) grouping of
-`Part` objects to be committed together.
-
-There is also a question of how mutable parts should be, and whether a
-`PartGroup` can appear as a part of another `PartGroup` for nested template
-instances or not. It doesn't make much sense for the list of _DOM parts_
-associated with `PartGroup` to get mutated after we've started committing things
-but there certainly is a room for adding or removing _DOM parts_ based on new
-input or state.
-
-If we made the relationship between DOM parts and `PartGroup` not dynamically
-mutable, users of this API could still create a new `PartGroup` each time such a
-mutation would have needed instead.
-
-The `parts` order would be the order in which DOM part was inserted to the
-`PartGroup`. Although there could be multiple DOM parts which reference the same
-element in different parts of the array, that doesn't necessarily pose an
-obvious issue other than a slight inefficiency in batching certain DOM
-operations.
-
-### Option 2. `DocumentPartGroup`
+## Retrieving a `DocumentPartRoot`
 
-A dynamic list of parts could be maintained at the `document` (and document
-fragment) level that would allow fetching all parts.
+For every document or document fragment, a new method `getPartRoot()` is added
+that returns a `DocumentPartRoot`.
 
 ```webidl
-interface DocumentPartGroup {
-  readonly attribute Array<Part> parts;
-  void commit();
-}
-
 partial interface Document {
-  readonly attribute DocumentPartGroup documentPart;
+  DocumentPartRoot getPartRoot();
 }
-```
-
-The list of parts would be cached initially on render, and then invalidated for
-lazy recalculation for any new `Part` that was declaratively or imperatively
-added to the `document`.
-
-The `parts` array would be in DOM-order. The exact algorithm for how to keep the
-`parts` array up to date with the `document` is an open question.
-
-### Option 3. `ChildNodePart` is a `PartGroup`
 
-To make `DocumentPartGroup` more performant and to provide better structure to
-`Part` relationships for a more optimal DOM walk, `ChildNodePart` could itself
-be a `PartGroup`, and would contain any `Part` objects that were nested inside
-its range, and child `parts` would not be part of any parent `ChildNodePart` or
-`DocumentPartGroup`.
-
-```webidl
-interface ChildNodePart {
-  readonly attribute Array<Part> parts;
-  void commit();
+partial interface DocumentFragment {
+  DocumentPartRoot getPartRoot();
 }
 ```
 
-The `parts` array would be in DOM-order. The exact algorithm for how to keep the
-`parts` array up to date with the DOM subtree rooted by the `ChildNodePart` is
-an open question.
+## Nested parts and cloning with `PartRoot`
 
-## Cloning Parts
+`DocumentPartRoot` and `ChildNodePart` both implement `PartRoot` and contain
+nested parts.
 
-Cloning parts along with the nodes they refer to is a major use case for DOM
-parts.
+```
+interface mixin PartRootMixin {
+  FrozenArray<Part> getParts();
+  PartRoot clone();
+};
 
-### Option 1: `cloneWithParts`
+ChildNodePart includes PartRootMixin;
+DocumentPartRoot includes PartRootMixin;
 
-One option would to add a new API to `Node`:
+typedef (DocumentPartRoot or ChildNodePart) PartRoot;
+```
 
-```webidl
-partial interface Node {
-    NodeWithParts cloneWithParts(optional CloneOptions options = {});
-};
+### `getParts()`
 
-dictionary CloneOptions {
-    boolean deep = true;
-    Document? document;
-    PartGroup? partGroup;
-};
+`getParts()` returns an array of parts that are contained within a `PartRoot`.
 
-dictionary NodeWithParts {
-    Node node;
-    PartGroup? partGroup;
-};
-```
+The array of parts would be cached initially on render, and then invalidated for
+lazy recalculation for any new `Part` that was declaratively or imperatively
+added to the `document` or for DOM node additions or removals.
 
-Here, we're proposing a slightly nicer API by combining
-[`importNode`](https://dom.spec.whatwg.org/#dom-document-importnode) and
-[`cloneNode`](https://dom.spec.whatwg.org/#dom-node-clonenode) and making the
-[cloning](https://dom.spec.whatwg.org/#concept-node-clone) deep by default.
+The array of parts would be in DOM-order. The exact algorithm for how to keep
+the array up to date with the `document` is up to the user-agent, but is
+invalidated anytime the user-agent detects changes to the DOM that could
+invalidate the array.
 
-### Option 2: `cloneWithParts` on `DocumentPart` and `ChildNodePart`
+#### Open nested part questions
 
-Since `DocumentPart` and `ChildNodePart` both are rooted at a specific node, the
-clone semantics are clearer:
+The precise specification of invalidation, caching, etc. is still yet to be
+described.
 
-```webidl
-partial interface DocumentPart {
-    NodeWithParts clone();
-}
+### `clone()`
 
-partial interface ChildNodePart {
-    NodeWithParts clone();
-}
-```
+`clone()` deep clones the `PartRoot`, its nested parts, and the DOM nodes. It
+returns a new `PartRoot` of the same type as the callee.
 
-### Other Cloning Questions
+#### Open cloning questions
 
-There are some questions here as well. What happens to the current values of DOM
-parts? Do we allow DOM parts to have some non-initial values and do we clone
-those values as well? If so, what do we do with proposed extensions like
-`PropertyPart` / `CustomPart`?
+There are some edge cases that are worth thinking about, like whether
+un-committed values of parts are cloned or whether invalid parts should be
+cloned.
 
 ## Partial Attribute Updates
 
@@ -256,156 +216,87 @@ had initially contained `mailto:` before `{email}` but we could not capture this
 prefix in the attribute value because `AttributePart` could only set the whole
 attribute value.
 
-There are a few options for how to support the use case of updating attributes
-with embedded static content such as `mailto:`
-
-### Option 1. Create Multiple `AttributePart`s Together
-
-In this approach, `AttributePart` gets a new static function which creates a
-list of `AttributePart`s which work together to set a value when the values are
-to be committed:
+Instead of `AttributePart` having a single string `value`, it could optionally
+take an `Array` that contains values that should be concatenated together. This
+allows updating individually parts of the attribute without needing to serialize
+the entire string.
 
 ```js
-const [firstName, lastName] = AttributePart.create(element, "title", null, [
-  null,
-  " ",
-  null,
-]);
-// Syntax to be improved. Here, a new AttributePart is created between each string.
+const part = AttributePart(document.getPartRoot(), element, "href");
+part.value = ["mailto: ", email];
 ```
 
-- **Pros**: Simplicity.
-- **Cons**: Coming up with a nice syntax to create a sequence of AttributePart
-  and string can be tricky.
-
-### Option 2. Introduce `AttributePartGroup`
-
-In this approach, we group multiple `AttributePart`s together by creating an
-explicit group:
+Additionally, `AttributePart` can be constructed with a list of static parts. If
+there are any static parts, the first static part will precede the first value,
+the second static part will precede the second value, and so on until the final static value is reached.
 
 ```js
-const firstName = new AttributePart();
-const lastName = new AttributePart();
-const group = AttributePartGroup(element, "title");
-group.append(firstName, " ", lastName);
-```
-
-This is morally equivalent to option 1 except there is an explicit grouping
-step.
-
-- **Pros**: Nicer syntax by the virtue of individual "partial" `AttributePart`'s
-  existence at the time of grouping. Code that assigns values to `AttributePart`
-  only needs to know about `AttributePart`
-- **Cons**: More objects / complexity. `AttributePart` will have two modes.
-
-### Option 3. Introduce `AttributePartFragment`
-
-Unlike option 2, this creates `AttributePartFragment`s from `AttributePart`,
-meaning that `AttributePart` in option 3 plays the role of `AttributePartGroup`
-in option 2:
-
-```js
-const firstNamePartial = new AttributePartFragment();
-const lastNamePartial = new AttributePartFragment();
-const part = AttributePart(element, "title");
-part.values = [firstNamePartial, " ", lastNamePartial];
+const part = AttributePart(document.getPartRoot(), element, "href", undefined, [
+  "mailto: ",
+]);
+part.value = email;
 ```
 
-- **Pros**: Nicer syntax by the virtue of individual `AttributePartFragment`'s
-  existence at the time of grouping. `AttributePart` just knows one thing to do:
-  to set the whole content attribute value.
-- **Cons**: More objects / complexity. Code that uses a template has to deal
-  with two different kinds of objects: `AttributePartFragment` and
-  `AttributePart`.
-
-### Option 4. Support arbitrary JavaScript objects
-
-One way of punting is to support arbitrary JavaScript objects as `value` that
-conform to some interface. This interface could be as simple as `toString()`, or
-could use `Symbol` to determine how to populate attributes. This would allow
-code that wanted to represent partial attributes, but would maintain the
-property that parts represent nodes or groupings of nodes.
+This API may be strengthened further to take in some parsed template string,
+which would allow the browser to determine which parts of the attribute were
+compile-time constants. This could allow using tagged template literals to pass
+static content to the browser.
 
 ```js
-class TitleAttributeValue {
-  constructor() {
-    this.firstName = "";
-    this.lastName = "";
-  }
-
-  toString() {
-    return `${this.firstName} ${this.lastName}`;
-  }
-}
-
-const part = AttributePart(element, "title");
-part.value = new TitleAttributeValue();
-part.value.firstName = "Ryosuke";
-part.value.lastName = "Niwa";
+const part = AttributePart(
+  document.getPartRoot(),
+  element,
+  "href",
+  undefined,
+  attribute`mailto: ${0}`
+);
+part.value = [email];
 ```
 
-- **Pros** No need for new `PartialAttributePart` or `AttributePart`
-  coordination. Does not block a future API object that represents partial
-  attributes.
-- **Cons** Need a way to represent partial attributes that are declaratively
-  defined.
+At this time there is no specific native representation of templates that could
+be inspected to determine with certainty which strings were compile time
+constants, but if some a representation were to exist, this API could provide
+better security for attributes that were sens
 
 ## Sibling `ChildNodePart`s
 
 Like partial attribute updates, when there are multiple points of interests
 under a single [parent](https://dom.spec.whatwg.org/#concept-tree-parent)
 [node](https://dom.spec.whatwg.org/#concept-node), and they're next to each
-other, index does not adequately describe a specific location in the DOM when
-other parts [insert](https://dom.spec.whatwg.org/#concept-node-insert) or
+other, previous and next sibling does not adequately describe a specific
+location in the DOM when other parts
+[insert](https://dom.spec.whatwg.org/#concept-node-insert) or
 [remove](https://dom.spec.whatwg.org/#concept-node-remove)
 [children](https://dom.spec.whatwg.org/#concept-tree-child).
 
-### Option 1. Create Multiple `ChildNodePart`s Together
+### Option 1. Create multiple `ChildNodePart`s together
 
 In this approach, `ChildNodePart` gets a new static function which creates a
 list of `ChildNodePart`s which work together to set a value when the values are
 to be committed:
 
 ```js
-const [firstName, lastName] = ChildNodePart.create(element, null, null, [
+const [firstName, lastName] = ChildNodePart.create(
+  document.getPartRoot(),
+  element,
   null,
-  " ",
   null,
-]);
+  [null, " ", null]
+);
 ```
 
 - **Pros**: Simplicity.
 - **Cons**: Coming up with a nice syntax to create a sequence of `ChildNodePart`
   and string can be tricky.
 
-### Option 2. Introduce `ChildNodePartGroup`
-
-In this approach, we group multiple `ChildNodePart`s together by creating an
-explicit group:
-
-```js
-const firstName = new ChildNodePart();
-const lastName = new ChildNodePart();
-const group = ChildNodePartGroup(element, null, null);
-group.append(firstName, " ", lastName);
-```
-
-This is morally equivalent to option 1 except there is an explicit grouping
-step.
-
-- **Pros**: Nicer syntax by the virtue of individual "partial" `ChildNodePart`s
-  existence at the time of grouping. Code that sets new children to
-  `ChildNodePart`s only needs to know about `ChildNodePart`.
-- **Cons**: More objects / complexity. `ChildNodePart` will have two modes.
-
-### Option 3. Introduce `PartialChildNodePart`
+### Option 2. Introduce `PartialChildNodePart`
 
 This creates `PartialChildNodePart` from `ChildNodePart`:
 
 ```js
 const firstNamePartial = new PartialChildNodePart();
 const lastNamePartial = new PartialChildNodePart();
-const part = ChildNodePart(element, null, null);
+const part = ChildNodePart(document.getPartRoot(), element, null, null);
 part.values = [firstNamePartial, " ", lastNamePartial];
 ```
 
@@ -415,17 +306,22 @@ part.values = [firstNamePartial, " ", lastNamePartial];
   with two different kinds of objects: `PartialChildNodePart` and
   `ChildNodePart`.
 
-### Option 4. Allow `nextSibling` and `previousSibling` to point to another `ChildNodePart`
+### Option 3. Allow `nextSibling` and `previousSibling` to point to another `ChildNodePart`
 
-We would update `ChildNodPart` interface as follows and allow `previousSibling`
-and `nextSibling` to point to another `ChildNodePart` as well as `Node`:
+Update `ChildNodPart` interface as follows and allow `previousSibling` and
+`nextSibling` to point to another `ChildNodePart` as well as `Node`:
 
 ```webidl
 interface ChildNodePart : Part {
-    constructor(Node node, (Node or ChildNodePart)? previousSibling, (Node or ChildNodePart)? nextSibling);
-    readonly attribute Node parentNode;
-    readonly attribute (Node or ChildNodePart)? previousSibling;
-    readonly attribute (Node or ChildNodePart)? nextSibling;
+  constructor(
+      PartRoot root,
+      optional (Node or ChildNodePart)? previousSibling = null,
+      optional (Node or ChildNodePart)? nextSibling = null,
+      optional PartInit init = {});
+
+  readonly attribute (Node or ChildNodePart)? previousSibling;
+  readonly attribute (Node or ChildNodePart)? nextSibling;
+  readonly attribute FrozenArray<Node> children;
 };
 ```
 
@@ -433,8 +329,8 @@ Then we can insert two consecutive `ChildNodePart`s by relating them in the
 constructor as follows:
 
 ```js
-const firstName = new ChildNodePart(element);
-const lastName = new ChildNodePart(element, firstName);
+const firstName = new ChildNodePart(document.getPartRoot(), element);
+const lastName = new ChildNodePart(document.getPartRoot(), element, firstName);
 ```
 
 Note that `lastName` takes `firstName` as the previous sibling but `firstName`
@@ -445,8 +341,8 @@ of previous/next sibling of other parts in the constructor.
 An alternative is to add an explicit API to chain multiple parts togethers:
 
 ```js
-const firstName = new ChildNodePart(element);
-const lastName = new ChildNodePart(element);
+const firstName = new ChildNodePart(document.getPartRoot(), element);
+const lastName = new ChildNodePart(document.getpartRoot(), element);
 ChildNodePart.chain(firstName, lastName);
 ```
 
@@ -460,8 +356,8 @@ Instead of worrying about coordination, the imperative API could throw an
 `Error` if users constructed two `ChildNodePart`s that overlapped.
 
 ```js
-const firstName = new ChildNodePart(element);
-const lastName = new ChildNodePart(element); // throws an Error.
+const firstName = new ChildNodePart(document.getPartRoot(), element);
+const lastName = new ChildNodePart(document.getPartRoot(), element); // throws an Error.
 ```
 
 Like in option 4, new APIs like `chain` or an a `append` could be added that
@@ -507,8 +403,8 @@ always are scoped to a single `Node`'s children.
 
 These invisible markers would not be `Node`s and so would be backwards
 compatible. DOM mutations would follow shrinking `Range` semantics, meaning the
-`ChildNodePart` would remove any `Node` that is removed in between the markers,
-and would only add a `Node` if it is added in between the markers.
+`ChildNodePart` would remove any `Node` that is removed in between the
+markers,and would only add a `Node` if it is added in between the markers.
 
 ## `PropertyPart` and `CustomCallbackPart`
 
diff --git a/proposals/DOM-Parts.md b/proposals/DOM-Parts.md
index 94e9aeb4..c9874826 100644
--- a/proposals/DOM-Parts.md
+++ b/proposals/DOM-Parts.md
@@ -103,4 +103,4 @@ There are a few component pieces to this proposal, so it is easiest to split it
 into multiple documents.
 
 1. [Imperative API to construct DOM parts](./DOM-Parts-Imperative.md)
-1. [Declarative API to construct DOM parts in `<template>`](./DOM-Parts-Declarative-Template.md)
+1. [Declarative API to construct DOM parts](./DOM-Parts-Declarative.md)