attempt to remove flag
diff --git a/packages/devtools_app/lib/src/inspector/diagnostics_node.dart b/packages/devtools_app/lib/src/inspector/diagnostics_node.dart
index 498966d..8f4b1ad 100644
--- a/packages/devtools_app/lib/src/inspector/diagnostics_node.dart
+++ b/packages/devtools_app/lib/src/inspector/diagnostics_node.dart
@@ -65,15 +65,21 @@
 
   final bool isProperty;
 
-  bool get isFlex => getBooleanMember('isFlex', false);
+  bool get isFlex => ['Row', 'Column', 'Flex'].contains(widgetRuntimeType);
 
-  int get flexFactor => json['flexFactor'];
+  int get flexFactor => cachedProperties
+      ?.firstWhere((property) => property.name == 'flex', orElse: () => null)
+      ?.getIntMember('value');
 
-  Map<String, Object> get constraints => json['constraints'];
+  RemoteDiagnosticsNode get constraints => renderObject?.cachedProperties
+      ?.firstWhere((property) => property.name == 'constraints');
 
-  Map<String, Object> get renderObject => json['renderObject'];
+  RemoteDiagnosticsNode _renderObject;
 
-  Map<String, Object> get size => json['size'];
+  RemoteDiagnosticsNode get renderObject => _renderObject;
+
+  RemoteDiagnosticsNode get size => renderObject?.cachedProperties
+      ?.firstWhere((property) => property.name == 'size');
 
   @override
   bool operator ==(dynamic other) {
@@ -328,6 +334,10 @@
     return JsonUtils.getStringMember(json, memberName);
   }
 
+  int getIntMember(String memberName) {
+    return JsonUtils.getIntMember(json, memberName);
+  }
+
   bool getBooleanMember(String memberName, bool defaultValue) {
     if (json[memberName] == null) {
       return defaultValue;
@@ -664,6 +674,19 @@
     await (await inspectorService)
         ?.setSelectionInspector(valueRef, uiAlreadyUpdated);
   }
+
+  Future<void> getRenderObject() async {
+    if (_renderObject != null) return;
+    final service = await inspectorService;
+    _renderObject = await service.renderObject(valueRef);
+    if (isFlex && _children != null)
+      for (var i = 0; i < _children.length; ++i) {
+        final List<dynamic> children =
+            _renderObject.json['children'];
+        _children[i]._renderObject = RemoteDiagnosticsNode(
+            children[i], inspectorService, true, _children[i]);
+      }
+  }
 }
 
 class InspectorSourceLocation {
diff --git a/packages/devtools_app/lib/src/inspector/flutter/inspector_data_models.dart b/packages/devtools_app/lib/src/inspector/flutter/inspector_data_models.dart
index ac1b994..11282e9 100644
--- a/packages/devtools_app/lib/src/inspector/flutter/inspector_data_models.dart
+++ b/packages/devtools_app/lib/src/inspector/flutter/inspector_data_models.dart
@@ -13,8 +13,6 @@
 import '../inspector_tree.dart';
 import 'story_of_your_layout/utils.dart';
 
-const Type boxConstraintsType = BoxConstraints;
-
 /// Compute real widget sizes into rendered sizes to be displayed on the details tab.
 /// The sum of the resulting render sizes may or may not be greater than the [maxSizeAvailable]
 /// In the case where it is greater, we should render it with scrolling capability.
@@ -95,11 +93,11 @@
 // TODO(albertusangga): Move this to [RemoteDiagnosticsNode] once dart:html app is removed
 class LayoutProperties {
   LayoutProperties(this.node, {int copyLevel = 1})
-      : description = node.diagnostic?.description,
-        size = deserializeSize(node.diagnostic?.size),
-        constraints = deserializeConstraints(node.diagnostic?.constraints),
-        isFlex = node.diagnostic?.isFlex,
-        flexFactor = node.diagnostic?.flexFactor,
+      : description = node.diagnostic.description,
+        size = deserializeSize(node.diagnostic.size),
+        constraints = deserializeConstraints(node.diagnostic.constraints),
+        isFlex = node.diagnostic.isFlex,
+        flexFactor = node.diagnostic.flexFactor,
         children = copyLevel == 0
             ? []
             : node.children
@@ -154,22 +152,75 @@
     return '${min.toStringAsFixed(1)}<=$axis<=${max.toStringAsFixed(1)}';
   }
 
-  static BoxConstraints deserializeConstraints(Map<String, Object> json) {
+  /// Return the string inside the parentheses
+  /// example:
+  /// getValue('BoxConstraints(value)'); # returns 'value'
+  static String getValue(String description) {
+    return description.substring(
+        description.indexOf('(') + 1, description.indexOf(')'));
+  }
+
+  /// This method implementation is based on [BoxConstraints].toString() implementation
+  static BoxConstraints deserializeConstraints(
+      RemoteDiagnosticsNode constraints) {
     // TODO(albertusangga): Support SliverConstraint
-    if (json == null || json['type'] != boxConstraintsType.toString())
-      return null;
-    // TODO(albertusangga): Simplify this json (i.e: when maxWidth is null it means it is unbounded)
+    if (constraints == null) return null;
+    final value = getValue(constraints.description);
+    if (value.contains('unconstrained'))
+      return const BoxConstraints(
+        minWidth: 0.0,
+        minHeight: 0.0,
+        maxWidth: double.infinity,
+        maxHeight: double.infinity,
+      );
+    if (value.contains('biggest'))
+      return const BoxConstraints(
+        minWidth: double.infinity,
+        minHeight: double.infinity,
+        maxWidth: double.infinity,
+        maxHeight: double.infinity,
+      );
+    final widthAndHeight = value.split(', ');
+    final width = widthAndHeight[0];
+    final height = widthAndHeight[1];
+    double minWidth, maxWidth, minHeight, maxHeight;
+    List<double> parseRangeValue(String value) {
+      // '0.0<=dim<=100.0' should be split as ['0.0', 'dim', '100.0']
+      final split = value.split('<='); // after the split it should conta
+      return [double.parse(split.first), double.parse(split.last)];
+    }
+
+    if (width.startsWith('w='))
+      minWidth = maxWidth = double.parse(width.substring(2));
+    else {
+      final rangeValue = parseRangeValue(width);
+      minWidth = rangeValue.first;
+      maxWidth = rangeValue.last;
+    }
+    if (height.startsWith('h='))
+      minHeight = maxHeight = double.parse(height.substring(2));
+    else {
+      final rangeValue = parseRangeValue(height);
+      minHeight = rangeValue.first;
+      maxHeight = rangeValue.last;
+    }
     return BoxConstraints(
-      minWidth: json['minWidth'],
-      maxWidth: json['hasBoundedWidth'] ? json['maxWidth'] : double.infinity,
-      minHeight: json['minHeight'],
-      maxHeight: json['hasBoundedHeight'] ? json['maxHeight'] : double.infinity,
+      minWidth: minWidth,
+      minHeight: minHeight,
+      maxWidth: maxWidth,
+      maxHeight: maxHeight,
     );
   }
 
-  static Size deserializeSize(Map<String, Object> json) {
-    if (json == null) return null;
-    return Size(json['width'], json['height']);
+  static Size deserializeSize(RemoteDiagnosticsNode size) {
+    if (size == null) return null;
+    // size.description will look like 'Size(100.0, 50.0)'
+    final value = getValue(size.description); // value will be '100.0, 50.0'
+    final split = value.split(', ');
+    return Size(
+      double.parse(split.first),
+      double.parse(split.last),
+    );
   }
 }
 
@@ -192,12 +243,13 @@
     // Cache the properties on an expando so that local tweaks to
     // FlexLayoutProperties persist across multiple lookups from an
     // InspectorTreeNode.
+    return _buildNode(node);
     return _flexLayoutExpando[node] ??= _buildNode(node);
   }
 
   static FlexLayoutProperties _buildNode(InspectorTreeNode node) {
     final Map<String, Object> renderObjectJson =
-        node.diagnostic.json['renderObject'];
+        node.diagnostic.renderObject.json;
     final List<dynamic> properties = renderObjectJson['properties'];
     final Map<String, Object> data = Map<String, Object>.fromIterable(
       properties,
diff --git a/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart b/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart
index 391762e..07ac47b 100644
--- a/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart
+++ b/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart
@@ -34,16 +34,13 @@
 
   @override
   Widget build(BuildContext context) {
-    final enableExperimentalStoryOfLayout =
-        InspectorController.enableExperimentalStoryOfLayout;
     final tabs = <Tab>[
       _buildTab('Details Tree'),
-      if (enableExperimentalStoryOfLayout) _buildTab('Layout Details'),
+      _buildTab('Layout Details'),
     ];
     final tabViews = <Widget>[
       detailsTree,
-      if (enableExperimentalStoryOfLayout)
-        LayoutDetailsTab(controller: controller),
+      LayoutDetailsTab(controller: controller),
     ];
     final focusColor = Theme.of(context).focusColor;
     return Container(
@@ -103,7 +100,15 @@
 
   InspectorTreeNode get selected => controller?.selectedNode;
 
-  void onSelectionChanged() {
+  Future<void> loadRenderObject() async {
+    final nearestFlex = selected.diagnostic.isFlex
+        ? selected.diagnostic
+        : selected.parent.diagnostic;
+    await nearestFlex.getRenderObject();
+  }
+
+  void onSelectionChanged() async {
+    await loadRenderObject();
     setState(() {});
   }
 
@@ -111,6 +116,7 @@
   void initState() {
     super.initState();
     controller.addSelectionListener(onSelectionChanged);
+    loadRenderObject();
   }
 
   @override
diff --git a/packages/devtools_app/lib/src/inspector/inspector_service.dart b/packages/devtools_app/lib/src/inspector/inspector_service.dart
index e21aba2..b43ef94 100644
--- a/packages/devtools_app/lib/src/inspector/inspector_service.dart
+++ b/packages/devtools_app/lib/src/inspector/inspector_service.dart
@@ -954,6 +954,31 @@
       args,
     ));
   }
+
+  Future<RemoteDiagnosticsNode> renderObject(InspectorInstanceRef ref) async {
+    // TODO(albertusangga): Make this new Service Extension in flutter/flutter
+    String command = '''
+      final id = '${ref.id}';
+      final instance = WidgetInspectorService.instance;
+      final Element object = WidgetInspectorService.instance.toObject(id);
+      final RenderObject renderObject = object.renderObject;
+      return instance._safeJsonEncode(
+        instance._nodeToJson(
+          renderObject.toDiagnosticsNode(),
+          _SerializationDelegate(
+            groupName: '',
+            service: instance,
+            includeProperties: true,
+          ),
+      ));
+    ''';
+    command = '((){${command.split('\n').join()})()';
+    final val = await inspectorLibrary.eval(
+      command,
+      isAlive: this,
+    );
+    return parseDiagnosticsNodeObservatory(val);
+  }
 }
 
 enum FlutterTreeType {