ITE-ASSETDOC
Knowledge Base
v1.0 · Field Documentation System
// Knowledge Base · ITE-ASSETDOC
Field Documentation System
Complete reference for ITE-ASSETDOC — a single-file HTML application for MSP field engineers to photograph rack equipment, trigger Claude Vision AI analysis, review pre-filled asset records, and build a searchable equipment registry tied to client and site context.
Format: Self-contained .html
AI Engine: Claude claude-sonnet-4-6 Vision
Storage: localStorage (browser)
Runtime: Browser — no install
01 //What Is This Tool

ITE-ASSETDOC is a browser-based field documentation tool built for MSP engineers performing on-site rack surveys. The core workflow is: photograph equipment → Claude AI identifies make/model/serial/observations → engineer reviews → one click to save. All data is stored locally in the browser and can be exported as CSV at any time.

Single File · No Server Required
Everything lives in one .html file — UI, AI integration, storage, and all logic. Open it locally in any modern browser. Works offline for manual entry; only the AI photo analysis requires an internet connection.
Claude Vision AI Integration
Photos are sent directly from the browser to api.anthropic.com/v1/messages using your Anthropic API key. Claude claude-sonnet-4-6 returns a structured JSON object identifying device type, manufacturer, model, serial, port count, and physical observations. No intermediate server ever sees the image or key.
Full Demo Mode — No API Key Needed
All features work without an API key. Demo mode uses simulated AI profiles to animate the full capture workflow. 15 pre-loaded seed records covering 4 clients across 3 sites demonstrate the search, filter, and detail views.
02 //Architecture

The application is entirely client-side. The only external connection is the optional direct API call to Anthropic when a photo is captured with a valid key. All record data lives in localStorage under the key ite_records.

Data & request flow
Browser (eng-_ite-assetdoc.html) │ ├── Photo upload → FileReader → base64 │ │ │ └─► api.anthropic.com/v1/messages (claude-sonnet-4-6, vision) │ Headers: x-api-key, anthropic-dangerous-direct-browser-access │ Body: base64 image + structured JSON prompt │ Response: JSON {device_type, manufacturer, model_number, │ serial_number, port_count, observations} │ ├── fillFields() → type-in animation → engineer reviews │ └── saveRecord() → localStorage['ite_records'] (JSON array) │ └── renderSidebar() · renderStats() · renderAssetsTable()
ComponentWhat it does
Capture ScreenThree-panel workspace: photo upload + client context | AI analysis fields | asset record form. Confirm bar at bottom triggers save.
runAI()Calls the Anthropic API with the base64 image. Parses JSON response. Calls fillFields() with results. Falls back to runAIDemo() if no API key.
runAIDemo()Picks a random profile from DEMO_PROFILES and animates the flow with simulated delays matching a real API call.
saveRecord()Collects all field values, timestamps, engineer name, and photo data URI into a record object. Pushes to the records array and saves to localStorage.
renderSidebar()Builds the client → site → asset accordion tree from the records array. Filters inline on the search field.
Search ScreenFull-text search across all record fields. Type-filter buttons (All/Server/Switch/etc). Card grid layout with thumbnails.
Detail ModalView and edit mode. Can update photo, all fields, status, and notes. "Enrich with Photo" loads the record back into the Capture screen for a new AI pass.
03 //UI Layout
📷
🗑
Asset Browser
Tabs: Capture · Search · All Assets
Breadcrumb: Client › Site › Action
Photo Upload
Camera zone · Client/Site · Rack
AI Analysis
Fields + Raw JSON
Asset Record
ID · IP · OS · Notes
Confirm bar: status · Retake · ✓ Save Record
ZoneDescription
TitlebarApp name, status pills (AI mode / SharePoint), engineer avatar and name, live clock. Non-interactive — display only.
Rail6-button vertical icon nav. Capture, Search, All Assets screens. API Settings modal. Clear All Data. Hover shows tooltip.
SidebarClient accordion tree: Client → Site → individual assets sorted by rack location. Search field at top filters in real time. Yellow dot on client = has Needs Review items.
TabsCapture / Search / All Assets. Sync with rail buttons — clicking either navigates to the same screen.
TopbarBreadcrumb (Client › Site › Action) and per-screen action buttons (Reset, Demo Mode, Manual Entry, How It Works).
Screen areaFull-height workspace that swaps based on active screen. Capture = 3-column grid. Search = card grid. Assets = data table.
Confirm barFixed bottom bar on Capture screen. Shows unsaved dot animation, current status text, asset ID preview, Retake and Save buttons.
ToastBottom-right slide-in notification. Green border = success. Red border = error. Auto-dismisses after 3.5 seconds.
04 //Capture Screen

The primary workspace for documenting new assets. Three panels run side by side on desktop: Photo Upload (left), AI Analysis (center), Asset Record (right). Below those, Flow Status and Session Stats panels provide real-time feedback.

📷Photo Upload panel
Camera Zone
Dashed drop zone, 170px tall normally. Click to open file picker. Shows scan-line animation after capture. Expands to 300px in enrich mode.
Corner brackets
Cyan corner decorators give the zone a viewfinder aesthetic. CSS only — no functional purpose.
Client / Site / Rack
Dropdowns for Client and Site update the breadcrumb immediately via updateBC(). Rack is free-text. These three values are stamped on every saved record.
AI Analysis panel
AI fields (purple border)
Device Type, Manufacturer, Model, Serial, Port Count, Observations. All readonly until AI completes. Purple border indicates AI-populated. Editable after result.
AI Status bar
Pulsing dot + status message at top of panel. States: idle (gray) → processing (purple, animated) → done (green) → error (red).
Raw JSON block
Shows the parsed JSON response from Claude — syntax highlighted. Useful for verifying AI extraction accuracy before saving.
Flow Status panel — 6 steps
01
Trigger
App calls flow — base64 photo + context passed to AI function
02
Save Photo
Photo stored in memory as data URI; will be embedded in record on save
03
Claude Vision
HTTP POST to api.anthropic.com/v1/messages with base64 image and structured prompt
04
Parse Response
JSON extracted from response, markdown fences stripped, fields mapped to form
05
Return to App
Fields typed into form with animation; engineer reviews and may edit any value
06
Create Record
Engineer clicks Confirm & Save — record written to localStorage and sidebar updates

Full-text search across all record fields. Results render as card grid with colored top border per device type, thumbnail if photo was captured, and key metadata. Click any card to open the detail modal.

Search scope
All text fields — Asset ID, Type, Manufacturer, Model, Serial, Rack, Client, Site, Notes, Observations. Case-insensitive substring match.
Type filters
All · Server · Switch · Firewall · UPS · Other. Applied on top of the text query — both must match for a card to appear.
Sort order
Always most-recently-added first (array reversed). No manual sort available in Search — use All Assets table for sortable columns.
Card top stripe
Colored by device type: Server = cyan, Switch = steel blue, Firewall = red, UPS = yellow, default = gray. Set via CSS variable --card-c.
06 //All Assets Table

Sortable data table of every record. Click any column header to sort. Click any row to open the detail modal. Toolbar provides Export CSV, Load Demo Data, and Clear All.

ColumnFieldSortable
(thumbnail)48×36 px photo preview or placeholder iconNo
Asset IDid — yellow, boldYes (id)
Devicemfr + modelYes (name)
TypetypeYes (type)
RackrackYes (rack)
ClientclientYes (client)
Datedate (ISO YYYY-MM-DD)Yes (date)
StatusColored badgeYes (status)
Sort state persists within the session
Sort column and direction are stored in state.sortCol and state.sortDir (in-memory only). Refreshing the page resets to default sort (date, descending). The table re-sorts automatically whenever the Assets screen is rendered after a save or delete.
07 //Detail Modal

Opens over any screen when a record is clicked from the sidebar, search results, or assets table. Two modes: View and Edit. A third mode tag "MANUAL" appears for records sourced via manual entry.

View mode
Photo (190×142) or placeholder. AI Observations block below fields with purple left border. Read-only field rows for all record data.
Footer: Delete (red, requires confirm dialog) · Enrich with Photo (loads back into Capture) · Edit Record · Close.
Edit mode
Yellow Unsaved changes bar appears between header and body when any field is modified.
All fields editable including photo. Left column: new photo upload + Status dropdown + Notes. Right grid: all AI and context fields.
Footer changes to: Save Changes (green) + Cancel. Cancel reverts all edits without saving.
Enrich with Photo — updating AI data on an existing record
Clicking Enrich with Photo in the detail modal's view footer does three things: loads the record's metadata into the Capture screen context fields; shows an enrichment banner identifying the record being updated; expands the camera zone to 300px and immediately opens the file picker. Uploading a new photo runs a fresh AI analysis. Saving merges AI results back into the existing record (preserving the original ID). The old photo is kept if no new photo is uploaded.
08 //AI Flow Overview

When a photo is uploaded, handleFile() reads it as a data URL, extracts the base64 payload, and calls runAI(). If no API key is set, it falls back to runAIDemo() automatically.

1
File selected → FileReader
handleFile() reads the image as data URL via FileReader.readAsDataURL(). The base64 payload is stored in currentImageB64; the full data URL in currentImageSrc (for photo embedding in the record). showPreview() renders it in the camera zone and starts the scan-line animation.
2
API call to Claude Vision
A POST to https://api.anthropic.com/v1/messages with model claude-sonnet-4-6, max_tokens: 1024. Message content contains the base64 image as image/jpeg and a structured text prompt. Headers include anthropic-dangerous-direct-browser-access: true to allow browser-direct calls.
3
JSON parsing
The response data.content[0].text is cleaned of any markdown fences (```json) and parsed with JSON.parse(). If parsing fails, an error is thrown and the form is unlocked for manual entry anyway.
4
fillFields() with type-in animation
fillFields() calls typeIn() for each field. Text is typed character-by-character at 14ms per char for single-line fields, 6ms for the observations textarea — giving a "live typing" visual effect. AI fields get a purple border until the engineer edits them.
5
Engineer review and save
The Save button is enabled. Engineer can edit any AI-filled field (they become white on focus). Adding IP, OS, status, and notes completes the record. Clicking Confirm & Save Record in the confirm bar calls saveRecord().
09 //Prompt & Response Schema

The prompt instructs Claude to return only valid JSON — no preamble, no markdown, no explanation. The six required fields are strictly typed with example values to maximize parsing reliability.

System prompt sent with every photo
You are a data center asset documentation assistant. Analyze this equipment photo and return ONLY valid JSON. No preamble. No markdown. No explanation. JSON only. Required fields: device_type (string: "Server" | "Switch" | "Firewall" | "UPS" | "Patch Panel" | "Other") manufacturer (string: brand name if visible, else "Unknown") model_number (string: full model string if visible, else "Unknown") serial_number (string: serial if label visible, else null) port_count (integer: port count if applicable, else null) observations (string: 2-3 sentence technical description of what you see) Example output: {"device_type":"Server","manufacturer":"Dell","model_number":"PowerEdge R750", "serial_number":"DX7B002194","port_count":null, "observations":"2U rack server in good physical condition..."}
JSON fieldTypeMapped to form fieldNotes
device_typestring (enum)f-dtypeOne of 6 fixed values; defaults to "Unknown" if unrecognized
manufacturerstringf-mfr"Unknown" if brand not legible from photo
model_numberstringf-model"Unknown" if model not visible; Claude often reads front-panel labels
serial_numberstring | nullf-serialFilled with "Not visible" in the form if null from AI
port_countinteger | nullf-portsAppended with " ports" in form; "N/A" if null
observationsstringf-obs2–3 sentences: physical condition, LED state, cabling, notable observations
Serial number accuracy depends heavily on photo quality
Claude can read serial number labels from photos but requires the label to be in focus, well-lit, and at a resolution where the text is legible. Blurry or angled shots reliably return null. Best practice: take a dedicated close-up of the serial label if serial accuracy is critical — or use the Enrich flow to add a second photo specifically of the label.
10 //Demo Mode

Demo mode is the fallback when no API key is configured. It animates the full 6-step flow using a random profile from DEMO_PROFILES, with realistic delays that match a real API call. The Demo Mode button in the topbar or the Demo button in the camera zone triggers it manually.

Demo ProfileTypeConfidence
Dell PowerEdge R750Server94%
Cisco Catalyst 9300-48PSwitch91%
Fortinet FortiGate 200FFirewall87%
APC Smart-UPS 3000VA RMUPS89%
Trigger conditions
No API key set, OR clicking Demo button, OR clicking Demo Mode topbar button. runAI() checks if (!apiKey) and routes to runAIDemo() automatically.
Simulated timing
Step 0 at 0ms → Step 1 at 600ms → Step 2 at 1400ms → Step 3 at 2400ms → fields filled + Save enabled at 3400ms.
Confidence bar
Shows in Session Stats panel only in demo mode. Real AI calls don't return a confidence score — the bar is hidden for real responses.
AI Source stamp
Records saved from demo mode show aiSource: "Demo Mode". The AI Analyzed counter in session stats excludes these records.
11 //API Key Setup

An Anthropic API key with access to claude-sonnet-4-6 is required for live AI photo analysis. The key is stored in localStorage under ite_api_key and never sent anywhere except directly to api.anthropic.com.

1
Get an Anthropic API key
Log in at console.anthropic.com → API Keys → Create Key. Key must start with sk-ant-. Ensure the key has access to claude-sonnet-4-6 (included in standard API access).
2
On first open — the API Key modal appears automatically
If no key is stored in localStorage, the modal opens on load. Paste the key and click Save & Connect. The title bar pill changes to Claude Vision Active (green).
3
Change or clear the key
Click the ⚙ Settings icon in the rail at any time. The current key is pre-filled. Update and click Save & Connect. To revert to demo mode, clear the field and click Use Demo Mode.
🔑
Key security — browser direct access
The key is stored in localStorage which is readable by any JS running in the same origin. Do not use this tool on shared or untrusted computers without clearing the key afterward. The anthropic-dangerous-direct-browser-access: true header is required because browsers normally block direct API calls to third-party origins — this header explicitly opts in to that pattern. Anthropic's API accepts it for browser-only use cases.
12 //Record Schema

Each record in the records array (and localStorage['ite_records']) follows this structure. All fields are strings unless noted.

{ id: "ASSET-0001", // auto-incremented, zero-padded 4 digits type: "Server", // AI-classified device type mfr: "Dell", // manufacturer from AI or manual entry model: "PowerEdge R750", // model number serial: "DX7B002194", // serial from photo or manual; "Not visible" if AI couldn't read ports: "48 ports", // port count with " ports" suffix, or "N/A" rack: "R01-U04", // rack + unit position (engineer-entered) client: "AcmeCorp", // from client dropdown site: "Chicago-HQ", // from site dropdown ip: "10.10.1.10", // optional, manual os: "Windows Server 2022", // optional, manual status: "Active", // "Active" | "Needs Review" | "Decommissioned" notes: "Primary DC...", // engineer notes (manual textarea) obs: "2U rack server...", // AI observations paragraph engineer: "M. Krawczyk", // hardcoded to engineer in current build date: "2026-03-01", // ISO date of capture (UTC) aiSource: "Claude claude-sonnet-4-6",// "Claude claude-sonnet-4-6" | "Demo Mode" | "Manual Entry" photo: "data:image/jpeg;base64,..." // full data URI embedded in record (or null) }
Photo embedding increases localStorage usage significantly
Each photo is stored as a full base64 data URI inside the record. A typical compressed JPEG from a phone adds ~500KB–2MB per record. localStorage has a 5–10 MB limit per origin. With photos embedded, you may hit this limit after 5–10 records with full-resolution images. Recommendations: resize photos before upload, use the browser's built-in downscaling, or use the Export CSV feature regularly to back up and clear data.
13 //Storage
localStorage keyContainsCleared by
ite_recordsJSON-serialized array of all record objects including embedded photosClear All button, manual DevTools clear, or localStorage.removeItem('ite_records')
ite_api_keyAnthropic API key stringSaving a blank key, Use Demo Mode, or manual DevTools clear
Data is per-browser, per-origin — not shared between machines
localStorage is scoped to the exact origin the file is opened from. If you open file:///C:/tools/ite-assetdoc.html on two different machines, or move the file to a different path, the data is not shared. Use Export CSV to move data between machines or share with the team.
14 //Demo Seed Data

15 pre-built records across 4 clients and 3 sites seed the app on first load via seedDemoData(). They load only if records.length === 0. Use Load Demo Data in the Assets toolbar to reload them into an existing session without replacing current records.

ClientSiteAssets (count)Types included
AcmeCorpChicago-HQ7Server ×3, Switch ×2, Firewall ×1, UPS ×1 — includes 1 Needs Review (UPS) and 1 Decommissioned (R630)
NovaTech IndustriesChicago-DR3Server ×1, Firewall ×1, UPS ×1 — all Active, DR site scenario
Harbor FinancialMilwaukee-Branch3Server ×1, Switch ×1 (Needs Review), Patch Panel ×1
Redline LogisticsChicago-HQ2Server ×1, Firewall ×1 — both Active
15 //Export CSV

The Export CSV button in the All Assets toolbar generates a downloadable CSV file named ITE-ASSETDOC-YYYY-MM-DD.csv. All fields except the embedded photo are included. Values are double-quoted with internal quotes escaped.

CSV columns (in order)
ID, Type, Manufacturer, Model, Serial, Ports, Rack, Client, Site, IP, OS, Status, Engineer, Date, AI Source, Notes, Observations
Photos are not included in the CSV export
Embedded photos (base64 data URIs) are excluded from the CSV to keep file sizes manageable. The full record data including photos only exists in localStorage. If you need photos archived, export them individually via the detail modal before clearing data.
16 //Photo Capture Workflow
1
Set Client, Site, and Rack
In the Photo Upload panel, select the correct Client and Site from the dropdowns. Enter the rack location (e.g. R02-U14). These stamp every record made until you change them — set them once at the start of each rack survey.
2
Click the camera zone or Upload Photo button
Opens the device file picker. Select a photo. On mobile, this typically offers camera or gallery. The image previews immediately in the camera zone and the scan-line animation starts.
3
Wait for AI analysis
The Flow Status panel animates through steps 01–05. The AI status bar at the top of the AI Analysis panel shows "Calling Claude Vision API..." then "Parsing AI response...". Fields type themselves in when complete (~2–4 seconds on a good connection).
4
Review and correct AI fields
All AI fields become editable on focus (white text). The Raw JSON block shows exactly what Claude returned. Common corrections: serial number if label wasn't readable, model when AI read a partial string, device type if it was ambiguous.
5
Fill Asset Record fields (right panel)
Asset ID is auto-generated (read-only). Add IP address, OS/firmware, status, and any engineer notes. Status defaults to Active.
6
Click Confirm & Save Record
The confirm bar at the bottom shows the asset ID and current status. Click the green button. The flow advances to step 06, a toast confirms the save, and the sidebar updates. The form resets and a new Asset ID is generated for the next capture.
17 //Manual Entry Workflow

Manual entry skips the photo and AI steps entirely. Use it when you know the asset details and don't have a photo, or when the AI analysis fails and you prefer to type data directly.

1
Click Manual Entry in the topbar
Calls startManualEntry() which: resets the form, sets all AI-tagged fields to readOnly=false and removes the ai CSS class (purple border), enables the Save button immediately, and stamps aiSource as "Manual Entry".
2
Fill all fields manually
All AI Analysis fields are now directly editable — no photo required. The record badge shows MANUAL (purple). The flow panel stays at step -1 (all waiting) since no AI flow ran.
3
Save as normal
Confirm & Save Record works identically. The saved record will show aiSource: "Manual Entry" in the detail view. No photo is embedded (null). The record is fully searchable and editable like any other.
18 //Record Enrichment Workflow

Enrichment lets you run a new AI photo analysis against an existing record — updating its AI fields without creating a duplicate. Useful when a record was created in manual or demo mode and you later have a photo, or when you want a better photo of a piece of equipment.

1
Open the record → Enrich with Photo
In the detail modal's view mode footer, click Enrich with Photo. The modal closes. loadIntoCapture() switches to the Capture screen, pre-fills Client, Site, and Rack from the existing record, and shows the enrichment banner at the top of the screen identifying which record is being updated.
2
File picker opens automatically
The camera zone expands to 300px (enrich mode) and the file picker fires automatically after 200ms. Select the new photo. AI analysis runs as normal.
3
Review and confirm
The confirm bar shows "Updating ASSET-XXXX". Click Confirm & Save Record. saveRecord() detects state.isUpdate === true and calls update logic instead of push — finds the existing record by state.updateId, merges the new data, and preserves the original ID. Old photo is kept if no new photo was uploaded.
4
Cancel enrichment
Click ✕ Cancel Update in the enrichment banner at any time. Calls cancelEnrich() which hides the banner, collapses the camera zone, resets state.isUpdate and state.updateId, and calls resetAll().
19 //Device Types & Color Coding
Server
Cyan — rack servers, blades, any compute
Switch
Steel blue — managed & unmanaged switches
Firewall
Red — NGFW, UTM, security appliances
UPS
Yellow — rack UPS, PDU, power gear
Patch Panel
Orange — Cat5/6/6A patch panels
Other
Gray — KVM, monitors, cable managers

Colors are defined in the TYPE_COLORS object in JS and applied to: sidebar icons, search card top borders, asset table placeholder icons, and detail modal header accents. The six types match the exact values Claude is instructed to return in the AI prompt's device_type enum — anything outside this set maps to "Other" / gray.

20 //Status Values
StatusBadgeSidebar indicatorUse when
Active Active Green dot on badge Equipment is operational and in production use. Default for all new records.
Needs Review Review Yellow dot on client accordion header Something needs attention — failing battery, intermittent port, suspected hardware issue, upcoming decommission. The yellow dot on the client in the sidebar signals this without opening the client.
Decommissioned Decomm Gray badge, no dot Equipment has been powered off and is awaiting disposal or has been removed. Kept in records for audit trail.
21 //Sidebar Asset Browser

The left sidebar renders an accordion tree of all records organized by Client → Site → Asset. Assets within each site are sorted by rack location alphabetically.

Client accordion
Click a client name to expand. Only one client expands at a time — clicking a second collapses the first. Exception: while searching, all matching clients expand simultaneously.
Site sub-header
Only shown when a client has more than one site in the current result set. Appears as a small dim label between site groups.
Asset row
Icon (device type color), display name (mfr + model), rack + type meta row, status badge. Click any row to open the detail modal for that record.
Search filter
Searches across: model, type, rack, manufacturer, client, site, serial, ID. Case-insensitive. Clears accordion state and shows all matches expanded. Clearing the search restores the accordion.
Yellow dot on client
Appears when any asset in that client has status === "Needs Review". Visible even when the client is collapsed.
22 //Troubleshooting
AI Error: "Failed to fetch" or CORS error
The API key is valid but the browser blocked the request. Ensure the file is opened directly in Chrome or Edge (not Safari, which has stricter CORS rules for direct API calls). The header anthropic-dangerous-direct-browser-access: true is required and already included in the request.
AI Error: "401 Unauthorized"
API key is incorrect or expired. Click the ⚙ Settings icon in the rail, clear the key field, paste the correct key starting with sk-ant-, and click Save & Connect.
AI Error: "Could not parse AI JSON response"
Claude returned text instead of pure JSON — this can happen with unusual images or if the model adds a preamble. The save button is still enabled so you can save with manual corrections. This error is rare with claude-sonnet-4-6 given the strict prompt.
localStorage quota exceeded — records not saving
Embedded photos fill localStorage quickly. Go to All Assets → Export CSV to back up your data, then use Clear All to free space. Consider resizing photos to under 800px wide before uploading to reduce storage impact.
Records disappeared after opening in a different browser
localStorage is browser-specific and not synced. If you used Chrome to capture records and open the file in Firefox, the data won't be there. Always use the same browser. Export CSV regularly to create portable backups.
Client or Site not in the dropdown
Client and site dropdowns are hardcoded in the HTML: <option> tags in both the Capture screen (f-client, f-site) and the detail modal edit mode (de-client, de-site). Edit the HTML to add new entries. Both dropdowns need to be updated for consistency.
Engineer name is hardcoded
The engineer field is hardcoded to "M. Krawczyk" in saveRecord(). To change this, search the JS for engineer: 'M. Krawczyk' and update it, or replace with a dynamic input field.
Demo data reloaded but IDs conflict with existing records
reloadDemoData() checks for ID conflicts before adding — it only adds demo records whose IDs don't already exist. If you have records ASSET-0001 through ASSET-0015 from a previous demo load, nothing will be added. Use Clear All first if you want a clean demo state.

ITE-ASSETDOC KB · KrawTech MSP Tooling · eng-_ite-assetdoc.html · v1.0