# External Links Feature

> The External Links feature provides administrators with the ability to configure and display custom navigation links to external resources, systems, and services directly within the SimpleChat interface, creating a…

- Skill: `tools-only/external-links-feature` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/external-links-feature`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/external-links-feature/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-29
- Page: https://skillmd.com/skills/tools-only/external-links-feature

---

# External Links Feature

**Version Implemented:** 0.229.001

## Overview
The External Links feature provides administrators with the ability to configure and display custom navigation links to external resources, systems, and services directly within the SimpleChat interface, creating a unified portal experience for users.

## Purpose
External Links enable organizations to:
- Integrate SimpleChat with existing organizational tools and systems
- Provide quick access to frequently used external resources
- Create a unified navigation experience across multiple platforms
- Reduce context switching between different applications
- Customize the user experience with organization-specific links

## Technical Specifications

### Architecture Overview
- **Admin Configuration**: Dynamic link management through admin interface
- **Database Storage**: External links stored in Cosmos DB settings container
- **Security Validation**: URL validation and security checks for external links
- **Responsive Design**: Links adapt to different screen sizes and navigation contexts

### Database Schema
```json
{
  "external_links": {
    "enabled": true,
    "links": [
      {
        "id": "link-uuid-1",
        "title": "Company Intranet",
        "url": "https://intranet.company.com",
        "description": "Access company policies and procedures",
        "icon": "fas fa-building",
        "target": "_blank",
        "order": 1,
        "visible_to_roles": ["all"],
        "category": "company",
        "enabled": true
      },
      {
        "id": "link-uuid-2", 
        "title": "IT Service Desk",
        "url": "https://servicedesk.company.com",
        "description": "Submit IT support requests",
        "icon": "fas fa-headset",
        "target": "_blank",
        "order": 2,
        "visible_to_roles": ["all"],
        "category": "support",
        "enabled": true
      }
    ],
    "display_location": ["navbar", "sidebar"],
    "max_links": 10
  }
}
```

### Link Validation
```javascript
class ExternalLinkValidator {
    static validateUrl(url) {
        const errors = [];
        
        // Basic URL format validation
        try {
            const urlObj = new URL(url);
            
            // Ensure HTTPS for security
            if (urlObj.protocol !== 'https:' && urlObj.protocol !== 'http:') {
                errors.push('URL must use HTTP or HTTPS protocol');
            }
            
            // Prevent localhost and internal IPs in production
            if (this.isInternalUrl(urlObj.hostname)) {
                errors.push('Internal URLs are not allowed');
            }
            
        } catch (e) {
            errors.push('Invalid URL format');
        }
        
        return errors;
    }
    
    static isInternalUrl(hostname) {
        const internalPatterns = [
            /^localhost$/,
            /^127\./,
            /^192\.168\./,
            /^10\./,
            /^172\.(1[6-9]|2[0-9]|3[0-1])\./
        ];
        
        return internalPatterns.some(pattern => pattern.test(hostname));
    }
}
```

## Configuration Options

### Admin Settings Interface
```html
<div class="external-links-section">
    <h5>External Links Configuration</h5>
    
    <div class="form-group">
        <div class="form-check">
            <input type="checkbox" id="enable-external-links" class="form-check-input">
            <label class="form-check-label">Enable External Links</label>
        </div>
    </div>
    
    <div class="links-configuration" id="links-config">
        <div class="form-group">
            <label>Display Locations</label>
            <div class="form-check">
                <input type="checkbox" id="display-navbar" class="form-check-input" value="navbar">
                <label class="form-check-label">Navigation Bar</label>
            </div>
            <div class="form-check">
                <input type="checkbox" id="display-sidebar" class="form-check-input" value="sidebar">
                <label class="form-check-label">Left Sidebar</label>
            </div>
        </div>
        
        <div class="links-list">
            <h6>Configured Links</h6>
            <div id="external-links-container">
                <!-- Dynamic link entries -->
            </div>
            
            <button type="button" class="btn btn-primary" id="add-external-link">
                <i class="fas fa-plus"></i> Add External Link
            </button>
        </div>
    </div>
</div>
```

### Link Entry Form
```html
<div class="external-link-entry" data-link-id="">
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label>Link Title <span class="text-danger">*</span></label>
                <input type="text" class="form-control link-title" maxlength="50" required>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label>URL <span class="text-danger">*</span></label>
                <input type="url" class="form-control link-url" required>
            </div>
        </div>
    </div>
    
    <div class="row">
        <div class="col-md-4">
            <div class="form-group">
                <label>Icon (Font Awesome)</label>
                <input type="text" class="form-control link-icon" placeholder="fas fa-external-link-alt">
            </div>
        </div>
        <div class="col-md-4">
            <div class="form-group">
                <label>Category</label>
                <select class="form-control link-category">
                    <option value="general">General</option>
                    <option value="company">Company</option>
                    <option value="support">Support</option>
                    <option value="tools">Tools</option>
                    <option value="documentation">Documentation</option>
                </select>
            </div>
        </div>
        <div class="col-md-4">
            <div class="form-group">
                <label>Display Order</label>
                <input type="number" class="form-control link-order" min="1" max="10" value="1">
            </div>
        </div>
    </div>
    
    <div class="form-group">
        <label>Description (Optional)</label>
        <input type="text" class="form-control link-description" maxlength="100" 
               placeholder="Brief description for tooltips">
    </div>
    
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label>Visible to Roles</label>
                <select class="form-control link-roles" multiple>
                    <option value="all" selected>All Users</option>
                    <option value="Admin">Administrators</option>
                    <option value="DocumentManager">Document Managers</option>
                    <option value="User">Regular Users</option>
                </select>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label>Target</label>
                <select class="form-control link-target">
                    <option value="_blank">New Tab/Window</option>
                    <option value="_self">Same Tab</option>
                </select>
            </div>
        </div>
    </div>
    
    <div class="link-actions">
        <button type="button" class="btn btn-sm btn-success test-link">
            <i class="fas fa-external-link-alt"></i> Test Link
        </button>
        <button type="button" class="btn btn-sm btn-danger remove-link">
            <i class="fas fa-trash"></i> Remove
        </button>
    </div>
</div>
```

## Usage Instructions

### For Administrators

#### Adding External Links
1. **Access Admin Settings**: Navigate to Admin Settings → UI Configuration → External Links
2. **Enable Feature**: Check "Enable External Links" to activate the feature
3. **Choose Display Locations**: Select where links should appear (navbar, sidebar, or both)
4. **Add Links**: Click "Add External Link" to create new link entries
5. **Configure Link Details**:
   - **Title**: Short, descriptive name (max 50 characters)
   - **URL**: Full URL including https:// protocol
   - **Icon**: Font Awesome icon class (optional)
   - **Category**: Logical grouping for organization
   - **Description**: Tooltip text for additional context
   - **Display Order**: Numerical order for link arrangement
   - **Visible to Roles**: Control which user roles can see the link
   - **Target**: Whether link opens in new tab or same tab

#### Link Management Best Practices
```javascript
const linkManagementGuidelines = {
    urlSecurity: {
        alwaysUseHttps: "Prefer HTTPS URLs for security",
        validateDomains: "Verify links point to trusted domains",
        testRegularly: "Test all links periodically for availability"
    },
    userExperience: {
        clearTitles: "Use descriptive, concise link titles",
        consistentIcons: "Choose icons that clearly represent the destination",
        logicalOrder: "Arrange links in order of frequency of use",
        appropriateTarget: "Use new tabs for external sites, same tab for internal tools"
    },
    organization: {
        categorization: "Group related links using categories",
        roleBasedAccess: "Show only relevant links to each user role",
        regularReview: "Review and update links quarterly"
    }
};
```

#### Testing External Links
```javascript
function testExternalLink(url) {
    // Client-side validation
    try {
        const testWindow = window.open(url, '_blank', 'width=800,height=600');
        
        setTimeout(() => {
            if (testWindow && !testWindow.closed) {
                console.log('Link test successful - page loaded');
                testWindow.close();
            } else {
                console.warn('Link test failed - page may have blocked popup');
            }
        }, 3000);
        
    } catch (error) {
        console.error('Link test error:', error);
    }
}
```

### For End Users

#### Accessing External Links

**From Navigation Bar:**
- External links appear as additional menu items in the main navigation
- Click any link to open the external resource
- Hover over links to see descriptions in tooltips

**From Left Sidebar:**
- External links appear in a dedicated "Quick Links" section
- Icons provide visual identification of link types
- Links are organized by category when multiple links exist

#### Link Interaction
```html
<!-- Navbar external link example -->
<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">
        Quick Links
    </a>
    <ul class="dropdown-menu">
        <li>
            <a class="dropdown-item" href="https://intranet.company.com" target="_blank"
               title="Access company policies and procedures">
                <i class="fas fa-building"></i> Company Intranet
            </a>
        </li>
        <li>
            <a class="dropdown-item" href="https://servicedesk.company.com" target="_blank"
               title="Submit IT support requests">
                <i class="fas fa-headset"></i> IT Service Desk
            </a>
        </li>
    </ul>
</li>

<!-- Sidebar external link example -->
<div class="sidebar-section external-links">
    <h6 class="sidebar-heading">Quick Links</h6>
    <ul class="nav nav-pills flex-column">
        <li class="nav-item">
            <a class="nav-link" href="https://intranet.company.com" target="_blank"
               title="Access company policies and procedures">
                <i class="fas fa-building"></i> Company Intranet
            </a>
        </li>
    </ul>
</div>
```

## Integration Points

### Authentication Integration
- Links respect user role-based visibility settings
- Authentication status affects which links are displayed
- Integration with organizational SSO for seamless access to external systems

### Theme Integration
```css
.external-links {
    .nav-link {
        color: var(--nav-link-color);
        
        &:hover {
            color: var(--nav-link-hover-color);
            background-color: var(--nav-link-hover-bg);
        }
        
        .icon {
            color: var(--icon-color);
            margin-right: 8px;
        }
    }
}

[data-bs-theme="dark"] .external-links {
    .nav-link {
        color: var(--nav-link-color-dark);
        
        &:hover {
            color: var(--nav-link-hover-color-dark);
            background-color: var(--nav-link-hover-bg-dark);
        }
    }
}
```

### Analytics Integration
```javascript
class ExternalLinkAnalytics {
    static trackLinkClick(linkId, linkTitle, linkUrl) {
        // Track external link usage for analytics
        if (typeof gtag !== 'undefined') {
            gtag('event', 'external_link_click', {
                link_id: linkId,
                link_title: linkTitle,
                link_url: linkUrl,
                source_page: window.location.pathname
            });
        }
        
        // Internal analytics tracking
        fetch('/api/analytics/external-link-click', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                linkId,
                linkTitle,
                linkUrl,
                timestamp: new Date().toISOString()
            })
        });
    }
}
```

## Security Considerations

### URL Validation and Sanitization
```python
import re
from urllib.parse import urlparse

class ExternalLinkSecurity:
    ALLOWED_PROTOCOLS = ['http', 'https']
    BLOCKED_DOMAINS = ['localhost', '127.0.0.1']
    
    @staticmethod
    def validate_external_url(url):
        try:
            parsed = urlparse(url)
            
            # Check protocol
            if parsed.scheme not in ExternalLinkSecurity.ALLOWED_PROTOCOLS:
                return False, "Only HTTP and HTTPS URLs are allowed"
            
            # Check for blocked domains
            if parsed.hostname in ExternalLinkSecurity.BLOCKED_DOMAINS:
                return False, "Internal URLs are not permitted"
            
            # Check for private IP ranges
            if ExternalLinkSecurity.is_private_ip(parsed.hostname):
                return False, "Private IP addresses are not allowed"
            
            return True, "URL is valid"
            
        except Exception as e:
            return False, f"Invalid URL format: {str(e)}"
    
    @staticmethod
    def is_private_ip(hostname):
        # Basic private IP detection
        private_patterns = [
            r'^192\.168\.',
            r'^10\.',
            r'^172\.(1[6-9]|2[0-9]|3[0-1])\.'
        ]
        return any(re.match(pattern, hostname) for pattern in private_patterns)
```

### Content Security Policy Integration
```html
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; 
               frame-ancestors 'none'; 
               form-action 'self' https://trusted-external-domain.com;">
```

## Testing and Validation

### Functional Testing
- Verify link creation, editing, and deletion through admin interface
- Test role-based visibility for different user types
- Validate URL validation and security checks
- Confirm proper rendering in both navbar and sidebar locations

### Security Testing
- Test URL validation with various malicious input patterns
- Verify blocked internal URLs cannot be saved
- Confirm role-based access controls work correctly
- Test link behavior with different Content Security Policy settings

### User Experience Testing
- Verify responsive behavior across different screen sizes
- Test link accessibility with keyboard navigation
- Confirm tooltip functionality for link descriptions
- Validate theme integration in both light and dark modes

## Known Limitations
- Maximum of 10 external links to prevent navigation clutter
- Links must use HTTP or HTTPS protocols only
- Internal/private IP addresses are blocked for security
- Link validation is performed client-side and server-side but cannot guarantee external site availability

## Future Enhancements
- Link health monitoring and broken link detection
- Advanced analytics and usage reporting for external links
- Link categorization with collapsible sections
- Integration with bookmark management systems
- Dynamic link updates based on user preferences or usage patterns
- Support for authenticated external links with token passing
