diff --git a/src/webui/proto/service_pb2.py b/src/webui/proto/service_pb2.py
index 806ec46386848e727cd6bb43f73501d0ce9dce69..7a006915b8be39710a17faab075e382e322d918f 100644
--- a/src/webui/proto/service_pb2.py
+++ b/src/webui/proto/service_pb2.py
@@ -20,7 +20,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   syntax='proto3',
   serialized_options=None,
   create_key=_descriptor._internal_create_key,
-  serialized_pb=b'\n\rservice.proto\x12\x07service\x1a\rcontext.proto2\xed\x02\n\x0eServiceService\x12\x38\n\x0eGetServiceList\x12\x0e.context.Empty\x1a\x14.context.ServiceList\"\x00\x12\x37\n\rCreateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x37\n\rUpdateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x35\n\rDeleteService\x12\x12.context.ServiceId\x1a\x0e.context.Empty\"\x00\x12\x38\n\x0eGetServiceById\x12\x12.context.ServiceId\x1a\x10.context.Service\"\x00\x12>\n\x11GetConnectionList\x12\x0e.context.Empty\x1a\x17.context.ConnectionList\"\x00\x62\x06proto3'
+  serialized_pb=b'\n\rservice.proto\x12\x07service\x1a\rcontext.proto2\xfd\x01\n\x0eServiceService\x12\x37\n\rCreateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x37\n\rUpdateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x35\n\rDeleteService\x12\x12.context.ServiceId\x1a\x0e.context.Empty\"\x00\x12\x42\n\x11GetConnectionList\x12\x12.context.ServiceId\x1a\x17.context.ConnectionList\"\x00\x62\x06proto3'
   ,
   dependencies=[context__pb2.DESCRIPTOR,])
 
@@ -38,22 +38,12 @@ _SERVICESERVICE = _descriptor.ServiceDescriptor(
   serialized_options=None,
   create_key=_descriptor._internal_create_key,
   serialized_start=42,
-  serialized_end=407,
+  serialized_end=295,
   methods=[
-  _descriptor.MethodDescriptor(
-    name='GetServiceList',
-    full_name='service.ServiceService.GetServiceList',
-    index=0,
-    containing_service=None,
-    input_type=context__pb2._EMPTY,
-    output_type=context__pb2._SERVICELIST,
-    serialized_options=None,
-    create_key=_descriptor._internal_create_key,
-  ),
   _descriptor.MethodDescriptor(
     name='CreateService',
     full_name='service.ServiceService.CreateService',
-    index=1,
+    index=0,
     containing_service=None,
     input_type=context__pb2._SERVICE,
     output_type=context__pb2._SERVICEID,
@@ -63,7 +53,7 @@ _SERVICESERVICE = _descriptor.ServiceDescriptor(
   _descriptor.MethodDescriptor(
     name='UpdateService',
     full_name='service.ServiceService.UpdateService',
-    index=2,
+    index=1,
     containing_service=None,
     input_type=context__pb2._SERVICE,
     output_type=context__pb2._SERVICEID,
@@ -73,29 +63,19 @@ _SERVICESERVICE = _descriptor.ServiceDescriptor(
   _descriptor.MethodDescriptor(
     name='DeleteService',
     full_name='service.ServiceService.DeleteService',
-    index=3,
+    index=2,
     containing_service=None,
     input_type=context__pb2._SERVICEID,
     output_type=context__pb2._EMPTY,
     serialized_options=None,
     create_key=_descriptor._internal_create_key,
   ),
-  _descriptor.MethodDescriptor(
-    name='GetServiceById',
-    full_name='service.ServiceService.GetServiceById',
-    index=4,
-    containing_service=None,
-    input_type=context__pb2._SERVICEID,
-    output_type=context__pb2._SERVICE,
-    serialized_options=None,
-    create_key=_descriptor._internal_create_key,
-  ),
   _descriptor.MethodDescriptor(
     name='GetConnectionList',
     full_name='service.ServiceService.GetConnectionList',
-    index=5,
+    index=3,
     containing_service=None,
-    input_type=context__pb2._EMPTY,
+    input_type=context__pb2._SERVICEID,
     output_type=context__pb2._CONNECTIONLIST,
     serialized_options=None,
     create_key=_descriptor._internal_create_key,
diff --git a/src/webui/service/device/forms.py b/src/webui/service/device/forms.py
index ba3d05ea76731fca85c7f5cfb45b0f705dd81935..6dda2cbba946a583c55b13d03d396fbec58e8c67 100644
--- a/src/webui/service/device/forms.py
+++ b/src/webui/service/device/forms.py
@@ -1,16 +1,41 @@
 # external imports
 from flask_wtf import FlaskForm
-from wtforms import StringField, SelectField, SubmitField
-from wtforms.validators import DataRequired, Length, NumberRange
+from wtforms import StringField, SelectField, TextAreaField, SubmitField
+from wtforms.validators import DataRequired, Length, NumberRange, Regexp, ValidationError
 
+from webui.utils.form_validators import key_value_validator
+from webui.proto.context_pb2 import (DeviceDriverEnum, DeviceOperationalStatusEnum)
 
 class AddDeviceForm(FlaskForm):
-    device_id = StringField('Device ID', 
+    device_id = StringField('ID', 
                            validators=[DataRequired(), Length(min=5)])
-    device_type = StringField('Device Type', 
+    device_type = StringField('Type', 
                            validators=[DataRequired(), Length(min=5)])
+    device_config = TextAreaField('Configurations', validators=[key_value_validator()])
     operational_status = SelectField('Operational Status',
-                           choices=[(-1, 'Select...'), (0, 'Undefined'), (1, 'Disabled'), (2, 'Enabled')],
+                        #    choices=[(-1, 'Select...'), (0, 'Undefined'), (1, 'Disabled'), (2, 'Enabled')],
                            coerce=int,
-                           validators=[DataRequired(), NumberRange(min=0)])
+                           validators=[NumberRange(min=0)])
+    device_drivers = TextAreaField('Drivers', validators=[DataRequired(), Regexp('^\d+(,\d+)*$')])
     submit = SubmitField('Add')
+
+    def validate_operational_status(form, field):
+        if field.data not in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_number:
+            raise ValidationError('The operational status value selected is incorrect!')
+    
+    def validate_device_drivers(form, field):
+        if ',' not in field.data:
+            data = str(field.data) + ','
+        else:
+            data = field.data
+        for value in data.split(','):
+            value = value.strip()
+            if len(value) == 0:
+                continue
+            try:
+                value_int = int(value)
+            except:
+                raise ValidationError(f'The value "{value}" is not a valid driver identified.')
+            if value_int not in DeviceDriverEnum.DESCRIPTOR.values_by_number:
+                values = ', '.join([str(x) for x in DeviceDriverEnum.DESCRIPTOR.values_by_number])
+                raise ValidationError(f'The device driver {value_int} is not correct. Allowed values are: {values}.')
diff --git a/src/webui/service/device/routes.py b/src/webui/service/device/routes.py
index 2773d088017e4f9459d936a5fee27f733016eb82..4d95faff877b2afa721261688a018b9970d003cd 100644
--- a/src/webui/service/device/routes.py
+++ b/src/webui/service/device/routes.py
@@ -1,4 +1,5 @@
 from flask import render_template, Blueprint, flash, session
+from context.proto.context_pb2 import ConfigActionEnum, ConfigRule, TopologyIdList, TopologyList
 from webui.Config import CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT
 from context.client.ContextClient import ContextClient
 from webui.proto.context_pb2 import (ContextId, DeviceList, DeviceId,
@@ -21,10 +22,63 @@ def home():
 @device.route('add', methods=['GET', 'POST'])
 def add():
     form = AddDeviceForm()
+
+    request: ContextId = ContextId()
+    request.context_uuid.uuid = session['context_uuid']
+    client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
+    response: TopologyIdList = client.ListTopologyIds(request)
+    client.close()
+
+    # listing enum values
+    form.operational_status.choices = [(-1, 'Select...')]
+    for key, value in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_name.items():
+        form.operational_status.choices.append((DeviceOperationalStatusEnum.Value(key), key.replace('DEVICEOPERATIONALSTATUS_', '')))
+    
+    # device driver ids
+    device_driver_ids = []
+    for key in DeviceDriverEnum.DESCRIPTOR.values_by_name:
+        device_driver_ids.append(f"{DeviceDriverEnum.Value(key)}={key.replace('DEVICEDRIVER_', '')}")
+    device_driver_ids = ', '.join(device_driver_ids)
+
     if form.validate_on_submit():
-        pass
+        device: Device = Device()
+        device.device_id.device_uuid.uuid = form.device_id.data
+        device.device_type = form.device_type.data
+        if '\n' not in form.device_config.data:
+            data = form.device_config.data.strip() + '\n'
+        else:
+            data = form.device_config.data.strip()
+        
+        for config in data.split('\n'):
+            if len(config.strip()) > 0:
+                parts = config.strip().split('=')
+                config_rule: ConfigRule = ConfigRule()
+                config_rule.action = ConfigActionEnum.CONFIGACTION_SET
+                config_rule.resource_key = parts[0].strip()
+                config_rule.resource_value = parts[1].strip()
+                device.device_config.config_rules.extend([config_rule])
+
+        device.device_operational_status = form.operational_status.data
+
+        if ',' not in form.device_drivers.data:
+            data = form.device_drivers.data.strip() + ','
+        else:
+            data = form.device_drivers.data.strip()
+        
+        for driver in data.split(','):
+            driver = driver.strip()
+            if len(driver) == 0:
+                continue
+            device.device_drivers.extend([int(driver)])
+        client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
+        response: DeviceId = client.SetDevice(request)
+        client.close()
+
+        flash(f'New device was created with ID "{response.device_uuid.uuid}".', 'success')
+        
     return render_template('device/add.html', form=form,
-                    submit_text='Add New Device')
+                    submit_text='Add New Device',
+                    device_driver_ids=device_driver_ids)
 
 @device.route('detail/<device_uuid>', methods=['GET', 'POST'])
 def detail(device_uuid: str):
@@ -32,6 +86,5 @@ def detail(device_uuid: str):
     request.device_uuid.uuid = device_uuid
     client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
     response: Device = client.GetDevice(request)
-    print(response)
     client.close()
     return render_template('device/detail.html', device=response)
diff --git a/src/webui/service/static/site.js b/src/webui/service/static/site.js
new file mode 100644
index 0000000000000000000000000000000000000000..e06cea8b0bed68602ad91ed5dc52229b7b7aad75
--- /dev/null
+++ b/src/webui/service/static/site.js
@@ -0,0 +1,4 @@
+var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
+var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
+  return new bootstrap.Tooltip(tooltipTriggerEl)
+})
diff --git a/src/webui/service/templates/base.html b/src/webui/service/templates/base.html
index e4a9e58d6201594ecfaacfdf1e91fbdb29c532a6..862ae6b44f745baf3f787634f95421fb2f0459bc 100644
--- a/src/webui/service/templates/base.html
+++ b/src/webui/service/templates/base.html
@@ -108,6 +108,7 @@
 
     <!-- Option 1: Bootstrap Bundle with Popper -->
     <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-kQtW33rZJAHjgefvhyyzcGF3C5TFyBQBA13V1RKPf4uH+bwyzQxZ6CmMZHmNBEfJ" crossorigin="anonymous"></script>
+    <!-- <script src="{{ url_for('static', filename='site.js') }}"/> -->
 
     <!-- Option 2: Separate Popper and Bootstrap JS -->
     <!--
diff --git a/src/webui/service/templates/device/add.html b/src/webui/service/templates/device/add.html
index e26bf0c36ab14b4cb925da87907f2384ada3e470..dae31a37689e9c7e9704401c38e3182aaed8c311 100644
--- a/src/webui/service/templates/device/add.html
+++ b/src/webui/service/templates/device/add.html
@@ -21,6 +21,70 @@
                     {% endif %}
                 </div>
             </div>
+            <div class="row mb-3">
+                {{ form.device_type.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.device_type.errors %}
+                        {{ form.device_type(class="form-control is-invalid") }}
+                        <div class="invalid-feedback">
+                            {% for error in form.device_type.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.device_type(class="form-control") }}
+                    {% endif %}
+                </div>
+            </div>
+            <div class="row mb-3">
+                {{ form.operational_status.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.operational_status.errors %}
+                        {{ form.operational_status(class="form-control is-invalid") }}
+                        <div class="invalid-feedback">
+                            {% for error in form.operational_status.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.operational_status(class="form-control") }}
+                    {% endif %}
+                </div>
+            </div>
+            <div class="row mb-3">
+                {{ form.device_config.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.device_config.errors %}
+                        {{ form.device_config(class="form-control is-invalid", rows=5) }}
+                        <div class="invalid-feedback">
+                            {% for error in form.device_config.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.device_config(class="form-control", rows=5) }}
+                    {% endif %}
+                </div>
+                <div id="device_config_help" class="form-text">The device configurations should follow a <i>key=value</i> format, one configuration per line.</div>
+            </div>
+            <div class="row mb-3">
+                {{ form.device_drivers.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.device_drivers.errors %}
+                        {{ form.device_drivers(class="form-control is-invalid", rows=5) }}
+                        <div class="invalid-feedback">
+                            {% for error in form.device_drivers.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.device_drivers(class="form-control", rows=5) }}
+                    {% endif %}
+                </div>
+                <div id="device_drivers_help" class="form-text">
+                    List the device drivers by their numerical ID, separated by commas, without spaces between them. Numerical IDs: {{ device_driver_ids }}.
+                </div>
+            </div>
             <div class="row mb-3">
                 <button type="submit" class="btn btn-primary">{{ submit_text }}</button>
             </div>
diff --git a/src/webui/tests/test_unitary.py b/src/webui/tests/test_unitary.py
index f73621f29d98bf9bdfd7ec3c498dd62455475c23..3096e66127c33c1ef5e45d927056646998a85bf2 100644
--- a/src/webui/tests/test_unitary.py
+++ b/src/webui/tests/test_unitary.py
@@ -68,7 +68,7 @@ def test_device_detail_page(client, device_id):
     assert rw.status_code == 200
     assert b'Device' in rw.data
     assert device_id in rw.data.decode()
-    assert b'Endpoints' in rw.data, 'Missing information on the device detail page.'
+    assert b'Endpoints' in rw.data, 'Missing endpoint information on the device detail page.'
     # assert b'Add New Device' in rw.data
 
 def test_device_add_page(client):
@@ -78,3 +78,6 @@ def test_device_add_page(client):
     assert rw.status_code == 200
     assert b'Add New Device' in rw.data
     assert b'Operational Status' in rw.data, 'Form is not correctly implemented.'
+    assert b'Type' in rw.data, 'Form is not correctly implemented.'
+    assert b'Configurations' in rw.data, 'Form is not correctly implemented.'
+    assert b'Drivers' in rw.data, 'Form is not correctly implemented.'
diff --git a/src/webui/utils/__init__.py b/src/webui/utils/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/webui/utils/form_validators.py b/src/webui/utils/form_validators.py
new file mode 100644
index 0000000000000000000000000000000000000000..e339fdcc096ae8994ff0eb61a30f93d778fbe41e
--- /dev/null
+++ b/src/webui/utils/form_validators.py
@@ -0,0 +1,14 @@
+from wtforms.validators import ValidationError
+
+def key_value_validator():
+    def _validate(form, field):
+        if len(field.data) > 0:
+            if '\n' not in field.data:  # case in which there is only one configuration
+                if '=' not in field.data:
+                    raise ValidationError(f'Configuration "{field.data}" does not follow the key=value pattern.')
+            else:  # case in which there are several configurations
+                configurations = field.data.split('\n')
+                for configutation in configurations:
+                    if '=' not in configutation:
+                        raise ValidationError(f'Configuration "{configutation}" does not follow the key=value pattern.')
+    return _validate