diff --git a/CONTRIBUTING-v4.md b/CONTRIBUTING-v4.md
new file mode 100644
index 000000000..883eb64b1
--- /dev/null
+++ b/CONTRIBUTING-v4.md
@@ -0,0 +1,163 @@
+## Design Goals - Simplicity
+
+- Easy to use
+- Easy to develop
+
+**Easy to use**
+
+- Don't mimick API spec. Ansible spec should be a simplified version of API spec.
+- Goal is to expose *minimum attributes* to create, update or delete the entity.
+- Keep backward & forward compatibility in mind when creating ansible spec.
+
+**Easy to develop**
+
+- Three things need to develop a module:
+
+ a. [Module spec](https://github.com/nutanix/nutanix.ansible/blob/main/plugins/modules/ntnx_subnets_v2.py#L606) inside `get_module_spec()`, spec for running the API via sdk.
+
+ Example:
+ ```
+ def get_module_spec():
+ dhcp_spec = dict(...)
+ metadata_spec = dict(...)
+
+ module_args = dict(
+ ext_id=dict(type="str"),
+ name=dict(type="str"),
+ description=dict(type="str"),
+ subnet_type=dict(type="str", choices=["OVERLAY", "VLAN"]),
+ network_id=dict(type="int"),
+ dhcp_options=dict(type="dict", options=dhcp_spec, obj=net_sdk.DhcpOptions),
+ metadata=dict(type="dict", options=metadata_spec, obj=net_sdk.Metadata),
+ )
+ return module_args
+ ```
+
+ b. [Bootstrap code](https://github.com/nutanix/nutanix.ansible/blob/main/plugins/modules/ntnx_subnets_v2.py#L705) for creating and deleting entity.
+ Use v4 sdks which are available on [v4-documentation](https://developers.nutanix.com/api-reference?namespace=networking&version=v4.0) in creation, updation or deletion.
+
+ c. [Ansible module](https://github.com/nutanix/nutanix.ansible/blob/main/plugins/modules/ntnx_subnets_v2.py) plugin with [`run_module()`](https://github.com/nutanix/nutanix.ansible/blob/main/plugins/modules/ntnx_subnets_v2.py#L832) implementation.
+
+ Example:
+ ```
+ def run_module():
+ module = BaseModule(
+ argument_spec=get_module_spec(),
+ supports_check_mode=True,
+ required_if=[
+ ("state", "present", ("name", "ext_id"), True),
+ (
+ "state",
+ "present",
+ ("ext_id", "cluster_reference", "vpc_reference"),
+ True,
+ ),
+ ("state", "absent", ("ext_id",)),
+ ],
+ )
+ if SDK_IMP_ERROR:
+ module.fail_json(
+ msg=missing_required_lib("ntnx_networking_py_client"),
+ exception=SDK_IMP_ERROR,
+ )
+
+ remove_param_with_none_value(module.params)
+ result = {
+ "changed": False,
+ "error": None,
+ "response": None,
+ "ext_id": None,
+ }
+ state = module.params["state"]
+ if state == "present":
+ if module.params.get("ext_id"):
+ update_subnet(module, result)
+ else:
+ create_subnet(module, result)
+ else:
+ delete_subnet(module, result)
+ module.exit_json(**result)
+ ```
+
+## Spec generator
+
+The `generate_spec` method is designed to populate a specification object (`obj`) based on input attributes (`attr`) and additional keyword arguments (`kwargs`). Here's a brief breakdown of how it works:
+
+1. **Type Check**: Ensures the obj is a valid object.
+
+2. **Module Arguments**: Retrieves module arguments from kwargs or uses a default set.
+
+3. **Attributes**: If attr is not provided, it defaults to a deep copy of self.module.params.
+
+4. **Attribute Processing**: Iterates over each key in module_args and processes it based on its type:
+ - **Dynamic Objects**: Handles attributes with dynamic objects.
+
+ - **Dict Type**: Recursively creates spec objects for dictionary-type attributes.
+
+ - **List Type**: Recursively creates a list of spec objects for list-type attributes.
+
+ - **Other Types**: Directly assigns the attribute value to the spec object.
+
+**Usage:**
+
+To use the `generate_spec` method, follow these steps:
+
+1. **Create a Spec Object**: Define the spec object that needs to be populated.
+
+2. **Define Attributes**: Prepare the attributes dictionary that contains the values to be assigned to the spec object.
+
+3. **Call the Method**: Invoke the `generate_spec` method with the spec object and attributes.
+
+**Example**
+
+Here's an example of how to use the `generate_spec` method:
+
+For Create Opearation:
+```
+sg = SpecGenerator(module)
+default_spec = net_sdk.Subnet() // Root Node
+spec, err = sg.generate_spec(obj=default_spec)
+```
+For Update Operation:
+```
+current_spec = get_subnet(module, subnets, ext_id=ext_id) // Fetch the current spec
+sg = SpecGenerator(module)
+update_spec, err = sg.generate_spec(obj=deepcopy(current_spec))
+```
+
+## Workflow
+
+1. Create a github issue with following details
+ * **Title** should contain one of the follwoing
+ - [Feat] Develop ansible module for \
+ - [Imprv] Modify ansible module to support \
+ - [Bug] Fix \ bug in \
+ * **Labels** should contain one of the following
+ - **feature**
+ - **enhancement**
+ - **bug**
+ - **test**
+
+ * **Project** should be selected
+ * **Assignees** - assign yourself
+ * **Task list** for list of tasks that needs to be developed as part of the fix
+ - unit tests
+ - integration tests
+ - sanity tests
+ - documentation
+
+2. Create one of the following git branch from `main` branch. Use `issue#` from 1).
+ * `feat/_issue#`
+ * `imprv/issue#`
+ * `bug/issue#`
+
+3. Develop `sanity`, `unit` and `integrtaion` tests.
+
+4. Create a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
+
+5. Ensure 85% code coverage on the pull request. Pull request with less than 85% coverage will be rejected.
+
+6. Link the pull request in `issue#`
+
+7. After the pull request is merged, close the `issue#`
+