diff --git a/Dockerfile b/Dockerfile
index 1c8e395..1bced80 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,4 +4,4 @@ COPY ./phonebox_plugin /source/phonebox_plugin/phonebox_plugin/
 COPY ./setup.py /source/phonebox_plugin/
 COPY ./MANIFEST.in /source/phonebox_plugin/
 COPY ./README.md /source/phonebox_plugin/
-RUN pip3 install --no-cache-dir /source/phonebox_plugin/
+RUN /usr/local/bin/uv pip install --no-cache-dir /source/phonebox_plugin/
diff --git a/README.md b/README.md
index 710d910..e82ae06 100644
--- a/README.md
+++ b/README.md
@@ -2,12 +2,30 @@
 
 A Telephone Number Management Plugin for [NetBox](https://github.com/netbox-community/netbox) and more.
 
+## Compatibility
+
+| NetBox Version      | Plugin Version |
+|:-------------------:|:--------------:|
+|      4.2.x          |     0.0.11     |
+
 >The plugin versions 0.0.1b1-0.0.1b4 support NetBox 2.10.x versions.
 >
 >Latest plugin version 0.0.1b5 supports NetBox 2.11.0+ versions
 
 I described some general considerations behind the plugin development and future plans in my [blog post](https://idebugall.github.io/phonebox-init/).
 
+
+## Configuration
+
+This plugin can be configured to use a top level netbox menu:
+```
+PLUGINS_CONFIG = {
+        "phonebox_plugin": {
+                "top_level_menu": True
+        }
+}
+```
+
 ### Preview
 
 
diff --git a/phonebox_plugin/__init__.py b/phonebox_plugin/__init__.py
index 97458ab..9893dac 100644
--- a/phonebox_plugin/__init__.py
+++ b/phonebox_plugin/__init__.py
@@ -1,22 +1,16 @@
-from packaging import version
-from django.conf import settings
-NETBOX_CURRENT_VERSION = version.parse(settings.VERSION)
-
-if NETBOX_CURRENT_VERSION >= version.parse("4.0.0"):
-    from netbox.plugins import PluginConfig
-else:
-    from extras.plugins import PluginConfig
-
+import importlib.metadata
+from netbox.plugins import PluginConfig
 
 class PhoneBoxConfig(PluginConfig):
     name = 'phonebox_plugin'
+    version = version = importlib.metadata.version('phonebox-plugin')
     verbose_name = 'PhoneBox Plugin'
     description = 'Telephone Number Management Plugin for NetBox.'
-    version = 'v0.0.10'
     author = 'Igor Korotchenkov'
     author_email = 'iDebugAll@gmail.com'
     base_url = 'phonebox'
-    min_version = "4.1.0"
+    min_version = "4.2.0"
+    max_version = "4.2.99"
     required_settings = []
     default_settings = {}
     caching_config = {
diff --git a/phonebox_plugin/admin.py b/phonebox_plugin/admin.py
deleted file mode 100644
index fa24117..0000000
--- a/phonebox_plugin/admin.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from django.contrib import admin
-from .models import Number
-
-
-@admin.register(Number)
-class NumPlanAdmin(admin.ModelAdmin):
-    list_display = ("number", "tenant", "description", "provider", "forward_to")
diff --git a/phonebox_plugin/api/serializers.py b/phonebox_plugin/api/serializers.py
index 996fa8b..05739bf 100644
--- a/phonebox_plugin/api/serializers.py
+++ b/phonebox_plugin/api/serializers.py
@@ -4,31 +4,33 @@
 from rest_framework.validators import UniqueTogetherValidator
 from ..models import Number, VoiceCircuit
 from tenancy.api.serializers import TenantSerializer
-from dcim.api.serializers import RegionSerializer, SiteSerializer
+from dcim.api.serializers import SiteSerializer, RegionSerializer, SiteSerializer
 from circuits.api.serializers import ProviderSerializer
-from extras.api.serializers import TagSerializer
 from netbox.api.fields import ContentTypeField
 from utilities.api import get_serializer_for_model
 from ..choices import VOICE_CIRCUIT_ASSIGNMENT_MODELS
+from netbox.api.serializers import NetBoxModelSerializer
 
 
-class NumberSerializer(TagSerializer, serializers.ModelSerializer):
+class NumberSerializer(NetBoxModelSerializer):
 
     label = serializers.CharField(source='number', read_only=True)
     tenant = TenantSerializer(required=True, allow_null=False, nested=True)
     region = RegionSerializer(required=False, allow_null=True, nested=True)
+    site = SiteSerializer(required=False, allow_null=True, nested=True)
     provider = ProviderSerializer(required=False, allow_null=True, nested=True)
     forward_to = serializers.PrimaryKeyRelatedField(queryset=Number.objects.all(), required=False, allow_null=True)
-    tags = TagSerializer(many=True, required=False, nested=True)
+
 
     class Meta:
         model = Number
-        fields = [
-            "id", "label", "number", "tenant", "region", "forward_to", "description", "provider", "tags",
-        ]
+        fields = (
+            "id", "url", "display", "label", "number", "tenant", "site", "region", "forward_to", "description", "provider", "tags",
+        )
+        brief_fields = ("id", "url", "number", "display")
 
 
-class VoiceCircuitSerializer(TagSerializer, serializers.ModelSerializer):
+class VoiceCircuitSerializer(NetBoxModelSerializer):
 
     label = serializers.CharField(source='voice_circuit', read_only=True)
     tenant = TenantSerializer(required=True, allow_null=False, nested=True)
@@ -41,7 +43,6 @@ class VoiceCircuitSerializer(TagSerializer, serializers.ModelSerializer):
         allow_null=False
     )
     assigned_object = serializers.SerializerMethodField(read_only=True)
-    tags = TagSerializer(many=True, required=False, nested=True)
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_assigned_object(self, obj):
@@ -53,8 +54,9 @@ def get_assigned_object(self, obj):
 
     class Meta:
         model = VoiceCircuit
-        fields = [
-            "id", "label", "name", "voice_circuit_type", "tenant", "region", "site", "description",
+        fields = (
+            "id", "url", "label", "display", "name", "voice_circuit_type", "tenant", "region", "site", "description",
             'assigned_object_type','assigned_object_id', 'assigned_object',
             "sip_source", "sip_target", "provider", "tags",
-        ]
+        )
+        brief_fields = ("id", "url", "name", "display")
diff --git a/phonebox_plugin/api/views.py b/phonebox_plugin/api/views.py
index 1fddb48..182ce26 100644
--- a/phonebox_plugin/api/views.py
+++ b/phonebox_plugin/api/views.py
@@ -5,12 +5,8 @@
 from django.conf import settings
 from packaging import version
 
-NETBOX_CURRENT_VERSION = version.parse(settings.VERSION)
 
-if NETBOX_CURRENT_VERSION >= version.parse("3.2"):
-    from netbox.api.viewsets import NetBoxModelViewSet as ModelViewSet
-else:
-    from netbox.api.views import ModelViewSet
+from netbox.api.viewsets import NetBoxModelViewSet
 
 
 class PhoneBoxPluginRootView(APIRootView):
@@ -21,12 +17,12 @@ def get_view_name(self):
         return 'PhoneBox'
 
 
-class NumberViewSet(ModelViewSet):
+class NumberViewSet(NetBoxModelViewSet):
     queryset = Number.objects.prefetch_related('tenant', 'region', 'tags')
     serializer_class = serializers.NumberSerializer
     filterset_class = filters.NumberFilterSet
 
-class VoiceCircuitsViewSet(ModelViewSet):
+class VoiceCircuitsViewSet(NetBoxModelViewSet):
     queryset = VoiceCircuit.objects.prefetch_related('tenant', 'region', 'tags')
     serializer_class = serializers.VoiceCircuitSerializer
     filterset_class = filters.VoiceCircuitFilterSet
diff --git a/phonebox_plugin/filters.py b/phonebox_plugin/filters.py
index 1a496f1..f23acae 100644
--- a/phonebox_plugin/filters.py
+++ b/phonebox_plugin/filters.py
@@ -7,14 +7,9 @@
 from packaging import version
 from django.conf import settings
 
-NETBOX_CURRENT_VERSION = version.parse(settings.VERSION)
 
-if NETBOX_CURRENT_VERSION < version.parse("2.11.3"):
-    from utilities.filters import BaseFilterSet
-    from utilities.filters import TagFilter
-else:
-    from netbox.filtersets import BaseFilterSet
-    from extras.filters import TagFilter
+from netbox.filtersets import BaseFilterSet
+from extras.filters import TagFilter
 
 
 class NumberFilterSet(BaseFilterSet):
@@ -41,6 +36,12 @@ class NumberFilterSet(BaseFilterSet):
         to_field_name='id',
         label='Region (id)',
     )
+    site = django_filters.ModelMultipleChoiceFilter(
+        queryset=Site.objects.all(),
+        field_name='site__id',
+        to_field_name='id',
+        label='Site (id)',
+    )
     provider = django_filters.ModelMultipleChoiceFilter(
         queryset=Provider.objects.all(),
         field_name='provider__id',
diff --git a/phonebox_plugin/forms.py b/phonebox_plugin/forms.py
index e0f9cfe..66058ca 100644
--- a/phonebox_plugin/forms.py
+++ b/phonebox_plugin/forms.py
@@ -9,18 +9,11 @@
 from .models import Number, VoiceCircuit
 from .choices import VoiceCircuitTypeChoices
 
-NETBOX_CURRENT_VERSION = version.parse(settings.VERSION)
-if NETBOX_CURRENT_VERSION < version.parse("3.5"):
-    from utilities.forms import (
-        DynamicModelMultipleChoiceField, DynamicModelChoiceField,
-        TagFilterField, BulkEditForm, CSVModelForm, CSVModelChoiceField
-    )
-else:
-    from utilities.forms import BulkEditForm, CSVModelForm
-    from utilities.forms.fields import (
-        DynamicModelMultipleChoiceField, DynamicModelChoiceField,
-        TagFilterField, CSVModelChoiceField
-    )
+from utilities.forms import BulkEditForm, CSVModelForm
+from utilities.forms.fields import (
+    DynamicModelMultipleChoiceField, DynamicModelChoiceField,
+    TagFilterField, CSVModelChoiceField
+)
 
 class AddRemoveTagsForm(forms.Form):
 
@@ -57,6 +50,12 @@ class NumberFilterForm(forms.Form):
         required=False,
         null_option='None',
     )
+    site = DynamicModelMultipleChoiceField(
+        queryset=Site.objects.all(),
+        to_field_name='id',
+        required=False,
+        null_option='None',
+    )
     provider = DynamicModelMultipleChoiceField(
         queryset=Provider.objects.all(),
         to_field_name='id',
@@ -86,7 +85,7 @@ class NumberEditForm(forms.ModelForm):
     
     class Meta:
         model = Number
-        fields = ('number', 'tenant', 'region', 'description', 'provider', 'forward_to', 'tags')
+        fields = ('number', 'tenant', 'site', 'region', 'description', 'provider', 'forward_to', 'tags')
 
 
 class NumberBulkEditForm(AddRemoveTagsForm, BulkEditForm):
@@ -107,6 +106,13 @@ class NumberBulkEditForm(AddRemoveTagsForm, BulkEditForm):
         required=False,
         null_option='None',
     )
+    site = DynamicModelChoiceField(
+        queryset=Site.objects.all(),
+        to_field_name='id',
+        required=False,
+        null_option='None',
+    )
+
     provider = DynamicModelChoiceField(
         queryset=Provider.objects.all(),
         to_field_name='id',
@@ -125,7 +131,7 @@ class NumberBulkEditForm(AddRemoveTagsForm, BulkEditForm):
     )
 
     class Meta:
-        nullable_fields = ('region', 'provider', 'forward_to', 'description')
+        nullable_fields = ('region', 'site', 'provider', 'forward_to', 'description')
 
 
 class NumberCSVForm(CSVModelForm):
@@ -147,6 +153,12 @@ class NumberCSVForm(CSVModelForm):
         to_field_name='name',
         help_text='Assigned region'
     )
+    site = CSVModelChoiceField(
+        queryset=Site.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Assigned site'
+    )
     forward_to = CSVModelChoiceField(
         queryset=Number.objects.all(),
         to_field_name="number",
diff --git a/phonebox_plugin/migrations/0005_number_custom_field_data_and_more.py b/phonebox_plugin/migrations/0005_number_custom_field_data_and_more.py
new file mode 100644
index 0000000..497e548
--- /dev/null
+++ b/phonebox_plugin/migrations/0005_number_custom_field_data_and_more.py
@@ -0,0 +1,24 @@
+# Generated by Django 5.1.5 on 2025-02-18 23:47
+
+import utilities.json
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('phonebox_plugin', '0004_alter_number_created_alter_number_id_and_more'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='number',
+            name='custom_field_data',
+            field=models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder),
+        ),
+        migrations.AddField(
+            model_name='voicecircuit',
+            name='custom_field_data',
+            field=models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder),
+        ),
+    ]
diff --git a/phonebox_plugin/migrations/0006_number_site.py b/phonebox_plugin/migrations/0006_number_site.py
new file mode 100644
index 0000000..a9079f6
--- /dev/null
+++ b/phonebox_plugin/migrations/0006_number_site.py
@@ -0,0 +1,20 @@
+# Generated by Django 5.1.5 on 2025-02-19 00:19
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('dcim', '0200_populate_mac_addresses'),
+        ('phonebox_plugin', '0005_number_custom_field_data_and_more'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='number',
+            name='site',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='site_set', to='dcim.site'),
+        ),
+    ]
diff --git a/phonebox_plugin/models.py b/phonebox_plugin/models.py
index 5dfe2c8..622499e 100644
--- a/phonebox_plugin/models.py
+++ b/phonebox_plugin/models.py
@@ -8,6 +8,7 @@
 from taggit.managers import TaggableManager
 from django.urls import reverse
 from .choices import VoiceCircuitTypeChoices, VOICE_CIRCUIT_ASSIGNMENT_MODELS
+from netbox.models import NetBoxModel
 
 number_validator = RegexValidator(
     r"^\+?[0-9A-D\#\*]*$",
@@ -15,7 +16,7 @@
 )
 
 
-class Number(ChangeLoggedModel):
+class Number(NetBoxModel):
     """A Number represents a single telephone number of an arbitrary format.
     A Number can contain only valid DTMF characters and leading plus sign for E.164 support:
       - leading plus ("+") sign (optional)
@@ -53,6 +54,13 @@ class Number(ChangeLoggedModel):
         null=True,
         related_name="region_set"
     )
+    site = models.ForeignKey(
+        to="dcim.Site",
+        on_delete=models.SET_NULL,
+        blank=True,
+        null=True,
+        related_name="site_set"
+    )
     forward_to = models.ForeignKey(
         to="self",
         on_delete=models.SET_NULL,
@@ -64,19 +72,21 @@ class Number(ChangeLoggedModel):
 
     objects = RestrictedQuerySet.as_manager()
 
-    csv_headers = ['number', 'tenant', 'region', 'description', 'provider', 'forward_to']
+    csv_headers = ['number', 'tenant', 'site', 'region', 'description', 'provider', 'forward_to']
+
+    class Meta:
+        unique_together = ("number", "tenant",)
 
     def __str__(self):
         return str(self.number)
 
     def get_absolute_url(self):
-        return reverse("plugins:phonebox_plugin:number_view", kwargs={"pk": self.pk})
+        return reverse("plugins:phonebox_plugin:number", kwargs={"pk": self.pk})
+
 
-    class Meta:
-        unique_together = ("number", "tenant",)
 
 
-class VoiceCircuit(ChangeLoggedModel):
+class VoiceCircuit(NetBoxModel):
     """A Voice Circuit represents a single circuit of one of the following types:
     - SIP Trunk.
     - Digital Voice Circuit (BRI/PRI/etc).
@@ -157,4 +167,4 @@ def __str__(self):
         return str(self.name)
 
     def get_absolute_url(self):
-        return reverse("plugins:phonebox_plugin:voice_circuit_view", kwargs={"pk": self.pk})
+        return reverse("plugins:phonebox_plugin:voicecircuit", kwargs={"pk": self.pk})
diff --git a/phonebox_plugin/navigation.py b/phonebox_plugin/navigation.py
index 6b16b24..f3826c0 100644
--- a/phonebox_plugin/navigation.py
+++ b/phonebox_plugin/navigation.py
@@ -1,21 +1,57 @@
 from packaging import version
 from django.conf import settings
-NETBOX_CURRENT_VERSION = version.parse(settings.VERSION)
 
-if NETBOX_CURRENT_VERSION >= version.parse("4.0.0"):
-    from netbox.plugins import PluginMenuItem
-else:
-    from extras.plugins import PluginMenuItem
+from netbox.plugins import PluginMenuItem, PluginMenu, PluginMenuButton
+
+plugin_settings = settings.PLUGINS_CONFIG["phonebox_plugin"]
+
 
-menu_items = (
+plugin_menu = (
     PluginMenuItem(
-        link='plugins:phonebox_plugin:list_view',
+        link='plugins:phonebox_plugin:number_list',
         link_text='Numbers',
-        buttons=()
+        permissions=["phonebox_plugin.view_number"],
+        buttons=(
+            PluginMenuButton(
+                link="plugins:phonebox_plugin:number_add",
+                title="Add",
+                icon_class="mdi mdi-plus-thick",
+                permissions=["phonebox_plugin.add_number"],
+            ),
+            PluginMenuButton(
+                link="plugins:phonebox_plugin:number_bulk_import",
+                title="Import",
+                icon_class="mdi mdi-upload",
+                permissions=["phonebox_plugin.add_number"],
+            ),
+        ),
     ),
     PluginMenuItem(
-        link='plugins:phonebox_plugin:voice_circuit_list_view',
+        link='plugins:phonebox_plugin:voicecircuit_list',
         link_text='Voice Circuits',
-        buttons=()
+        permissions=["phonebox_plugin.view_voicecircuit"],
+        buttons=(
+            PluginMenuButton(
+                link="plugins:phonebox_plugin:voicecircuit_add",
+                title="Add",
+                icon_class="mdi mdi-plus-thick",
+                permissions=["phonebox_plugin.add_voicecircuit"],
+            ),
+            PluginMenuButton(
+                link="plugins:phonebox_plugin:voicecircuit_bulk_import",
+                title="Import",
+                icon_class="mdi mdi-upload",
+                permissions=["phonebox_plugin.add_voicecircuit"],
+            ),
+        ),
     ),
 )
+
+if plugin_settings.get("top_level_menu"):
+    menu = PluginMenu(
+        label="PhoneBox Plugin",
+        groups=(("Voice", plugin_menu),),
+        icon_class="mdi mdi-phone-dial",
+    )
+else:
+    menu_items = plugin_menu
diff --git a/phonebox_plugin/tables.py b/phonebox_plugin/tables.py
index e28e5df..6af467f 100644
--- a/phonebox_plugin/tables.py
+++ b/phonebox_plugin/tables.py
@@ -3,13 +3,8 @@
 from django.conf import settings
 from packaging import version
 
-NETBOX_CURRENT_VERSION = version.parse(settings.VERSION)
-
-if NETBOX_CURRENT_VERSION >= version.parse("3.2"):
-    from netbox.tables import BaseTable, columns
-    ToggleColumn = columns.ToggleColumn
-else:
-    from utilities.tables import BaseTable, ToggleColumn
+from netbox.tables import BaseTable, columns
+ToggleColumn = columns.ToggleColumn
 
 
 class NumberTable(BaseTable):
@@ -18,13 +13,14 @@ class NumberTable(BaseTable):
     number = tables.LinkColumn()
     tenant = tables.LinkColumn()
     region = tables.LinkColumn()
+    site = tables.LinkColumn()
     provider = tables.LinkColumn()
     forward_to = tables.LinkColumn()
     tags = columns.TagColumn()
 
     class Meta(BaseTable.Meta):
         model = Number
-        fields = ('pk', 'number', 'tenant', 'region', 'description', 'provider', 'forward_to', 'tags')
+        fields = ('pk', 'number', 'tenant', 'site', 'region', 'description', 'provider', 'forward_to', 'tags')
 
 
 class VoiceCircuitTable(BaseTable):
diff --git a/phonebox_plugin/templates/phonebox_plugin/add_number.html b/phonebox_plugin/templates/phonebox_plugin/add_number.html
deleted file mode 100644
index 4ad5861..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/add_number.html
+++ /dev/null
@@ -1,19 +0,0 @@
-{% extends 'generic/object_edit.html' %}
-{% load static %}
-{% load form_helpers %}
-
-{% block form %}
-    
-        
Number 
-        
-            {% render_field form.number %}
-            {% render_field form.tenant %}
-            {% render_field form.region %}
-            {% render_field form.provider %}
-            {% render_field form.forward_to %}
-            {% render_field form.description %}
-            {% render_field form.tags %}
-        
-    
-        
Number 
-        
-            {% render_field form.number %}
-            {% render_field form.tenant %}
-            {% render_field form.region %}
-            {% render_field form.provider %}
-            {% render_field form.forward_to %}
-            {% render_field form.description %}
-            {% render_field form.tags %}
-        
-    
-        
Voice Circuit 
-        
-            {% render_field form.name %}
-            {% render_field form.voice_circuit_type %}
-            {% render_field form.tenant %}
-            {% render_field form.site %}
-            {% render_field form.region %}
-            {% render_field form.provider %}
-            {% render_field form.provider_circuit_id %}
-            {% render_field form.description %}
-            {% render_field form.tags %}
-        
-        
-            
-                Interface Assignment 
-            
-            
-                {% with vm_tab_active=form.initial.vminterface %}
-                    
-                    
-                        
-                            {% render_field form.device %}
-                            {% render_field form.interface %}
-                        
-                        
-                            {% render_field form.virtual_machine %}
-                            {% render_field form.vminterface %}
-                        
-                    
-                {% endwith %}
-                {% render_field form.primary_for_parent %}
-            
-        
-        
-            
-                SIP Trunk Details 
-            
-            
-                {% render_field form.sip_source %}
-                {% render_field form.sip_target %}
-            
-        
-        
-        
-        
-        
-    
-        
Voice Circuit 
-        
-            {% render_field form.name %}
-            {% render_field form.voice_circuit_type %}
-            {% render_field form.tenant %}
-            {% render_field form.site %}
-            {% render_field form.region %}
-            {% render_field form.provider %}
-            {% render_field form.provider_circuit_id %}
-            {% render_field form.description %}
-            {% render_field form.tags %}
-        
-        
-            
-              
Interface Assignment 
-            
-            {% with vm_tab_active=form.initial.vminterface %}
-              
-                
-                  
-                    
-                        
-                            Device
-                         
-                     
-                    
-                        
-                            Virtual Machine
-                         
-                     
-                   
-                
-              
-              
-                
-                  {% render_field form.device %}
-                  {% render_field form.interface %}
-                
-                
-                  {% render_field form.virtual_machine %}
-                  {% render_field form.vminterface %}
-                
-              
-            {% endwith %}
-        
-        
-            
-                SIP Trunk Details 
-            
-            
-                {% render_field form.sip_source %}
-                {% render_field form.sip_target %}
-            
-        
-        
-        
-        
-        
-    
-	{% if perms.phonebox_plugin.add_number %}
-		{% add_button 'plugins:phonebox_plugin:add_number' %}
-	{% endif %}
-	{% if permissions.add and 'import' in action_buttons %}
-        {% import_button 'plugins:phonebox_plugin:import_numbers' %}
-    {% endif %}
-
-{% block title %}Numbers{% endblock %} 
-
-	
-        {% include 'utilities/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:number_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:number_bulk_edit" %}
-    
-	
-		{% include 'inc/search_panel.html' %}
-	
-
-	{% if perms.phonebox_plugin.add_number %}
-	  
-		 
-	{% endif %}
-	{% if perms.phonebox_plugin.add_number %}
-	  
-		 
-    {% endif %}
-
-	
-	  
-		Numbers
-	   
-	 
-	
-	
-		Filters
-		{% if filter_form %}{% badge filter_form.changed_data|length %}{% endif %}
-	 
-	 
- 
-
-
-	
-
-		{# Applied filters #}
-		{% if filter_form %}
-		  {% applied_filters model filter_form request.GET %}
-		{% endif %}
-
-		
{% block title %}Numbers{% endblock %} 
-		
-			
-				{% include 'phonebox_plugin/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:number_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:number_bulk_edit" %}
-			
-		
-	
-	
-        {% include 'inc/filter_list.html' %}
-    
-
-	{% if perms.phonebox_plugin.add_number %}
-	  
-		 
-	{% endif %}
-	{% if perms.phonebox_plugin.add_number %}
-	  
-		 
-    {% endif %}
-
-	
-	  
-		Numbers
-	   
-	 
-	
-	
-		Filters
-		{% if filter_form %}{% badge filter_form.changed_data|length %}{% endif %}
-	 
-	 
- 
-
-
-	
-		
-		{# Applied filters #}
-		{% if filter_form %}
-		  {% applied_filters filter_form request.GET %}
-		{% endif %}
-		
-		
{% block title %}Numbers{% endblock %} 
-		
-			
-				{% include 'phonebox_plugin/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:number_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:number_bulk_edit" %}
-			
-		
-	
-	
-        {% include 'inc/filter_list.html' %}
-    
-
-        {% if perms.phonebox_plugin.change_number %}
-            
-                 
-        {% endif %}
-        {% if perms.phonebox_plugin.delete_number %}
-            
-                 
-        {% endif %}
-    
{% block title %}{{ object }}{% endblock %} 
-    
-{% endblock %}
+{% extends 'generic/object.html' %}
 
 {% block content %}
 
-	
-        
-            
-                Number 
-            
+	
+        
+            
             
                 
                     Tenant 
@@ -74,6 +31,16 @@ {% block title %}{{ object }}{% endblock %} 
                         {% endif %}
                     
                  
+                
+                    Site 
+                    
+                        {% if object.site %}
+                            {{ object.site }} 
+                        {% else %}
+                            None 
+                        {% endif %}
+                     
+                 
                 
                     Provider 
                     
@@ -100,8 +67,11 @@ {% block title %}{{ object }}{% endblock %} 
                   
             
         
-        {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='plugins:phonebox_plugin:list_view' %}
+        {% include 'inc/panels/custom_fields.html' %}
+    
+    
+        {% include 'inc/panels/tags.html' %}
     
 
 
-{% endblock %}
+{% endblock content%}
diff --git a/phonebox_plugin/templates/phonebox_plugin/number_3.x.html b/phonebox_plugin/templates/phonebox_plugin/number_3.x.html
deleted file mode 100644
index 46a34c0..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/number_3.x.html
+++ /dev/null
@@ -1,108 +0,0 @@
-{% extends 'base/layout.html' %}
-{% load static %}
-
-{% block header %}
-    
-    
-        
-            
{{ object }} 
-        
-        
-            {% if perms.phonebox_plugin.change_number %}
-                
-                     
-            {% endif %}
-            {% if perms.phonebox_plugin.delete_number %}
-                
-                     
-            {% endif %}
-        
-    
-
-{% endblock %}
-
-
-{% block content %}
-
-	
-        
-            
-            
-                
-                    
-                        Tenant 
-                        
-                            {% if object.tenant %}
-                                {% if object.tenant.group %}
-                                    {{ object.tenant.group }}  /
-                                {% endif %}
-                                {{ object.tenant }} 
-                            {% else %}
-                                None 
-                            {% endif %}
-                         
-                     
-                    
-                        Region 
-                        
-                            {% if object.region %}
-                                {{ object.region }} 
-                            {% else %}
-                                None 
-                            {% endif %}
-                         
-                     
-                    
-                        Provider 
-                        
-                            {% if object.provider %}
-                                {{ object.provider }} 
-                            {% else %}
-                                None 
-                            {% endif %}
-                         
-                     
-                    
-                        Forward To 
-                        
-                            {% if object.forward_to %}
-                                {{ object.forward_to }} 
-                            {% else %}
-                                None 
-                            {% endif %}
-                         
-                     
-                    
-                        Description 
-                        {{ object.description }} 
-                     
-                
-            
-        
-        {% include 'phonebox_plugin/tags_panel.html' with tags=object.tags.all url='plugins:phonebox_plugin:list_view' %}
-    
-
-
-{% endblock content%}
diff --git a/phonebox_plugin/templates/phonebox_plugin/number_list_view_4.x.html b/phonebox_plugin/templates/phonebox_plugin/number_list_view_4.x.html
deleted file mode 100644
index 4f4992e..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/number_list_view_4.x.html
+++ /dev/null
@@ -1,73 +0,0 @@
-{% extends 'base/layout.html' %}
-{% load buttons %}
-{% load static %}
-{% load plugins %}
-{% load helpers %}
-
-
-{% block content %}
-
-
-	
-
-	  
-		
Numbers 
-		
-	  
-
-	  
-		
-
-
-	{% if perms.phonebox_plugin.add_number %}
-	
-	 
-	{% endif %}
-	{% if perms.phonebox_plugin.add_number %}
-	
-	 
-	{% endif %}
-
-
-	  
-	
-
-
-
-
-	
-	  
-		Numbers
-	   
-	 
-	
-	
-		Filters
-		{% if filter_form %}{% badge filter_form.changed_data|length %}{% endif %}
-	 
-	 
- 
-
-
-	
-		
-		{# Applied filters #}
-		{% if filter_form %}
-		  {% applied_filters model filter_form request.GET %}
-		{% endif %}
-
-		
-			
-				{% include 'phonebox_plugin/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:number_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:number_bulk_edit" %}
-			
-		
-
-	
-	
-        {% include 'inc/filter_list.html' %}
-    
-
-
-{% endblock %}
\ No newline at end of file
diff --git a/phonebox_plugin/templates/phonebox_plugin/obj_table.html b/phonebox_plugin/templates/phonebox_plugin/obj_table.html
deleted file mode 100644
index 842a90a..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/obj_table.html
+++ /dev/null
@@ -1,62 +0,0 @@
-{% load helpers %}
-{% load render_table from django_tables2 %}
-
-{% if perms.phonebox_plugin.change or perms.phonebox_plugin.delete %}
-    
-{% else %}
-
-    
-      {% render_table table 'inc/table.html' %}
-    
-
-{% endif %}
-
-{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
diff --git a/phonebox_plugin/templates/phonebox_plugin/tags_panel.html b/phonebox_plugin/templates/phonebox_plugin/tags_panel.html
deleted file mode 100644
index e67098c..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/tags_panel.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% load helpers %}
-
-  
-  
-    {% for tag in tags.all %} {% tag tag url %} {% empty %}
-    No tags assigned 
-    {% endfor %}
-  
-
diff --git a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_3.x.html b/phonebox_plugin/templates/phonebox_plugin/voice_circuit_3.x.html
deleted file mode 100644
index 0ade239..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_3.x.html
+++ /dev/null
@@ -1,170 +0,0 @@
-{% extends 'base/layout.html' %}
-{% load static %}
-
-{% block header %}
-    
-    
-        
-            
{{ object }} 
-        
-        
-            {% if perms.phonebox_plugin.change_voicecircuit %}
-                
-                     
-            {% endif %}
-            {% if perms.phonebox_plugin.delete_voicecircuit %}
-                
-                     
-            {% endif %}
-        
-    
-
-{% endblock %}
-
-
-{% block content %}
-
-	
-        
-        {% include 'phonebox_plugin/tags_panel.html' with tags=object.tags.all url='plugins:phonebox_plugin:voice_circuit_list_view' %}
-    
-    {% if object.voice_circuit_type == "sip_trunk" %}
-        
-            
-                
-                
-                    
-                        
-                            Source 
-                            {{ object.sip_source }} 
-                         
-                        
-                            Target 
-                            {{ object.sip_target }} 
-                         
-                    
-                
-            
-        
-    {% endif %}
-    {% if object.voice_circuit_type == "digital_voice_circuit" %}
-        
-    {% endif %}
-    {% if object.voice_circuit_type == "analog_voice_circuit" %}
-        
-    {% endif %}
-
-
-{% endblock content %}
diff --git a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view.html b/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view.html
deleted file mode 100644
index 29a55d9..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% extends 'base.html' %}
-{% load buttons %}
-
-{% block content %}
-
-	{% if perms.phonebox_plugin.add_voicecircuit %}
-		{% add_button 'plugins:phonebox_plugin:add_voice_circuit' %}
-	{% endif %}
-	{% if permissions.add and 'import' in action_buttons %}
-        {% import_button 'plugins:phonebox_plugin:import_voice_circuits' %}
-    {% endif %}
-
-
{% block title %}Voice Circuits{% endblock %} 
-
-	
-        {% include 'utilities/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:voice_circuit_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:voice_circuit_bulk_edit" %}
-    
-	
-		{% include 'inc/search_panel.html' %}
-	
-
-{% endblock %}
\ No newline at end of file
diff --git a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_3.4.html b/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_3.4.html
deleted file mode 100644
index e5f4ad5..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_3.4.html
+++ /dev/null
@@ -1,62 +0,0 @@
-{% extends 'base/layout.html' %}
-{% load buttons %}
-{% load static %}
-{% load plugins %}
-{% load helpers %}
-
-
-{% block controls %}
-
-
-	{% if perms.phonebox_plugin.add_voice_circuit %}
-	  
-		 
-	{% endif %}
-	{% if perms.phonebox_plugin.add_voice_circuit %}
-	  
-		 
-    {% endif %}
-
-
-{% endblock %}
-
-
-{% block content %}
-
-
-	
-	  
-		Voice Circuits
-	   
-	 
-	
-	
-		Filters
-		{% if filter_form %}{% badge filter_form.changed_data|length %}{% endif %}
-	 
-	 
- 
-
-
-	
-
-		{# Applied filters #}
-		{% if filter_form %}
-		  {% applied_filters model filter_form request.GET %}
-		{% endif %}
-
-		
{% block title %}Voice Circuits{% endblock %} 
-		
-			
-				{% include 'phonebox_plugin/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:voice_circuit_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:voice_circuit_bulk_edit" %}
-			
-		
-	
-	
-        {% include 'inc/filter_list.html' %}
-    
-
-
-{% endblock %}
diff --git a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_3.x.html b/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_3.x.html
deleted file mode 100644
index dc93dc7..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_3.x.html
+++ /dev/null
@@ -1,62 +0,0 @@
-{% extends 'base/layout.html' %}
-{% load buttons %}
-{% load static %}
-{% load plugins %}
-{% load helpers %}
-
-
-{% block controls %}
-
-
-	{% if perms.phonebox_plugin.add_voice_circuit %}
-	  
-		 
-	{% endif %}
-	{% if perms.phonebox_plugin.add_voice_circuit %}
-	  
-		 
-    {% endif %}
-
-
-{% endblock %}
-
-
-{% block content %}
-
-
-	
-	  
-		Voice Circuits
-	   
-	 
-	
-	
-		Filters
-		{% if filter_form %}{% badge filter_form.changed_data|length %}{% endif %}
-	 
-	 
- 
-
-
-	
-		
-		{# Applied filters #}
-		{% if filter_form %}
-		  {% applied_filters filter_form request.GET %}
-		{% endif %}
-		
-		
{% block title %}Voice Circuits{% endblock %} 
-		
-			
-				{% include 'phonebox_plugin/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:voice_circuit_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:voice_circuit_bulk_edit" %}
-			
-		
-	
-	
-        {% include 'inc/filter_list.html' %}
-    
-
-
-{% endblock %}
\ No newline at end of file
diff --git a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_4.x.html b/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_4.x.html
deleted file mode 100644
index 715e7ad..0000000
--- a/phonebox_plugin/templates/phonebox_plugin/voice_circuit_list_view_4.x.html
+++ /dev/null
@@ -1,73 +0,0 @@
-{% extends 'base/layout.html' %}
-{% load buttons %}
-{% load static %}
-{% load plugins %}
-{% load helpers %}
-
-
-{% block content %}
-
-
-	
-
-	  
-		
Voice Circuits 
-		
-	  
-
-	  
-	  
-		
-
-
-	{% if perms.phonebox_plugin.add_voice_circuit %}
-	
-	 
-	{% endif %}
-	{% if perms.phonebox_plugin.add_voice_circuit %}
-	
-	 
-	{% endif %}
-
-
-	  
-	
-
-
-
-
-	
-	  
-		Voice Circuits
-	   
-	 
-	
-	
-		Filters
-		{% if filter_form %}{% badge filter_form.changed_data|length %}{% endif %}
-	 
-	 
- 
-
-
-	
-
-		{# Applied filters #}
-		{% if filter_form %}
-		  {% applied_filters model filter_form request.GET %}
-		{% endif %}
-
-		
-			
-				{% include 'phonebox_plugin/obj_table.html' with bulk_delete_url="plugins:phonebox_plugin:voice_circuit_bulk_delete" bulk_edit_url="plugins:phonebox_plugin:voice_circuit_bulk_edit" %}
-			
-		
-	
-	
-        {% include 'inc/filter_list.html' %}
-    
-
-
-{% endblock %}
diff --git a/phonebox_plugin/templates/phonebox_plugin/voice_circuit.html b/phonebox_plugin/templates/phonebox_plugin/voicecircuit.html
similarity index 53%
rename from phonebox_plugin/templates/phonebox_plugin/voice_circuit.html
rename to phonebox_plugin/templates/phonebox_plugin/voicecircuit.html
index 83a2d33..9e881fd 100644
--- a/phonebox_plugin/templates/phonebox_plugin/voice_circuit.html
+++ b/phonebox_plugin/templates/phonebox_plugin/voicecircuit.html
@@ -1,55 +1,14 @@
-{% extends 'base.html' %}
-{% load buttons %}
+{% extends 'generic/object.html' %}
 {% load static %}
 
-{% block header %}
-    
-    
-        {% if perms.phonebox_plugin.change_voicecircuit %}
-            
-                 
-        {% endif %}
-        {% if perms.phonebox_plugin.delete_voicecircuit %}
-            
-                 
-        {% endif %}
-    
-    
{% block title %}{{ object }}{% endblock %} 
-    
-{% endblock %}
-
 {% block content %}
 
-	
-        
-            
-                Voice Circuit 
-            
+	
+        
+            
+
             
                 
                     Type 
@@ -80,20 +39,20 @@ {% block title %}{{ object }}{% endblock %} 
                     
                  
                 
-                    Site 
+                    Region 
                     
-                        {% if object.site %}
-                            {{ object.site }} 
+                        {% if object.region %}
+                            {{ object.region }} 
                         {% else %}
                             None 
                         {% endif %}
                      
                  
                 
-                    Region 
+                    Site 
                     
-                        {% if object.region %}
-                            {{ object.region }} 
+                        {% if object.forward_to %}
+                            {{ object.site }} 
                         {% else %}
                             None 
                         {% endif %}
@@ -119,47 +78,54 @@ {% block title %}{{ object }}{% endblock %} 
                   
             
         
-        {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='plugins:phonebox_plugin:list_view' %}
+        {% include 'inc/panels/custom_fields.html' %}
     
-
-
-{% if object.voice_circuit_type == "sip_trunk" %}
-        
-            
-                
+    {% if object.voice_circuit_type == "sip_trunk" %}
+        
+            
+                
-                
-                    
-                        Source 
-                        {{ object.sip_source }} 
-                     
-                    
-                        Target 
-                        {{ object.sip_target }} 
-                     
-                
+                
+                    
+                        
+                            Source 
+                            {{ object.sip_source }} 
+                         
+                        
+                            Target 
+                            {{ object.sip_target }} 
+                         
+                    
+                
-            
-                
+        
     {% endif %}
     {% if object.voice_circuit_type == "analog_voice_circuit" %}
-        
-            
-                
+        
     {% endif %}
+     
+        {% include 'inc/panels/tags.html' %}
+    
 
 
-{% endblock %}
+{% endblock content %}
diff --git a/phonebox_plugin/urls.py b/phonebox_plugin/urls.py
index 1c4c1ce..93dea93 100644
--- a/phonebox_plugin/urls.py
+++ b/phonebox_plugin/urls.py
@@ -1,24 +1,24 @@
-from django.urls import path
+from django.urls import path, include
 from . import views
+from utilities.urls import get_model_urls
 
+app_name = "phonebox_plugin"
 
-urlpatterns = [
-    path("", views.NumberListView.as_view(), name="list_view"),
-    path("number_list/", views.NumberListView.as_view(), name="number_list"),
-    path("number/
/", views.NumberView.as_view(), name="number_view"),
-    path("add_number/", views.NumberEditView.as_view(), name="add_number"),
-    path('import_numbers/', views.NumberBulkImportView.as_view(), name='import_numbers'),
-    path("/edit/", views.NumberEditView.as_view(), name="number_edit"),
-    path("number_bulk_edit/", views.NumberBulkEditView.as_view(), name="number_bulk_edit"),
-    path("/delete/", views.NumberDeleteView.as_view(), name="number_delete"),
-    path("number_bulk_delete/", views.NumberBulkDeleteView.as_view(), name="number_bulk_delete"),
-    path("voice_circuit//", views.VoiceCircuitView.as_view(), name="voice_circuit_view"),
-    path("voice_circuit_list_view/", views.VoiceCircuitListView.as_view(), name="voice_circuit_list_view"),
-    path("voicecircuit_list/", views.VoiceCircuitListView.as_view(), name="voicecircuit_list"),
-    path("add_voice_circuit/", views.VoiceCircuitEditView.as_view(), name="add_voice_circuit"),
-    path('import_voice_circuits/', views.VoiceCircuitBulkImportView.as_view(), name='import_voice_circuits'),
-    path("voice_circuit//edit/", views.VoiceCircuitEditView.as_view(), name="voice_circuit_edit"),
-    path("voice_circuit_bulk_edit/", views.VoiceCircuitBulkEditView.as_view(), name="voice_circuit_bulk_edit"),
-    path("voice_circuit//delete/", views.VoiceCircuitDeleteView.as_view(), name="voice_circuit_delete"),
-    path("voice_circuit_bulk_delete/", views.VoiceCircuitBulkDeleteView.as_view(), name="voice_circuit_bulk_delete"),
-]
+urlpatterns = (
+    path(
+        "numbers/",
+        include(get_model_urls("phonebox_plugin", "number", detail=False)),
+    ),
+    path(
+        "numbers//",
+        include(get_model_urls("phonebox_plugin", "number")),
+    ),
+    path(
+        "voicecircuits/",
+        include(get_model_urls("phonebox_plugin", "voicecircuit", detail=False)),
+    ),
+    path(
+        "voicecircuits//",
+        include(get_model_urls("phonebox_plugin", "voicecircuit")),
+    ),
+)
diff --git a/phonebox_plugin/views.py b/phonebox_plugin/views.py
index 05d22b8..822d4f8 100644
--- a/phonebox_plugin/views.py
+++ b/phonebox_plugin/views.py
@@ -1,55 +1,37 @@
 #!./venv/bin/python
 
 from netbox.views import generic
+from utilities.views import ViewTab, register_model_view
 from .models import Number, VoiceCircuit
 from . import filters
 from . import forms
 from . import tables
-
 from django.conf import settings
 from packaging import version
 
 
-NETBOX_CURRENT_VERSION = version.parse(settings.VERSION)
-
-
+@register_model_view(Number, "list", path="", detail=False)
 class NumberListView(generic.ObjectListView):
     queryset = Number.objects.all()
     filterset = filters.NumberFilterSet
     filterset_form = forms.NumberFilterForm
     table = tables.NumberTable
-    if NETBOX_CURRENT_VERSION >= version.parse("4.0"):
-        template_name = "phonebox_plugin/number_list_view_4.x.html"
-    elif NETBOX_CURRENT_VERSION >= version.parse("3.0") and NETBOX_CURRENT_VERSION < version.parse("3.4"):
-        template_name = "phonebox_plugin/list_view_3.x.html"
-    elif NETBOX_CURRENT_VERSION >= version.parse("3.4"):
-        template_name = "phonebox_plugin/list_view_3.4.html"
-    else:
-        template_name = "phonebox_plugin/list_view.html"
 
 
+@register_model_view(Number)
 class NumberView(generic.ObjectView):
     queryset = Number.objects.prefetch_related('tenant')
-    if NETBOX_CURRENT_VERSION >= version.parse("3.0"):
-        template_name = "phonebox_plugin/number_3.x.html"
-    else:
-        template_name = "phonebox_plugin/number.html"
+    template_name = "phonebox_plugin/number.html"
 
 
+@register_model_view(Number, "add", detail=False)
+@register_model_view(Number, "edit")
 class NumberEditView(generic.ObjectEditView):
     queryset = Number.objects.all()
-
-    if NETBOX_CURRENT_VERSION >= version.parse("3.2"):
-        form = forms.NumberEditForm
-    else:
-        model_form = forms.NumberEditForm
-
-    if NETBOX_CURRENT_VERSION >= version.parse("3.0"):
-        template_name = "phonebox_plugin/add_number_3.x.html"
-    else:
-        template_name = "phonebox_plugin/add_number.html"
+    form = forms.NumberEditForm
 
 
+@register_model_view(Number, "bulk_edit", path="edit", detail=False)
 class NumberBulkEditView(generic.BulkEditView):
     queryset = Number.objects.prefetch_related('tenant')
     filterset = filters.NumberFilterSet
@@ -57,61 +39,46 @@ class NumberBulkEditView(generic.BulkEditView):
     form = forms.NumberBulkEditForm
 
 
+@register_model_view(Number, "delete")
 class NumberDeleteView(generic.ObjectDeleteView):
     queryset = Number.objects.all()
-    default_return_url = "plugins:phonebox_plugin:list_view"
 
 
+@register_model_view(Number, "bulk_delete", path="delete", detail=False)
 class NumberBulkDeleteView(generic.BulkDeleteView):
     queryset = Number.objects.filter()
     filterset = filters.NumberFilterSet
     table = tables.NumberTable
-    default_return_url = "plugins:phonebox_plugin:list_view"
 
 
+@register_model_view(Number, "bulk_import", detail=False)
 class NumberBulkImportView(generic.BulkImportView):
     queryset = Number.objects.all()
     model_form = forms.NumberCSVForm
     table = tables.NumberTable
 
 
+@register_model_view(VoiceCircuit, "list", path="", detail=False)
 class VoiceCircuitListView(generic.ObjectListView):
     queryset = VoiceCircuit.objects.all()
     filterset = filters.VoiceCircuitFilterSet
     filterset_form = forms.VoiceCircuitFilterForm
     table = tables.VoiceCircuitTable
-    if NETBOX_CURRENT_VERSION >= version.parse("4.0"):
-        template_name = "phonebox_plugin/voice_circuit_list_view_4.x.html"
-    elif NETBOX_CURRENT_VERSION >= version.parse("3.0") and NETBOX_CURRENT_VERSION < version.parse("3.4"):
-        template_name = "phonebox_plugin/voice_circuit_list_view_3.x.html"
-    elif NETBOX_CURRENT_VERSION >= version.parse("3.4"):
-        template_name = "phonebox_plugin/voice_circuit_list_view_3.4.html"
-    else:
-        template_name = "phonebox_plugin/voice_circuit_list_view.html"
 
 
+@register_model_view(VoiceCircuit)
 class VoiceCircuitView(generic.ObjectView):
     queryset = VoiceCircuit.objects.prefetch_related('tenant')
-    if NETBOX_CURRENT_VERSION >= version.parse("3.0"):
-        template_name = "phonebox_plugin/voice_circuit_3.x.html"
-    else:
-        template_name = "phonebox_plugin/voice_circuit.html"
-
+    template_name = "phonebox_plugin/voicecircuit.html"
 
+@register_model_view(VoiceCircuit, "add", detail=False)
+@register_model_view(VoiceCircuit, "edit")
 class VoiceCircuitEditView(generic.ObjectEditView):
     queryset = VoiceCircuit.objects.all()
-    
-    if NETBOX_CURRENT_VERSION >= version.parse("3.2"):
-        form = forms.VoiceCircuitEditForm
-    else:
-        model_form = forms.VoiceCircuitEditForm
-
-    if NETBOX_CURRENT_VERSION >= version.parse("3.0"):
-        template_name = "phonebox_plugin/add_voice_circuit_3.x.html"
-    else:
-        template_name = "phonebox_plugin/add_voice_circuit.html"
+    form = forms.VoiceCircuitEditForm
 
 
+@register_model_view(VoiceCircuit, "bulk_edit", path="edit", detail=False)
 class VoiceCircuitBulkEditView(generic.BulkEditView):
     queryset = VoiceCircuit.objects.prefetch_related('tenant')
     filterset = filters.VoiceCircuitFilterSet
@@ -119,18 +86,19 @@ class VoiceCircuitBulkEditView(generic.BulkEditView):
     form = forms.VoiceCircuitBulkEditForm
 
 
+@register_model_view(VoiceCircuit, "delete")
 class VoiceCircuitDeleteView(generic.ObjectDeleteView):
     queryset = VoiceCircuit.objects.all()
-    default_return_url = "plugins:phonebox_plugin:voice_circuit_list_view"
 
 
+@register_model_view(VoiceCircuit, "bulk_delete", path="delete", detail=False)
 class VoiceCircuitBulkDeleteView(generic.BulkDeleteView):
     queryset = VoiceCircuit.objects.filter()
     filterset = filters.VoiceCircuitFilterSet
     table = tables.VoiceCircuitTable
-    default_return_url = "plugins:phonebox_plugin:voice_circuit_list_view"
 
 
+@register_model_view(VoiceCircuit, "bulk_import", detail=False)
 class VoiceCircuitBulkImportView(generic.BulkImportView):
     queryset = VoiceCircuit.objects.all()
     model_form = forms.VoiceCircuitCSVForm
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..9cb9a05
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,52 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools]
+packages = ["phonebox_plugin"]
+package-data = {"phonebox_plugin" = ["**/*", "templates/**"]}
+
+
+[tool.black]
+line-length = 140
+
+[tool.isort]
+profile = "black"
+include_trailing_comma = true
+multi_line_output = 3
+
+[tool.pylint]
+max-line-length = 140
+
+[tool.pyright]
+include = ["phonebox_plugin"]
+exclude = [
+    "**/node_modules",
+    "**/__pycache__",
+]
+reportMissingImports = true
+reportMissingTypeStubs = false
+
+[tool.ruff]
+line-length = 140
+
+[project]
+name = "phonebox-plugin"
+version = "0.0.11"
+readme = "README.md"
+requires-python = ">=3.10.0"
+classifiers=[
+    'Development Status :: 4 - Beta',
+    'Programming Language :: Python :: 3',
+    'Programming Language :: Python :: 3.6',
+    'Programming Language :: Python :: 3.7',
+    'Programming Language :: Python :: 3.8',
+]
+keywords = ["netbox", "netbox-plugin"]
+license = {file = "LICENSE"}
+
+
+[project.urls]
+Documentation = "https://github.com/iDebugAll/phonebox_plugin/blob/main/README.md"
+Source = "https://github.com/iDebugAll/phonebox_plugin/"
+Tracker = "https://github.com/iDebugAll/phonebox_plugin/issues"
\ No newline at end of file
diff --git a/setup.py b/setup.py
deleted file mode 100644
index a876f11..0000000
--- a/setup.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from setuptools import find_packages, setup
-
-from os import path
-top_level_directory = path.abspath(path.dirname(__file__))
-with open(path.join(top_level_directory, 'README.md'), encoding='utf-8') as file:
-    long_description = file.read()
-
-setup(
-    name='phonebox_plugin',
-    version='v0.0.10',
-    url='https://github.com/iDebugAll/phonebox-plugin.git',
-    download_url='https://github.com/iDebugAll/phonebox-plugin/archive/v0.0.10.tar.gz',
-    description='A phone numbers management plugin for NetBox.',
-    long_description=long_description,
-    long_description_content_type='text/markdown',
-    author='Igor Korotchenkov',
-    author_email='iDebugAll@gmail.com',
-    install_requires=[],
-    packages=find_packages(),
-    license='MIT',
-    include_package_data=True,
-    keywords=['netbox', 'netbox-plugin', 'plugin'],
-    classifiers=[
-        'Development Status :: 4 - Beta',
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.6',
-        'Programming Language :: Python :: 3.7',
-        'Programming Language :: Python :: 3.8',
-    ],
-)