diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index 3d56bf0ff9c57a0312f159c63c2f2c9bfe51d669..9074af7c3ccfd6ab3777c021a92dbce128c144a3 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -45,6 +45,7 @@ from gso.utils.types.interfaces import JuniperLAGMember, LAGMember, LAGMemberLis
 from gso.utils.types.netbox_router import NetboxEnabledRouter
 from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import prompt_sharepoint_checklist_url
+from gso.workflows.shared import create_summary_form
 
 
 def initial_input_form_generator(product_name: str) -> FormGenerator:
@@ -160,8 +161,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         side_b_ae_members: ae_members_side_b
 
     user_input_side_b = yield CreateIptrunkSideBForm
-
-    return (
+    input_forms_data = (
         initial_user_input.model_dump()
         | verify_minimum_links.model_dump()
         | user_input_router_side_a.model_dump()
@@ -169,6 +169,25 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         | user_input_router_side_b.model_dump()
         | user_input_side_b.model_dump()
     )
+    summary_form_data = input_forms_data | {"side_a_node": router_a_fqdn, "side_b_node": router_b_fqdn}
+    summary_fields = [
+        "geant_s_sid",
+        "iptrunk_type",
+        "iptrunk_speed",
+        "iptrunk_description",
+        "iptrunk_minimum_links",
+        "side_a_node",
+        "side_a_ae_iface",
+        "side_a_ae_members",
+        "side_a_ae_geant_a_sid",
+        "side_b_node",
+        "side_b_ae_iface",
+        "side_b_ae_members",
+        "side_b_ae_geant_a_sid",
+    ]
+    yield from create_summary_form(summary_form_data, product_name, summary_fields)
+
+    return input_forms_data
 
 
 @step("Create subscription")
diff --git a/gso/workflows/iptrunk/modify_isis_metric.py b/gso/workflows/iptrunk/modify_isis_metric.py
index 7d77510728354e40b9cd8a1424672a9fc499d4b9..45865e39b68f1263f9058edab376e94319ac2830 100644
--- a/gso/workflows/iptrunk/modify_isis_metric.py
+++ b/gso/workflows/iptrunk/modify_isis_metric.py
@@ -13,6 +13,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services.lso_client import LSOState, lso_interaction
 from gso.utils.types.tt_number import TTNumber
+from gso.workflows.shared import modify_summary_form
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
@@ -24,8 +25,11 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
         isis_metric: int = subscription.iptrunk.iptrunk_isis_metric
 
     user_input = yield ModifyIptrunkForm
-
-    return user_input.model_dump()
+    user_input = user_input.model_dump()
+    yield from modify_summary_form(
+        {"iptrunk_isis_metric": user_input["isis_metric"]}, subscription.iptrunk, ["iptrunk_isis_metric"]
+    )
+    return user_input
 
 
 @step("Update subscription")
diff --git a/gso/workflows/router/create_router.py b/gso/workflows/router/create_router.py
index 4492e86e9b1d5b3ad4a733ada87df51efae84248..edc4ec0b7877313f28af8508c3da4833e9161c55 100644
--- a/gso/workflows/router/create_router.py
+++ b/gso/workflows/router/create_router.py
@@ -33,6 +33,7 @@ from gso.utils.workflow_steps import (
     prompt_sharepoint_checklist_url,
     run_checks_after_base_config,
 )
+from gso.workflows.shared import create_summary_form
 
 
 def initial_input_form_generator(product_name: str) -> FormGenerator:
@@ -65,8 +66,11 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
             return self
 
     user_input = yield CreateRouterForm
+    user_input = user_input.model_dump()
+    summary_fields = ["hostname", "router_site", "vendor", "ts_port", "router_role"]
+    yield from create_summary_form(user_input, product_name, summary_fields)
 
-    return user_input.model_dump()
+    return user_input
 
 
 @step("Create subscription")
diff --git a/gso/workflows/shared.py b/gso/workflows/shared.py
new file mode 100644
index 0000000000000000000000000000000000000000..9cc61837bb9fdd7bde636a12ce4b0531d3ef2798
--- /dev/null
+++ b/gso/workflows/shared.py
@@ -0,0 +1,41 @@
+"""Shared functions for the workflows."""
+
+from collections.abc import Generator
+from typing import TypeAlias, cast
+
+from orchestrator.domain.base import ProductBlockModel
+from orchestrator.forms import FormPage
+from orchestrator.forms.validators import MigrationSummary, migration_summary
+from pydantic import ConfigDict
+
+
+def summary_form(product_name: str, summary_data: dict) -> Generator:
+    """Generate a summary form for the product."""
+    ProductSummary: TypeAlias = cast(type[MigrationSummary], migration_summary(summary_data))  # type: ignore[no-redef]
+
+    class SummaryForm(FormPage):
+        model_config = ConfigDict(title=f"{product_name} summary")
+
+        product_summary: ProductSummary
+
+    yield SummaryForm
+
+
+def create_summary_form(user_input: dict, product_name: str, fields: list[str]) -> Generator:
+    """Create a summary form for the product."""
+    columns = [[str(user_input[nm]) for nm in fields]]
+    yield from summary_form(product_name, {"labels": fields, "columns": columns})
+
+
+def modify_summary_form(user_input: dict, block: ProductBlockModel, fields: list[str]) -> Generator:
+    """Modify the summary form for the product."""
+    before = [str(getattr(block, nm)) for nm in fields]
+    after = [str(user_input[nm]) for nm in fields]
+    yield from summary_form(
+        block.subscription.product.name,
+        {
+            "labels": fields,
+            "headers": ["Before", "After"],
+            "columns": [before, after],
+        },
+    )
diff --git a/gso/workflows/site/create_site.py b/gso/workflows/site/create_site.py
index eb5409d778c019e41ae82c85376ec48fcf4bdcc6..384dd59f0945885f54bfd5c51b51f477b3a30f69 100644
--- a/gso/workflows/site/create_site.py
+++ b/gso/workflows/site/create_site.py
@@ -15,6 +15,7 @@ from gso.services.partners import get_partner_by_name
 from gso.utils.types.base_site import BaseSiteValidatorModel
 from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
 from gso.utils.types.ip_address import IPAddress
+from gso.workflows.shared import create_summary_form
 
 
 def initial_input_form_generator(product_name: str) -> FormGenerator:
@@ -25,8 +26,23 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         partner: ReadOnlyField("GEANT", default_type=str)  # type: ignore[valid-type]
 
     user_input = yield CreateSiteForm
-
-    return user_input.model_dump()
+    user_input = user_input.model_dump()
+    summary_fields = [
+        "site_name",
+        "site_bgp_community_id",
+        "site_internal_id",
+        "site_tier",
+        "site_ts_address",
+        "site_country_code",
+        "site_city",
+        "site_country",
+        "site_latitude",
+        "site_longitude",
+        "partner",
+    ]
+    yield from create_summary_form(user_input, product_name, summary_fields)
+
+    return user_input
 
 
 @step("Create subscription")
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index c21f26cc1c2ce9fdcab5871c14f552d3c7d5eb06..7a38a234a7e0ba98dea56081b07e0bcc8be21c7e 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -90,6 +90,7 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
         "side_b_ae_geant_a_sid": faker.geant_sid(),
         "side_b_ae_members": side_b_members,
     }
+    summary_view_step = {}
 
     return [
         create_ip_trunk_step,
@@ -98,6 +99,7 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
         create_ip_trunk_side_a_step,
         create_ip_trunk_side_b_router_name,
         create_ip_trunk_side_b_step,
+        summary_view_step,
     ]
 
 
diff --git a/test/workflows/iptrunk/test_modify_isis_metric.py b/test/workflows/iptrunk/test_modify_isis_metric.py
index 1c739b74340ba9c64c0ca81d9109500c4e08aa0e..f81baac86f23d5abb4e85d84b61ac84edccaeb92 100644
--- a/test/workflows/iptrunk/test_modify_isis_metric.py
+++ b/test/workflows/iptrunk/test_modify_isis_metric.py
@@ -26,6 +26,7 @@ def test_iptrunk_modify_isis_metric_success(
     initial_iptrunk_data = [
         {"subscription_id": product_id},
         {"tt_number": faker.tt_number(), "isis_metric": new_isis_metric},
+        {},
     ]
     result, process_stat, step_log = run_workflow("modify_isis_metric", initial_iptrunk_data)
 
diff --git a/test/workflows/router/test_create_router.py b/test/workflows/router/test_create_router.py
index 104bea75db4a4f9e74b3f537e60538372e5ed726..f9fb37fcfa38159a5d92c1aca8a9bd0aea2c5051 100644
--- a/test/workflows/router/test_create_router.py
+++ b/test/workflows/router/test_create_router.py
@@ -68,7 +68,7 @@ def test_create_nokia_router_success(
     mock_sharepoint_client.return_value = MockedSharePointClient
 
     #  Run workflow
-    initial_router_data = [{"product": product_id}, router_creation_input_form_data]
+    initial_router_data = [{"product": product_id}, router_creation_input_form_data, {}]
     result, process_stat, step_log = run_workflow("create_router", initial_router_data)
 
     state = extract_state(result)
@@ -176,7 +176,7 @@ def test_create_nokia_router_lso_failure(
 
     #  Run workflow
     product_id = get_product_id_by_name(ProductName.ROUTER)
-    initial_router_data = [{"product": product_id}, router_creation_input_form_data]
+    initial_router_data = [{"product": product_id}, router_creation_input_form_data, {}]
     result, process_stat, step_log = run_workflow("create_router", initial_router_data)
 
     result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
diff --git a/test/workflows/site/test_create_site.py b/test/workflows/site/test_create_site.py
index 7642debea0c2739b1a5845db4404f35c5205884a..112e078f39c78a1545ada8d14be18dbd61da7858 100644
--- a/test/workflows/site/test_create_site.py
+++ b/test/workflows/site/test_create_site.py
@@ -25,6 +25,7 @@ def test_create_site(responses, faker):
             "site_tier": SiteTier.TIER1,
             "site_ts_address": faker.ipv4(),
         },
+        {},
     ]
     result, _, _ = run_workflow("create_site", initial_site_data)
     assert_complete(result)
@@ -66,6 +67,7 @@ def test_site_name_is_incorrect(responses, faker):
             "site_ts_address": faker.ipv4(),
             "partner": "GEANT",
         },
+        {},
     ]
 
     with pytest.raises(FormValidationError, match=expected_exception_msg):
diff --git a/test/workflows/site/test_modify_site.py b/test/workflows/site/test_modify_site.py
index a79b3b01b111f4aaf200d70b028bc6f487dd20db..fb45a9576e6917e66af9370dab3a69435bdf20db 100644
--- a/test/workflows/site/test_modify_site.py
+++ b/test/workflows/site/test_modify_site.py
@@ -15,6 +15,7 @@ def test_modify_site(responses, site_subscription_factory, faker):
             "site_internal_id": faker.pyint(),
             "site_ts_address": faker.ipv4(),
         },
+        {},
     ]
     result, _, _ = run_workflow("modify_site", initial_site_data)
     assert_complete(result)
@@ -39,6 +40,7 @@ def test_modify_site_with_duplicate_bgp_community_id(faker, site_subscription_fa
         {
             "site_bgp_community_id": duplicate_bgp_community_id,
         },
+        {},
     ]
 
     with pytest.raises(FormValidationError, match="site_bgp_community_id must be unique"):
@@ -57,6 +59,7 @@ def test_modify_site_with_duplicate_internal_id(faker, site_subscription_factory
         {
             "site_internal_id": duplicate_internal_id,
         },
+        {},
     ]
 
     with pytest.raises(FormValidationError, match="site_internal_id must be unique"):
@@ -75,6 +78,7 @@ def test_modify_site_with_duplicate_ts_address(faker, site_subscription_factory)
         {
             "site_ts_address": duplicate_ts_address,
         },
+        {},
     ]
 
     with pytest.raises(FormValidationError, match="site_ts_address must be unique"):