# Autodesk Forge Viewer SDK – Example code

html
```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>APS Model Viewer</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css">
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { height: 100vh; overflow: hidden; font-family: Arial, sans-serif;}
        .header { padding: 4px; background: #3f51b5; color: white; display: flex; align-items: center; gap: 16px; height: 48px; }
        .header h1 { flex: 1; font-size: 16px; font-weight: normal; }
        .nav { display: flex; align-items: center; gap: 16px; }
        .adsk-viewing-viewer { height: calc(100vh - 48px) !important; }
        #fileInput { display: none; }
        #status { font-size: 14px; min-width: 80px; }
        select, button { padding: 8px; border: none; border-radius: 4px; }
        button { background: #2196f3; color: white; cursor: pointer; display: flex; align-items: center; gap: 8px; }
        select { background: white; }
    </style>
</head>
<body>
    <div class="header">
        <h1>APS Model Viewer</h1>
        <div class="nav">
            <input type="file" id="fileInput">
            <span id="status"></span>
            <select id="modelSelect" onchange="loadModel()">
                <option value="">Select Model</option>
            </select>
            <button onclick="$('fileInput').click()">
                <i class="material-icons">upload</i> Upload
            </button>
        </div>
    </div>
    <div id="viewer"></div>

    <script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.min.js"></script>
    <script>
        const $ = id => document.getElementById(id);
        const api = async (url, opt = {}) => (await fetch(url, opt)).json();
        const load = urn => Autodesk.Viewing.Document.load(`urn:${urn}`, d => viewer.loadDocumentNode(d, d.getRoot().getDefaultGeometry()));
        let viewer, token;

        async function init() {
            token = (await api('/api/token')).access_token;
            Autodesk.Viewing.Initializer({ env: 'AutodeskProduction', api: 'streamingV2', accessToken: token }, () => {
		const options = { extensions: ["Autodesk.SmartSection"] }; // more extensions go here
                viewer = new Autodesk.Viewing.GuiViewer3D($('viewer'), options);
                viewer.start();
	        viewer.setTheme("light-theme");

            });
            list();
        }
        
        const viewer = new AV.Private.GuiViewer3D(div, options);
        viewer.start();

        async function list() {
            const data = await api('/api/list');
            const s = $('modelSelect');
            s.innerHTML = '<option value="">Select Model</option>';
            data.items?.forEach(item => {
                const o = document.createElement('option');
                o.value = btoa(item.objectId);
                o.textContent = item.objectKey;
                s.appendChild(o);
            });
        }

        async function upload(file) {
            const fd = new FormData();
            fd.append('file', file);
            const data = await api('/api/upload', { method: 'POST', body: fd });
            monitor(data.urn);
            list();
        }

        async function monitor(urn) {
            const st = $('status');
            for (let i = 0; i < 30; i++) {
                const d = await api(`/api/status/${urn}`);
                if (d.status === 'success') {
                    st.textContent = 'Complete';
                    load(urn);
                    break;
                }
                if (d.status === 'failed') {
                    st.textContent = 'Failed';
                    break;
                }
                st.textContent = (d.progress?.match(/\d+/)?.[0] || '...') + '%';
                await new Promise(r => setTimeout(r, 2000));
            }
        }

        function loadModel() {
            const urn = $('modelSelect').value;
            if (urn) load(urn);
        }

        $('fileInput').onchange = e => e.target.files[0] && upload(e.target.files[0]);
        init();
    </script>
</body>
</html> 
```