Geolocated asset monitoring system built on MongoDB, showcasing Schema-less capabilities and native TimeSeries collections.
This application demonstrates:
- Schema-less MongoDB: insert arbitrary fields without altering the schema
- Native TimeSeries: collections optimized for temporal data
- Geospatial queries: search assets by geographic proximity
- Premium UI/UX: design inspired by Areti.it with institutional colors
Important
CRITICAL CONFIGURATION: the Asset model MUST keep strict: false to enable schema-less features. Do not remove this setting!
- Node.js + Express
- Mongoose with
{ strict: false }for schema-less - RESTful API for assets and telemetry
- 2dsphere geospatial indexes
- React + Vite
- Tailwind CSS with Areti palette
- Leaflet.js for interactive maps
- Recharts for TimeSeries visualization
- Asset collection (hybrid): base schema + dynamic fields
- Telemetry collection (TimeSeries): optimized temporal data
- Node.js 18+
- MongoDB 6.0+ running locally (or an Atlas connection string)
# Clone the repository
git clone https://github.com/Miccolomi/AretiAsset.git
cd AretiAsset
# Configure backend environment
cp backend/.env.example backend/.env
# Edit backend/.env with your MongoDB URI (default: mongodb://localhost:27017/areti-assets)
# Install backend dependencies
cd backend
npm install
# Install frontend dependencies
cd ../frontend
npm installFrom the backend/ folder, run the seed script that creates 30 synthetic assets + 5,400 TimeSeries telemetry records:
cd backend
node scripts/seed.jsUse the automated startup script:
chmod +x start.sh
./start.shOr start manually:
# Terminal 1 - Backend
cd backend
npm start
# Terminal 2 - Frontend
cd frontend
npm run dev- Frontend: http://localhost:5173
- Backend API: http://localhost:5000/api
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/assets |
List all assets |
| GET | /api/assets/:id |
Single asset detail |
| POST | /api/assets |
Create new asset (with schema-less fields) |
| GET | /api/assets/nearby/:lng/:lat/:distance |
Nearby assets (distance in meters) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/telemetry/:assetId |
Historical data for an asset |
| POST | /api/telemetry |
Insert telemetry record |
| POST | /api/telemetry/bulk |
Generate demo data |
const assetSchema = new Schema({
nome: String,
dataInstallazione: Date,
stato: String,
posizione: GeoJSON
}, {
strict: false // MAGIC! Allows undefined fields
});The UI lets users add dynamic key-value pairs:
Extra fields:
┌──────────────┬──────────┐
│ tensione │ 20kV │
│ potenza │ 5MVA │
│ numeroSerie │ ABC123 │
└──────────────┴──────────┘
The AssetCard component excludes standard fields and shows all the others:
const standardFields = ['_id', 'nome', 'stato', 'posizione'];
const schemalessFields = Object.entries(asset)
.filter(([key]) => !standardFields.includes(key));- Institutional blue:
#003366— header, sidebar, primary elements - Energy yellow:
#FFD700— accents, highlights, CTAs - Font: Inter (Google Fonts)
- Header: blue gradient with Areti logo
- Sidebar: navigation with Lucide icons
- Map: Leaflet with custom markers
- Card: premium design with gradients
- Form: rounded fields, live validation
The telemetry collection uses the native TimeSeries type:
{
timeseries: {
timeField: 'timestamp',
metaField: 'metadata',
granularity: 'minutes'
}
}Benefits:
- Automatic compression
- Optimized temporal queries
- High-performance aggregations
assetSchema.index({ posizione: '2dsphere' });// Find assets within 5000 meters
GET /api/assets/nearby/12.4964/41.9028/5000-
Add an asset:
- Fill in the base fields
- Click on the map to set coordinates
- Add extra fields: "Tensione" → "20kV", "Potenza" → "5MVA"
- Submit
-
View on map:
- See the marker on the Rome map
- Click the marker → card with ALL fields (extras included)
-
TimeSeries analysis:
- Select an asset
- Generate 50 demo data points
- View the Recharts chart
- Insert telemetry with extra fields
AretiAsset/
├── backend/
│ ├── models/
│ │ ├── Asset.js # Schema with strict: false
│ │ └── Telemetry.js # TimeSeries collection
│ ├── routes/
│ │ ├── assets.js # CRUD + geospatial
│ │ └── telemetry.js # TimeSeries API
│ ├── scripts/
│ │ └── seed.js # Seed demo data
│ ├── server.js # Express app
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ │ ├── Header.jsx
│ │ │ ├── Sidebar.jsx
│ │ │ ├── MapView.jsx # Leaflet map
│ │ │ ├── AssetCard.jsx # Schema-less display
│ │ │ ├── AssetForm.jsx # Dynamic fields
│ │ │ └── TimeSeriesView.jsx # Recharts
│ │ ├── App.jsx
│ │ └── api.js
│ ├── tailwind.config.js # Areti colors
│ └── package.json
├── start.sh # Startup script
├── README.md # English (this file)
└── README.it.md # Italian version
db.assets.findOne()
// Output shows different fields per document!db.getCollectionInfos({ name: "telemetries" })
// type: "timeseries"- Flexibility: each asset can carry different fields
- No migrations: add fields without
ALTER TABLE - Performance: TimeSeries optimized for IoT/telemetry
- Geospatial: complex queries in milliseconds
- UI/UX: professional Areti-branded design
- Authentication: not implemented (demo only)
- Validation: basic, extendable for production
- MongoDB URI: configurable in
.env
System developed for MongoDB POV demonstrations focused on schema-less and native TimeSeries.
Powered by MongoDB Atlas & Node.js 🍃