You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2023/02/14 18:01:42 UTC

[beam] branch master updated: Test loading URLs (#25034)

This is an automated email from the ASF dual-hosted git repository.

pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new ed7eae82b31 Test loading URLs (#25034)
ed7eae82b31 is described below

commit ed7eae82b31f24ce3562b43a287be0dcf6bda101
Author: alexeyinkin <al...@akvelon.com>
AuthorDate: Tue Feb 14 22:01:35 2023 +0400

    Test loading URLs (#25034)
    
    * Add Playground embedding examples to README (#22180)
    
    * Improve README (#22180)
    
    * Integration test to load an example by URL (#24959)
    
    * Move and improve the go example (#24959)
    
    * Update the example (#24959)
    
    * Move the example (#24959)
    
    * Add a test (#24959)
    
    * Remove unused code, add comments (#24959)
    
    * Revert changes in extracted symbols (#24959)
    
    * Fix after review (#24959)
    
    * Fix after review (#24959)
    
    * Add ExampleDescriptor instances to replace example constants (#24959)
    
    * Remove unused code (#24959)
    
    * Fix testing HttpExampleLoader with visible sections (#24959)
    
    * Strip ExampleViewOptions when opening standalone playgounrd from embedded one (#24959)
    
    * Upgrade app_state and flutter_code_editor (#24959)
    
    * Test default examples on frontend (#25131) (#406)
    
    * Test default examples on frontend (#25131)
    
    * Add SCIO example descriptor (#25131)
    
    * Add missing files (#25131)
    
    * Add license comments (#25131)
    
    * Minor renaming (#25131)
    
    * Restore the real running for Java (#25131)
    
    * Display missing errors (#24959)
    
    * Upgrade flutter_code_editor (#24959)
    
    * Update backend URLs (#24959)
    
    * Add HTML embedding example in README, remove obsolete parts (#24959)
    
    * Trigger integration tests workflow (#24959)
    
    * Upgrade Flutter to 3.7.3 in playground_frontend_test workflow (#24959)
    
    * Less specific output expectations in a test, add comments (#24959)
    
    * Update README (#24959)
    
    * Upgrade Flutter in frontend Dockerfile (#24959)
    
    * Add headless testing to README (#24959)
    
    * Typo (#24959)
---
 .github/workflows/playground_frontend_test.yml     |   2 +-
 learning/tour-of-beam/frontend/pubspec.yaml        |   2 +-
 playground/README.md                               |   6 +
 playground/frontend/Dockerfile                     |   3 +-
 playground/frontend/README.md                      | 164 ++++-
 playground/frontend/build.gradle                   |  14 +
 .../common/examples.dart}                          |  18 +-
 .../common/widget_tester.dart}                     |  17 +-
 .../integration_test/initial_urls_test.dart        | 272 +++++++
 .../standalone_change_example_sdk_run_test.dart    |  66 +-
 .../standalone_default_examples_test.dart          |  95 +++
 playground/frontend/lib/locator.dart               |   9 +-
 playground/frontend/lib/main.dart                  |   5 +-
 .../no_url_example_loading_descriptor.dart         |   3 +
 .../widgets/embedded_actions.dart                  |   4 +-
 .../lib/src/assets/assets.gen.dart                 |  22 +-
 .../lib/src/cache/example_cache.dart               |   7 +-
 .../lib/src/constants/constants.dart}              |   5 +-
 .../example_loaders/content_example_loader.dart    |   1 +
 .../example_loaders/http_example_loader.dart       |   4 +
 .../example_loaders/standard_example_loader.dart   |   2 +-
 .../user_shared_example_loader.dart                |   5 +-
 .../snippet_file_editing_controller.dart           |   6 +-
 ...catalog_default_example_loading_descriptor.dart |  12 +-
 .../content_example_loading_descriptor.dart        |  36 +-
 .../empty_example_loading_descriptor.dart          |   5 +-
 .../example_loading_descriptor.dart                |   2 +
 .../examples_loading_descriptor.dart               |  20 +
 .../http_example_loading_descriptor.dart           |   8 +
 .../standard_example_loading_descriptor.dart       |   8 +
 .../user_shared_example_loading_descriptor.dart    |   8 +
 .../lib/src/models/example_view_options.dart       |   9 +
 .../frontend/playground_components/pubspec.yaml    |  16 +-
 .../test/src/common/example_cache.mocks.dart       |  94 ++-
 .../src/common/example_repository_mock.mocks.dart  |  62 +-
 .../src/controllers/example_loaders/common.dart    |   3 +
 .../example_loader_factory_test.dart               |   3 +
 .../examples_loader_test.mocks.dart                | 248 +++++--
 .../http_example_loader_test.mocks.dart            |  94 ++-
 .../playground_controller_test.mocks.dart          | 119 ++-
 ...og_default_example_loading_descriptor_test.dart |  17 +-
 .../content_example_loading_descriptor_test.dart   |  16 +-
 .../empty_example_loading_descriptor_test.dart     |   4 +
 .../examples_loading_descriptor_test.dart          |  36 +
 .../http_example_loading_descriptor_test.dart      |  14 +-
 .../standard_example_loading_descriptor_test.dart  |  16 +-
 ...ser_shared_example_loading_descriptor_test.dart |  14 +-
 .../repositories/code_repository_test.mocks.dart   | 115 ++-
 .../example_repository_test.mocks.dart             | 156 +++-
 .../lib/playground_components_dev.dart             |  19 +-
 .../playground_components_dev/lib/src/code.dart    |   3 +-
 .../lib/src/examples.dart                          |  35 -
 .../lib/src/examples/example_descriptor.dart       | 131 ++++
 .../lib/src/examples/go/content/example.go}        |  28 +-
 .../lib/src/examples/go/example.dart}              |  61 +-
 .../lib/src/examples/go/minimal_word_count.dart    |  61 ++
 .../lib/src/examples/go/word_count.dart}           |  17 +-
 .../java/aggregation_max.dart}                     |  23 +-
 .../lib/src/examples/java/minimal_word_count.dart} |  22 +-
 .../lib/src/examples/python/aggregation_mean.dart} |  18 +-
 .../examples/python/word_count_with_metrics.dart}  |  21 +-
 .../scio/common.dart}                              |  11 +-
 .../lib/src/examples/scio/minimal_word_count.dart} |  23 +-
 .../playground_components_dev/lib/src/expect.dart  |  43 +-
 .../lib/src/widget_tester.dart                     |  51 ++
 .../playground_components_dev/pubspec.yaml         |   8 +-
 playground/frontend/pubspec.lock                   | 808 ++++++++++++++-------
 playground/frontend/pubspec.yaml                   |  12 +-
 .../states/example_selector_state_test.mocks.dart  |  56 +-
 .../www/site/layouts/shortcodes/playground.html    |   2 +
 .../layouts/shortcodes/playground_snippet.html     |   5 +-
 71 files changed, 2576 insertions(+), 749 deletions(-)

diff --git a/.github/workflows/playground_frontend_test.yml b/.github/workflows/playground_frontend_test.yml
index 129234887b1..4813b6c6994 100644
--- a/.github/workflows/playground_frontend_test.yml
+++ b/.github/workflows/playground_frontend_test.yml
@@ -35,7 +35,7 @@ jobs:
     runs-on: ubuntu-latest
 
     env:
-      FLUTTER_VERSION: '3.3.2'
+      FLUTTER_VERSION: '3.7.3'
 
     steps:
       - uses: actions/checkout@v3
diff --git a/learning/tour-of-beam/frontend/pubspec.yaml b/learning/tour-of-beam/frontend/pubspec.yaml
index ee3b6ae3d77..be0579d0885 100644
--- a/learning/tour-of-beam/frontend/pubspec.yaml
+++ b/learning/tour-of-beam/frontend/pubspec.yaml
@@ -27,7 +27,7 @@ environment:
   flutter: '>=3.3.2'
 
 dependencies:
-  app_state: ^0.8.4
+  app_state: ^0.9.0
   collection: ^1.16.0
   easy_localization: ^3.0.1
   easy_localization_ext: ^0.1.0
diff --git a/playground/README.md b/playground/README.md
index e92effe1697..958e58ce1d7 100644
--- a/playground/README.md
+++ b/playground/README.md
@@ -96,6 +96,12 @@ cd beam
 ./gradlew playground:dockerComposeLocalDown
 ```
 
+This way of running may not work in all environments because it is not maintained.
+It is used occasionally by the Frontend team to test complex tasks against
+a not-yet-deployed backend.
+The full start may take ~30 minutes and is demanding, so you should likely enable
+only one backend runner for the SDK you need.
+
 If you do not need particular runners, comment out:
 1. Dependencies on them in `/playground/build.gradle.kts` in `dockerComposeLocalUp` task.
 2. Their Docker image configurations in `/playground/docker-compose.local.yaml`.
diff --git a/playground/frontend/Dockerfile b/playground/frontend/Dockerfile
index fc4c034a3c8..7800159255e 100644
--- a/playground/frontend/Dockerfile
+++ b/playground/frontend/Dockerfile
@@ -17,7 +17,7 @@
 ###############################################################################
 
 FROM debian:11 as build
-ARG FLUTTER_VERSION=3.3.2
+ARG FLUTTER_VERSION=3.7.3
 
 # ------------------------------------------------
 # Setting up.
@@ -28,6 +28,7 @@ RUN apt-get update && apt-get install -y wget xz-utils git
 RUN wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$FLUTTER_VERSION-stable.tar.xz &&\
     tar -xf flutter_linux_$FLUTTER_VERSION-stable.tar.xz &&\
     mv flutter /opt/ &&\
+    git config --global --add safe.directory /opt/flutter &&\
     ln -s /opt/flutter/bin/flutter /usr/bin/flutter &&\
     ln -s /opt/flutter/bin/dart /usr/bin/dart &&\
     dart pub global activate protoc_plugin &&\
diff --git a/playground/frontend/README.md b/playground/frontend/README.md
index de8b99c8d3d..705e96b9d84 100644
--- a/playground/frontend/README.md
+++ b/playground/frontend/README.md
@@ -172,7 +172,11 @@ Server testing has not been verified yet.
 4. Run:
 
 ```bash
+# To run in a visible Chrome window:
 ./gradlew :playground:frontend:integrationTest
+
+# Headless run without a browser window:
+./gradlew :playground:frontend:integrationTest -PdeviceId=web-server
 ```
 
 ## Localization
@@ -208,20 +212,164 @@ To add a new localization (using `fr` as an example):
 
 3. Add the locale to the list in `lib/l10n/l10n.dart`.
 
-### Configuration
+## URLs and Embedding
 
-The app could be configured using gradle task (e.g. api url)
+### Linking to a single example
 
-```bash
-cd beam
-./gradlew :playground:frontend:createConfig
+#### 1. Linking to a catalog example by path
+
+`https://play.beam.apache.org/?path=SDK_JAVA/PRECOMPILED_OBJECT_TYPE_KATA/AggregationMax&sdk=java`
+
+Handled by `StandardExampleLoader`.
+
+#### 2. Linking to the default catalog example
+
+`https://play.beam.apache.org/?sdk=python&default=true`
+
+Handled by `CatalogDefaultExampleLoader`.
+
+#### 3. Linking to a user-shared example
+
+`https://play.beam.apache.org/?sdk=java&shared=sdFdNV324HC`
+
+Handled by `UserSharedExampleLoader`.
+
+#### 4. Linking to an example by URL
+
+`https://play.beam.apache.org/?sdk=go&url=https://raw.githubusercontent.com/golang/go/master/src/fmt/format.go`
+
+Handled by `HttpExampleLoader`. The server with the example file must allow
+the cross-origin access. GitHub is known to allow it.
+Some servers may have different cross-origin policies when requested from localhost
+and other domains.
+
+#### 5. Linking to an empty editor
+
+`https://play.beam.apache.org/?sdk=go&empty=true`
+
+Handled by `EmptyExampleLoader`.
+
+### Passing view options
+
+Additional options may be passed with any of the above URL patterns.
+For them to work, the example must contain sections with the following syntax:
+
+```
+// [START section_name]
+void method() {
+...
+}
+// [END section_name]
+```
+
+See more on the syntax and limitations in the
+[README of the editor](https://pub.dev/packages/flutter_code_editor)
+that Playground uses.
+
+These options can be combined.
+
+#### Read-only sections
+
+Add `readonly` parameter with comma-separated section names:
+
+`https://play.beam.apache.org/?sdk=go&url=https://raw.githubusercontent.com/GoogleCloudPlatform/golang-samples/main/iam/snippets/roles_get.go&readonly=iam_get_role`
+
+#### Folding everything except sections
+
+Add `unfold` parameter with comma-separated section names:
+
+`https://play.beam.apache.org/?sdk=go&url=https://raw.githubusercontent.com/GoogleCloudPlatform/golang-samples/main/iam/snippets/roles_get.go&unfold=iam_get_role`
+
+This folds all foldable blocks that do not overlap with
+any of the given sections.
+
+#### Hiding everything except a section
+
+Add `show` parameter with a single section name:
+
+`https://play.beam.apache.org/?sdk=go&url=https://raw.githubusercontent.com/GoogleCloudPlatform/golang-samples/main/iam/snippets/roles_get.go&show=iam_get_role`
+
+It is still the whole snippet that is sent for execution although only the given section
+is visible.
+
+This also makes the editor read-only so the user cannot add code that conflicts
+with the hidden text.
+
+### Linking to multiple examples
+
+With the above URLs, when the SDK is switched the following will be shown:
+
+- The catalog default example for the new SDK in the standalone playground.
+- The empty editor for the new SDK in the embedded playground.
+
+This can be changed by linking to multiple examples, up to one per SDK.
+
+For this purpose, make a JSON array with any combination of parameters that
+are allowed for loading single examples, for instance:
+
+```json
+[
+   {
+      "sdk": "java",
+      "path": "SDK_JAVA/PRECOMPILED_OBJECT_TYPE_KATA/AggregationMax"
+   },
+   {
+      "sdk": "go",
+      "url": "https://raw.githubusercontent.com/GoogleCloudPlatform/golang-samples/main/iam/snippets/roles_get.go",
+      "readonly": "iam_get_role"
+   }
+]
+```
+
+Then pass it in`examples` query parameter like this:
+
+`https://play.beam.apache.org/?sdk=go&examples=[{"sdk":"java","path":"SDK_JAVA/PRECOMPILED_OBJECT_TYPE_KATA/AggregationMax"},{"sdk":"go","url":"https://raw.githubusercontent.com/GoogleCloudPlatform/golang-samples/main/iam/snippets/roles_get.go","readonly":"iam_get_role"}]`
+
+This starts with the Go example loaded from the URL.
+If SDK is then switched to Java, the `AggregationMax` catalog example is loaded for it.
+If SDK is switched to any other one, the default example for that SDK is loaded
+because no override was provided.
+
+### Embedded vs Standalone Playground URLs
+
+Embedded Playground is a simplified interface supporting all the same features
+as the primary interface which is also known as the Standalone Playground.
+
+The embedded Playground URLs start with `https://play.beam.apache.org/embedded`
+and use the same query string parameters as the standalone playground.
+
+Additionally the Embedded playground supports the following parameters:
+
+- `editable=0` to make the editor read-only.
+
+### Embedding into HTML
+
+Use the `<iframe>` tag to embed playground with any of the above URL patterns, for example:
+
+```html
+<iframe
+  src="https://play-dev.beam.apache.org/embedded?path=SDK_JAVA/PRECOMPILED_OBJECT_TYPE_KATA/AggregationMax&sdk=java"
+  width="800px"
+  height="500px"
+  allow="clipboard-write"
+/>
 ```
 
-For more information see See [CONTRIBUTE.md](CONTRIBUTE.md)
+Note that for the simplified embedded interface you need to use `/embedded` in the URL
+otherwise the more complex default interface is shown.
+
+Such URLs and `iframe` code can also be generated by clicking "Share my code" button
+in the Standalone Playground.
+
+### Embedding into the Beam documentation
+
+Beam documentation is written in Markdown and uses [Hugo Markdown preprocessor](https://gohugo.io).
+Use the custom shortcodes to embed Playground into the documentation:
 
-### Additional
+- `playground` shortcode, see [a comment in it](https://github.com/apache/beam/blob/master/website/www/site/layouts/shortcodes/playground.html) for a complete example.
+- `playground_snippet` shortcode, see [a comment in it](https://github.com/apache/beam/blob/master/website/www/site/layouts/shortcodes/playground_snippet.html) for all supported options.
 
-The full list of commands can be found [here](https://flutter.dev/docs/reference/flutter-cli)
+These shortcodes generate an `iframe` with the URLs described above.
 
 ## Contribution guide
 
diff --git a/playground/frontend/build.gradle b/playground/frontend/build.gradle
index 8bd1399d7e1..403fbf21229 100644
--- a/playground/frontend/build.gradle
+++ b/playground/frontend/build.gradle
@@ -181,16 +181,30 @@ ext.deleteFilesByRegExp = { re ->
 }
 
 tasks.register("integrationTest") {
+  dependsOn("integrationTest_initial_urls")
   dependsOn("integrationTest_standalone_change_example_sdk_run")
+  dependsOn("integrationTest_standalone_default_examples")
   dependsOn("integrationTest_standalone_miscellaneous_ui")
 }
 
+tasks.register("integrationTest_initial_urls") {
+  doLast {
+    runIntegrationTest("initial_urls", "/")
+  }
+}
+
 tasks.register("integrationTest_standalone_change_example_sdk_run") {
   doLast {
     runIntegrationTest("standalone_change_example_sdk_run", "/")
   }
 }
 
+tasks.register("integrationTest_standalone_default_examples") {
+  doLast {
+    runIntegrationTest("standalone_default_examples", "/")
+  }
+}
+
 tasks.register("integrationTest_standalone_miscellaneous_ui") {
   doLast {
     runIntegrationTest("standalone_miscellaneous_ui", "/")
diff --git a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart b/playground/frontend/integration_test/common/examples.dart
similarity index 79%
copy from playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
copy to playground/frontend/integration_test/common/examples.dart
index 3fbc31e4bba..5a00e5088b9 100644
--- a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
+++ b/playground/frontend/integration_test/common/examples.dart
@@ -17,15 +17,11 @@
  */
 
 import 'package:playground_components/playground_components.dart';
+import 'package:playground_components_dev/playground_components_dev.dart';
 
-/// An [ExampleLoadingDescriptor] to produce a blank URL when
-/// pushed to the address bar.
-class NoUrlExampleLoadingDescriptor extends ExampleLoadingDescriptor {
-  const NoUrlExampleLoadingDescriptor();
-
-  @override
-  List<Object?> get props => const [];
-
-  @override
-  Map<String, dynamic> toJson() => {};
-}
+final defaultExamples = {
+  Sdk.java: javaMinimalWordCount,
+  Sdk.go: goMinimalWordCount,
+  Sdk.python: pythonWordCountWithMetrics,
+  // Sdk.scio: scioMinimalWordCount,
+};
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart b/playground/frontend/integration_test/common/widget_tester.dart
similarity index 74%
copy from playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
copy to playground/frontend/integration_test/common/widget_tester.dart
index ab939bfbedd..c91e580ecfb 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
+++ b/playground/frontend/integration_test/common/widget_tester.dart
@@ -19,15 +19,14 @@
 import 'package:flutter_test/flutter_test.dart';
 import 'package:playground_components/playground_components.dart';
 
-void main() {
-  group('EmptyExampleLoadingDescriptor', () {
-    const descriptor = EmptyExampleLoadingDescriptor(sdk: Sdk.go);
+import 'common_finders.dart';
 
-    test('toJson -> tryParse', () {
-      final map = descriptor.toJson();
-      final parsed = EmptyExampleLoadingDescriptor.tryParse(map);
+extension WidgetTesterExtension on WidgetTester {
+  Future<void> changeSdk(Sdk sdk) async {
+    await tap(find.sdkSelector());
+    await pumpAndSettle();
 
-      expect(parsed, descriptor);
-    });
-  });
+    await tap(find.sdkItemInDropdown(sdk));
+    await pumpAndSettle();
+  }
 }
diff --git a/playground/frontend/integration_test/initial_urls_test.dart b/playground/frontend/integration_test/initial_urls_test.dart
new file mode 100644
index 00000000000..c88a9ba7865
--- /dev/null
+++ b/playground/frontend/integration_test/initial_urls_test.dart
@@ -0,0 +1,272 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'dart:convert';
+
+import 'package:flutter/widgets.dart';
+import 'package:flutter_code_editor/flutter_code_editor.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'package:playground_components/playground_components.dart';
+import 'package:playground_components_dev/playground_components_dev.dart';
+
+import 'common/common.dart';
+
+// This test loads the app with most of the startup URL combinations.
+// They cannot be tested directly due to a Flutter bug:
+//     https://github.com/flutter/flutter/issues/118028
+// So the test performs in-app navigation to these URLs.
+// Many state objects are re-created this way, but not all,
+// so the test is not clean.
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+  testWidgets('Initial URLs', (WidgetTester wt) async {
+    await init(wt);
+
+    await _testEmbeddedRoot(wt);
+    await _testStandaloneRoot(wt);
+
+    await _testEmbeddedSdkOnly(wt);
+    await _testStandaloneSdkOnly(wt);
+
+    await _testCatalogDefaultExampleLoader(wt);
+    await _testContentExampleLoader(wt);
+    await _testEmptyExampleLoader(wt);
+    await _testHttpExampleLoader(wt);
+    await _testStandardExampleLoader(wt);
+    await _testUserSharedExampleLoader(wt);
+
+    await _testMultipleExamples(wt);
+  });
+}
+
+const _embeddedPath = '/embedded';
+const _standalonePath = '/';
+const _paths = [_embeddedPath, _standalonePath];
+
+const _fullViewOptionsMap = {
+  'readonly': 'readonly1,readonly2',
+  'unfold': 'unfold1,unfold2',
+};
+final _croppedViewOptionsMap = {
+  ..._fullViewOptionsMap,
+  'show': 'show',
+};
+
+final _fullViewOptions = _mapToQueryString(_fullViewOptionsMap);
+final _croppedViewOptions = _mapToQueryString(_croppedViewOptionsMap);
+
+Future<void> _testEmbeddedRoot(WidgetTester wt) async {
+  await wt.navigateAndSettle(_embeddedPath);
+  expectSdk(Sdk.java, wt);
+  expectVisibleText('', wt);
+}
+
+Future<void> _testStandaloneRoot(WidgetTester wt) async {
+  final visibleText = await javaMinimalWordCount.getVisibleText();
+  await wt.navigateAndSettle(_standalonePath);
+
+  expectSdk(Sdk.java, wt);
+  expectVisibleText(visibleText, wt);
+}
+
+Future<void> _testEmbeddedSdkOnly(WidgetTester wt) async {
+  await wt.navigateAndSettle('$_embeddedPath?sdk=go');
+  expectSdk(Sdk.go, wt);
+  expectVisibleText('', wt);
+}
+
+Future<void> _testStandaloneSdkOnly(WidgetTester wt) async {
+  final visibleText = await goMinimalWordCount.getVisibleText();
+  await wt.navigateAndSettle('$_standalonePath?sdk=go');
+
+  expectSdk(Sdk.go, wt);
+  expectVisibleText(visibleText, wt);
+}
+
+Future<void> _testCatalogDefaultExampleLoader(WidgetTester wt) async {
+  final visibleText = await goMinimalWordCount.getVisibleText();
+  await wt.navigateAndSettle('$_standalonePath?sdk=go&default=true');
+
+  expectSdk(Sdk.go, wt);
+  expectVisibleText(visibleText, wt);
+}
+
+Future<void> _testContentExampleLoader(WidgetTester wt) async {
+  final content = await goExample.getFullText();
+
+  for (final path in _paths) {
+    final files = jsonEncode([
+      {'content': content, 'isMain': true}
+    ]);
+    await wt.navigateAndSettle(
+      '$path?sdk=go&files=${Uri.encodeComponent(files)}&$_fullViewOptions',
+    );
+    expectSdk(Sdk.go, wt);
+    expectVisibleText(goExample.foldedVisibleText, wt);
+    await _expectEditableAndReadOnly(wt);
+
+    await wt.navigateAndSettle(
+      '$path?sdk=go&files=${Uri.encodeComponent(files)}&$_croppedViewOptions',
+    );
+    expectSdk(Sdk.go, wt);
+    expectVisibleText(goExample.croppedFoldedVisibleText, wt);
+    _expectReadOnly(wt);
+  }
+}
+
+Future<void> _testEmptyExampleLoader(WidgetTester wt) async {
+  for (final path in _paths) {
+    await wt.navigateAndSettle('$path?sdk=go&empty=true');
+    expectSdk(Sdk.go, wt);
+    expectVisibleText('', wt);
+  }
+}
+
+Future<void> _testHttpExampleLoader(WidgetTester wt) async {
+  for (final path in _paths) {
+    await wt.navigateAndSettle(
+      '$path?sdk=go&url=${goExample.url}&$_fullViewOptions',
+    );
+    expectSdk(Sdk.go, wt);
+    expectVisibleText(goExample.foldedVisibleText, wt);
+    await _expectEditableAndReadOnly(wt);
+
+    await wt.navigateAndSettle(
+      '$path?sdk=go&url=${goExample.url}&$_croppedViewOptions',
+    );
+    expectSdk(Sdk.go, wt);
+    expectVisibleText(goExample.croppedFoldedVisibleText, wt);
+    _expectReadOnly(wt);
+  }
+}
+
+Future<void> _testStandardExampleLoader(WidgetTester wt) async {
+  final visibleText = await goWordCount.getVisibleText();
+
+  for (final path in _paths) {
+    await wt.navigateAndSettle(
+      '$path?sdk=go&path=${goWordCount.dbPath}',
+    );
+    expectSdk(Sdk.go, wt);
+    expectVisibleText(visibleText, wt);
+  }
+}
+
+Future<void> _testUserSharedExampleLoader(WidgetTester wt) async {
+  final template = await goExample.getFullText();
+  final tail = '\n//${DateTime.now().millisecondsSinceEpoch}';
+  final content = '$template$tail';
+
+  final exampleCache = wt.findPlaygroundController().exampleCache;
+  final snippetId = await exampleCache.saveSnippet(
+    files: [SnippetFile(content: content, isMain: false, name: 'name')],
+    sdk: Sdk.go,
+    pipelineOptions: 'a=b',
+  );
+
+  print('Created user-shared example ID: $snippetId');
+
+  for (final path in _paths) {
+    await wt.navigateAndSettle(
+      '$path?sdk=go&shared=$snippetId&$_fullViewOptions',
+    );
+    expectSdk(Sdk.go, wt);
+    expectVisibleText('${goExample.foldedVisibleText}$tail', wt);
+    await _expectEditableAndReadOnly(wt);
+
+    await wt.navigateAndSettle(
+      '$path?sdk=go&url=${goExample.url}&$_croppedViewOptions',
+    );
+    expectSdk(Sdk.go, wt);
+    expectVisibleText(goExample.croppedFoldedVisibleText, wt);
+    _expectReadOnly(wt);
+  }
+}
+
+Future<void> _testMultipleExamples(WidgetTester wt) async {
+  final javaVisibleText = await javaAggregationMax.getVisibleText();
+  final goVisibleText = goExample.foldedVisibleText;
+
+  final examplesList = [
+    {
+      'sdk': Sdk.java.id,
+      'path': javaAggregationMax.dbPath,
+      ..._fullViewOptionsMap,
+    },
+    {
+      'sdk': Sdk.go.id,
+      'url': goExample.url,
+      ..._fullViewOptionsMap,
+    },
+  ];
+  final examples = jsonEncode(examplesList);
+
+  for (final path in _paths) {
+    await wt.navigateAndSettle('$path?sdk=go&examples=$examples');
+    expectSdk(Sdk.go, wt);
+    expectVisibleText(goVisibleText, wt);
+    await _expectEditableAndReadOnly(wt);
+
+    final playgroundController = wt.findPlaygroundController();
+    playgroundController.setSdk(Sdk.java);
+    await wt.pumpAndSettle();
+
+    expectSdk(Sdk.java, wt);
+    expectVisibleText(javaVisibleText, wt);
+  }
+}
+
+/// Checks that the example contains:
+/// - at least two 'editable' substrings, and they are editable,
+/// - at least two 'readonly' substrings, and they are read-only.
+Future<void> _expectEditableAndReadOnly(WidgetTester wt) async {
+  final controller = wt.findOneCodeController();
+
+  for (int i = 0; i < 2; i++) {
+    controller.value = controller.value.select('editable')!;
+
+    final edited = controller.value.typed('');
+    controller.value = edited;
+    await wt.pumpAndSettle();
+    expect(controller.value, edited, reason: 'Cannot edit an editable line');
+
+    controller.value = controller.value.select('readonly')!.typed('');
+    await wt.pumpAndSettle();
+    expect(controller.value, edited, reason: 'Can edit a read-only line');
+  }
+}
+
+/// Checks that every character in the editor is read-only.
+void _expectReadOnly(WidgetTester wt) {
+  final controller = wt.findOneCodeController();
+  final value = controller.value;
+  final text = controller.text;
+
+  for (int i = text.length; --i >= 0;) {
+    controller.value = value
+        .copyWith(selection: TextSelection.collapsed(offset: i))
+        .typed('a');
+    expect(controller.value, value, reason: 'Can edit a read-only controller');
+  }
+}
+
+String _mapToQueryString(Map<String, String> map) {
+  return [for (final e in map.entries) '${e.key}=${e.value}'].join('&');
+}
diff --git a/playground/frontend/integration_test/standalone_change_example_sdk_run_test.dart b/playground/frontend/integration_test/standalone_change_example_sdk_run_test.dart
index f7b601c877e..8c553d62a0a 100644
--- a/playground/frontend/integration_test/standalone_change_example_sdk_run_test.dart
+++ b/playground/frontend/integration_test/standalone_change_example_sdk_run_test.dart
@@ -17,70 +17,37 @@
  */
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:highlight/languages/java.dart';
-import 'package:highlight/languages/python.dart';
 import 'package:integration_test/integration_test.dart';
 import 'package:playground_components/playground_components.dart';
 import 'package:playground_components_dev/playground_components_dev.dart';
 
 import 'common/common.dart';
 import 'common/common_finders.dart';
+import 'common/widget_tester.dart';
 
 const _outputPrefix = 'The processing has started\n';
 
 void main() {
   IntegrationTestWidgetsFlutterBinding.ensureInitialized();
 
-  /// Runs and expects that the execution is as fast as it should be for cache.
-  Future<void> runExpectCached(WidgetTester wt) async {
-    final dateTimeStart = DateTime.now();
-
-    await wt.tap(find.runOrCancelButton());
-    await wt.pumpAndSettle();
-
-    expect(
-      DateTime.now().difference(dateTimeStart),
-      lessThan(const Duration(milliseconds: 2000)),
-    );
-  }
-
-  Future<void> expectJavaMinimalWordCount(WidgetTester wt) async {
-    expect(
-      wt.findOneCodeController().lastTextSpan!.toPlainText().isAsIfCutFrom(
-        await Examples.getVisibleTextByPath(
-          ExamplePaths.javaMinimalWordCount,
-          java,
-        ),
-      ),
-      true,
-    );
-
-    expect(find.graphTab(), findsOneWidget);
-    expect(find.resultTab(), findsOneWidget);
-    expect(wt.findOutputTabController().index, 0);
-  }
-
   Future<void> changeToJavaAggregationMax(WidgetTester wt) async {
     await wt.tap(find.exampleSelector());
     await wt.pumpAndSettle();
 
-    await wt.tap(find.exampleItemInDropdown(ExampleNames.aggregationMax));
+    await wt.tap(find.exampleItemInDropdown(javaAggregationMax.name));
     await wt.pumpAndSettle();
 
     expect(
       wt.findOneCodeController().lastTextSpan!.toPlainText().isAsIfCutFrom(
-        await Examples.getVisibleTextByPath(
-          ExamplePaths.javaAggregationMax,
-          java,
-        ),
-      ),
+            await javaAggregationMax.getVisibleText(),
+          ),
       true,
     );
   }
 
   Future<void> runExpectJavaAggregationMax(WidgetTester wt) async {
-    await runExpectCached(wt);
-    expectOutputEndsWith(ExampleOutputs.javaAggregationMaxTail, wt);
+    await wt.runExpectCached();
+    expectOutputEndsWith(javaAggregationMax.outputTail, wt);
   }
 
   Future<void> runCustomJava(WidgetTester wt) async {
@@ -103,18 +70,11 @@ public class MyClass {
   }
 
   Future<void> switchToPython(WidgetTester wt) async {
-    await wt.tap(find.sdkSelector());
-    await wt.pumpAndSettle();
-
-    await wt.tap(find.sdkItemInDropdown(Sdk.python));
-    await wt.pumpAndSettle();
+    await wt.changeSdk(Sdk.python);
 
     expect(
       wt.findOneCodeController().lastTextSpan!.toPlainText().isAsIfCutFrom(
-            await Examples.getVisibleTextByPath(
-              ExamplePaths.pythonMinimalWordCountWithMetrics,
-              python,
-            ),
+            await pythonWordCountWithMetrics.getVisibleText(),
           ),
       true,
     );
@@ -124,7 +84,7 @@ public class MyClass {
     await wt.tap(find.exampleSelector());
     await wt.pumpAndSettle();
 
-    await wt.tap(find.exampleItemInDropdown(ExampleNames.aggregationMean));
+    await wt.tap(find.exampleItemInDropdown(pythonAggregationMean.name));
     await wt.pumpAndSettle();
 
     // Cannot test this because the DB examples differ from GitHub now.
@@ -141,8 +101,11 @@ public class MyClass {
   }
 
   Future<void> runExpectPythonAggregationMean(WidgetTester wt) async {
-    await runExpectCached(wt);
-    expectOutputContains(ExampleOutputs.pythonAggregationMeanContains, wt);
+    await wt.runExpectCached();
+
+    for (final str in pythonAggregationMean.outputContains!) {
+      expectOutputContains(str, wt);
+    }
   }
 
   Future<void> runCustomPython(WidgetTester wt) async {
@@ -161,7 +124,6 @@ public class MyClass {
   testWidgets('Change example, change SDK, run', (WidgetTester wt) async {
     await init(wt);
 
-    await expectJavaMinimalWordCount(wt);
     await changeToJavaAggregationMax(wt);
     await runExpectJavaAggregationMax(wt);
     await runCustomJava(wt);
diff --git a/playground/frontend/integration_test/standalone_default_examples_test.dart b/playground/frontend/integration_test/standalone_default_examples_test.dart
new file mode 100644
index 00000000000..2e3ddcf6b65
--- /dev/null
+++ b/playground/frontend/integration_test/standalone_default_examples_test.dart
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'package:playground_components_dev/playground_components_dev.dart';
+
+import 'common/common.dart';
+import 'common/examples.dart';
+import 'common/widget_tester.dart';
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+  testWidgets('Default examples', (WidgetTester wt) async {
+    await init(wt);
+
+    final playgroundController = wt.findPlaygroundController();
+
+    for (final entry in defaultExamples.entries) {
+      final sdk = entry.key;
+      final example = entry.value;
+
+      print('${sdk.id}: ${example.path}');
+
+      if (sdk != playgroundController.sdk) {
+        await wt.changeSdk(sdk);
+      }
+
+      await _expectExample(example, wt);
+      await _runCached(example, wt);
+      await _runReal(example, wt);
+    }
+  });
+}
+
+Future<void> _expectExample(ExampleDescriptor example, WidgetTester wt) async {
+  final visibleText = await example.getVisibleText();
+
+  expectSdk(example.sdk, wt);
+  expectVisibleText(visibleText, wt);
+
+  if (example.contextLine1Based != null) {
+    expectContextLine(example.contextLine1Based!, wt);
+  }
+
+  if (example.hasGraphTab) {
+    expect(find.graphTab(), findsOneWidget);
+  }
+
+  expect(find.resultTab(), findsOneWidget);
+  expect(wt.findOutputTabController().index, 0);
+}
+
+Future<void> _runCached(ExampleDescriptor example, WidgetTester wt) async {
+  await wt.runExpectCached();
+  _expectOutput(example, wt);
+}
+
+Future<void> _runReal(ExampleDescriptor example, WidgetTester wt) async {
+  // Add a character into the first comment.
+  // This relies on that the position 10 is inside a license comment.
+  final controller = wt.findOneCodeController();
+  final text = controller.fullText;
+  controller.fullText = text.substring(0, 10) + '+' + text.substring(10);
+
+  await wt.runExpectReal();
+  _expectOutput(example, wt);
+}
+
+void _expectOutput(ExampleDescriptor example, WidgetTester wt) {
+  if (example.outputTail != null) {
+    expectOutputEndsWith(example.outputTail, wt);
+  } else if (example.outputContains != null) {
+    for (final str in example.outputContains!) {
+      expectOutputContains(str, wt);
+    }
+  } else {
+    throw AssertionError('No pattern to check example output: ${example.path}');
+  }
+}
diff --git a/playground/frontend/lib/locator.dart b/playground/frontend/lib/locator.dart
index 72e6a8dbd50..5e5f7ce4e50 100644
--- a/playground/frontend/lib/locator.dart
+++ b/playground/frontend/lib/locator.dart
@@ -27,7 +27,7 @@ import 'router/route_information_parser.dart';
 
 Future<void> initializeServiceLocator() async {
   _initializeRepositories();
-  _initializeState();
+  _initializeRouter();
 }
 
 void _initializeRepositories() {
@@ -48,7 +48,7 @@ void _initializeRepositories() {
   ));
 }
 
-void _initializeState() {
+void _initializeRouter() {
   GetIt.instance.registerSingleton(
     PageStack(
       bottomPage: LoadingPage(),
@@ -56,4 +56,9 @@ void _initializeState() {
       routeInformationParser: PlaygroundRouteInformationParser(),
     ),
   );
+
+  GetIt.instance.registerSingleton<PageStackRouteInformationParser>(
+    PlaygroundRouteInformationParser(),
+  );
+  print('Initialized PageStackRouteInformationParser');
 }
diff --git a/playground/frontend/lib/main.dart b/playground/frontend/lib/main.dart
index f65bf8aa916..dd0b894fb0d 100644
--- a/playground/frontend/lib/main.dart
+++ b/playground/frontend/lib/main.dart
@@ -30,7 +30,6 @@ import 'package:url_strategy/url_strategy.dart';
 import 'l10n/l10n.dart';
 import 'locator.dart';
 import 'playground_app.dart';
-import 'router/route_information_parser.dart';
 
 void main() async {
   FlutterIssue106664Workaround.instance.apply();
@@ -43,7 +42,7 @@ void main() async {
   // Router API specific initialization.
   final pageStack = GetIt.instance.get<PageStack>();
   final routerDelegate = BeamRouterDelegate(pageStack);
-  final routeInformationParser = PlaygroundRouteInformationParser();
+  final parser = GetIt.instance.get<PageStackRouteInformationParser>();
   final backButtonDispatcher = PageStackBackButtonDispatcher(pageStack);
 
   await findSystemLocale();
@@ -60,7 +59,7 @@ void main() async {
       child: PlaygroundApp(
         backButtonDispatcher: backButtonDispatcher,
         routerDelegate: routerDelegate,
-        routeInformationParser: routeInformationParser,
+        routeInformationParser: parser,
       ),
     ),
   );
diff --git a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart b/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
index 3fbc31e4bba..e315201f76a 100644
--- a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
+++ b/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
@@ -26,6 +26,9 @@ class NoUrlExampleLoadingDescriptor extends ExampleLoadingDescriptor {
   @override
   List<Object?> get props => const [];
 
+  @override
+  ExampleLoadingDescriptor copyWithoutViewOptions() => this;
+
   @override
   Map<String, dynamic> toJson() => {};
 }
diff --git a/playground/frontend/lib/pages/embedded_playground/widgets/embedded_actions.dart b/playground/frontend/lib/pages/embedded_playground/widgets/embedded_actions.dart
index fcd80618545..2cbb228ac21 100644
--- a/playground/frontend/lib/pages/embedded_playground/widgets/embedded_actions.dart
+++ b/playground/frontend/lib/pages/embedded_playground/widgets/embedded_actions.dart
@@ -82,7 +82,9 @@ class EmbeddedActions extends StatelessWidget {
       '',
     );
 
-    final descriptor = controller.getLoadingDescriptor();
+    final descriptor =
+        controller.getLoadingDescriptor().copyWithoutViewOptions();
+
     javaScriptPostMessageRepeated(
       window,
       SetContentMessage(
diff --git a/playground/frontend/playground_components/lib/src/assets/assets.gen.dart b/playground/frontend/playground_components/lib/src/assets/assets.gen.dart
index 2b64543628d..288b595d38b 100644
--- a/playground/frontend/playground_components/lib/src/assets/assets.gen.dart
+++ b/playground/frontend/playground_components/lib/src/assets/assets.gen.dart
@@ -5,7 +5,7 @@
 
 // coverage:ignore-file
 // ignore_for_file: type=lint
-// ignore_for_file: directives_ordering,unnecessary_import
+// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use
 
 import 'package:flutter/widgets.dart';
 
@@ -17,6 +17,9 @@ class $AssetsButtonsGen {
 
   /// File path: assets/buttons/theme-mode.svg
   String get themeMode => 'assets/buttons/theme-mode.svg';
+
+  /// List of all assets
+  List<String> get values => [reset, themeMode];
 }
 
 class $AssetsNotificationIconsGen {
@@ -33,6 +36,9 @@ class $AssetsNotificationIconsGen {
 
   /// File path: assets/notification_icons/warning.svg
   String get warning => 'assets/notification_icons/warning.svg';
+
+  /// List of all assets
+  List<String> get values => [error, info, success, warning];
 }
 
 class $AssetsPngGen {
@@ -40,6 +46,9 @@ class $AssetsPngGen {
 
   /// File path: assets/png/beam-logo.png
   AssetGenImage get beamLogo => const AssetGenImage('assets/png/beam-logo.png');
+
+  /// List of all assets
+  List<AssetGenImage> get values => [beamLogo];
 }
 
 class $AssetsSvgGen {
@@ -50,6 +59,9 @@ class $AssetsSvgGen {
 
   /// File path: assets/svg/drag-vertical.svg
   String get dragVertical => 'assets/svg/drag-vertical.svg';
+
+  /// List of all assets
+  List<String> get values => [dragHorizontal, dragVertical];
 }
 
 class $AssetsSymbolsGen {
@@ -63,6 +75,9 @@ class $AssetsSymbolsGen {
 
   /// File path: assets/symbols/python.g.yaml
   String get pythonG => 'assets/symbols/python.g.yaml';
+
+  /// List of all assets
+  List<String> get values => [goG, javaG, pythonG];
 }
 
 class $AssetsTranslationsGen {
@@ -70,6 +85,9 @@ class $AssetsTranslationsGen {
 
   /// File path: assets/translations/en.yaml
   String get en => 'assets/translations/en.yaml';
+
+  /// List of all assets
+  List<String> get values => [en];
 }
 
 class Assets {
@@ -142,6 +160,8 @@ class AssetGenImage {
     );
   }
 
+  ImageProvider provider() => AssetImage(_assetName);
+
   String get path => _assetName;
 
   String get keyName => _assetName;
diff --git a/playground/frontend/playground_components/lib/src/cache/example_cache.dart b/playground/frontend/playground_components/lib/src/cache/example_cache.dart
index ee59253a269..19a362952de 100644
--- a/playground/frontend/playground_components/lib/src/cache/example_cache.dart
+++ b/playground/frontend/playground_components/lib/src/cache/example_cache.dart
@@ -27,6 +27,7 @@ import '../exceptions/snippet_saving_exception.dart';
 import '../models/category_with_examples.dart';
 import '../models/example.dart';
 import '../models/example_base.dart';
+import '../models/example_view_options.dart';
 import '../models/loading_status.dart';
 import '../models/sdk.dart';
 import '../models/snippet_file.dart';
@@ -118,7 +119,10 @@ class ExampleCache extends ChangeNotifier {
     );
   }
 
-  Future<Example> loadSharedExample(String id) async {
+  Future<Example> loadSharedExample(
+    String id, {
+    required ExampleViewOptions viewOptions,
+  }) async {
     final result = await _exampleRepository.getSnippet(
       GetSnippetRequest(id: id),
     );
@@ -131,6 +135,7 @@ class ExampleCache extends ChangeNotifier {
       sdk: result.sdk,
       pipelineOptions: result.pipelineOptions,
       type: ExampleType.example,
+      viewOptions: viewOptions,
     );
   }
 
diff --git a/playground/frontend/playground_components_dev/lib/src/example_names.dart b/playground/frontend/playground_components/lib/src/constants/constants.dart
similarity index 86%
rename from playground/frontend/playground_components_dev/lib/src/example_names.dart
rename to playground/frontend/playground_components/lib/src/constants/constants.dart
index 204a6578ecd..843837cf8a7 100644
--- a/playground/frontend/playground_components_dev/lib/src/example_names.dart
+++ b/playground/frontend/playground_components/lib/src/constants/constants.dart
@@ -16,7 +16,4 @@
  * limitations under the License.
  */
 
-class ExampleNames {
-  static const aggregationMax = 'AggregationMax';
-  static const aggregationMean = 'AggregationMean';
-}
+const spaceCount = 2;
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart
index bc629e07001..fa431e2d70b 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart
@@ -47,5 +47,6 @@ class ContentExampleLoader extends ExampleLoader {
         path: '',
         sdk: descriptor.sdk,
         type: ExampleType.example,
+        viewOptions: descriptor.viewOptions,
       );
 }
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/http_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/http_example_loader.dart
index a3a1887f459..c29d7e9d96b 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/http_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/http_example_loader.dart
@@ -47,6 +47,10 @@ class HttpExampleLoader extends ExampleLoader {
   Future<Example> get future async {
     final response = await http.get(descriptor.uri);
 
+    if (response.statusCode >= 400) {
+      throw Exception('Example not found: Error code ${response.statusCode}');
+    }
+
     return Example(
       name: descriptor.uri.path.split('/').lastOrNull ?? 'HTTP Example',
       files: [
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart
index 5f180589ea3..0afb6828f9b 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart
@@ -55,7 +55,7 @@ class StandardExampleLoader extends ExampleLoader {
       final example = await _loadExampleBase();
 
       if (example == null) {
-        _completer.completeError('Example not found: $descriptor');
+        _completer.completeError(Exception('Example not found: $descriptor'));
         return;
       }
 
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/user_shared_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/user_shared_example_loader.dart
index 8f2ddf8c7f6..23fd43d4683 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/user_shared_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/user_shared_example_loader.dart
@@ -43,6 +43,9 @@ class UserSharedExampleLoader extends ExampleLoader {
   @override
   Future<Example> get future async {
     return _example ??
-        (_example = await exampleCache.loadSharedExample(descriptor.snippetId));
+        (_example = await exampleCache.loadSharedExample(
+          descriptor.snippetId,
+          viewOptions: descriptor.viewOptions,
+        ));
   }
 }
diff --git a/playground/frontend/playground_components/lib/src/controllers/snippet_file_editing_controller.dart b/playground/frontend/playground_components/lib/src/controllers/snippet_file_editing_controller.dart
index d6802b9655c..7223b56ef1b 100644
--- a/playground/frontend/playground_components/lib/src/controllers/snippet_file_editing_controller.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/snippet_file_editing_controller.dart
@@ -22,6 +22,7 @@ import 'package:flutter/widgets.dart';
 import 'package:flutter_code_editor/flutter_code_editor.dart';
 import 'package:get_it/get_it.dart';
 
+import '../constants/constants.dart';
 import '../models/example_view_options.dart';
 import '../models/sdk.dart';
 import '../models/snippet_file.dart';
@@ -43,6 +44,8 @@ class SnippetFileEditingController extends ChangeNotifier {
     required ExampleViewOptions viewOptions,
     int? contextLine1Based,
   }) : codeController = CodeController(
+          // ignore: avoid_redundant_argument_values
+          params: const EditorParams(tabSpaces: spaceCount),
           language: sdk.highlightMode,
           namedSectionParser: const BracketsStartEndNamedSectionParser(),
           text: savedFile.content,
@@ -110,7 +113,8 @@ class SnippetFileEditingController extends ChangeNotifier {
   bool get isChanged => _isChanged;
 
   bool _isCodeChanged() {
-    return savedFile.content != codeController.fullText;
+    return savedFile.content.tabsToSpaces(spaceCount) !=
+        codeController.fullText;
   }
 
   void _updateIsChanged() {
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor.dart
index b293e585e72..32393ec273b 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor.dart
@@ -32,12 +32,22 @@ class CatalogDefaultExampleLoadingDescriptor extends ExampleLoadingDescriptor {
   });
 
   @override
-  List<Object> get props => [sdk.id];
+  List<Object> get props => [
+        sdk.id,
+        viewOptions,
+      ];
+
+  @override
+  CatalogDefaultExampleLoadingDescriptor copyWithoutViewOptions() =>
+      CatalogDefaultExampleLoadingDescriptor(
+        sdk: sdk,
+      );
 
   @override
   Map<String, dynamic> toJson() => {
         'sdk': sdk.id,
         _key: true,
+        ...viewOptions.toShortMap(),
       };
 
   static CatalogDefaultExampleLoadingDescriptor? tryParse(
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart
index b86336023ae..441b874cf73 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+import 'dart:convert';
+
 import '../../enums/complexity.dart';
 import '../example_view_options.dart';
 import '../sdk.dart';
@@ -42,8 +44,8 @@ class ContentExampleLoadingDescriptor extends ExampleLoadingDescriptor {
   });
 
   static ContentExampleLoadingDescriptor? tryParse(Map<String, dynamic> map) {
-    final files = map['files'];
-    if (files is! List) {
+    final files = _getFilesFromMap(map);
+    if (files == null) {
       return null;
     }
 
@@ -53,7 +55,7 @@ class ContentExampleLoadingDescriptor extends ExampleLoadingDescriptor {
     }
 
     return ContentExampleLoadingDescriptor(
-      files: (map['files'] as List<dynamic>)
+      files: files
           .map((file) => SnippetFile.fromJson(file as Map<String, dynamic>))
           .toList(growable: false),
       name: map['name']?.toString(),
@@ -63,19 +65,47 @@ class ContentExampleLoadingDescriptor extends ExampleLoadingDescriptor {
     );
   }
 
+  static List? _getFilesFromMap(Map<String, dynamic> map) {
+    final files = map['files'];
+
+    if (files is List) {
+      return files;
+    }
+
+    if (files is String) {
+      final list = jsonDecode(files);
+      if (list is List) {
+        return list;
+      }
+    }
+
+    return null;
+  }
+
   @override
   List<Object?> get props => [
         complexity,
         files,
         name,
         sdk.id,
+        viewOptions,
       ];
 
+  @override
+  ContentExampleLoadingDescriptor copyWithoutViewOptions() =>
+      ContentExampleLoadingDescriptor(
+        complexity: complexity,
+        files: files,
+        name: name,
+        sdk: sdk,
+      );
+
   @override
   Map<String, dynamic> toJson() => {
         'complexity': complexity?.name,
         'files': files.map((e) => e.toJson()).toList(growable: false),
         'name': name,
         'sdk': sdk.id,
+        ...viewOptions.toShortMap(),
       };
 }
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/empty_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/empty_example_loading_descriptor.dart
index d2e903fe949..a5be851361f 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/empty_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/empty_example_loading_descriptor.dart
@@ -32,6 +32,9 @@ class EmptyExampleLoadingDescriptor extends ExampleLoadingDescriptor {
   @override
   List<Object> get props => [sdk.id];
 
+  @override
+  EmptyExampleLoadingDescriptor copyWithoutViewOptions() => this;
+
   @override
   Map<String, dynamic> toJson() => {
         _key: true,
@@ -41,7 +44,7 @@ class EmptyExampleLoadingDescriptor extends ExampleLoadingDescriptor {
   static EmptyExampleLoadingDescriptor? tryParse(
     Map<String, dynamic> map,
   ) {
-    if (map[_key] != true) {
+    if (!map.containsKey(_key)) {
       return null;
     }
 
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
index 4697fce0536..fef12568098 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
@@ -28,5 +28,7 @@ abstract class ExampleLoadingDescriptor with EquatableMixin {
 
   final ExampleViewOptions viewOptions;
 
+  ExampleLoadingDescriptor copyWithoutViewOptions();
+
   Map<String, dynamic> toJson();
 }
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/examples_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/examples_loading_descriptor.dart
index bd6218bab2a..8f424cddd19 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/examples_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/examples_loading_descriptor.dart
@@ -113,6 +113,26 @@ class ExamplesLoadingDescriptor with EquatableMixin {
     );
   }
 
+  ExamplesLoadingDescriptor copyWithoutViewOptions() {
+    return ExamplesLoadingDescriptor(
+      //
+      descriptors: descriptors
+          .map((d) => d.copyWithoutViewOptions())
+          .toList(growable: false),
+
+      initialSdk: initialSdk,
+
+      lazyLoadDescriptors: lazyLoadDescriptors.map(
+        (sdk, descriptors) => MapEntry(
+          sdk,
+          descriptors
+              .map((d) => d.copyWithoutViewOptions())
+              .toList(growable: false),
+        ),
+      ),
+    );
+  }
+
   /// Tries to parse a [map] into an [ExamplesLoadingDescriptor].
   ///
   /// [singleDescriptorFactory] is tried on nested collections of the [map].
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/http_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/http_example_loading_descriptor.dart
index 60b72a68313..0eb9c071e5d 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/http_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/http_example_loading_descriptor.dart
@@ -38,10 +38,18 @@ class HttpExampleLoadingDescriptor extends ExampleLoadingDescriptor {
         viewOptions,
       ];
 
+  @override
+  HttpExampleLoadingDescriptor copyWithoutViewOptions() =>
+      HttpExampleLoadingDescriptor(
+        sdk: sdk,
+        uri: uri,
+      );
+
   @override
   Map<String, dynamic> toJson() => {
         'sdk': sdk.id,
         'url': uri.toString(),
+        ...viewOptions.toShortMap(),
       };
 
   static HttpExampleLoadingDescriptor? tryParse(Map<String, dynamic> map) {
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
index 2f2a9e553ff..34779ada27d 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
@@ -39,10 +39,18 @@ class StandardExampleLoadingDescriptor extends ExampleLoadingDescriptor {
         viewOptions,
       ];
 
+  @override
+  StandardExampleLoadingDescriptor copyWithoutViewOptions() =>
+      StandardExampleLoadingDescriptor(
+        path: path,
+        sdk: sdk,
+      );
+
   @override
   Map<String, dynamic> toJson() => {
         'path': path,
         'sdk': sdk.id,
+        ...viewOptions.toShortMap(),
       };
 
   static StandardExampleLoadingDescriptor? tryParse(Map<String, dynamic> map) {
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart
index 5d3a4ed071d..5c32e67d0bd 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart
@@ -38,10 +38,18 @@ class UserSharedExampleLoadingDescriptor extends ExampleLoadingDescriptor {
         viewOptions,
       ];
 
+  @override
+  UserSharedExampleLoadingDescriptor copyWithoutViewOptions() =>
+      UserSharedExampleLoadingDescriptor(
+        sdk: sdk,
+        snippetId: snippetId,
+      );
+
   @override
   Map<String, dynamic> toJson() => {
         'sdk': sdk.id,
         'shared': snippetId,
+        ...viewOptions.toShortMap(),
       };
 
   static UserSharedExampleLoadingDescriptor? tryParse(
diff --git a/playground/frontend/playground_components/lib/src/models/example_view_options.dart b/playground/frontend/playground_components/lib/src/models/example_view_options.dart
index b3d02a3ae86..be1d1575341 100644
--- a/playground/frontend/playground_components/lib/src/models/example_view_options.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_view_options.dart
@@ -51,6 +51,15 @@ class ExampleViewOptions with EquatableMixin {
     return value.splitNotEmpty(',');
   }
 
+  Map<String, String> toShortMap() {
+    return {
+      if (readOnlySectionNames.isNotEmpty)
+        'readonly': readOnlySectionNames.join(','),
+      if (showSectionNames.isNotEmpty) 'show': showSectionNames.join(','),
+      if (unfoldSectionNames.isNotEmpty) 'unfold': unfoldSectionNames.join(','),
+    };
+  }
+
   static const empty = ExampleViewOptions(
     readOnlySectionNames: [],
     showSectionNames: [],
diff --git a/playground/frontend/playground_components/pubspec.yaml b/playground/frontend/playground_components/pubspec.yaml
index a87ac0f2a23..7a239a399af 100644
--- a/playground/frontend/playground_components/pubspec.yaml
+++ b/playground/frontend/playground_components/pubspec.yaml
@@ -21,12 +21,12 @@ version: 0.0.1
 publish_to: none
 
 environment:
-  sdk: '>=2.18.1 <3.0.0'
-  flutter: '>=3.3.2'
+  sdk: '>=2.19.2 <4.0.0'
+  flutter: '>=3.7.3'
 
 dependencies:
   aligned_dialog: ^0.0.6
-  app_state: ^0.8.4
+  app_state: ^0.9.0
   collection: ^1.16.0
   easy_localization: ^3.0.1
   easy_localization_ext: ^0.1.1
@@ -34,12 +34,12 @@ dependencies:
   enum_map: ^0.2.1
   equatable: ^2.0.5
   flutter: { sdk: flutter }
-  flutter_code_editor: ^0.2.5
+  flutter_code_editor: ^0.2.9
   flutter_markdown: ^0.6.12
-  flutter_svg: ^1.0.3
+  flutter_svg: ^2.0.0+1
   fluttertoast: ^8.1.1
   get_it: ^7.2.0
-  google_fonts: ^3.0.1
+  google_fonts: ^4.0.3
   grpc: ^3.0.2
   highlight: ^0.7.0
   http: ^0.13.5
@@ -55,10 +55,10 @@ dependencies:
 dev_dependencies:
   build_runner: ^2.2.0
   enum_map_gen: ^0.2.0
-  flutter_gen_runner: ^4.3.0
+  flutter_gen_runner: ^5.2.0
   flutter_test: { sdk: flutter }
   json_serializable: ^6.4.1
-  mockito: 5.2.0
+  mockito: ^5.3.2
   total_lints: ^2.17.4
 
 flutter:
diff --git a/playground/frontend/playground_components/test/src/common/example_cache.mocks.dart b/playground/frontend/playground_components/test/src/common/example_cache.mocks.dart
index 5ce9a48c2f3..dbf423fd94f 100644
--- a/playground/frontend/playground_components/test/src/common/example_cache.mocks.dart
+++ b/playground/frontend/playground_components/test/src/common/example_cache.mocks.dart
@@ -1,10 +1,10 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground_components/test/src/common/example_cache.dart.
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
 import 'dart:async' as _i7;
-import 'dart:ui' as _i10;
+import 'dart:ui' as _i11;
 
 import 'package:mockito/mockito.dart' as _i1;
 import 'package:playground_components/src/cache/example_cache.dart' as _i4;
@@ -12,9 +12,11 @@ import 'package:playground_components/src/models/category_with_examples.dart'
     as _i6;
 import 'package:playground_components/src/models/example.dart' as _i3;
 import 'package:playground_components/src/models/example_base.dart' as _i2;
+import 'package:playground_components/src/models/example_view_options.dart'
+    as _i9;
 import 'package:playground_components/src/models/loading_status.dart' as _i8;
 import 'package:playground_components/src/models/sdk.dart' as _i5;
-import 'package:playground_components/src/models/snippet_file.dart' as _i9;
+import 'package:playground_components/src/models/snippet_file.dart' as _i10;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -25,10 +27,27 @@ import 'package:playground_components/src/models/snippet_file.dart' as _i9;
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeExampleBase_0 extends _i1.Fake implements _i2.ExampleBase {}
+class _FakeExampleBase_0 extends _i1.SmartFake implements _i2.ExampleBase {
+  _FakeExampleBase_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExample_1 extends _i1.Fake implements _i3.Example {}
+class _FakeExample_1 extends _i1.SmartFake implements _i3.Example {
+  _FakeExample_1(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [ExampleCache].
 ///
@@ -65,7 +84,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
   @override
   _i7.Future<void> get allExamplesFuture => (super.noSuchMethod(
         Invocation.getter(#allExamplesFuture),
-        returnValue: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i8.LoadingStatus get catalogStatus => (super.noSuchMethod(
@@ -83,8 +102,8 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadAllPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   List<_i6.CategoryWithExamples> getCategories(_i5.Sdk? sdk) =>
@@ -108,21 +127,42 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
             sdk,
           ],
         ),
-        returnValue: Future<_i2.ExampleBase>.value(_FakeExampleBase_0()),
+        returnValue: _i7.Future<_i2.ExampleBase>.value(_FakeExampleBase_0(
+          this,
+          Invocation.method(
+            #getPrecompiledObject,
+            [
+              path,
+              sdk,
+            ],
+          ),
+        )),
       ) as _i7.Future<_i2.ExampleBase>);
   @override
-  _i7.Future<_i3.Example> loadSharedExample(String? id) => (super.noSuchMethod(
+  _i7.Future<_i3.Example> loadSharedExample(
+    String? id, {
+    required _i9.ExampleViewOptions? viewOptions,
+  }) =>
+      (super.noSuchMethod(
         Invocation.method(
           #loadSharedExample,
           [id],
+          {#viewOptions: viewOptions},
         ),
-        returnValue: Future<_i3.Example>.value(_FakeExample_1()),
+        returnValue: _i7.Future<_i3.Example>.value(_FakeExample_1(
+          this,
+          Invocation.method(
+            #loadSharedExample,
+            [id],
+            {#viewOptions: viewOptions},
+          ),
+        )),
       ) as _i7.Future<_i3.Example>);
   @override
   _i7.Future<String> saveSnippet({
-    List<_i9.SnippetFile>? files,
-    _i5.Sdk? sdk,
-    String? pipelineOptions,
+    required List<_i10.SnippetFile>? files,
+    required _i5.Sdk? sdk,
+    required String? pipelineOptions,
   }) =>
       (super.noSuchMethod(
         Invocation.method(
@@ -134,7 +174,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
             #pipelineOptions: pipelineOptions,
           },
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i7.Future<String>.value(''),
       ) as _i7.Future<String>);
   @override
   _i7.Future<_i3.Example> loadExampleInfo(_i2.ExampleBase? example) =>
@@ -143,7 +183,13 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadExampleInfo,
           [example],
         ),
-        returnValue: Future<_i3.Example>.value(_FakeExample_1()),
+        returnValue: _i7.Future<_i3.Example>.value(_FakeExample_1(
+          this,
+          Invocation.method(
+            #loadExampleInfo,
+            [example],
+          ),
+        )),
       ) as _i7.Future<_i3.Example>);
   @override
   void setSelectorOpened(bool? value) => super.noSuchMethod(
@@ -160,7 +206,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #getDefaultExampleBySdk,
           [sdk],
         ),
-        returnValue: Future<_i3.Example?>.value(),
+        returnValue: _i7.Future<_i3.Example?>.value(),
       ) as _i7.Future<_i3.Example?>);
   @override
   _i7.Future<void> loadDefaultPrecompiledObjects() => (super.noSuchMethod(
@@ -168,8 +214,8 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadDefaultPrecompiledObjects,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i7.Future<void> loadDefaultPrecompiledObjectsIfNot() => (super.noSuchMethod(
@@ -177,8 +223,8 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadDefaultPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i7.Future<_i2.ExampleBase?> getCatalogExampleByPath(String? path) =>
@@ -187,10 +233,10 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #getCatalogExampleByPath,
           [path],
         ),
-        returnValue: Future<_i2.ExampleBase?>.value(),
+        returnValue: _i7.Future<_i2.ExampleBase?>.value(),
       ) as _i7.Future<_i2.ExampleBase?>);
   @override
-  void addListener(_i10.VoidCallback? listener) => super.noSuchMethod(
+  void addListener(_i11.VoidCallback? listener) => super.noSuchMethod(
         Invocation.method(
           #addListener,
           [listener],
@@ -198,7 +244,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
         returnValueForMissingStub: null,
       );
   @override
-  void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod(
+  void removeListener(_i11.VoidCallback? listener) => super.noSuchMethod(
         Invocation.method(
           #removeListener,
           [listener],
diff --git a/playground/frontend/playground_components/test/src/common/example_repository_mock.mocks.dart b/playground/frontend/playground_components/test/src/common/example_repository_mock.mocks.dart
index aa55c5193fb..b426f3c0150 100644
--- a/playground/frontend/playground_components/test/src/common/example_repository_mock.mocks.dart
+++ b/playground/frontend/playground_components/test/src/common/example_repository_mock.mocks.dart
@@ -1,4 +1,4 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground_components/test/src/common/example_repository_mock.dart.
 // Do not manually edit this file.
 
@@ -35,11 +35,28 @@ import 'package:playground_components/src/repositories/models/save_snippet_reque
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeExampleBase_0 extends _i1.Fake implements _i2.ExampleBase {}
+class _FakeExampleBase_0 extends _i1.SmartFake implements _i2.ExampleBase {
+  _FakeExampleBase_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeGetSnippetResponse_1 extends _i1.Fake
-    implements _i3.GetSnippetResponse {}
+class _FakeGetSnippetResponse_1 extends _i1.SmartFake
+    implements _i3.GetSnippetResponse {
+  _FakeGetSnippetResponse_1(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [ExampleRepository].
 ///
@@ -58,7 +75,7 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
               [request],
             ),
             returnValue:
-                Future<Map<_i6.Sdk, List<_i7.CategoryWithExamples>>>.value(
+                _i5.Future<Map<_i6.Sdk, List<_i7.CategoryWithExamples>>>.value(
                     <_i6.Sdk, List<_i7.CategoryWithExamples>>{}),
           ) as _i5.Future<Map<_i6.Sdk, List<_i7.CategoryWithExamples>>>);
   @override
@@ -69,7 +86,13 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           #getDefaultPrecompiledObject,
           [request],
         ),
-        returnValue: Future<_i2.ExampleBase>.value(_FakeExampleBase_0()),
+        returnValue: _i5.Future<_i2.ExampleBase>.value(_FakeExampleBase_0(
+          this,
+          Invocation.method(
+            #getDefaultPrecompiledObject,
+            [request],
+          ),
+        )),
       ) as _i5.Future<_i2.ExampleBase>);
   @override
   _i5.Future<List<_i10.SnippetFile>> getPrecompiledObjectCode(
@@ -79,7 +102,8 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           #getPrecompiledObjectCode,
           [request],
         ),
-        returnValue: Future<List<_i10.SnippetFile>>.value(<_i10.SnippetFile>[]),
+        returnValue:
+            _i5.Future<List<_i10.SnippetFile>>.value(<_i10.SnippetFile>[]),
       ) as _i5.Future<List<_i10.SnippetFile>>);
   @override
   _i5.Future<String> getPrecompiledObjectOutput(
@@ -89,7 +113,7 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           #getPrecompiledObjectOutput,
           [request],
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i5.Future<String>.value(''),
       ) as _i5.Future<String>);
   @override
   _i5.Future<String> getPrecompiledObjectLogs(
@@ -99,7 +123,7 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           #getPrecompiledObjectLogs,
           [request],
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i5.Future<String>.value(''),
       ) as _i5.Future<String>);
   @override
   _i5.Future<String> getPrecompiledObjectGraph(
@@ -109,7 +133,7 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           #getPrecompiledObjectGraph,
           [request],
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i5.Future<String>.value(''),
       ) as _i5.Future<String>);
   @override
   _i5.Future<_i2.ExampleBase> getPrecompiledObject(
@@ -119,7 +143,13 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           #getPrecompiledObject,
           [request],
         ),
-        returnValue: Future<_i2.ExampleBase>.value(_FakeExampleBase_0()),
+        returnValue: _i5.Future<_i2.ExampleBase>.value(_FakeExampleBase_0(
+          this,
+          Invocation.method(
+            #getPrecompiledObject,
+            [request],
+          ),
+        )),
       ) as _i5.Future<_i2.ExampleBase>);
   @override
   _i5.Future<_i3.GetSnippetResponse> getSnippet(
@@ -130,7 +160,13 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           [request],
         ),
         returnValue:
-            Future<_i3.GetSnippetResponse>.value(_FakeGetSnippetResponse_1()),
+            _i5.Future<_i3.GetSnippetResponse>.value(_FakeGetSnippetResponse_1(
+          this,
+          Invocation.method(
+            #getSnippet,
+            [request],
+          ),
+        )),
       ) as _i5.Future<_i3.GetSnippetResponse>);
   @override
   _i5.Future<String> saveSnippet(_i13.SaveSnippetRequest? request) =>
@@ -139,6 +175,6 @@ class MockExampleRepository extends _i1.Mock implements _i4.ExampleRepository {
           #saveSnippet,
           [request],
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i5.Future<String>.value(''),
       ) as _i5.Future<String>);
 }
diff --git a/playground/frontend/playground_components/test/src/controllers/example_loaders/common.dart b/playground/frontend/playground_components/test/src/controllers/example_loaders/common.dart
index 5015991528d..42c0eec3010 100644
--- a/playground/frontend/playground_components/test/src/controllers/example_loaders/common.dart
+++ b/playground/frontend/playground_components/test/src/controllers/example_loaders/common.dart
@@ -32,6 +32,9 @@ class TestExampleLoadingDescriptor extends ExampleLoadingDescriptor {
   @override
   List<Object?> get props => [sdk, succeed];
 
+  @override
+  ExampleLoadingDescriptor copyWithoutViewOptions() => this;
+
   @override
   Map<String, dynamic> toJson() => throw UnimplementedError();
 }
diff --git a/playground/frontend/playground_components/test/src/controllers/example_loaders/example_loader_factory_test.dart b/playground/frontend/playground_components/test/src/controllers/example_loaders/example_loader_factory_test.dart
index 90eda9b2709..a0d046b1aa9 100644
--- a/playground/frontend/playground_components/test/src/controllers/example_loaders/example_loader_factory_test.dart
+++ b/playground/frontend/playground_components/test/src/controllers/example_loaders/example_loader_factory_test.dart
@@ -55,6 +55,9 @@ class _UnregisteredDescriptor extends ExampleLoadingDescriptor {
   @override
   List<Object?> get props => [];
 
+  @override
+  ExampleLoadingDescriptor copyWithoutViewOptions() => this;
+
   @override
   Map<String, dynamic> toJson() => throw UnimplementedError();
 }
diff --git a/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.mocks.dart b/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.mocks.dart
index 35b0ac0a006..982c97d7f51 100644
--- a/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.mocks.dart
+++ b/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.mocks.dart
@@ -1,4 +1,4 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground_components/test/src/controllers/example_loaders/examples_loader_test.dart.
 // Do not manually edit this file.
 
@@ -27,10 +27,12 @@ import 'package:playground_components/src/models/example_loading_descriptors/exa
     as _i9;
 import 'package:playground_components/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart'
     as _i8;
+import 'package:playground_components/src/models/example_view_options.dart'
+    as _i19;
 import 'package:playground_components/src/models/loading_status.dart' as _i18;
 import 'package:playground_components/src/models/sdk.dart' as _i13;
 import 'package:playground_components/src/models/shortcut.dart' as _i6;
-import 'package:playground_components/src/models/snippet_file.dart' as _i19;
+import 'package:playground_components/src/models/snippet_file.dart' as _i20;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -41,30 +43,112 @@ import 'package:playground_components/src/models/snippet_file.dart' as _i19;
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeExampleCache_0 extends _i1.Fake implements _i2.ExampleCache {}
+class _FakeExampleCache_0 extends _i1.SmartFake implements _i2.ExampleCache {
+  _FakeExampleCache_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExamplesLoader_1 extends _i1.Fake implements _i3.ExamplesLoader {}
+class _FakeExamplesLoader_1 extends _i1.SmartFake
+    implements _i3.ExamplesLoader {
+  _FakeExamplesLoader_1(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeOutputFilterTypeController_2 extends _i1.Fake
-    implements _i4.OutputFilterTypeController {}
+class _FakeOutputFilterTypeController_2 extends _i1.SmartFake
+    implements _i4.OutputFilterTypeController {
+  _FakeOutputFilterTypeController_2(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeCodeRunner_3 extends _i1.Fake implements _i5.CodeRunner {}
+class _FakeCodeRunner_3 extends _i1.SmartFake implements _i5.CodeRunner {
+  _FakeCodeRunner_3(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeBeamShortcut_4 extends _i1.Fake implements _i6.BeamShortcut {}
+class _FakeBeamShortcut_4 extends _i1.SmartFake implements _i6.BeamShortcut {
+  _FakeBeamShortcut_4(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeSnippetEditingController_5 extends _i1.Fake
-    implements _i7.SnippetEditingController {}
+class _FakeSnippetEditingController_5 extends _i1.SmartFake
+    implements _i7.SnippetEditingController {
+  _FakeSnippetEditingController_5(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeUserSharedExampleLoadingDescriptor_6 extends _i1.Fake
-    implements _i8.UserSharedExampleLoadingDescriptor {}
+class _FakeUserSharedExampleLoadingDescriptor_6 extends _i1.SmartFake
+    implements _i8.UserSharedExampleLoadingDescriptor {
+  _FakeUserSharedExampleLoadingDescriptor_6(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExamplesLoadingDescriptor_7 extends _i1.Fake
-    implements _i9.ExamplesLoadingDescriptor {}
+class _FakeExamplesLoadingDescriptor_7 extends _i1.SmartFake
+    implements _i9.ExamplesLoadingDescriptor {
+  _FakeExamplesLoadingDescriptor_7(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExampleBase_8 extends _i1.Fake implements _i10.ExampleBase {}
+class _FakeExampleBase_8 extends _i1.SmartFake implements _i10.ExampleBase {
+  _FakeExampleBase_8(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExample_9 extends _i1.Fake implements _i11.Example {}
+class _FakeExample_9 extends _i1.SmartFake implements _i11.Example {
+  _FakeExample_9(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [PlaygroundController].
 ///
@@ -78,23 +162,35 @@ class MockPlaygroundController extends _i1.Mock
   @override
   _i2.ExampleCache get exampleCache => (super.noSuchMethod(
         Invocation.getter(#exampleCache),
-        returnValue: _FakeExampleCache_0(),
+        returnValue: _FakeExampleCache_0(
+          this,
+          Invocation.getter(#exampleCache),
+        ),
       ) as _i2.ExampleCache);
   @override
   _i3.ExamplesLoader get examplesLoader => (super.noSuchMethod(
         Invocation.getter(#examplesLoader),
-        returnValue: _FakeExamplesLoader_1(),
+        returnValue: _FakeExamplesLoader_1(
+          this,
+          Invocation.getter(#examplesLoader),
+        ),
       ) as _i3.ExamplesLoader);
   @override
   _i4.OutputFilterTypeController get outputTypeController =>
       (super.noSuchMethod(
         Invocation.getter(#outputTypeController),
-        returnValue: _FakeOutputFilterTypeController_2(),
+        returnValue: _FakeOutputFilterTypeController_2(
+          this,
+          Invocation.getter(#outputTypeController),
+        ),
       ) as _i4.OutputFilterTypeController);
   @override
   _i5.CodeRunner get codeRunner => (super.noSuchMethod(
         Invocation.getter(#codeRunner),
-        returnValue: _FakeCodeRunner_3(),
+        returnValue: _FakeCodeRunner_3(
+          this,
+          Invocation.getter(#codeRunner),
+        ),
       ) as _i5.CodeRunner);
   @override
   set codeRunner(_i5.CodeRunner? _codeRunner) => super.noSuchMethod(
@@ -107,7 +203,10 @@ class MockPlaygroundController extends _i1.Mock
   @override
   _i6.BeamShortcut get runShortcut => (super.noSuchMethod(
         Invocation.getter(#runShortcut),
-        returnValue: _FakeBeamShortcut_4(),
+        returnValue: _FakeBeamShortcut_4(
+          this,
+          Invocation.getter(#runShortcut),
+        ),
       ) as _i6.BeamShortcut);
   @override
   set runShortcut(_i6.BeamShortcut? _runShortcut) => super.noSuchMethod(
@@ -120,7 +219,10 @@ class MockPlaygroundController extends _i1.Mock
   @override
   _i6.BeamShortcut get resetShortcut => (super.noSuchMethod(
         Invocation.getter(#resetShortcut),
-        returnValue: _FakeBeamShortcut_4(),
+        returnValue: _FakeBeamShortcut_4(
+          this,
+          Invocation.getter(#resetShortcut),
+        ),
       ) as _i6.BeamShortcut);
   @override
   set resetShortcut(_i6.BeamShortcut? _resetShortcut) => super.noSuchMethod(
@@ -157,7 +259,13 @@ class MockPlaygroundController extends _i1.Mock
           #requireSnippetEditingController,
           [],
         ),
-        returnValue: _FakeSnippetEditingController_5(),
+        returnValue: _FakeSnippetEditingController_5(
+          this,
+          Invocation.method(
+            #requireSnippetEditingController,
+            [],
+          ),
+        ),
       ) as _i7.SnippetEditingController);
   @override
   void setEmptyIfNoSdk(_i13.Sdk? sdk) => super.noSuchMethod(
@@ -170,7 +278,7 @@ class MockPlaygroundController extends _i1.Mock
   @override
   void setEmptyIfNotExists(
     _i13.Sdk? sdk, {
-    bool? setCurrentSdk,
+    required bool? setCurrentSdk,
   }) =>
       super.noSuchMethod(
         Invocation.method(
@@ -187,14 +295,14 @@ class MockPlaygroundController extends _i1.Mock
           #setExampleBase,
           [exampleBase],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i14.Future<void>.value(),
+        returnValueForMissingStub: _i14.Future<void>.value(),
       ) as _i14.Future<void>);
   @override
   void setExample(
     _i11.Example? example, {
-    _i15.ExampleLoadingDescriptor? descriptor,
-    bool? setCurrentSdk,
+    required _i15.ExampleLoadingDescriptor? descriptor,
+    required bool? setCurrentSdk,
   }) =>
       super.noSuchMethod(
         Invocation.method(
@@ -226,8 +334,8 @@ class MockPlaygroundController extends _i1.Mock
           #reset,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i14.Future<void>.value(),
+        returnValueForMissingStub: _i14.Future<void>.value(),
       ) as _i14.Future<void>);
   @override
   void resetErrorMessageText() => super.noSuchMethod(
@@ -252,8 +360,14 @@ class MockPlaygroundController extends _i1.Mock
           #saveSnippet,
           [],
         ),
-        returnValue: Future<_i8.UserSharedExampleLoadingDescriptor>.value(
-            _FakeUserSharedExampleLoadingDescriptor_6()),
+        returnValue: _i14.Future<_i8.UserSharedExampleLoadingDescriptor>.value(
+            _FakeUserSharedExampleLoadingDescriptor_6(
+          this,
+          Invocation.method(
+            #saveSnippet,
+            [],
+          ),
+        )),
       ) as _i14.Future<_i8.UserSharedExampleLoadingDescriptor>);
   @override
   _i9.ExamplesLoadingDescriptor getLoadingDescriptor() => (super.noSuchMethod(
@@ -261,7 +375,13 @@ class MockPlaygroundController extends _i1.Mock
           #getLoadingDescriptor,
           [],
         ),
-        returnValue: _FakeExamplesLoadingDescriptor_7(),
+        returnValue: _FakeExamplesLoadingDescriptor_7(
+          this,
+          Invocation.method(
+            #getLoadingDescriptor,
+            [],
+          ),
+        ),
       ) as _i9.ExamplesLoadingDescriptor);
   @override
   void dispose() => super.noSuchMethod(
@@ -332,7 +452,7 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
   @override
   _i14.Future<void> get allExamplesFuture => (super.noSuchMethod(
         Invocation.getter(#allExamplesFuture),
-        returnValue: Future<void>.value(),
+        returnValue: _i14.Future<void>.value(),
       ) as _i14.Future<void>);
   @override
   _i18.LoadingStatus get catalogStatus => (super.noSuchMethod(
@@ -350,8 +470,8 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
           #loadAllPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i14.Future<void>.value(),
+        returnValueForMissingStub: _i14.Future<void>.value(),
       ) as _i14.Future<void>);
   @override
   List<_i17.CategoryWithExamples> getCategories(_i13.Sdk? sdk) =>
@@ -375,22 +495,42 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
             sdk,
           ],
         ),
-        returnValue: Future<_i10.ExampleBase>.value(_FakeExampleBase_8()),
+        returnValue: _i14.Future<_i10.ExampleBase>.value(_FakeExampleBase_8(
+          this,
+          Invocation.method(
+            #getPrecompiledObject,
+            [
+              path,
+              sdk,
+            ],
+          ),
+        )),
       ) as _i14.Future<_i10.ExampleBase>);
   @override
-  _i14.Future<_i11.Example> loadSharedExample(String? id) =>
+  _i14.Future<_i11.Example> loadSharedExample(
+    String? id, {
+    required _i19.ExampleViewOptions? viewOptions,
+  }) =>
       (super.noSuchMethod(
         Invocation.method(
           #loadSharedExample,
           [id],
-        ),
-        returnValue: Future<_i11.Example>.value(_FakeExample_9()),
+          {#viewOptions: viewOptions},
+        ),
+        returnValue: _i14.Future<_i11.Example>.value(_FakeExample_9(
+          this,
+          Invocation.method(
+            #loadSharedExample,
+            [id],
+            {#viewOptions: viewOptions},
+          ),
+        )),
       ) as _i14.Future<_i11.Example>);
   @override
   _i14.Future<String> saveSnippet({
-    List<_i19.SnippetFile>? files,
-    _i13.Sdk? sdk,
-    String? pipelineOptions,
+    required List<_i20.SnippetFile>? files,
+    required _i13.Sdk? sdk,
+    required String? pipelineOptions,
   }) =>
       (super.noSuchMethod(
         Invocation.method(
@@ -402,7 +542,7 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
             #pipelineOptions: pipelineOptions,
           },
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i14.Future<String>.value(''),
       ) as _i14.Future<String>);
   @override
   _i14.Future<_i11.Example> loadExampleInfo(_i10.ExampleBase? example) =>
@@ -411,7 +551,13 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
           #loadExampleInfo,
           [example],
         ),
-        returnValue: Future<_i11.Example>.value(_FakeExample_9()),
+        returnValue: _i14.Future<_i11.Example>.value(_FakeExample_9(
+          this,
+          Invocation.method(
+            #loadExampleInfo,
+            [example],
+          ),
+        )),
       ) as _i14.Future<_i11.Example>);
   @override
   void setSelectorOpened(bool? value) => super.noSuchMethod(
@@ -428,7 +574,7 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
           #getDefaultExampleBySdk,
           [sdk],
         ),
-        returnValue: Future<_i11.Example?>.value(),
+        returnValue: _i14.Future<_i11.Example?>.value(),
       ) as _i14.Future<_i11.Example?>);
   @override
   _i14.Future<void> loadDefaultPrecompiledObjects() => (super.noSuchMethod(
@@ -436,8 +582,8 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
           #loadDefaultPrecompiledObjects,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i14.Future<void>.value(),
+        returnValueForMissingStub: _i14.Future<void>.value(),
       ) as _i14.Future<void>);
   @override
   _i14.Future<void> loadDefaultPrecompiledObjectsIfNot() => (super.noSuchMethod(
@@ -445,8 +591,8 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
           #loadDefaultPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i14.Future<void>.value(),
+        returnValueForMissingStub: _i14.Future<void>.value(),
       ) as _i14.Future<void>);
   @override
   _i14.Future<_i10.ExampleBase?> getCatalogExampleByPath(String? path) =>
@@ -455,7 +601,7 @@ class MockExampleCache extends _i1.Mock implements _i2.ExampleCache {
           #getCatalogExampleByPath,
           [path],
         ),
-        returnValue: Future<_i10.ExampleBase?>.value(),
+        returnValue: _i14.Future<_i10.ExampleBase?>.value(),
       ) as _i14.Future<_i10.ExampleBase?>);
   @override
   void addListener(_i16.VoidCallback? listener) => super.noSuchMethod(
diff --git a/playground/frontend/playground_components/test/src/controllers/example_loaders/http_example_loader_test.mocks.dart b/playground/frontend/playground_components/test/src/controllers/example_loaders/http_example_loader_test.mocks.dart
index a697f1105ad..bc6585c7a9e 100644
--- a/playground/frontend/playground_components/test/src/controllers/example_loaders/http_example_loader_test.mocks.dart
+++ b/playground/frontend/playground_components/test/src/controllers/example_loaders/http_example_loader_test.mocks.dart
@@ -1,10 +1,10 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground_components/test/src/controllers/example_loaders/http_example_loader_test.dart.
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
 import 'dart:async' as _i7;
-import 'dart:ui' as _i10;
+import 'dart:ui' as _i11;
 
 import 'package:mockito/mockito.dart' as _i1;
 import 'package:playground_components/src/cache/example_cache.dart' as _i4;
@@ -12,9 +12,11 @@ import 'package:playground_components/src/models/category_with_examples.dart'
     as _i6;
 import 'package:playground_components/src/models/example.dart' as _i3;
 import 'package:playground_components/src/models/example_base.dart' as _i2;
+import 'package:playground_components/src/models/example_view_options.dart'
+    as _i9;
 import 'package:playground_components/src/models/loading_status.dart' as _i8;
 import 'package:playground_components/src/models/sdk.dart' as _i5;
-import 'package:playground_components/src/models/snippet_file.dart' as _i9;
+import 'package:playground_components/src/models/snippet_file.dart' as _i10;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -25,10 +27,27 @@ import 'package:playground_components/src/models/snippet_file.dart' as _i9;
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeExampleBase_0 extends _i1.Fake implements _i2.ExampleBase {}
+class _FakeExampleBase_0 extends _i1.SmartFake implements _i2.ExampleBase {
+  _FakeExampleBase_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExample_1 extends _i1.Fake implements _i3.Example {}
+class _FakeExample_1 extends _i1.SmartFake implements _i3.Example {
+  _FakeExample_1(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [ExampleCache].
 ///
@@ -65,7 +84,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
   @override
   _i7.Future<void> get allExamplesFuture => (super.noSuchMethod(
         Invocation.getter(#allExamplesFuture),
-        returnValue: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i8.LoadingStatus get catalogStatus => (super.noSuchMethod(
@@ -83,8 +102,8 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadAllPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   List<_i6.CategoryWithExamples> getCategories(_i5.Sdk? sdk) =>
@@ -108,21 +127,42 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
             sdk,
           ],
         ),
-        returnValue: Future<_i2.ExampleBase>.value(_FakeExampleBase_0()),
+        returnValue: _i7.Future<_i2.ExampleBase>.value(_FakeExampleBase_0(
+          this,
+          Invocation.method(
+            #getPrecompiledObject,
+            [
+              path,
+              sdk,
+            ],
+          ),
+        )),
       ) as _i7.Future<_i2.ExampleBase>);
   @override
-  _i7.Future<_i3.Example> loadSharedExample(String? id) => (super.noSuchMethod(
+  _i7.Future<_i3.Example> loadSharedExample(
+    String? id, {
+    required _i9.ExampleViewOptions? viewOptions,
+  }) =>
+      (super.noSuchMethod(
         Invocation.method(
           #loadSharedExample,
           [id],
+          {#viewOptions: viewOptions},
         ),
-        returnValue: Future<_i3.Example>.value(_FakeExample_1()),
+        returnValue: _i7.Future<_i3.Example>.value(_FakeExample_1(
+          this,
+          Invocation.method(
+            #loadSharedExample,
+            [id],
+            {#viewOptions: viewOptions},
+          ),
+        )),
       ) as _i7.Future<_i3.Example>);
   @override
   _i7.Future<String> saveSnippet({
-    List<_i9.SnippetFile>? files,
-    _i5.Sdk? sdk,
-    String? pipelineOptions,
+    required List<_i10.SnippetFile>? files,
+    required _i5.Sdk? sdk,
+    required String? pipelineOptions,
   }) =>
       (super.noSuchMethod(
         Invocation.method(
@@ -134,7 +174,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
             #pipelineOptions: pipelineOptions,
           },
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i7.Future<String>.value(''),
       ) as _i7.Future<String>);
   @override
   _i7.Future<_i3.Example> loadExampleInfo(_i2.ExampleBase? example) =>
@@ -143,7 +183,13 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadExampleInfo,
           [example],
         ),
-        returnValue: Future<_i3.Example>.value(_FakeExample_1()),
+        returnValue: _i7.Future<_i3.Example>.value(_FakeExample_1(
+          this,
+          Invocation.method(
+            #loadExampleInfo,
+            [example],
+          ),
+        )),
       ) as _i7.Future<_i3.Example>);
   @override
   void setSelectorOpened(bool? value) => super.noSuchMethod(
@@ -160,7 +206,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #getDefaultExampleBySdk,
           [sdk],
         ),
-        returnValue: Future<_i3.Example?>.value(),
+        returnValue: _i7.Future<_i3.Example?>.value(),
       ) as _i7.Future<_i3.Example?>);
   @override
   _i7.Future<void> loadDefaultPrecompiledObjects() => (super.noSuchMethod(
@@ -168,8 +214,8 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadDefaultPrecompiledObjects,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i7.Future<void> loadDefaultPrecompiledObjectsIfNot() => (super.noSuchMethod(
@@ -177,8 +223,8 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #loadDefaultPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i7.Future<_i2.ExampleBase?> getCatalogExampleByPath(String? path) =>
@@ -187,10 +233,10 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
           #getCatalogExampleByPath,
           [path],
         ),
-        returnValue: Future<_i2.ExampleBase?>.value(),
+        returnValue: _i7.Future<_i2.ExampleBase?>.value(),
       ) as _i7.Future<_i2.ExampleBase?>);
   @override
-  void addListener(_i10.VoidCallback? listener) => super.noSuchMethod(
+  void addListener(_i11.VoidCallback? listener) => super.noSuchMethod(
         Invocation.method(
           #addListener,
           [listener],
@@ -198,7 +244,7 @@ class MockExampleCache extends _i1.Mock implements _i4.ExampleCache {
         returnValueForMissingStub: null,
       );
   @override
-  void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod(
+  void removeListener(_i11.VoidCallback? listener) => super.noSuchMethod(
         Invocation.method(
           #removeListener,
           [listener],
diff --git a/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart b/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart
index 9bccb3f91f7..6ab8b1e9dbb 100644
--- a/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart
+++ b/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart
@@ -1,10 +1,10 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground_components/test/src/controllers/playground_controller_test.dart.
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
 import 'dart:async' as _i7;
-import 'dart:ui' as _i14;
+import 'dart:ui' as _i15;
 
 import 'package:mockito/mockito.dart' as _i1;
 import 'package:playground_components/src/cache/example_cache.dart' as _i10;
@@ -20,9 +20,11 @@ import 'package:playground_components/src/models/example.dart' as _i4;
 import 'package:playground_components/src/models/example_base.dart' as _i3;
 import 'package:playground_components/src/models/example_loading_descriptors/examples_loading_descriptor.dart'
     as _i8;
+import 'package:playground_components/src/models/example_view_options.dart'
+    as _i13;
 import 'package:playground_components/src/models/loading_status.dart' as _i12;
 import 'package:playground_components/src/models/sdk.dart' as _i9;
-import 'package:playground_components/src/models/snippet_file.dart' as _i13;
+import 'package:playground_components/src/models/snippet_file.dart' as _i14;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -33,13 +35,38 @@ import 'package:playground_components/src/models/snippet_file.dart' as _i13;
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeExampleLoaderFactory_0 extends _i1.Fake
-    implements _i2.ExampleLoaderFactory {}
+class _FakeExampleLoaderFactory_0 extends _i1.SmartFake
+    implements _i2.ExampleLoaderFactory {
+  _FakeExampleLoaderFactory_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExampleBase_1 extends _i1.Fake implements _i3.ExampleBase {}
+class _FakeExampleBase_1 extends _i1.SmartFake implements _i3.ExampleBase {
+  _FakeExampleBase_1(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeExample_2 extends _i1.Fake implements _i4.Example {}
+class _FakeExample_2 extends _i1.SmartFake implements _i4.Example {
+  _FakeExample_2(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [ExamplesLoader].
 ///
@@ -52,7 +79,10 @@ class MockExamplesLoader extends _i1.Mock implements _i5.ExamplesLoader {
   @override
   _i2.ExampleLoaderFactory get defaultFactory => (super.noSuchMethod(
         Invocation.getter(#defaultFactory),
-        returnValue: _FakeExampleLoaderFactory_0(),
+        returnValue: _FakeExampleLoaderFactory_0(
+          this,
+          Invocation.getter(#defaultFactory),
+        ),
       ) as _i2.ExampleLoaderFactory);
   @override
   void setPlaygroundController(_i6.PlaygroundController? value) =>
@@ -70,8 +100,8 @@ class MockExamplesLoader extends _i1.Mock implements _i5.ExamplesLoader {
           #load,
           [descriptor],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i7.Future<void> loadDefaultIfAny(_i9.Sdk? sdk) => (super.noSuchMethod(
@@ -79,8 +109,8 @@ class MockExamplesLoader extends _i1.Mock implements _i5.ExamplesLoader {
           #loadDefaultIfAny,
           [sdk],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
 }
 
@@ -119,7 +149,7 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
   @override
   _i7.Future<void> get allExamplesFuture => (super.noSuchMethod(
         Invocation.getter(#allExamplesFuture),
-        returnValue: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i12.LoadingStatus get catalogStatus => (super.noSuchMethod(
@@ -137,8 +167,8 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
           #loadAllPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   List<_i11.CategoryWithExamples> getCategories(_i9.Sdk? sdk) =>
@@ -162,21 +192,42 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
             sdk,
           ],
         ),
-        returnValue: Future<_i3.ExampleBase>.value(_FakeExampleBase_1()),
+        returnValue: _i7.Future<_i3.ExampleBase>.value(_FakeExampleBase_1(
+          this,
+          Invocation.method(
+            #getPrecompiledObject,
+            [
+              path,
+              sdk,
+            ],
+          ),
+        )),
       ) as _i7.Future<_i3.ExampleBase>);
   @override
-  _i7.Future<_i4.Example> loadSharedExample(String? id) => (super.noSuchMethod(
+  _i7.Future<_i4.Example> loadSharedExample(
+    String? id, {
+    required _i13.ExampleViewOptions? viewOptions,
+  }) =>
+      (super.noSuchMethod(
         Invocation.method(
           #loadSharedExample,
           [id],
+          {#viewOptions: viewOptions},
         ),
-        returnValue: Future<_i4.Example>.value(_FakeExample_2()),
+        returnValue: _i7.Future<_i4.Example>.value(_FakeExample_2(
+          this,
+          Invocation.method(
+            #loadSharedExample,
+            [id],
+            {#viewOptions: viewOptions},
+          ),
+        )),
       ) as _i7.Future<_i4.Example>);
   @override
   _i7.Future<String> saveSnippet({
-    List<_i13.SnippetFile>? files,
-    _i9.Sdk? sdk,
-    String? pipelineOptions,
+    required List<_i14.SnippetFile>? files,
+    required _i9.Sdk? sdk,
+    required String? pipelineOptions,
   }) =>
       (super.noSuchMethod(
         Invocation.method(
@@ -188,7 +239,7 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
             #pipelineOptions: pipelineOptions,
           },
         ),
-        returnValue: Future<String>.value(''),
+        returnValue: _i7.Future<String>.value(''),
       ) as _i7.Future<String>);
   @override
   _i7.Future<_i4.Example> loadExampleInfo(_i3.ExampleBase? example) =>
@@ -197,7 +248,13 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
           #loadExampleInfo,
           [example],
         ),
-        returnValue: Future<_i4.Example>.value(_FakeExample_2()),
+        returnValue: _i7.Future<_i4.Example>.value(_FakeExample_2(
+          this,
+          Invocation.method(
+            #loadExampleInfo,
+            [example],
+          ),
+        )),
       ) as _i7.Future<_i4.Example>);
   @override
   void setSelectorOpened(bool? value) => super.noSuchMethod(
@@ -214,7 +271,7 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
           #getDefaultExampleBySdk,
           [sdk],
         ),
-        returnValue: Future<_i4.Example?>.value(),
+        returnValue: _i7.Future<_i4.Example?>.value(),
       ) as _i7.Future<_i4.Example?>);
   @override
   _i7.Future<void> loadDefaultPrecompiledObjects() => (super.noSuchMethod(
@@ -222,8 +279,8 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
           #loadDefaultPrecompiledObjects,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i7.Future<void> loadDefaultPrecompiledObjectsIfNot() => (super.noSuchMethod(
@@ -231,8 +288,8 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
           #loadDefaultPrecompiledObjectsIfNot,
           [],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i7.Future<void>.value(),
+        returnValueForMissingStub: _i7.Future<void>.value(),
       ) as _i7.Future<void>);
   @override
   _i7.Future<_i3.ExampleBase?> getCatalogExampleByPath(String? path) =>
@@ -241,10 +298,10 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
           #getCatalogExampleByPath,
           [path],
         ),
-        returnValue: Future<_i3.ExampleBase?>.value(),
+        returnValue: _i7.Future<_i3.ExampleBase?>.value(),
       ) as _i7.Future<_i3.ExampleBase?>);
   @override
-  void addListener(_i14.VoidCallback? listener) => super.noSuchMethod(
+  void addListener(_i15.VoidCallback? listener) => super.noSuchMethod(
         Invocation.method(
           #addListener,
           [listener],
@@ -252,7 +309,7 @@ class MockExampleCache extends _i1.Mock implements _i10.ExampleCache {
         returnValueForMissingStub: null,
       );
   @override
-  void removeListener(_i14.VoidCallback? listener) => super.noSuchMethod(
+  void removeListener(_i15.VoidCallback? listener) => super.noSuchMethod(
         Invocation.method(
           #removeListener,
           [listener],
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor_test.dart
index 6c90be765bf..1dde95e1729 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/catalog_default_example_loading_descriptor_test.dart
@@ -23,7 +23,10 @@ import 'common.dart';
 
 void main() {
   group('CatalogDefaultExampleLoadingDescriptor', () {
-    const descriptor = CatalogDefaultExampleLoadingDescriptor(sdk: Sdk.go);
+    const descriptor = CatalogDefaultExampleLoadingDescriptor(
+      sdk: Sdk.go,
+      viewOptions: viewOptions,
+    );
 
     test('toJson -> tryParse', () {
       final map = descriptor.toJson();
@@ -32,11 +35,13 @@ void main() {
       expect(parsed, descriptor);
     });
 
-    test('parses viewOptions', (){
-      final map = descriptor.toJson()..addAll(viewOptionsMap);
-      final parsed = CatalogDefaultExampleLoadingDescriptor.tryParse(map);
-
-      expect(parsed?.viewOptions, viewOptions);
+    test('copyWithoutViewOptions', () {
+      expect(
+        descriptor.copyWithoutViewOptions(),
+        CatalogDefaultExampleLoadingDescriptor(
+          sdk: descriptor.sdk,
+        ),
+      );
     });
   });
 }
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/content_example_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/content_example_loading_descriptor_test.dart
index d8e5a70c3ea..48868c52caa 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/content_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/content_example_loading_descriptor_test.dart
@@ -40,6 +40,7 @@ void main() {
       files: [SnippetFile(content: 'abc', isMain: true)],
       name: 'name',
       sdk: Sdk.go,
+      viewOptions: viewOptions,
     );
 
     test('toJson -> tryParse', () {
@@ -49,11 +50,16 @@ void main() {
       expect(parsed, descriptor);
     });
 
-    test('parses viewOptions', () {
-      final map = descriptor.toJson()..addAll(viewOptionsMap);
-      final parsed = ContentExampleLoadingDescriptor.tryParse(map);
-
-      expect(parsed?.viewOptions, viewOptions);
+    test('copyWithoutViewOptions', () {
+      expect(
+        descriptor.copyWithoutViewOptions(),
+        ContentExampleLoadingDescriptor(
+          complexity: descriptor.complexity,
+          files: descriptor.files,
+          name: descriptor.name,
+          sdk: descriptor.sdk,
+        ),
+      );
     });
   });
 }
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
index ab939bfbedd..d1572682709 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
@@ -29,5 +29,9 @@ void main() {
 
       expect(parsed, descriptor);
     });
+
+    test('copyWithoutViewOptions', () {
+      expect(descriptor.copyWithoutViewOptions(), descriptor);
+    });
   });
 }
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/examples_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/examples_loading_descriptor_test.dart
index 0b425556218..f2e35646855 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/examples_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/examples_loading_descriptor_test.dart
@@ -21,6 +21,8 @@
 import 'package:flutter_test/flutter_test.dart';
 import 'package:playground_components/playground_components.dart';
 
+import 'common.dart';
+
 void main() {
   group('ExamplesLoadingDescriptor', () {
     test('Empty map -> null', () {
@@ -122,6 +124,40 @@ void main() {
         ),
       );
     });
+
+    test('copyWithoutViewOptions', () {
+      final descriptorWithOptions = ExamplesLoadingDescriptor(
+        descriptors: const [
+          CatalogDefaultExampleLoadingDescriptor(
+            sdk: Sdk.go,
+            viewOptions: viewOptions,
+          ),
+        ],
+        initialSdk: Sdk.python,
+        lazyLoadDescriptors: {
+          Sdk.scio: const [
+            StandardExampleLoadingDescriptor(
+              sdk: Sdk.scio,
+              path: 'path',
+              viewOptions: viewOptions,
+            ),
+          ],
+        },
+      );
+
+      final expected = ExamplesLoadingDescriptor(
+        descriptors: const [_d1],
+        initialSdk: Sdk.python,
+        lazyLoadDescriptors: {
+          Sdk.scio: const [_d2],
+        },
+      );
+
+      expect(
+        descriptorWithOptions.copyWithoutViewOptions(),
+        expected,
+      );
+    });
   });
 }
 
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/http_example_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/http_example_loading_descriptor_test.dart
index db54d526702..783e3592d93 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/http_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/http_example_loading_descriptor_test.dart
@@ -26,6 +26,7 @@ void main() {
     final descriptor = HttpExampleLoadingDescriptor(
       sdk: Sdk.go,
       uri: Uri.parse('https://example.com'),
+      viewOptions: viewOptions,
     );
 
     test('toJson -> tryParse', () {
@@ -35,11 +36,14 @@ void main() {
       expect(parsed, descriptor);
     });
 
-    test('parses viewOptions', () {
-      final map = descriptor.toJson()..addAll(viewOptionsMap);
-      final parsed = HttpExampleLoadingDescriptor.tryParse(map);
-
-      expect(parsed?.viewOptions, viewOptions);
+    test('copyWithoutViewOptions', () {
+      expect(
+        descriptor.copyWithoutViewOptions(),
+        HttpExampleLoadingDescriptor(
+          sdk: descriptor.sdk,
+          uri: descriptor.uri,
+        ),
+      );
     });
   });
 }
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/standard_example_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/standard_example_loading_descriptor_test.dart
index 1da4b6ed1a8..256ce657e5c 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/standard_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/standard_example_loading_descriptor_test.dart
@@ -24,8 +24,9 @@ import 'common.dart';
 void main() {
   group('StandardExampleLoadingDescriptor', () {
     const descriptor = StandardExampleLoadingDescriptor(
-      sdk: Sdk.go,
       path: 'path',
+      sdk: Sdk.go,
+      viewOptions: viewOptions,
     );
 
     test('toJson -> tryParse', () {
@@ -35,11 +36,14 @@ void main() {
       expect(parsed, descriptor);
     });
 
-    test('parses viewOptions', () {
-      final map = descriptor.toJson()..addAll(viewOptionsMap);
-      final parsed = StandardExampleLoadingDescriptor.tryParse(map);
-
-      expect(parsed?.viewOptions, viewOptions);
+    test('copyWithoutViewOptions', () {
+      expect(
+        descriptor.copyWithoutViewOptions(),
+        StandardExampleLoadingDescriptor(
+          path: descriptor.path,
+          sdk: descriptor.sdk,
+        ),
+      );
     });
   });
 }
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/user_shared_example_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/user_shared_example_loading_descriptor_test.dart
index 49ed81d2939..9e0fa735c89 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/user_shared_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/user_shared_example_loading_descriptor_test.dart
@@ -26,6 +26,7 @@ void main() {
     const descriptor = UserSharedExampleLoadingDescriptor(
       sdk: Sdk.go,
       snippetId: 'snippetId',
+      viewOptions: viewOptions,
     );
 
     test('toJson -> tryParse', () {
@@ -35,11 +36,14 @@ void main() {
       expect(parsed, descriptor);
     });
 
-    test('parses viewOptions', () {
-      final map = descriptor.toJson()..addAll(viewOptionsMap);
-      final parsed = UserSharedExampleLoadingDescriptor.tryParse(map);
-
-      expect(parsed?.viewOptions, viewOptions);
+    test('copyWithoutViewOptions', () {
+      expect(
+        descriptor.copyWithoutViewOptions(),
+        UserSharedExampleLoadingDescriptor(
+          sdk: descriptor.sdk,
+          snippetId: descriptor.snippetId,
+        ),
+      );
     });
   });
 }
diff --git a/playground/frontend/playground_components/test/src/repositories/code_repository_test.mocks.dart b/playground/frontend/playground_components/test/src/repositories/code_repository_test.mocks.dart
index 78c1cdb8959..8963431373a 100644
--- a/playground/frontend/playground_components/test/src/repositories/code_repository_test.mocks.dart
+++ b/playground/frontend/playground_components/test/src/repositories/code_repository_test.mocks.dart
@@ -1,4 +1,4 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground_components/test/src/repositories/code_repository_test.dart.
 // Do not manually edit this file.
 
@@ -26,13 +26,40 @@ import 'package:playground_components/src/repositories/models/run_code_response.
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeRunCodeResponse_0 extends _i1.Fake implements _i2.RunCodeResponse {}
+class _FakeRunCodeResponse_0 extends _i1.SmartFake
+    implements _i2.RunCodeResponse {
+  _FakeRunCodeResponse_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeCheckStatusResponse_1 extends _i1.Fake
-    implements _i3.CheckStatusResponse {}
+class _FakeCheckStatusResponse_1 extends _i1.SmartFake
+    implements _i3.CheckStatusResponse {
+  _FakeCheckStatusResponse_1(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeOutputResponse_2 extends _i1.Fake implements _i4.OutputResponse {}
+class _FakeOutputResponse_2 extends _i1.SmartFake
+    implements _i4.OutputResponse {
+  _FakeOutputResponse_2(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [CodeClient].
 ///
@@ -50,7 +77,13 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           [request],
         ),
         returnValue:
-            Future<_i2.RunCodeResponse>.value(_FakeRunCodeResponse_0()),
+            _i6.Future<_i2.RunCodeResponse>.value(_FakeRunCodeResponse_0(
+          this,
+          Invocation.method(
+            #runCode,
+            [request],
+          ),
+        )),
       ) as _i6.Future<_i2.RunCodeResponse>);
   @override
   _i6.Future<void> cancelExecution(String? pipelineUuid) => (super.noSuchMethod(
@@ -58,8 +91,8 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #cancelExecution,
           [pipelineUuid],
         ),
-        returnValue: Future<void>.value(),
-        returnValueForMissingStub: Future<void>.value(),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
       ) as _i6.Future<void>);
   @override
   _i6.Future<_i3.CheckStatusResponse> checkStatus(String? pipelineUuid) =>
@@ -68,8 +101,14 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #checkStatus,
           [pipelineUuid],
         ),
-        returnValue:
-            Future<_i3.CheckStatusResponse>.value(_FakeCheckStatusResponse_1()),
+        returnValue: _i6.Future<_i3.CheckStatusResponse>.value(
+            _FakeCheckStatusResponse_1(
+          this,
+          Invocation.method(
+            #checkStatus,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i3.CheckStatusResponse>);
   @override
   _i6.Future<_i4.OutputResponse> getCompileOutput(String? pipelineUuid) =>
@@ -78,7 +117,13 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #getCompileOutput,
           [pipelineUuid],
         ),
-        returnValue: Future<_i4.OutputResponse>.value(_FakeOutputResponse_2()),
+        returnValue: _i6.Future<_i4.OutputResponse>.value(_FakeOutputResponse_2(
+          this,
+          Invocation.method(
+            #getCompileOutput,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i4.OutputResponse>);
   @override
   _i6.Future<_i4.OutputResponse> getRunOutput(String? pipelineUuid) =>
@@ -87,7 +132,13 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #getRunOutput,
           [pipelineUuid],
         ),
-        returnValue: Future<_i4.OutputResponse>.value(_FakeOutputResponse_2()),
+        returnValue: _i6.Future<_i4.OutputResponse>.value(_FakeOutputResponse_2(
+          this,
+          Invocation.method(
+            #getRunOutput,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i4.OutputResponse>);
   @override
   _i6.Future<_i4.OutputResponse> getLogOutput(String? pipelineUuid) =>
@@ -96,7 +147,13 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #getLogOutput,
           [pipelineUuid],
         ),
-        returnValue: Future<_i4.OutputResponse>.value(_FakeOutputResponse_2()),
+        returnValue: _i6.Future<_i4.OutputResponse>.value(_FakeOutputResponse_2(
+          this,
+          Invocation.method(
+            #getLogOutput,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i4.OutputResponse>);
   @override
   _i6.Future<_i4.OutputResponse> getRunErrorOutput(String? pipelineUuid) =>
@@ -105,7 +162,13 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #getRunErrorOutput,
           [pipelineUuid],
         ),
-        returnValue: Future<_i4.OutputResponse>.value(_FakeOutputResponse_2()),
+        returnValue: _i6.Future<_i4.OutputResponse>.value(_FakeOutputResponse_2(
+          this,
+          Invocation.method(
+            #getRunErrorOutput,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i4.OutputResponse>);
   @override
   _i6.Future<_i4.OutputResponse> getValidationErrorOutput(
@@ -115,7 +178,13 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #getValidationErrorOutput,
           [pipelineUuid],
         ),
-        returnValue: Future<_i4.OutputResponse>.value(_FakeOutputResponse_2()),
+        returnValue: _i6.Future<_i4.OutputResponse>.value(_FakeOutputResponse_2(
+          this,
+          Invocation.method(
+            #getValidationErrorOutput,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i4.OutputResponse>);
   @override
   _i6.Future<_i4.OutputResponse> getPreparationErrorOutput(
@@ -125,7 +194,13 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #getPreparationErrorOutput,
           [pipelineUuid],
         ),
-        returnValue: Future<_i4.OutputResponse>.value(_FakeOutputResponse_2()),
+        returnValue: _i6.Future<_i4.OutputResponse>.value(_FakeOutputResponse_2(
+          this,
+          Invocation.method(
+            #getPreparationErrorOutput,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i4.OutputResponse>);
   @override
   _i6.Future<_i4.OutputResponse> getGraphOutput(String? pipelineUuid) =>
@@ -134,6 +209,12 @@ class MockCodeClient extends _i1.Mock implements _i5.CodeClient {
           #getGraphOutput,
           [pipelineUuid],
         ),
-        returnValue: Future<_i4.OutputResponse>.value(_FakeOutputResponse_2()),
+        returnValue: _i6.Future<_i4.OutputResponse>.value(_FakeOutputResponse_2(
+          this,
+          Invocation.method(
+            #getGraphOutput,
+            [pipelineUuid],
+          ),
+        )),
       ) as _i6.Future<_i4.OutputResponse>);
 }
diff --git a/playground/frontend/playground_components/test/src/repositories/example_repository_test.mocks.dart b/playground/frontend/playground_components/test/src/repositories/example_repository_test.mocks.dart
index 30c1109f2bd..ab944a04c75 100644
--- a/playground/frontend/playground_components/test/src/repositories/example_repository_test.mocks.dart
+++ b/playground/frontend/playground_components/test/src/repositories/example_repository_test.mocks.dart
@@ -1,4 +1,4 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground_components/test/src/repositories/example_repository_test.dart.
 // Do not manually edit this file.
 
@@ -40,23 +40,73 @@ import 'package:playground_components/src/repositories/models/save_snippet_respo
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeGetPrecompiledObjectsResponse_0 extends _i1.Fake
-    implements _i2.GetPrecompiledObjectsResponse {}
+class _FakeGetPrecompiledObjectsResponse_0 extends _i1.SmartFake
+    implements _i2.GetPrecompiledObjectsResponse {
+  _FakeGetPrecompiledObjectsResponse_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeGetPrecompiledObjectCodeResponse_1 extends _i1.Fake
-    implements _i3.GetPrecompiledObjectCodeResponse {}
+class _FakeGetPrecompiledObjectCodeResponse_1 extends _i1.SmartFake
+    implements _i3.GetPrecompiledObjectCodeResponse {
+  _FakeGetPrecompiledObjectCodeResponse_1(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeGetPrecompiledObjectResponse_2 extends _i1.Fake
-    implements _i4.GetPrecompiledObjectResponse {}
+class _FakeGetPrecompiledObjectResponse_2 extends _i1.SmartFake
+    implements _i4.GetPrecompiledObjectResponse {
+  _FakeGetPrecompiledObjectResponse_2(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeOutputResponse_3 extends _i1.Fake implements _i5.OutputResponse {}
+class _FakeOutputResponse_3 extends _i1.SmartFake
+    implements _i5.OutputResponse {
+  _FakeOutputResponse_3(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeGetSnippetResponse_4 extends _i1.Fake
-    implements _i6.GetSnippetResponse {}
+class _FakeGetSnippetResponse_4 extends _i1.SmartFake
+    implements _i6.GetSnippetResponse {
+  _FakeGetSnippetResponse_4(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
-class _FakeSaveSnippetResponse_5 extends _i1.Fake
-    implements _i7.SaveSnippetResponse {}
+class _FakeSaveSnippetResponse_5 extends _i1.SmartFake
+    implements _i7.SaveSnippetResponse {
+  _FakeSaveSnippetResponse_5(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [ExampleClient].
 ///
@@ -74,8 +124,14 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #getPrecompiledObjects,
           [request],
         ),
-        returnValue: Future<_i2.GetPrecompiledObjectsResponse>.value(
-            _FakeGetPrecompiledObjectsResponse_0()),
+        returnValue: _i9.Future<_i2.GetPrecompiledObjectsResponse>.value(
+            _FakeGetPrecompiledObjectsResponse_0(
+          this,
+          Invocation.method(
+            #getPrecompiledObjects,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i2.GetPrecompiledObjectsResponse>);
   @override
   _i9.Future<_i3.GetPrecompiledObjectCodeResponse> getPrecompiledObjectCode(
@@ -85,8 +141,14 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #getPrecompiledObjectCode,
           [request],
         ),
-        returnValue: Future<_i3.GetPrecompiledObjectCodeResponse>.value(
-            _FakeGetPrecompiledObjectCodeResponse_1()),
+        returnValue: _i9.Future<_i3.GetPrecompiledObjectCodeResponse>.value(
+            _FakeGetPrecompiledObjectCodeResponse_1(
+          this,
+          Invocation.method(
+            #getPrecompiledObjectCode,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i3.GetPrecompiledObjectCodeResponse>);
   @override
   _i9.Future<_i4.GetPrecompiledObjectResponse> getDefaultPrecompiledObject(
@@ -96,8 +158,14 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #getDefaultPrecompiledObject,
           [request],
         ),
-        returnValue: Future<_i4.GetPrecompiledObjectResponse>.value(
-            _FakeGetPrecompiledObjectResponse_2()),
+        returnValue: _i9.Future<_i4.GetPrecompiledObjectResponse>.value(
+            _FakeGetPrecompiledObjectResponse_2(
+          this,
+          Invocation.method(
+            #getDefaultPrecompiledObject,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i4.GetPrecompiledObjectResponse>);
   @override
   _i9.Future<_i4.GetPrecompiledObjectResponse> getPrecompiledObject(
@@ -107,8 +175,14 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #getPrecompiledObject,
           [request],
         ),
-        returnValue: Future<_i4.GetPrecompiledObjectResponse>.value(
-            _FakeGetPrecompiledObjectResponse_2()),
+        returnValue: _i9.Future<_i4.GetPrecompiledObjectResponse>.value(
+            _FakeGetPrecompiledObjectResponse_2(
+          this,
+          Invocation.method(
+            #getPrecompiledObject,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i4.GetPrecompiledObjectResponse>);
   @override
   _i9.Future<_i5.OutputResponse> getPrecompiledObjectOutput(
@@ -118,7 +192,13 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #getPrecompiledObjectOutput,
           [request],
         ),
-        returnValue: Future<_i5.OutputResponse>.value(_FakeOutputResponse_3()),
+        returnValue: _i9.Future<_i5.OutputResponse>.value(_FakeOutputResponse_3(
+          this,
+          Invocation.method(
+            #getPrecompiledObjectOutput,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i5.OutputResponse>);
   @override
   _i9.Future<_i5.OutputResponse> getPrecompiledObjectLogs(
@@ -128,7 +208,13 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #getPrecompiledObjectLogs,
           [request],
         ),
-        returnValue: Future<_i5.OutputResponse>.value(_FakeOutputResponse_3()),
+        returnValue: _i9.Future<_i5.OutputResponse>.value(_FakeOutputResponse_3(
+          this,
+          Invocation.method(
+            #getPrecompiledObjectLogs,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i5.OutputResponse>);
   @override
   _i9.Future<_i5.OutputResponse> getPrecompiledObjectGraph(
@@ -138,7 +224,13 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #getPrecompiledObjectGraph,
           [request],
         ),
-        returnValue: Future<_i5.OutputResponse>.value(_FakeOutputResponse_3()),
+        returnValue: _i9.Future<_i5.OutputResponse>.value(_FakeOutputResponse_3(
+          this,
+          Invocation.method(
+            #getPrecompiledObjectGraph,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i5.OutputResponse>);
   @override
   _i9.Future<_i6.GetSnippetResponse> getSnippet(
@@ -149,7 +241,13 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           [request],
         ),
         returnValue:
-            Future<_i6.GetSnippetResponse>.value(_FakeGetSnippetResponse_4()),
+            _i9.Future<_i6.GetSnippetResponse>.value(_FakeGetSnippetResponse_4(
+          this,
+          Invocation.method(
+            #getSnippet,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i6.GetSnippetResponse>);
   @override
   _i9.Future<_i7.SaveSnippetResponse> saveSnippet(
@@ -159,7 +257,13 @@ class MockExampleClient extends _i1.Mock implements _i8.ExampleClient {
           #saveSnippet,
           [request],
         ),
-        returnValue:
-            Future<_i7.SaveSnippetResponse>.value(_FakeSaveSnippetResponse_5()),
+        returnValue: _i9.Future<_i7.SaveSnippetResponse>.value(
+            _FakeSaveSnippetResponse_5(
+          this,
+          Invocation.method(
+            #saveSnippet,
+            [request],
+          ),
+        )),
       ) as _i9.Future<_i7.SaveSnippetResponse>);
 }
diff --git a/playground/frontend/playground_components_dev/lib/playground_components_dev.dart b/playground/frontend/playground_components_dev/lib/playground_components_dev.dart
index 19a653be0ad..c37f6182c9d 100644
--- a/playground/frontend/playground_components_dev/lib/playground_components_dev.dart
+++ b/playground/frontend/playground_components_dev/lib/playground_components_dev.dart
@@ -17,10 +17,21 @@
  */
 
 export 'src/common_finders.dart';
-export 'src/example_names.dart';
-export 'src/example_outputs.dart';
-export 'src/example_paths.dart';
-export 'src/examples.dart';
+
+export 'src/examples/example_descriptor.dart';
+
+export 'src/examples/go/example.dart';
+export 'src/examples/go/minimal_word_count.dart';
+export 'src/examples/go/word_count.dart';
+
+export 'src/examples/java/aggregation_max.dart';
+export 'src/examples/java/minimal_word_count.dart';
+
+export 'src/examples/python/aggregation_mean.dart';
+export 'src/examples/python/word_count_with_metrics.dart';
+
+export 'src/examples/scio/minimal_word_count.dart';
+
 export 'src/expect.dart';
 export 'src/finder.dart';
 export 'src/string.dart';
diff --git a/playground/frontend/playground_components_dev/lib/src/code.dart b/playground/frontend/playground_components_dev/lib/src/code.dart
index 2f85ac9f029..82ce8d89e06 100644
--- a/playground/frontend/playground_components_dev/lib/src/code.dart
+++ b/playground/frontend/playground_components_dev/lib/src/code.dart
@@ -21,8 +21,9 @@ import 'package:highlight/highlight_core.dart';
 
 String foldLicenseAndImports(String text, Mode language) {
   final controller = CodeController(
-    text: text,
     language: language,
+    namedSectionParser: const BracketsStartEndNamedSectionParser(),
+    text: text,
   );
 
   controller.foldCommentAtLineZero();
diff --git a/playground/frontend/playground_components_dev/lib/src/examples.dart b/playground/frontend/playground_components_dev/lib/src/examples.dart
deleted file mode 100644
index c558133d742..00000000000
--- a/playground/frontend/playground_components_dev/lib/src/examples.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import 'package:highlight/highlight_core.dart';
-import 'package:http/http.dart' as http;
-
-import 'code.dart';
-
-class Examples {
-  static const _repoAndBranch = 'apache/beam/master';
-
-  static Future<String> getVisibleTextByPath(String path, Mode language) async {
-    final uri =
-        Uri.parse('https://raw.githubusercontent.com/$_repoAndBranch$path');
-    final response = await http.get(uri);
-    final content = response.body;
-
-    return foldLicenseAndImports(content, language);
-  }
-}
diff --git a/playground/frontend/playground_components_dev/lib/src/examples/example_descriptor.dart b/playground/frontend/playground_components_dev/lib/src/examples/example_descriptor.dart
new file mode 100644
index 00000000000..e1890760569
--- /dev/null
+++ b/playground/frontend/playground_components_dev/lib/src/examples/example_descriptor.dart
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ignore_for_file: prefer_interpolation_to_compose_strings
+
+import 'package:http/http.dart' as http;
+import 'package:playground_components/playground_components.dart';
+
+import '../code.dart';
+
+const _noGraphSdks = [Sdk.go, Sdk.scio];
+
+/// Describes an example for the purpose of integration tests.
+class ExampleDescriptor {
+  static const _schemaAndHost = 'https://raw.githubusercontent.com/';
+
+  // static const _defaultRepositoryAndRef = 'apache/beam/master';
+  // If running before this is deployed, change to this:
+  static const _defaultRepositoryAndRef =
+      'akvelon/beam/issue24959_test-loading-url';
+
+  const ExampleDescriptor(
+    this.name, {
+    required this.dbPath,
+    required this.path,
+    required this.sdk,
+    this.contextLine1Based,
+    this.croppedFoldedVisibleText,
+    this.foldedVisibleText,
+    this.outputContains,
+    this.outputTail,
+    this.repositoryAndRef = _defaultRepositoryAndRef,
+  });
+
+  /// 1-based line index to set cursor to.
+  final int? contextLine1Based;
+
+  /// A token to retrieve the example from server.
+  final String dbPath;
+
+  /// Name as shown in the dropdown.
+  final String name;
+
+  /// File path relative to the repository root, starting with `/`.
+  final String path;
+
+  /// The part in GitHub URL corresponding to repository and branch names.
+  final String repositoryAndRef;
+
+  /// The SDK of this example.
+  final Sdk sdk;
+
+  /// Visible text when using `visibleSectionNames` and `foldOutsideSections()`.
+  final String? croppedFoldedVisibleText;
+
+  /// Visible text when using `foldOutsideSections()`.
+  final String? foldedVisibleText;
+
+  /// The strings that the example's output must contain.
+  final List<String>? outputContains;
+
+  /// The string that the example's output must end with.
+  final String? outputTail;
+
+  /// Whether the example tab must be visible after running this example.
+  bool get hasGraphTab => !_noGraphSdks.contains(sdk);
+
+  /// The URL to view the file raw content on GitHub.
+  String get url => '$_schemaAndHost$repositoryAndRef$path';
+
+  /// The visible text in the code editor after required foldings.
+  Future<String> getVisibleText() async {
+    final content = await getFullText();
+
+    return foldLicenseAndImports(content, sdk.highlightMode!);
+  }
+
+  /// The full code of the example.
+  Future<String> getFullText() async {
+    final response = await http.get(Uri.parse(url));
+    return cutTagComments(response.body);
+  }
+
+  /// Cuts the comments containing meta tags from the file in the repository
+  /// so that it matches the source that must be provided by the backend.
+  static String cutTagComments(String code) {
+    const commentSequences = ['//', '#'];
+    const firstString = 'beam-playground:';
+
+    for (final commentSequence in commentSequences) {
+      final firstStringRe = RegExp(
+        '^' +
+            RegExp.escape(commentSequence) +
+            r'\s+' +
+            RegExp.escape(firstString) +
+            r'$',
+        multiLine: true,
+      );
+
+      final start = code.indexOf(firstStringRe);
+      if (start == -1) {
+        continue;
+      }
+
+      final lastStringRe = RegExp(r'^(\s)*$', multiLine: true);
+      final end = code.indexOf(lastStringRe, start);
+      if (end == -1) {
+        continue;
+      }
+
+      return code.substring(0, start) + code.substring(end);
+    }
+
+    return code;
+  }
+}
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart b/playground/frontend/playground_components_dev/lib/src/examples/go/content/example.go
similarity index 65%
copy from playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
copy to playground/frontend/playground_components_dev/lib/src/examples/go/content/example.go
index 4697fce0536..eb403bdfbe4 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/go/content/example.go
@@ -16,17 +16,27 @@
  * limitations under the License.
  */
 
-import 'package:equatable/equatable.dart';
+package main
 
-import '../example_view_options.dart';
+import (
+	"fmt"
+	"github.com/apache/beam/sdks/v2/go/pkg/beam"
+)
 
-/// Describes a single example to be loaded.
-abstract class ExampleLoadingDescriptor with EquatableMixin {
-  const ExampleLoadingDescriptor({
-    this.viewOptions = ExampleViewOptions.empty,
-  });
+func OutsideOfSections() {
+}
+
+// [START show]
+func Folded() {
+}
 
-  final ExampleViewOptions viewOptions;
+func Unfolded1() {
+	fmt.Print("editable")// [START unfold1]
+	fmt.Print("readonly")// [START readonly1] [END unfold1] [END readonly1]
+}
 
-  Map<String, dynamic> toJson();
+func Unfolded2() {
+	fmt.Print("editable")// [START unfold2]
+	fmt.Print("readonly")// [START readonly2] [END unfold2] [END readonly2]
 }
+// [END show]
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/http_example_loading_descriptor_test.dart b/playground/frontend/playground_components_dev/lib/src/examples/go/example.dart
similarity index 55%
copy from playground/frontend/playground_components/test/src/models/example_loading_descriptors/http_example_loading_descriptor_test.dart
copy to playground/frontend/playground_components_dev/lib/src/examples/go/example.dart
index db54d526702..3a910870a01 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/http_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/go/example.dart
@@ -16,30 +16,53 @@
  * limitations under the License.
  */
 
-import 'package:flutter_test/flutter_test.dart';
 import 'package:playground_components/playground_components.dart';
 
-import 'common.dart';
+import '../example_descriptor.dart';
 
-void main() {
-  group('HttpExampleLoadingDescriptor', () {
-    final descriptor = HttpExampleLoadingDescriptor(
-      sdk: Sdk.go,
-      uri: Uri.parse('https://example.com'),
-    );
+/// To test code folding, read-only, and visible sections. Not runnable.
+const goExample = ExampleDescriptor(
+  //
+  '',
+  dbPath: '',
+  path:
+      '/playground/frontend/playground_components_dev/lib/src/examples/go/content/example.go',
+  sdk: Sdk.go,
 
-    test('toJson -> tryParse', () {
-      final map = descriptor.toJson();
-      final parsed = HttpExampleLoadingDescriptor.tryParse(map);
+  croppedFoldedVisibleText: '''
 
-      expect(parsed, descriptor);
-    });
+func Folded() {
 
-    test('parses viewOptions', () {
-      final map = descriptor.toJson()..addAll(viewOptionsMap);
-      final parsed = HttpExampleLoadingDescriptor.tryParse(map);
+func Unfolded1() {
+  fmt.Print("editable")
+  fmt.Print("readonly")
+}
+
+func Unfolded2() {
+  fmt.Print("editable")
+  fmt.Print("readonly")
+}
+
+''',
+  foldedVisibleText: '''
+/*
+
+package main
 
-      expect(parsed?.viewOptions, viewOptions);
-    });
-  });
+func OutsideOfSections() {
+
+
+func Folded() {
+
+func Unfolded1() {
+  fmt.Print("editable")
+  fmt.Print("readonly")
 }
+
+func Unfolded2() {
+  fmt.Print("editable")
+  fmt.Print("readonly")
+}
+
+''',
+);
diff --git a/playground/frontend/playground_components_dev/lib/src/examples/go/minimal_word_count.dart b/playground/frontend/playground_components_dev/lib/src/examples/go/minimal_word_count.dart
new file mode 100644
index 00000000000..50a11e85926
--- /dev/null
+++ b/playground/frontend/playground_components_dev/lib/src/examples/go/minimal_word_count.dart
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'package:playground_components/playground_components.dart';
+
+import '../example_descriptor.dart';
+
+const goMinimalWordCount = ExampleDescriptor(
+  //
+  'MinimalWordCount',
+  contextLine1Based: 69,
+  dbPath: 'SDK_GO/PRECOMPILED_OBJECT_TYPE_EXAMPLE/MinimalWordCount',
+  path: '/sdks/go/examples/minimal_wordcount/minimal_wordcount.go',
+  sdk: Sdk.go,
+
+  outputContains: [
+    'Reading from gs://apache-beam-samples/shakespeare/kinglear.txt',
+    'Writing to wordcounts.txt',
+    '''
+Nodes: {1: []uint8/bytes GLO}
+{2: string/string GLO}
+{3: string/string GLO}
+{4: KV<string,int64>/KV<string,varint> GLO}
+{5: string/string GLO}
+{6: string/string GLO}
+{7: KV<string,int>/KV<string,int[varintz]> GLO}
+{8: CoGBK<string,int>/CoGBK<string,int[varintz]> GLO}
+{9: KV<string,int>/KV<string,int[varintz]> GLO}
+{10: string/string GLO}
+{11: KV<int,string>/KV<int[varintz],string> GLO}
+{12: CoGBK<int,string>/CoGBK<int[varintz],string> GLO}
+Edges: 1: Impulse [] -> [Out: []uint8 -> {1: []uint8/bytes GLO}]
+2: ParDo [In(Main): []uint8 <- {1: []uint8/bytes GLO}] -> [Out: T -> {2: string/string GLO}]
+3: ParDo [In(Main): string <- {2: string/string GLO}] -> [Out: string -> {3: string/string GLO}]
+4: ParDo [In(Main): string <- {3: string/string GLO}] -> [Out: KV<string,int64> -> {4: KV<string,int64>/KV<string,varint> GLO}]
+5: ParDo [In(Main): KV<string,int64> <- {4: KV<string,int64>/KV<string,varint> GLO}] -> [Out: string -> {5: string/string GLO}]
+6: ParDo [In(Main): string <- {5: string/string GLO}] -> [Out: string -> {6: string/string GLO}]
+7: ParDo [In(Main): T <- {6: string/string GLO}] -> [Out: KV<T,int> -> {7: KV<string,int>/KV<string,int[varintz]> GLO}]
+8: CoGBK [In(Main): KV<string,int> <- {7: KV<string,int>/KV<string,int[varintz]> GLO}] -> [Out: CoGBK<string,int> -> {8: CoGBK<string,int>/CoGBK<string,int[varintz]> GLO}]
+9: Combine [In(Main): int <- {8: CoGBK<string,int>/CoGBK<string,int[varintz]> GLO}] -> [Out: KV<string,int> -> {9: KV<string,int>/KV<string,int[varintz]> GLO}]
+10: ParDo [In(Main): KV<string,int> <- {9: KV<string,int>/KV<string,int[varintz]> GLO}] -> [Out: string -> {10: string/string GLO}]
+11: ParDo [In(Main): T <- {10: string/string GLO}] -> [Out: KV<int,T> -> {11: KV<int,string>/KV<int[varintz],string> GLO}]
+12: CoGBK [In(Main): KV<int,string> <- {11: KV<int,string>/KV<int[varintz],string> GLO}] -> [Out: CoGBK<int,string> -> {12: CoGBK<int,string>/CoGBK<int[varintz],string> GLO}]
+13: ParDo [In(Main): CoGBK<int,string> <- {12: CoGBK<int,string>/CoGBK<int[varintz],string> GLO}] -> []
+'''],
+);
diff --git a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart b/playground/frontend/playground_components_dev/lib/src/examples/go/word_count.dart
similarity index 73%
copy from playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
copy to playground/frontend/playground_components_dev/lib/src/examples/go/word_count.dart
index 3fbc31e4bba..da5dd09cbcd 100644
--- a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/go/word_count.dart
@@ -18,14 +18,11 @@
 
 import 'package:playground_components/playground_components.dart';
 
-/// An [ExampleLoadingDescriptor] to produce a blank URL when
-/// pushed to the address bar.
-class NoUrlExampleLoadingDescriptor extends ExampleLoadingDescriptor {
-  const NoUrlExampleLoadingDescriptor();
+import '../example_descriptor.dart';
 
-  @override
-  List<Object?> get props => const [];
-
-  @override
-  Map<String, dynamic> toJson() => {};
-}
+const goWordCount = ExampleDescriptor(
+  'WordCount',
+  dbPath: 'SDK_GO/PRECOMPILED_OBJECT_TYPE_EXAMPLE/WordCount',
+  path: '/sdks/go/examples/wordcount/wordcount.go',
+  sdk: Sdk.go,
+);
diff --git a/playground/frontend/playground_components_dev/lib/src/example_paths.dart b/playground/frontend/playground_components_dev/lib/src/examples/java/aggregation_max.dart
similarity index 68%
rename from playground/frontend/playground_components_dev/lib/src/example_paths.dart
rename to playground/frontend/playground_components_dev/lib/src/examples/java/aggregation_max.dart
index f0f554c7922..ecc3d532b63 100644
--- a/playground/frontend/playground_components_dev/lib/src/example_paths.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/java/aggregation_max.dart
@@ -16,14 +16,17 @@
  * limitations under the License.
  */
 
-class ExamplePaths {
-  static const javaAggregationMax =
-      '/learning/katas/java/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.java';
-  static const javaMinimalWordCount =
-      '/examples/java/src/main/java/org/apache/beam/examples/MinimalWordCount.java';
+import 'package:playground_components/playground_components.dart';
 
-  static const pythonAggregationMean =
-      '/learning/katas/python/Common Transforms/Aggregation/Mean/task.py';
-  static const pythonMinimalWordCountWithMetrics =
-      '/sdks/python/apache_beam/examples/wordcount_with_metrics.py';
-}
+import '../example_descriptor.dart';
+
+const javaAggregationMax = ExampleDescriptor(
+  //
+  'AggregationMax',
+  dbPath: 'SDK_JAVA/PRECOMPILED_OBJECT_TYPE_KATA/AggregationMax',
+  path:
+      '/learning/katas/java/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.java',
+  sdk: Sdk.java,
+
+  outputTail: 'INFO: 10\n',
+);
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart b/playground/frontend/playground_components_dev/lib/src/examples/java/minimal_word_count.dart
similarity index 70%
copy from playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
copy to playground/frontend/playground_components_dev/lib/src/examples/java/minimal_word_count.dart
index ab939bfbedd..6b651f0e7e1 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/java/minimal_word_count.dart
@@ -16,18 +16,18 @@
  * limitations under the License.
  */
 
-import 'package:flutter_test/flutter_test.dart';
 import 'package:playground_components/playground_components.dart';
 
-void main() {
-  group('EmptyExampleLoadingDescriptor', () {
-    const descriptor = EmptyExampleLoadingDescriptor(sdk: Sdk.go);
+import '../example_descriptor.dart';
 
-    test('toJson -> tryParse', () {
-      final map = descriptor.toJson();
-      final parsed = EmptyExampleLoadingDescriptor.tryParse(map);
+const javaMinimalWordCount = ExampleDescriptor(
+  //
+  'MinimalWordCount',
+  contextLine1Based: 71,
+  dbPath: 'SDK_JAVA/PRECOMPILED_OBJECT_TYPE_EXAMPLE/MinimalWordCount',
+  path:
+      '/examples/java/src/main/java/org/apache/beam/examples/MinimalWordCount.java',
+  sdk: Sdk.java,
 
-      expect(parsed, descriptor);
-    });
-  });
-}
+  outputContains: ['Finalizing for destination'],
+);
diff --git a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart b/playground/frontend/playground_components_dev/lib/src/examples/python/aggregation_mean.dart
similarity index 71%
copy from playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
copy to playground/frontend/playground_components_dev/lib/src/examples/python/aggregation_mean.dart
index 3fbc31e4bba..0f2c9d1cfb5 100644
--- a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/no_url_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/python/aggregation_mean.dart
@@ -18,14 +18,14 @@
 
 import 'package:playground_components/playground_components.dart';
 
-/// An [ExampleLoadingDescriptor] to produce a blank URL when
-/// pushed to the address bar.
-class NoUrlExampleLoadingDescriptor extends ExampleLoadingDescriptor {
-  const NoUrlExampleLoadingDescriptor();
+import '../example_descriptor.dart';
 
-  @override
-  List<Object?> get props => const [];
+const pythonAggregationMean = ExampleDescriptor(
+  //
+  'AggregationMean',
+  dbPath: 'SDK_PYTHON/PRECOMPILED_OBJECT_TYPE_KATA/AggregationMean',
+  path: '/learning/katas/python/Common Transforms/Aggregation/Mean/task.py',
+  sdk: Sdk.python,
 
-  @override
-  Map<String, dynamic> toJson() => {};
-}
+  outputContains: ['16 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]'],
+);
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart b/playground/frontend/playground_components_dev/lib/src/examples/python/word_count_with_metrics.dart
similarity index 70%
copy from playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
copy to playground/frontend/playground_components_dev/lib/src/examples/python/word_count_with_metrics.dart
index ab939bfbedd..e94ddb4ba59 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/python/word_count_with_metrics.dart
@@ -16,18 +16,17 @@
  * limitations under the License.
  */
 
-import 'package:flutter_test/flutter_test.dart';
 import 'package:playground_components/playground_components.dart';
 
-void main() {
-  group('EmptyExampleLoadingDescriptor', () {
-    const descriptor = EmptyExampleLoadingDescriptor(sdk: Sdk.go);
+import '../example_descriptor.dart';
 
-    test('toJson -> tryParse', () {
-      final map = descriptor.toJson();
-      final parsed = EmptyExampleLoadingDescriptor.tryParse(map);
+const pythonWordCountWithMetrics = ExampleDescriptor(
+  //
+  'WordCountWithMetrics',
+  contextLine1Based: 48,
+  dbPath: 'SDK_PYTHON/PRECOMPILED_OBJECT_TYPE_EXAMPLE/WordCountWithMetrics',
+  path: '/sdks/python/apache_beam/examples/wordcount_with_metrics.py',
+  sdk: Sdk.python,
 
-      expect(parsed, descriptor);
-    });
-  });
-}
+  outputContains: ['average word length: 4'],
+);
diff --git a/playground/frontend/playground_components_dev/lib/src/example_outputs.dart b/playground/frontend/playground_components_dev/lib/src/examples/scio/common.dart
similarity index 75%
rename from playground/frontend/playground_components_dev/lib/src/example_outputs.dart
rename to playground/frontend/playground_components_dev/lib/src/examples/scio/common.dart
index 5a548be683c..edafb443152 100644
--- a/playground/frontend/playground_components_dev/lib/src/example_outputs.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/scio/common.dart
@@ -16,11 +16,6 @@
  * limitations under the License.
  */
 
-class ExampleOutputs {
-  static const javaAggregationMaxTail = 'INFO: 10\n';
-
-  static const pythonAggregationMeanContains =
-      '16 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]';
-
-  static const pythonWordCountWithMetricsTail = 'average word length: 4\n';
-}
+/// Commit in spotify/scio at which deployed examples match GitHub.
+/// Must be hardcoded because we do not control the Spotify repository.
+const spotifyScioRef = '72423169818a25b0cf9321dc24660a1252890a54';
diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart b/playground/frontend/playground_components_dev/lib/src/examples/scio/minimal_word_count.dart
similarity index 67%
copy from playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
copy to playground/frontend/playground_components_dev/lib/src/examples/scio/minimal_word_count.dart
index ab939bfbedd..6fd03614c1c 100644
--- a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/empty_example_loading_descriptor_test.dart
+++ b/playground/frontend/playground_components_dev/lib/src/examples/scio/minimal_word_count.dart
@@ -16,18 +16,19 @@
  * limitations under the License.
  */
 
-import 'package:flutter_test/flutter_test.dart';
 import 'package:playground_components/playground_components.dart';
 
-void main() {
-  group('EmptyExampleLoadingDescriptor', () {
-    const descriptor = EmptyExampleLoadingDescriptor(sdk: Sdk.go);
+import '../example_descriptor.dart';
+import 'common.dart';
 
-    test('toJson -> tryParse', () {
-      final map = descriptor.toJson();
-      final parsed = EmptyExampleLoadingDescriptor.tryParse(map);
+const scioMinimalWordCount = ExampleDescriptor(
+  //
+  'MinimalWordCount',
+  dbPath: 'SDK_SCIO/PRECOMPILED_OBJECT_TYPE_EXAMPLE/MinimalWordCount',
+  path:
+      '/scio-examples/src/main/scala/com/spotify/scio/examples/MinimalWordCount.scala',
+  repositoryAndRef: 'spotify/scio/$spotifyScioRef',
+  sdk: Sdk.scio,
 
-      expect(parsed, descriptor);
-    });
-  });
-}
+  outputContains: ['Finalizing 5 file results'],
+);
diff --git a/playground/frontend/playground_components_dev/lib/src/expect.dart b/playground/frontend/playground_components_dev/lib/src/expect.dart
index 34e338dbec7..369fc675d9f 100644
--- a/playground/frontend/playground_components_dev/lib/src/expect.dart
+++ b/playground/frontend/playground_components_dev/lib/src/expect.dart
@@ -16,7 +16,10 @@
  * limitations under the License.
  */
 
+import 'dart:ui';
+
 import 'package:flutter_test/flutter_test.dart';
+import 'package:playground_components/playground_components.dart';
 
 import 'widget_tester.dart';
 
@@ -25,12 +28,46 @@ void expectOutput(String text, WidgetTester wt) {
   expect(actualText, text);
 }
 
-void expectOutputContains(String text, WidgetTester wt) {
+void expectOutputContains(String? text, WidgetTester wt) {
   final actualText = wt.findOutputText();
+  expect(text, isNotNull);
   expect(actualText, contains(text));
 }
 
-void expectOutputEndsWith(String text, WidgetTester wt) {
+void expectOutputEndsWith(String? text, WidgetTester wt) {
+  final actualText = wt.findOutputText();
+  expect(text, isNotNull);
+  expect(actualText, endsWith(text!));
+}
+
+void expectOutputStartsWith(String? text, WidgetTester wt) {
   final actualText = wt.findOutputText();
-  expect(actualText, endsWith(text));
+  expect(text, isNotNull);
+  expect(actualText, startsWith(text!));
+}
+
+void expectSdk(Sdk sdk, WidgetTester wt) {
+  final controller = wt.findPlaygroundController();
+  expect(controller.sdk, sdk);
+}
+
+void expectVisibleText(String? visibleText, WidgetTester wt) {
+  final controller = wt.findOneCodeController();
+  expect(visibleText, isNotNull);
+  expect(controller.text, visibleText);
+}
+
+void expectContextLine(int contextLine1Based, WidgetTester wt) {
+  final controller = wt.findOneCodeController();
+  final selection = controller.selection;
+  final position = controller.code.hiddenRanges.recoverPosition(
+    selection.baseOffset,
+    placeHiddenRanges: TextAffinity.downstream,
+  );
+
+  expect(selection.isCollapsed, true);
+  expect(
+    controller.code.lines.characterIndexToLineIndex(position),
+    contextLine1Based - 1,
+  );
 }
diff --git a/playground/frontend/playground_components_dev/lib/src/widget_tester.dart b/playground/frontend/playground_components_dev/lib/src/widget_tester.dart
index 6a833f0bcb8..c69574380b0 100644
--- a/playground/frontend/playground_components_dev/lib/src/widget_tester.dart
+++ b/playground/frontend/playground_components_dev/lib/src/widget_tester.dart
@@ -16,13 +16,16 @@
  * limitations under the License.
  */
 
+import 'package:app_state/app_state.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_code_editor/flutter_code_editor.dart';
 import 'package:flutter_test/flutter_test.dart';
+import 'package:get_it/get_it.dart';
 import 'package:playground_components/playground_components.dart';
 import 'package:provider/provider.dart';
 
 import 'common_finders.dart';
+import 'expect.dart';
 
 extension WidgetTesterExtension on WidgetTester {
   CodeController findOneCodeController() {
@@ -50,4 +53,52 @@ extension WidgetTesterExtension on WidgetTester {
     final context = element(find.codeField());
     return context.read<PlaygroundController>();
   }
+
+  /// Runs and expects that the execution is as fast as it should be for cache.
+  Future<void> runExpectCached() async {
+    final dateTimeStart = DateTime.now();
+
+    await tap(find.runOrCancelButton());
+    await pumpAndSettle();
+
+    expectOutputStartsWith(kCachedResultsLog, this);
+    expect(
+      DateTime.now().difference(dateTimeStart),
+      /// This is the safe threshold considering test delays.
+      lessThan(const Duration(milliseconds: 3000)),
+    );
+  }
+
+  /// Runs and expects that the execution is as fast as it should be for cache.
+  Future<void> runExpectReal() async {
+    await tap(find.runOrCancelButton());
+    await pumpAndSettle();
+
+    final actualText = findOutputText();
+    expect(actualText, isNot(startsWith(kCachedResultsLog)));
+  }
+
+  Future<void> navigateAndSettle(String urlString) async {
+    final url = Uri.parse(urlString);
+    print('Navigating: $url\n');
+    await _navigate(url);
+
+    // These appears to be the minimal reliable delay.
+    await Future.delayed(const Duration(seconds: 3));
+    await pumpAndSettle();
+  }
+
+  Future<void> _navigate(Uri uri) async {
+    final parser = GetIt.instance.get<PageStackRouteInformationParser>();
+    final path = await parser.parsePagePath(
+      RouteInformation(location: uri.toString()),
+    );
+
+    if (path == null) {
+      fail('Cannot parse $uri into PagePath');
+    }
+
+    final pageStack = GetIt.instance.get<PageStack>();
+    await pageStack.replacePath(path, mode: PageStackMatchMode.none);
+  }
 }
diff --git a/playground/frontend/playground_components_dev/pubspec.yaml b/playground/frontend/playground_components_dev/pubspec.yaml
index 0630dce0633..6064454b229 100644
--- a/playground/frontend/playground_components_dev/pubspec.yaml
+++ b/playground/frontend/playground_components_dev/pubspec.yaml
@@ -21,13 +21,15 @@ version: 0.0.1
 publish_to: none
 
 environment:
-  sdk: '>=2.18.1 <4.0.0'
-  flutter: '>=3.3.2'
+  sdk: '>=2.19.2 <4.0.0'
+  flutter: '>=3.7.3'
 
 dependencies:
+  app_state: ^0.9.0
   flutter: { sdk: flutter }
-  flutter_code_editor: ^0.2.5
+  flutter_code_editor: ^0.2.9
   flutter_test: { sdk: flutter }
+  get_it: ^7.2.0
   highlight: ^0.7.0
   http: ^0.13.5
   playground_components: { path: ../playground_components }
diff --git a/playground/frontend/pubspec.lock b/playground/frontend/pubspec.lock
index c5d387dc1ec..84e011cfcab 100644
--- a/playground/frontend/pubspec.lock
+++ b/playground/frontend/pubspec.lock
@@ -5,282 +5,386 @@ packages:
     dependency: transitive
     description:
       name: _fe_analyzer_shared
-      url: "https://pub.dartlang.org"
+      sha256: "0c80aeab9bc807ab10022cd3b2f4cf2ecdf231949dc1ddd9442406a003f19201"
+      url: "https://pub.dev"
     source: hosted
-    version: "40.0.0"
+    version: "52.0.0"
   akvelon_flutter_issue_106664_workaround:
     dependency: "direct main"
     description:
       name: akvelon_flutter_issue_106664_workaround
-      url: "https://pub.dartlang.org"
+      sha256: "1b8e38a65afa6058bc365b5e1762786a1e7618f549f1ea6215151d8d3b346207"
+      url: "https://pub.dev"
     source: hosted
     version: "0.1.2"
   aligned_dialog:
     dependency: "direct main"
     description:
       name: aligned_dialog
-      url: "https://pub.dartlang.org"
+      sha256: c6ce4f82a5ab35dde2c48caa436eab4da9d6a4238802f67312c878394caf055d
+      url: "https://pub.dev"
     source: hosted
     version: "0.0.6"
   analyzer:
     dependency: transitive
     description:
       name: analyzer
-      url: "https://pub.dartlang.org"
+      sha256: cd8ee83568a77f3ae6b913a36093a1c9b1264e7cb7f834d9ddd2311dade9c1f4
+      url: "https://pub.dev"
     source: hosted
-    version: "4.1.0"
+    version: "5.4.0"
   app_state:
     dependency: "direct main"
     description:
       name: app_state
-      url: "https://pub.dartlang.org"
+      sha256: "1024c48f723b02e726976143361020bf44b4a351bc2180c77764ac7aa191356c"
+      url: "https://pub.dev"
     source: hosted
-    version: "0.8.4"
+    version: "0.9.1"
   archive:
     dependency: transitive
     description:
       name: archive
-      url: "https://pub.dartlang.org"
+      sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb"
+      url: "https://pub.dev"
     source: hosted
-    version: "3.3.0"
+    version: "3.3.2"
   args:
     dependency: transitive
     description:
       name: args
-      url: "https://pub.dartlang.org"
+      sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.3.1"
+    version: "2.4.0"
   async:
     dependency: transitive
     description:
       name: async
-      url: "https://pub.dartlang.org"
+      sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
+      url: "https://pub.dev"
     source: hosted
-    version: "2.9.0"
+    version: "2.10.0"
   autotrie:
     dependency: transitive
     description:
       name: autotrie
-      url: "https://pub.dartlang.org"
+      sha256: "55da6faefb53cfcb0abb2f2ca8636123fb40e35286bb57440d2cf467568188f8"
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.0"
   boolean_selector:
     dependency: transitive
     description:
       name: boolean_selector
-      url: "https://pub.dartlang.org"
+      sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.0"
+    version: "2.1.1"
   build:
     dependency: transitive
     description:
       name: build
-      url: "https://pub.dartlang.org"
+      sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.3.0"
+    version: "2.3.1"
   build_config:
     dependency: transitive
     description:
       name: build_config
-      url: "https://pub.dartlang.org"
+      sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.0"
+    version: "1.1.1"
   build_daemon:
     dependency: transitive
     description:
       name: build_daemon
-      url: "https://pub.dartlang.org"
+      sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf"
+      url: "https://pub.dev"
     source: hosted
     version: "3.1.0"
   build_resolvers:
     dependency: transitive
     description:
       name: build_resolvers
-      url: "https://pub.dartlang.org"
+      sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.9"
+    version: "2.1.0"
   build_runner:
     dependency: "direct dev"
     description:
       name: build_runner
-      url: "https://pub.dartlang.org"
+      sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.11"
+    version: "2.3.3"
   build_runner_core:
     dependency: transitive
     description:
       name: build_runner_core
-      url: "https://pub.dartlang.org"
+      sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292"
+      url: "https://pub.dev"
     source: hosted
-    version: "7.2.3"
+    version: "7.2.7"
   built_collection:
     dependency: transitive
     description:
       name: built_collection
-      url: "https://pub.dartlang.org"
+      sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
+      url: "https://pub.dev"
     source: hosted
     version: "5.1.1"
   built_value:
     dependency: transitive
     description:
       name: built_value
-      url: "https://pub.dartlang.org"
+      sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725"
+      url: "https://pub.dev"
     source: hosted
-    version: "8.3.2"
+    version: "8.4.3"
   characters:
     dependency: transitive
     description:
       name: characters
-      url: "https://pub.dartlang.org"
+      sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
+      url: "https://pub.dev"
     source: hosted
     version: "1.2.1"
   charcode:
     dependency: transitive
     description:
       name: charcode
-      url: "https://pub.dartlang.org"
+      sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
+      url: "https://pub.dev"
     source: hosted
     version: "1.3.1"
   checked_yaml:
     dependency: transitive
     description:
       name: checked_yaml
-      url: "https://pub.dartlang.org"
+      sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.1"
+    version: "2.0.2"
   clock:
     dependency: transitive
     description:
       name: clock
-      url: "https://pub.dartlang.org"
+      sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+      url: "https://pub.dev"
     source: hosted
     version: "1.1.1"
   code_builder:
     dependency: transitive
     description:
       name: code_builder
-      url: "https://pub.dartlang.org"
+      sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe"
+      url: "https://pub.dev"
     source: hosted
-    version: "4.1.0"
+    version: "4.4.0"
   collection:
     dependency: "direct main"
     description:
       name: collection
-      url: "https://pub.dartlang.org"
+      sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.17.0"
+  connectivity_plus:
+    dependency: transitive
+    description:
+      name: connectivity_plus
+      sha256: "3f8fe4e504c2d33696dac671a54909743bc6a902a9bb0902306f7a2aed7e528e"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.3.9"
+  connectivity_plus_linux:
+    dependency: transitive
+    description:
+      name: connectivity_plus_linux
+      sha256: "3caf859d001f10407b8e48134c761483e4495ae38094ffcca97193f6c271f5e2"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.3.1"
+  connectivity_plus_macos:
+    dependency: transitive
+    description:
+      name: connectivity_plus_macos
+      sha256: "488d2de1e47e1224ad486e501b20b088686ba1f4ee9c4420ecbc3b9824f0b920"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.16.0"
+    version: "1.2.6"
+  connectivity_plus_platform_interface:
+    dependency: transitive
+    description:
+      name: connectivity_plus_platform_interface
+      sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.4"
+  connectivity_plus_web:
+    dependency: transitive
+    description:
+      name: connectivity_plus_web
+      sha256: "81332be1b4baf8898fed17bb4fdef27abb7c6fd990bf98c54fd978478adf2f1a"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.5"
+  connectivity_plus_windows:
+    dependency: transitive
+    description:
+      name: connectivity_plus_windows
+      sha256: "535b0404b4d5605c4dd8453d67e5d6d2ea0dd36e3b477f50f31af51b0aeab9dd"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.2"
   convert:
     dependency: transitive
     description:
       name: convert
-      url: "https://pub.dartlang.org"
+      sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
+      url: "https://pub.dev"
     source: hosted
-    version: "3.0.2"
+    version: "3.1.1"
+  coverage:
+    dependency: transitive
+    description:
+      name: coverage
+      sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.6.3"
   crypto:
     dependency: transitive
     description:
       name: crypto
-      url: "https://pub.dartlang.org"
+      sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
+      url: "https://pub.dev"
     source: hosted
     version: "3.0.2"
   csslib:
     dependency: transitive
     description:
       name: csslib
-      url: "https://pub.dartlang.org"
+      sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745
+      url: "https://pub.dev"
     source: hosted
     version: "0.17.2"
   csv:
     dependency: transitive
     description:
       name: csv
-      url: "https://pub.dartlang.org"
+      sha256: "18aef53ab72181a0b5384562d18c8cbd57e941e24cb8e54eb41409d3d8abdc6d"
+      url: "https://pub.dev"
     source: hosted
     version: "5.0.1"
   dart_style:
     dependency: transitive
     description:
       name: dart_style
-      url: "https://pub.dartlang.org"
+      sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.2.3"
+    version: "2.2.4"
+  dbus:
+    dependency: transitive
+    description:
+      name: dbus
+      sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.7.8"
   easy_localization:
     dependency: "direct main"
     description:
       name: easy_localization
-      url: "https://pub.dartlang.org"
+      sha256: "6a2e99fa0bfe5765bf4c6ca9b137d5de2c75593007178c5e4cd2ae985f870080"
+      url: "https://pub.dev"
     source: hosted
     version: "3.0.1"
   easy_localization_ext:
     dependency: "direct main"
     description:
       name: easy_localization_ext
-      url: "https://pub.dartlang.org"
+      sha256: "7a5ff2595436141f2e4873b69576ff33034fe23fef252fa592b2575be3fba33a"
+      url: "https://pub.dev"
     source: hosted
     version: "0.1.1"
   easy_localization_loader:
     dependency: "direct main"
     description:
       name: easy_localization_loader
-      url: "https://pub.dartlang.org"
+      sha256: "89e70b2516123d639e8e68b8dd08fc07c8b83b0cfee17c642165e7e8807ebc86"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.0"
+    version: "1.0.1+1"
   easy_logger:
     dependency: transitive
     description:
       name: easy_logger
-      url: "https://pub.dartlang.org"
+      sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7
+      url: "https://pub.dev"
     source: hosted
     version: "0.0.2"
   enum_map:
     dependency: transitive
     description:
       name: enum_map
-      url: "https://pub.dartlang.org"
+      sha256: "0dfe18306d2e9b0e9d381f5e11aac4c8255d5f5eddc68b0ab037f7d00aa36126"
+      url: "https://pub.dev"
     source: hosted
     version: "0.2.1"
   equatable:
     dependency: "direct main"
     description:
       name: equatable
-      url: "https://pub.dartlang.org"
+      sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.5"
   expansion_widget:
     dependency: "direct main"
     description:
       name: expansion_widget
-      url: "https://pub.dartlang.org"
+      sha256: c1ab07f475c6a5381e6f068de1d6a8e6e736a07a664787267503c1cd085844f7
+      url: "https://pub.dev"
     source: hosted
     version: "0.0.3"
   fake_async:
     dependency: "direct dev"
     description:
       name: fake_async
-      url: "https://pub.dartlang.org"
+      sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+      url: "https://pub.dev"
     source: hosted
     version: "1.3.1"
   ffi:
     dependency: transitive
     description:
       name: ffi
-      url: "https://pub.dartlang.org"
+      sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.0"
+    version: "2.0.1"
   file:
     dependency: transitive
     description:
       name: file
-      url: "https://pub.dartlang.org"
+      sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+      url: "https://pub.dev"
     source: hosted
-    version: "6.1.2"
+    version: "6.1.4"
   fixnum:
     dependency: transitive
     description:
       name: fixnum
-      url: "https://pub.dartlang.org"
+      sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.1"
+    version: "1.1.0"
   flutter:
     dependency: "direct main"
     description: flutter
@@ -290,9 +394,10 @@ packages:
     dependency: "direct dev"
     description:
       name: flutter_code_editor
-      url: "https://pub.dartlang.org"
+      sha256: a5d46c1740709997bbf6c2d21168b54db2a521606cbec7b1a01b79339ad4359e
+      url: "https://pub.dev"
     source: hosted
-    version: "0.2.5"
+    version: "0.2.10"
   flutter_driver:
     dependency: transitive
     description: flutter
@@ -302,21 +407,24 @@ packages:
     dependency: transitive
     description:
       name: flutter_highlight
-      url: "https://pub.dartlang.org"
+      sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c"
+      url: "https://pub.dev"
     source: hosted
     version: "0.7.0"
   flutter_issue_108697_workaround:
     dependency: transitive
     description:
       name: flutter_issue_108697_workaround
-      url: "https://pub.dartlang.org"
+      sha256: "71401a9196e1e8ed7a6463b8ab8ea6bf8d8cc719783c4be309553d64d8c353ec"
+      url: "https://pub.dev"
     source: hosted
     version: "0.1.2"
   flutter_lints:
     dependency: "direct dev"
     description:
       name: flutter_lints
-      url: "https://pub.dartlang.org"
+      sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.1"
   flutter_localizations:
@@ -328,16 +436,18 @@ packages:
     dependency: transitive
     description:
       name: flutter_markdown
-      url: "https://pub.dartlang.org"
+      sha256: "7b25c10de1fea883f3c4f9b8389506b54053cd00807beab69fd65c8653a2711f"
+      url: "https://pub.dev"
     source: hosted
-    version: "0.6.12"
+    version: "0.6.14"
   flutter_svg:
     dependency: "direct main"
     description:
       name: flutter_svg
-      url: "https://pub.dartlang.org"
+      sha256: f999d84ad2efda1c4c3956e7968b713b3a24b06f0a0e4798e844e16bbb9bb70b
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.3"
+    version: "2.0.0+1"
   flutter_test:
     dependency: "direct dev"
     description: flutter
@@ -352,16 +462,18 @@ packages:
     dependency: transitive
     description:
       name: fluttertoast
-      url: "https://pub.dartlang.org"
+      sha256: "774fa28b07f3a82c93596bc137be33189fec578ed3447a93a5a11c93435de394"
+      url: "https://pub.dev"
     source: hosted
-    version: "8.1.1"
+    version: "8.1.3"
   frontend_server_client:
     dependency: transitive
     description:
       name: frontend_server_client
-      url: "https://pub.dartlang.org"
+      sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.3"
+    version: "3.2.0"
   fuchsia_remote_debug_protocol:
     dependency: transitive
     description: flutter
@@ -371,93 +483,106 @@ packages:
     dependency: "direct main"
     description:
       name: get_it
-      url: "https://pub.dartlang.org"
+      sha256: "290fde3a86072e4b37dbb03c07bec6126f0ecc28dad403c12ffe2e5a2d751ab7"
+      url: "https://pub.dev"
     source: hosted
     version: "7.2.0"
   glob:
     dependency: transitive
     description:
       name: glob
-      url: "https://pub.dartlang.org"
+      sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.2"
+    version: "2.1.1"
   google_fonts:
     dependency: "direct main"
     description:
       name: google_fonts
-      url: "https://pub.dartlang.org"
+      sha256: "927573f2e8a8d65c17931e21918ad0ab0666b1b636537de7c4932bdb487b190f"
+      url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "4.0.3"
   googleapis_auth:
     dependency: transitive
     description:
       name: googleapis_auth
-      url: "https://pub.dartlang.org"
+      sha256: "127b1bbd32170ab8312f503bd57f1d654d8e4039ddfbc63c027d3f7ade0eff74"
+      url: "https://pub.dev"
     source: hosted
     version: "1.3.1"
   graphs:
     dependency: transitive
     description:
       name: graphs
-      url: "https://pub.dartlang.org"
+      sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.0"
+    version: "2.2.0"
   grpc:
     dependency: transitive
     description:
       name: grpc
-      url: "https://pub.dartlang.org"
+      sha256: a73c16e4f6a4a819be892bb2c73cc1d0b00e36095f69b0738cc91a733e3d27ba
+      url: "https://pub.dev"
     source: hosted
-    version: "3.0.2"
+    version: "3.1.0"
   highlight:
     dependency: "direct main"
     description:
       name: highlight
-      url: "https://pub.dartlang.org"
+      sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21"
+      url: "https://pub.dev"
     source: hosted
     version: "0.7.0"
   hive:
     dependency: transitive
     description:
       name: hive
-      url: "https://pub.dartlang.org"
+      sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
+      url: "https://pub.dev"
     source: hosted
     version: "2.2.3"
   html:
     dependency: transitive
     description:
       name: html
-      url: "https://pub.dartlang.org"
+      sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269
+      url: "https://pub.dev"
     source: hosted
-    version: "0.15.0"
+    version: "0.15.1"
   http:
     dependency: transitive
     description:
       name: http
-      url: "https://pub.dartlang.org"
+      sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482"
+      url: "https://pub.dev"
     source: hosted
     version: "0.13.5"
   http2:
     dependency: transitive
     description:
       name: http2
-      url: "https://pub.dartlang.org"
+      sha256: "58805ebc6513eed3b98ee0a455a8357e61d187bf2e0fdc1e53120770f78de258"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.0"
+    version: "2.0.1"
   http_multi_server:
     dependency: transitive
     description:
       name: http_multi_server
-      url: "https://pub.dartlang.org"
+      sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
+      url: "https://pub.dev"
     source: hosted
-    version: "3.2.0"
+    version: "3.2.1"
   http_parser:
     dependency: transitive
     description:
       name: http_parser
-      url: "https://pub.dartlang.org"
+      sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+      url: "https://pub.dev"
     source: hosted
-    version: "4.0.1"
+    version: "4.0.2"
   integration_test:
     dependency: "direct dev"
     description: flutter
@@ -467,203 +592,240 @@ packages:
     dependency: "direct main"
     description:
       name: intl
-      url: "https://pub.dartlang.org"
+      sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
+      url: "https://pub.dev"
     source: hosted
     version: "0.17.0"
   io:
     dependency: transitive
     description:
       name: io
-      url: "https://pub.dartlang.org"
+      sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.3"
+    version: "1.0.4"
   js:
     dependency: transitive
     description:
       name: js
-      url: "https://pub.dartlang.org"
+      sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
+      url: "https://pub.dev"
     source: hosted
-    version: "0.6.4"
+    version: "0.6.5"
   json_annotation:
     dependency: transitive
     description:
       name: json_annotation
-      url: "https://pub.dartlang.org"
+      sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317
+      url: "https://pub.dev"
     source: hosted
-    version: "4.7.0"
+    version: "4.8.0"
   keyed_collection_widgets:
     dependency: transitive
     description:
       name: keyed_collection_widgets
-      url: "https://pub.dartlang.org"
+      sha256: "9db2df4c4897c35fe167bdca82d307d81baa4161c3118da3f06ab4fd2d75291b"
+      url: "https://pub.dev"
     source: hosted
     version: "0.4.3"
   linked_scroll_controller:
     dependency: transitive
     description:
       name: linked_scroll_controller
-      url: "https://pub.dartlang.org"
+      sha256: e6020062bcf4ffc907ee7fd090fa971e65d8dfaac3c62baf601a3ced0b37986a
+      url: "https://pub.dev"
     source: hosted
     version: "0.2.0"
   lints:
     dependency: transitive
     description:
       name: lints
-      url: "https://pub.dartlang.org"
+      sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.0"
+    version: "2.0.1"
   logging:
     dependency: transitive
     description:
       name: logging
-      url: "https://pub.dartlang.org"
+      sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.2"
+    version: "1.1.1"
   markdown:
     dependency: transitive
     description:
       name: markdown
-      url: "https://pub.dartlang.org"
+      sha256: "4ed544d2ce84975b2ab5cbd4268f2d31f47858553ae2295c92fdf5d6e431a927"
+      url: "https://pub.dev"
     source: hosted
-    version: "6.0.1"
+    version: "7.0.0"
   matcher:
     dependency: transitive
     description:
       name: matcher
-      url: "https://pub.dartlang.org"
+      sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
+      url: "https://pub.dev"
     source: hosted
-    version: "0.12.12"
+    version: "0.12.13"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      url: "https://pub.dartlang.org"
+      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      url: "https://pub.dev"
     source: hosted
-    version: "0.1.5"
+    version: "0.2.0"
   meta:
     dependency: transitive
     description:
       name: meta
-      url: "https://pub.dartlang.org"
+      sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
+      url: "https://pub.dev"
     source: hosted
     version: "1.8.0"
   mime:
     dependency: transitive
     description:
       name: mime
-      url: "https://pub.dartlang.org"
+      sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.2"
+    version: "1.0.4"
   mockito:
     dependency: "direct dev"
     description:
       name: mockito
-      url: "https://pub.dartlang.org"
+      sha256: "2a8a17b82b1bde04d514e75d90d634a0ac23f6cb4991f6098009dd56836aeafe"
+      url: "https://pub.dev"
     source: hosted
-    version: "5.2.0"
+    version: "5.3.2"
+  mocktail:
+    dependency: transitive
+    description:
+      name: mocktail
+      sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.3.0"
   nested:
     dependency: transitive
     description:
       name: nested
-      url: "https://pub.dartlang.org"
+      sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
+      url: "https://pub.dev"
     source: hosted
     version: "1.0.0"
+  nm:
+    dependency: transitive
+    description:
+      name: nm
+      sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.5.0"
+  node_preamble:
+    dependency: transitive
+    description:
+      name: node_preamble
+      sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.1"
   onmessage:
     dependency: "direct main"
     description:
       name: onmessage
-      url: "https://pub.dartlang.org"
+      sha256: "262fee2df9a3cf361446ad743cb556ebf0552c2ae5c1220a041a781346f8a1a9"
+      url: "https://pub.dev"
     source: hosted
     version: "0.2.0"
   package_config:
     dependency: transitive
     description:
       name: package_config
-      url: "https://pub.dartlang.org"
+      sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.2"
+    version: "2.1.0"
   path:
     dependency: transitive
     description:
       name: path
-      url: "https://pub.dartlang.org"
+      sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
+      url: "https://pub.dev"
     source: hosted
     version: "1.8.2"
-  path_drawing:
-    dependency: transitive
-    description:
-      name: path_drawing
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.1"
   path_parsing:
     dependency: transitive
     description:
       name: path_parsing
-      url: "https://pub.dartlang.org"
+      sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
+      url: "https://pub.dev"
     source: hosted
     version: "1.0.1"
   path_provider:
     dependency: transitive
     description:
       name: path_provider
-      url: "https://pub.dartlang.org"
+      sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.10"
+    version: "2.0.12"
   path_provider_android:
     dependency: transitive
     description:
       name: path_provider_android
-      url: "https://pub.dartlang.org"
+      sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.14"
-  path_provider_ios:
+    version: "2.0.22"
+  path_provider_foundation:
     dependency: transitive
     description:
-      name: path_provider_ios
-      url: "https://pub.dartlang.org"
+      name: path_provider_foundation
+      sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.9"
+    version: "2.1.1"
   path_provider_linux:
     dependency: transitive
     description:
       name: path_provider_linux
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.1.7"
-  path_provider_macos:
-    dependency: transitive
-    description:
-      name: path_provider_macos
-      url: "https://pub.dartlang.org"
+      sha256: "2e32f1640f07caef0d3cb993680f181c79e54a3827b997d5ee221490d131fbd9"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.6"
+    version: "2.1.8"
   path_provider_platform_interface:
     dependency: transitive
     description:
       name: path_provider_platform_interface
-      url: "https://pub.dartlang.org"
+      sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.4"
+    version: "2.0.5"
   path_provider_windows:
     dependency: transitive
     description:
       name: path_provider_windows
-      url: "https://pub.dartlang.org"
+      sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.0"
+    version: "2.1.3"
   petitparser:
     dependency: transitive
     description:
       name: petitparser
-      url: "https://pub.dartlang.org"
+      sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4"
+      url: "https://pub.dev"
     source: hosted
-    version: "5.0.0"
+    version: "5.1.0"
   platform:
     dependency: transitive
     description:
       name: platform
-      url: "https://pub.dartlang.org"
+      sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+      url: "https://pub.dev"
     source: hosted
     version: "3.1.0"
   playground_components:
@@ -684,135 +846,162 @@ packages:
     dependency: transitive
     description:
       name: plugin_platform_interface
-      url: "https://pub.dartlang.org"
+      sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.3"
   pool:
     dependency: transitive
     description:
       name: pool
-      url: "https://pub.dartlang.org"
+      sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.5.0"
+    version: "1.5.1"
   process:
     dependency: transitive
     description:
       name: process
-      url: "https://pub.dartlang.org"
+      sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
+      url: "https://pub.dev"
     source: hosted
     version: "4.2.4"
   protobuf:
     dependency: transitive
     description:
       name: protobuf
-      url: "https://pub.dartlang.org"
+      sha256: "01dd9bd0fa02548bf2ceee13545d4a0ec6046459d847b6b061d8a27237108a08"
+      url: "https://pub.dev"
     source: hosted
     version: "2.1.0"
   provider:
     dependency: "direct main"
     description:
       name: provider
-      url: "https://pub.dartlang.org"
+      sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
+      url: "https://pub.dev"
     source: hosted
-    version: "6.0.3"
+    version: "6.0.5"
   pub_semver:
     dependency: transitive
     description:
       name: pub_semver
-      url: "https://pub.dartlang.org"
+      sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.1"
+    version: "2.1.3"
   pubspec_parse:
     dependency: transitive
     description:
       name: pubspec_parse
-      url: "https://pub.dartlang.org"
+      sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   rxdart:
     dependency: transitive
     description:
       name: rxdart
-      url: "https://pub.dartlang.org"
+      sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
+      url: "https://pub.dev"
     source: hosted
     version: "0.27.7"
   scrollable_positioned_list:
     dependency: transitive
     description:
       name: scrollable_positioned_list
-      url: "https://pub.dartlang.org"
+      sha256: ca7fcaa743db712d4f7b1580526f494d0093c77a721a65705ee51fbeac7a2bd3
+      url: "https://pub.dev"
     source: hosted
     version: "0.3.5"
   shared_preferences:
     dependency: "direct main"
     description:
       name: shared_preferences
-      url: "https://pub.dartlang.org"
+      sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.15"
+    version: "2.0.17"
   shared_preferences_android:
     dependency: transitive
     description:
       name: shared_preferences_android
-      url: "https://pub.dartlang.org"
+      sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.12"
-  shared_preferences_ios:
+    version: "2.0.15"
+  shared_preferences_foundation:
     dependency: transitive
     description:
-      name: shared_preferences_ios
-      url: "https://pub.dartlang.org"
+      name: shared_preferences_foundation
+      sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.1"
+    version: "2.1.3"
   shared_preferences_linux:
     dependency: transitive
     description:
       name: shared_preferences_linux
-      url: "https://pub.dartlang.org"
+      sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.1"
-  shared_preferences_macos:
-    dependency: transitive
-    description:
-      name: shared_preferences_macos
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.4"
+    version: "2.1.3"
   shared_preferences_platform_interface:
     dependency: transitive
     description:
       name: shared_preferences_platform_interface
-      url: "https://pub.dartlang.org"
+      sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.0"
+    version: "2.1.0"
   shared_preferences_web:
     dependency: transitive
     description:
       name: shared_preferences_web
-      url: "https://pub.dartlang.org"
+      sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.4"
   shared_preferences_windows:
     dependency: transitive
     description:
       name: shared_preferences_windows
-      url: "https://pub.dartlang.org"
+      sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.1"
+    version: "2.1.3"
   shelf:
     dependency: transitive
     description:
       name: shelf
-      url: "https://pub.dartlang.org"
+      sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.4.0"
+  shelf_packages_handler:
+    dependency: transitive
+    description:
+      name: shelf_packages_handler
+      sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306
+      url: "https://pub.dev"
     source: hosted
-    version: "1.3.0"
+    version: "3.0.1"
+  shelf_static:
+    dependency: transitive
+    description:
+      name: shelf_static
+      sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.1"
   shelf_web_socket:
     dependency: transitive
     description:
       name: shelf_web_socket
-      url: "https://pub.dartlang.org"
+      sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.1"
+    version: "1.0.3"
   sky_engine:
     dependency: transitive
     description: flutter
@@ -822,247 +1011,346 @@ packages:
     dependency: transitive
     description:
       name: source_gen
-      url: "https://pub.dartlang.org"
+      sha256: c2bea18c95cfa0276a366270afaa2850b09b4a76db95d546f3d003dcc7011298
+      url: "https://pub.dev"
     source: hosted
-    version: "1.2.2"
+    version: "1.2.7"
+  source_map_stack_trace:
+    dependency: transitive
+    description:
+      name: source_map_stack_trace
+      sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
+  source_maps:
+    dependency: transitive
+    description:
+      name: source_maps
+      sha256: "490098075234dcedb83c5d949b4c93dad5e6b7702748de000be2b57b8e6b2427"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.10.11"
   source_span:
     dependency: transitive
     description:
       name: source_span
-      url: "https://pub.dartlang.org"
+      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      url: "https://pub.dev"
     source: hosted
-    version: "1.9.0"
+    version: "1.9.1"
   stack_trace:
     dependency: transitive
     description:
       name: stack_trace
-      url: "https://pub.dartlang.org"
+      sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+      url: "https://pub.dev"
     source: hosted
-    version: "1.10.0"
+    version: "1.11.0"
   stream_channel:
     dependency: transitive
     description:
       name: stream_channel
-      url: "https://pub.dartlang.org"
+      sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.0"
+    version: "2.1.1"
   stream_transform:
     dependency: transitive
     description:
       name: stream_transform
-      url: "https://pub.dartlang.org"
+      sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.0"
+    version: "2.1.0"
   string_scanner:
     dependency: transitive
     description:
       name: string_scanner
-      url: "https://pub.dartlang.org"
+      sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.1.1"
+    version: "1.2.0"
   sync_http:
     dependency: transitive
     description:
       name: sync_http
-      url: "https://pub.dartlang.org"
+      sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
+      url: "https://pub.dev"
     source: hosted
     version: "0.3.1"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
-      url: "https://pub.dartlang.org"
+      sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+      url: "https://pub.dev"
     source: hosted
     version: "1.2.1"
+  test:
+    dependency: transitive
+    description:
+      name: test
+      sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.22.0"
   test_api:
     dependency: transitive
     description:
       name: test_api
-      url: "https://pub.dartlang.org"
+      sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
+      url: "https://pub.dev"
     source: hosted
-    version: "0.4.12"
+    version: "0.4.16"
+  test_core:
+    dependency: transitive
+    description:
+      name: test_core
+      sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.4.20"
   timing:
     dependency: transitive
     description:
       name: timing
-      url: "https://pub.dartlang.org"
+      sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.0"
+    version: "1.0.1"
   total_lints:
     dependency: transitive
     description:
       name: total_lints
-      url: "https://pub.dartlang.org"
+      sha256: "5424a55034e89a9c6198518356842dfdc33b6f0b4d557071f84d6095e5a9f8ea"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.18.0"
+    version: "2.19.0"
   tuple:
     dependency: transitive
     description:
       name: tuple
-      url: "https://pub.dartlang.org"
+      sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa"
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.1"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
-      url: "https://pub.dartlang.org"
+      sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
+      url: "https://pub.dev"
     source: hosted
     version: "1.3.1"
   universal_html:
     dependency: transitive
     description:
       name: universal_html
-      url: "https://pub.dartlang.org"
+      sha256: "5ff50b7c14d201421cf5230ec389a0591c4deb5c817c9d7ccca3b26fe5f31e34"
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.8"
   universal_io:
     dependency: transitive
     description:
       name: universal_io
-      url: "https://pub.dartlang.org"
+      sha256: "79f78ddad839ee3aae3ec7c01eb4575faf0d5c860f8e5223bc9f9c17f7f03cef"
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.4"
   url_launcher:
     dependency: "direct main"
     description:
       name: url_launcher
-      url: "https://pub.dartlang.org"
+      sha256: e8f2efc804810c0f2f5b485f49e7942179f56eabcfe81dce3387fec4bb55876b
+      url: "https://pub.dev"
     source: hosted
-    version: "6.1.2"
+    version: "6.1.9"
   url_launcher_android:
     dependency: transitive
     description:
       name: url_launcher_android
-      url: "https://pub.dartlang.org"
+      sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1"
+      url: "https://pub.dev"
     source: hosted
-    version: "6.0.17"
+    version: "6.0.23"
   url_launcher_ios:
     dependency: transitive
     description:
       name: url_launcher_ios
-      url: "https://pub.dartlang.org"
+      sha256: "0a5af0aefdd8cf820dd739886efb1637f1f24489900204f50984634c07a54815"
+      url: "https://pub.dev"
     source: hosted
-    version: "6.0.17"
+    version: "6.1.0"
   url_launcher_linux:
     dependency: transitive
     description:
       name: url_launcher_linux
-      url: "https://pub.dartlang.org"
+      sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc"
+      url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.2"
   url_launcher_macos:
     dependency: transitive
     description:
       name: url_launcher_macos
-      url: "https://pub.dartlang.org"
+      sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094"
+      url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.2"
   url_launcher_platform_interface:
     dependency: transitive
     description:
       name: url_launcher_platform_interface
-      url: "https://pub.dartlang.org"
+      sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.5"
+    version: "2.1.1"
   url_launcher_web:
     dependency: transitive
     description:
       name: url_launcher_web
-      url: "https://pub.dartlang.org"
+      sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.0.11"
+    version: "2.0.14"
   url_launcher_windows:
     dependency: transitive
     description:
       name: url_launcher_windows
-      url: "https://pub.dartlang.org"
+      sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615
+      url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.3"
   url_strategy:
     dependency: "direct main"
     description:
       name: url_strategy
-      url: "https://pub.dartlang.org"
+      sha256: "42b68b42a9864c4d710401add17ad06e28f1c1d5500c93b98c431f6b0ea4ab87"
+      url: "https://pub.dev"
     source: hosted
     version: "0.2.0"
   usage:
     dependency: "direct main"
     description:
       name: usage
-      url: "https://pub.dartlang.org"
+      sha256: ccc861ca619157046d961a1d7fa21a364476c574bb8f3e90219e41b9103adee0
+      url: "https://pub.dev"
     source: hosted
-    version: "4.0.2"
+    version: "4.1.0"
+  vector_graphics:
+    dependency: transitive
+    description:
+      name: vector_graphics
+      sha256: "09562ef5f47aa84f6567495adb6b9cb2a3192b82c352623b8bd00b300d62603b"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.1"
+  vector_graphics_codec:
+    dependency: transitive
+    description:
+      name: vector_graphics_codec
+      sha256: "886e57742644ebed024dc3ade29712e37eea1b03d294fb314c0a3386243fe5a6"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.1"
+  vector_graphics_compiler:
+    dependency: transitive
+    description:
+      name: vector_graphics_compiler
+      sha256: "5d9010c4a292766c55395b2288532579a85673f8148460d1e233d98ffe10d24e"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.1"
   vector_math:
     dependency: transitive
     description:
       name: vector_math
-      url: "https://pub.dartlang.org"
+      sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+      url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.4"
   vm_service:
     dependency: transitive
     description:
       name: vm_service
-      url: "https://pub.dartlang.org"
+      sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7
+      url: "https://pub.dev"
     source: hosted
-    version: "9.0.0"
+    version: "9.4.0"
   watcher:
     dependency: transitive
     description:
       name: watcher
-      url: "https://pub.dartlang.org"
+      sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
+      url: "https://pub.dev"
     source: hosted
-    version: "1.0.1"
+    version: "1.0.2"
   web_browser_detect:
     dependency: transitive
     description:
       name: web_browser_detect
-      url: "https://pub.dartlang.org"
+      sha256: "78ba66860b61a993030788a3a4586fb21cb7d9cef966cfd24faa9ad487c3fd8b"
+      url: "https://pub.dev"
     source: hosted
     version: "2.0.3"
   web_socket_channel:
     dependency: transitive
     description:
       name: web_socket_channel
-      url: "https://pub.dartlang.org"
+      sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b
+      url: "https://pub.dev"
     source: hosted
-    version: "2.2.0"
+    version: "2.3.0"
   webdriver:
     dependency: transitive
     description:
       name: webdriver
-      url: "https://pub.dartlang.org"
+      sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841
+      url: "https://pub.dev"
     source: hosted
-    version: "3.0.0"
+    version: "3.0.1"
+  webkit_inspection_protocol:
+    dependency: transitive
+    description:
+      name: webkit_inspection_protocol
+      sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.0"
   win32:
     dependency: transitive
     description:
       name: win32
-      url: "https://pub.dartlang.org"
+      sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46
+      url: "https://pub.dev"
     source: hosted
-    version: "2.7.0"
+    version: "3.1.3"
   xdg_directories:
     dependency: transitive
     description:
       name: xdg_directories
-      url: "https://pub.dartlang.org"
+      sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
+      url: "https://pub.dev"
     source: hosted
-    version: "0.2.0+1"
+    version: "1.0.0"
   xml:
     dependency: transitive
     description:
       name: xml
-      url: "https://pub.dartlang.org"
+      sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5"
+      url: "https://pub.dev"
     source: hosted
-    version: "5.4.1"
+    version: "6.2.2"
   yaml:
     dependency: transitive
     description:
       name: yaml
-      url: "https://pub.dartlang.org"
+      sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370"
+      url: "https://pub.dev"
     source: hosted
     version: "3.1.1"
 sdks:
-  dart: ">=2.18.1 <3.0.0"
-  flutter: ">=3.3.2"
+  dart: ">=2.19.2 <3.0.0"
+  flutter: ">=3.7.3"
diff --git a/playground/frontend/pubspec.yaml b/playground/frontend/pubspec.yaml
index 3c65a5aab12..982427dc5a7 100644
--- a/playground/frontend/pubspec.yaml
+++ b/playground/frontend/pubspec.yaml
@@ -21,13 +21,13 @@ publish_to: 'none'
 version: 1.0.0+1
 
 environment:
-  sdk: ">=2.18.1 <3.0.0"
-  flutter: ">=3.3.2"
+  sdk: ">=2.19.2 <4.0.0"
+  flutter: ">=3.7.3"
 
 dependencies:
   akvelon_flutter_issue_106664_workaround: ^0.1.2
   aligned_dialog: ^0.0.6
-  app_state: ^0.8.4
+  app_state: ^0.9.0
   collection: ^1.15.0
   easy_localization: ^3.0.1
   easy_localization_ext: ^0.1.1
@@ -36,10 +36,10 @@ dependencies:
   expansion_widget: ^0.0.2
   flutter: { sdk: flutter }
   flutter_localizations: { sdk: flutter }
-  flutter_svg: ^1.0.3
+  flutter_svg: ^2.0.0+1
   flutter_web_plugins: { sdk: flutter }
   get_it: ^7.2.0
-  google_fonts: ^3.0.1
+  google_fonts: ^4.0.3
   highlight: ^0.7.0
   intl: ^0.17.0
   onmessage: ^0.2.0
@@ -53,7 +53,7 @@ dependencies:
 dev_dependencies:
   build_runner: ^2.1.4
   fake_async: ^1.3.0
-  flutter_code_editor: ^0.2.5
+  flutter_code_editor: ^0.2.9
   flutter_lints: ^2.0.1
   flutter_test: { sdk: flutter }
   integration_test: { sdk: flutter }
diff --git a/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart b/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart
index 2117f7fccb4..d341e3c0566 100644
--- a/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart
+++ b/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart
@@ -1,7 +1,8 @@
-// Mocks generated by Mockito 5.2.0 from annotations
+// Mocks generated by Mockito 5.3.2 from annotations
 // in playground/test/pages/playground/states/example_selector_state_test.dart.
 // Do not manually edit this file.
 
+// ignore_for_file: no_leading_underscores_for_library_prefixes
 import 'dart:async' as _i5;
 
 import 'package:mockito/mockito.dart' as _i1;
@@ -24,9 +25,18 @@ import 'package:playground_components/src/models/sdk.dart' as _i7;
 // ignore_for_file: prefer_const_constructors
 // ignore_for_file: unnecessary_parenthesis
 // ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
 
-class _FakeExampleLoaderFactory_0 extends _i1.Fake
-    implements _i2.ExampleLoaderFactory {}
+class _FakeExampleLoaderFactory_0 extends _i1.SmartFake
+    implements _i2.ExampleLoaderFactory {
+  _FakeExampleLoaderFactory_0(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
 
 /// A class which mocks [ExamplesLoader].
 ///
@@ -38,20 +48,38 @@ class MockExamplesLoader extends _i1.Mock implements _i3.ExamplesLoader {
 
   @override
   _i2.ExampleLoaderFactory get defaultFactory => (super.noSuchMethod(
-      Invocation.getter(#defaultFactory),
-      returnValue: _FakeExampleLoaderFactory_0()) as _i2.ExampleLoaderFactory);
+        Invocation.getter(#defaultFactory),
+        returnValue: _FakeExampleLoaderFactory_0(
+          this,
+          Invocation.getter(#defaultFactory),
+        ),
+      ) as _i2.ExampleLoaderFactory);
   @override
   void setPlaygroundController(_i4.PlaygroundController? value) =>
-      super.noSuchMethod(Invocation.method(#setPlaygroundController, [value]),
-          returnValueForMissingStub: null);
+      super.noSuchMethod(
+        Invocation.method(
+          #setPlaygroundController,
+          [value],
+        ),
+        returnValueForMissingStub: null,
+      );
   @override
   _i5.Future<void> load(_i6.ExamplesLoadingDescriptor? descriptor) =>
-      (super.noSuchMethod(Invocation.method(#load, [descriptor]),
-          returnValue: Future<void>.value(),
-          returnValueForMissingStub: Future<void>.value()) as _i5.Future<void>);
+      (super.noSuchMethod(
+        Invocation.method(
+          #load,
+          [descriptor],
+        ),
+        returnValue: _i5.Future<void>.value(),
+        returnValueForMissingStub: _i5.Future<void>.value(),
+      ) as _i5.Future<void>);
   @override
-  _i5.Future<void> loadDefaultIfAny(_i7.Sdk? sdk) =>
-      (super.noSuchMethod(Invocation.method(#loadDefaultIfAny, [sdk]),
-          returnValue: Future<void>.value(),
-          returnValueForMissingStub: Future<void>.value()) as _i5.Future<void>);
+  _i5.Future<void> loadDefaultIfAny(_i7.Sdk? sdk) => (super.noSuchMethod(
+        Invocation.method(
+          #loadDefaultIfAny,
+          [sdk],
+        ),
+        returnValue: _i5.Future<void>.value(),
+        returnValueForMissingStub: _i5.Future<void>.value(),
+      ) as _i5.Future<void>);
 }
diff --git a/website/www/site/layouts/shortcodes/playground.html b/website/www/site/layouts/shortcodes/playground.html
index be6b2b80095..0868c779f88 100644
--- a/website/www/site/layouts/shortcodes/playground.html
+++ b/website/www/site/layouts/shortcodes/playground.html
@@ -22,6 +22,8 @@ Embedding example:
 {{< playground_snippet language="scio" path="SDK_SCIO/PRECOMPILED_OBJECT_TYPE_EXAMPLE/MinimalWordCount" >}}
 {{< /playground >}}
 
+See playground_snippet for all supported options.
+
 */}}
 <div class="playground-wrapper">
     <div class="playground-snippets">
diff --git a/website/www/site/layouts/shortcodes/playground_snippet.html b/website/www/site/layouts/shortcodes/playground_snippet.html
index a7bd6b15be7..212ee43ddf3 100644
--- a/website/www/site/layouts/shortcodes/playground_snippet.html
+++ b/website/www/site/layouts/shortcodes/playground_snippet.html
@@ -16,8 +16,11 @@ because here only a div is created and not an iframe. It is 'playground' that ac
 an iframe.
 
 Required parameters:
-- example - the example ID or snippet ID.
 - language - the string to be passed as SDK to playground. 'py' translates to 'python'.
+- any of the following:
+    - path - the example in the catalog.
+    - shared - the snippet ID shared by a user.
+    - url - the URL of the example code.
 
 Optional parameters:
 - readonly - comma-separated section names to make read-only.