How the City of Kings Mountain Modernized Zoning Code Enforcement
Kings Mountain modernizes zoning enforcement with a mobile GIS solution using ArcGIS Survey123 & Dashboards, enhancing efficiency, visibility, and response times for managing violations.
Overview
The City of Kings Mountain, with a population of just over 11,000 residents, has been experiencing development pressures more commonly seen in much larger communities.
To improve zoning code enforcement, the City implemented a mobile-based solution using Esri’s ArcGIS Online ecosystem. Survey123 was used for field data collection, while ArcGIS Dashboards provided a centralized view of active violations and enforcement activity. Zoning officers can now capture location information, violation details, and photos directly from the field using mobile devices.
By moving to a connected GIS workflow, the City improved response times, reduced manual effort, and increased visibility into ongoing cases and compliance activity.
The Challenge
As development activity increased, the City of Kings Mountain needed a more reliable way to manage zoning enforcement across departments and field staff. The existing process depended on paper records, spreadsheets, phone calls, and informal tracking methods. This made it difficult to keep information consistent or maintain a clear view of what was happening in the field.
Violation details were often recorded in multiple places, and it was not always easy to connect photos, inspection notes, and follow-up actions to the same case. Tracking unresolved violations or checking compliance timelines required manual effort, which slowed down response times and created gaps in visibility for supervisors.
Field staff also had limited access to historical context while on site. Understanding whether a property had prior violations or whether a case was still open often required returning to the office or checking separate records after inspections were completed.
As the volume of inspections grew, these limitations made it harder to prioritize follow-ups, monitor overdue cases, and maintain a consistent enforcement process across the city.
Our Approach
1. Field Data Capture with Survey123
We built a mobile-first workflow using Survey123 to standardize how zoning violations are collected in the field.
Key features include:
- Dynamic forms with conditional logic based on violation type
- Real-time capture of GPS location, photos, and inspection notes
- Offline support with automatic sync to ArcGIS Online
- Built-in access to historical violations for context during inspections
This ensures every violation is recorded consistently and can be submitted directly from the field without returning to the office.
2. Centralized Web Maps and Reporting
All submitted violations are published to ArcGIS Online and displayed through a centralized web map.
Key features include:
- A single operational view of all violations across the City
- Clear separation of open, pending, and resolved cases
- Simplified pop-ups focused on key enforcement details
- Direct linkage between map features, photos, and inspection records
- Support for automated reporting and enforcement notices
This creates a reliable, always-updated source of truth for zoning enforcement data.
3. Real-Time Dashboards and Monitoring
To reduce manual tracking and improve visibility, ArcGIS Dashboard is used to provide a live operational view of zoning enforcement activity.
Key features include:
- Real-time indicators for open, pending, and resolved violations
- Dynamic lists for tracking active and overdue cases
- Map-based visualization of enforcement activity across the City
- Quick access to inspection details and supporting photos
- Arcade expressions used to calculate status, timelines, and priority cases
This gives staff and supervisors immediate visibility into what needs attention without relying on manual reporting and keeps dashboards lightweight while improving real-time decision-making.
Flowchart
Why This Was the Right Fit
The City already had an investment in Esri’s ArcGIS platform, which allowed the solution to be built without introducing new systems or additional infrastructure.
Survey123 was selected because it provides a simple, structured way to collect accurate field data. It works both online and offline, which supports inspections in all areas of the City while ensuring consistent capture of photos, locations, and inspection details.
ArcGIS Dashboard was used to bring all enforcement activity into a single, real-time view. This gave staff and leadership immediate visibility into enforcement activity without relying exclusively on manual reports. Within the dashboard, Arcade expressions were used to calculate key information from live data. This added a layer of intelligence to the dashboard, reducing manual tracking and ensuring information stays current as new cases are submitted.
Impact
Since implementing the new workflow, the City of Kings Mountain has significantly improved how zoning violations are managed from the field to the office. What was once a manual, multi-step process is now handled through a connected, real-time system that improves speed, visibility, and coordination across teams.
The impact has been clear and measurable:
- Approximately 75% reduction in workflow time
- Fewer reporting errors and inconsistent records
- Real-time access to actionable enforcement data
- Greater efficiency with the same small field team
- Faster identification and follow-up of open violations
What once took days to compile and track can now be reviewed in minutes. Staff no longer rely on memory, paper notes, or disconnected spreadsheets, as all enforcement data is consistently up to date and centrally available.
Words from our client
"The Esri ecosystem has allowed us to input complaints both in and out of the office and generate base reports, eliminating the need to create reports from scratch or copy previous ones. This system has enabled our department to broaden its efforts in enforcing the City's regulations, even with just one enforcement officer."
Jaylon M. Smallwood
Zoning Administrator, City of Kings Mountain
Key Lessons & Tips
- Keep Forms Simple and Focussed
Use logic and constraints to reduce visible fields, creating a cleaner workflow that improves focus in the field and reduces errors. - Use Smart Defaults
Auto-populate fields such as date, inspector name, and location to reduce manual entry and improve consistency. - Design for Decision-Making
Structure dashboards around actions and decisions, not just data display, so staff can quickly understand what needs attention. - Prioritize Real-Time Visibility
Replace manual reporting cycles with live data views to improve responsiveness and reduce delays in decision-making. - Involve Field Staff Early
Engage end users during design to ensure workflows reflect real inspection practices and improve adoption. - Leverage Arcade for Data Expressions
Use Arcade to calculate inspection due dates, highlight overdue cases, and surface high-priority issues dynamically in dashboard indicators and lists.
Common Examples of Arcade in Dashboards
We have compiled some nifty Arcade examples that you could try in your Dashboards next
1. Calculating Inspection Status and Time Since Last Update
Data expressions can be used to create dynamic fields that update in real time based on simple business logic.
This example calculates how many days have passed since the last inspection and assigns a status depending on whether action is needed.
// Pull only required fields, no geometry for better performancevar myFeatureSet = FeatureSetByPortalItem(Portal("https://your-portal-url.com/"), "your-item-id", 0, ["AssetID", "Status", "LastInspectionDate"], false)// Store processed output featuresvar features = []// Loop through each recordfor (var f in myFeatureSet)// Days since last inspectionvar daysSince = DateDiff(Today(), f.LastInspectionDate, "days")// Set default statusvar inspectionStatus = ""// Closed records stay closedif (f.Status == "Closed") {inspectionStatus = "Closed"}// Recently inspected within 14 dayselse if (!IsEmpty(f.LastInspectionDate) && daysSince <= 14) {inspectionStatus = "Inspected"}// Open records needing inspectionelse if (f.Status == "Open" && (IsEmpty(f.LastInspectionDate) || daysSince > 14)) {inspectionStatus = "Inspection Needed"}// Build output recordPush(features, {attributes: {AssetID: f.AssetID,DaysSinceInspection: daysSince,InspectionStatus: inspectionStatus}})}// Return final FeatureSetreturn FeatureSet({fields: [{ name: "AssetID", type: "esriFieldTypeString" },{ name: "DaysSinceInspection", type: "esriFieldTypeInteger" },{ name: "InspectionStatus", type: "esriFieldTypeString" }],features: features})
2. Grouping Records by Status and Incident Category
Data expressions can also be used to create custom groupings that go beyond what is available directly in the dashboard. By combining multiple fields, you can easily summarize data in a more meaningful way.
This example groups records by their status and an existing incident category field.
// Pull required fields, no geometryvar myFeatureSet = FeatureSetByPortalItem(Portal("https://your-portal-url.com/"), "your-item-id", 0, ["Status", "IncidentCategory"], false)// Prepare outputvar features = []// Loop through recordsfor (var f in myFeatureSet) {// Build simplified datasetPush(features, {attributes: {Status: f.Status,IncidentCategory: f.IncidentCategory,Count: 1}})}// Create FeatureSetvar fs = FeatureSet({fields: [{ name: "Status", type: "esriFieldTypeString" },{ name: "IncidentCategory", type: "esriFieldTypeString" },{ name: "Count", type: "esriFieldTypeInteger" }],features: features})// Group by multiple fieldsreturn GroupBy(fs,["Status", "IncidentCategory"],[{ name: "Total", expression: "Count", statistic: "SUM" }]
)
3. Styling Dashboard Elements Based on Status
Data expressions can also be used to control how data is visually represented inside dashboard elements. This allows you to highlight important records directly within lists or tables using conditional formatting.
For example, you can change text colors based on the inspection status to quickly draw attention to records that need action.
// Get status value from the current data pointvar Status = $datapoint.InspectionStatus// Set text color based on statusvar txtColor = When(Status == "Closed", "#008000",Status == "Inspected", "#002fff",Status == "Inspection Needed", "#cf0808","#000000")// Return styling properties for the dashboard elementreturn {textColor: txtColor,backgroundColor: "",separatorColor: "",selectionColor: "",selectionTextColor: "#0c5885"}
Where to Go Next
For those looking to explore Arcade data expressions and dashboard workflows further, the following resources are a good starting point:
- Getting Started with Advanced Formatting Using Arcade in Dashboards (David Nyenhuis) – A beginner-friendly introduction to Arcade and dashboard styling techniques.
- Pushing the Limits of Arcade in Dashboards (David Nyenhuis) – Advanced use cases and deeper exploration of Arcade capabilities.
- GitHub – Arcade Expressions for Dashboards – A collection of reusable scripts and templates for common dashboard and data expression patterns.