InspectionJanuary 1, 2024Β· 14 min read
Website Technology Stack Detection: Uncover What Powers Any Site
A practical Fusebox guide to website technology stack detection.
Website Technology Stack Detection: Uncover What Powers Any Site
Published: January 2024
Reading time: 9 minutes
Every website leaves digital fingerprints. From the JavaScript framework to the hosting provider, each technology choice reveals itself through patterns, headers, and behaviors. Here's how to detect any website's tech stack and understand what it means for performance and security.
Why Stack Detection Matters
Strategic Intelligence
- Competitive analysis - Know exactly what competitors use
- Migration planning - Understand current stack before changes
- Security assessment - Each technology has known vulnerabilities
- Performance insights - Some stacks are inherently faster
- Integration compatibility - Ensure third-party services work
Real-World Applications
Developer: "What CMS does this site use?"
Security: "Is this running an outdated framework?"
Business: "Can we build something similar?"
Support: "Why is this integration failing?"
Sales: "What technologies does the prospect use?"
Quick Stack Detection
1. Instant Technology Finder
// Detect technologies on current page
(function detectTechStack() {
console.log('π Technology Stack Detection\n');
const detected = {
frontend: {},
backend: {},
infrastructure: {},
analytics: {},
security: {},
cms: {}
};
// 1. Frontend Framework Detection
console.log('1οΈβ£ Frontend Technologies:');
// React
if (window.React || document.querySelector('[data-reactroot]') ||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
detected.frontend.React = {
version: window.React?.version || 'Unknown',
devTools: !!window.__REACT_DEVTOOLS_GLOBAL_HOOK__
};
console.log(` βοΈ React ${detected.frontend.React.version}`);
}
// Vue.js
if (window.Vue || document.querySelector('[data-v-]')) {
const vueVersion = window.Vue?.version ||
document.querySelector('[data-server-rendered]') ? '2.x/3.x SSR' : 'Unknown';
detected.frontend.Vue = { version: vueVersion };
console.log(` π’ Vue.js ${vueVersion}`);
}
// Angular
if (window.ng || window.angular || document.querySelector('[ng-version]')) {
const ngVersion = document.querySelector('[ng-version]')?.getAttribute('ng-version') ||
window.angular?.version?.full || 'Unknown';
detected.frontend.Angular = { version: ngVersion };
console.log(` πΊ Angular ${ngVersion}`);
}
// jQuery
if (window.jQuery || window.$) {
detected.frontend.jQuery = {
version: window.jQuery?.fn?.jquery || 'Unknown',
plugins: []
};
console.log(` π² jQuery ${detected.frontend.jQuery.version}`);
// Detect jQuery plugins
if (window.jQuery) {
const plugins = Object.keys(jQuery.fn).filter(key =>
!['init', 'constructor', 'jquery'].includes(key)
).slice(0, 5);
if (plugins.length > 0) {
console.log(` Plugins: ${plugins.join(', ')}`);
}
}
}
// Next.js
if (window.__NEXT_DATA__ || document.querySelector('[id="__next"]')) {
detected.frontend.NextJS = {
version: window.__NEXT_DATA__?.buildId || 'Unknown',
isSSG: !!window.__NEXT_DATA__?.gssp,
isSSR: !!window.__NEXT_DATA__?.props
};
console.log(` β² Next.js (${detected.frontend.NextJS.isSSG ? 'SSG' : 'SSR'})`);
}
// Gatsby
if (window.___gatsby || document.querySelector('[id="___gatsby"]')) {
detected.frontend.Gatsby = { detected: true };
console.log(' π£ Gatsby');
}
// Svelte
if (document.querySelector('[class*="svelte-"]')) {
detected.frontend.Svelte = { detected: true };
console.log(' π Svelte');
}
// 2. CSS Framework Detection
console.log('\n2οΈβ£ CSS Frameworks:');
const cssFrameworks = {
Bootstrap: {
check: () => window.bootstrap || document.querySelector('[class*="col-md-"]'),
version: () => window.bootstrap?.VERSION
},
Tailwind: {
check: () => document.querySelector('[class*="flex "][class*="items-"][class*="justify-"]'),
version: () => 'Unknown'
},
Bulma: {
check: () => document.querySelector('[class*="columns "][class*="column "]'),
version: () => 'Unknown'
},
Foundation: {
check: () => window.Foundation || document.querySelector('[class*="small-"][class*="medium-"]'),
version: () => window.Foundation?.version
},
MaterialUI: {
check: () => document.querySelector('[class*="MuiButton-"][class*="MuiPaper-"]'),
version: () => 'Unknown'
}
};
Object.entries(cssFrameworks).forEach(([name, framework]) => {
if (framework.check()) {
const version = framework.version();
detected.frontend[name] = { version };
console.log(` π¨ ${name} ${version || ''}`);
}
});
// 3. Backend/Server Detection
console.log('\n3οΈβ£ Backend Detection:');
// Server headers (would need to be fetched)
fetch(window.location.href, { method: 'HEAD' })
.then(response => {
const server = response.headers.get('server');
const poweredBy = response.headers.get('x-powered-by');
if (server) {
console.log(` π₯οΈ Server: ${server}`);
detected.backend.server = server;
}
if (poweredBy) {
console.log(` β‘ Powered By: ${poweredBy}`);
detected.backend.poweredBy = poweredBy;
}
})
.catch(() => {});
// CMS Detection
console.log('\n4οΈβ£ CMS Detection:');
// WordPress
if (document.querySelector('meta[name="generator"][content*="WordPress"]') ||
document.querySelector('link[href*="wp-content"]') ||
document.querySelector('link[href*="wp-includes"]')) {
const wpVersion = document.querySelector('meta[name="generator"]')?.content?.match(/WordPress ([\d.]+)/)?.[1];
detected.cms.WordPress = { version: wpVersion || 'Unknown' };
console.log(` π WordPress ${wpVersion || ''}`);
// Detect WP plugins
const wpPlugins = [];
document.querySelectorAll('link[href*="wp-content/plugins"]').forEach(link => {
const plugin = link.href.match(/plugins\/([^\/]+)/)?.[1];
if (plugin && !wpPlugins.includes(plugin)) {
wpPlugins.push(plugin);
}
});
if (wpPlugins.length > 0) {
console.log(` Plugins: ${wpPlugins.slice(0, 3).join(', ')}`);
}
}
// Shopify
if (window.Shopify || document.querySelector('[id="shopify-features"]')) {
detected.cms.Shopify = { detected: true };
console.log(' ποΈ Shopify');
}
// Wix
if (document.querySelector('[href*=".wix.com"]') || window.wixBiSession) {
detected.cms.Wix = { detected: true };
console.log(' π― Wix');
}
// Squarespace
if (window.Squarespace || document.querySelector('[class*="sqs-"]')) {
detected.cms.Squarespace = { detected: true };
console.log(' β¬ Squarespace');
}
// 5. Analytics & Tracking
console.log('\n5οΈβ£ Analytics & Tracking:');
// Google Analytics
if (window.ga || window.gtag || window.google_analytics_uacct) {
const gaVersion = window.gtag ? 'GA4' : 'Universal Analytics';
detected.analytics.GoogleAnalytics = { version: gaVersion };
console.log(` π Google Analytics (${gaVersion})`);
}
// Google Tag Manager
if (window.google_tag_manager || document.querySelector('[src*="googletagmanager.com"]')) {
detected.analytics.GTM = { detected: true };
console.log(' π·οΈ Google Tag Manager');
}
// Facebook Pixel
if (window._fbq || window.fbq) {
detected.analytics.FacebookPixel = { detected: true };
console.log(' π Facebook Pixel');
}
// Hotjar
if (window.hj || window._hjSettings) {
detected.analytics.Hotjar = { detected: true };
console.log(' π₯ Hotjar');
}
// 6. Infrastructure
console.log('\n6οΈβ£ Infrastructure & CDN:');
// Cloudflare
if (window.__CF || document.querySelector('[data-cf-beacon]')) {
detected.infrastructure.Cloudflare = { detected: true };
console.log(' βοΈ Cloudflare');
}
// Check for CDN by analyzing resource URLs
const cdnPatterns = {
'CloudFront': /cloudfront\.net/,
'Fastly': /fastly\.net/,
'Akamai': /akamaihd\.net/,
'MaxCDN': /maxcdn\.com/,
'jsDelivr': /jsdelivr\.net/,
'unpkg': /unpkg\.com/
};
const resources = performance.getEntriesByType('resource');
const detectedCDNs = new Set();
resources.forEach(resource => {
Object.entries(cdnPatterns).forEach(([cdn, pattern]) => {
if (pattern.test(resource.name)) {
detectedCDNs.add(cdn);
}
});
});
detectedCDNs.forEach(cdn => {
console.log(` π ${cdn} CDN`);
detected.infrastructure[cdn] = { detected: true };
});
// Summary
console.log('\nπ Detection Summary:');
let totalDetected = 0;
Object.entries(detected).forEach(([category, items]) => {
const count = Object.keys(items).length;
if (count > 0) {
totalDetected += count;
console.log(` ${category}: ${count} technologies`);
}
});
console.log(`\nTotal technologies detected: ${totalDetected}`);
return detected;
})();
2. Deep Framework Analysis
// Analyze framework versions and configurations
function analyzeFrameworks() {
console.log('\n㪠Deep Framework Analysis\n');
// React Analysis
if (window.React || window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
console.log('βοΈ React Framework Analysis:');
// Check React version
const reactVersion = window.React?.version || 'Unknown';
console.log(` Version: ${reactVersion}`);
// Check for React Router
if (window.ReactRouter || document.querySelector('[class*="react-router"]')) {
console.log(' β
React Router detected');
}
// Check for Redux
if (window.__REDUX_DEVTOOLS_EXTENSION__ || window.Redux) {
console.log(' β
Redux state management');
if (window.__REDUX_DEVTOOLS_EXTENSION__) {
console.log(' π§ Redux DevTools enabled');
}
}
// Check for Material-UI
if (document.querySelector('[class*="MuiButton-"]')) {
console.log(' β
Material-UI components');
}
// Performance mode
if (window._REACT_FIBER_) {
console.log(' β
React Fiber enabled');
}
// Server-side rendering
if (document.querySelector('[data-reactroot]')?.innerHTML.length > 1000) {
console.log(' β
Likely server-side rendered');
}
}
// Vue.js Analysis
if (window.Vue || document.querySelector('[data-v-]')) {
console.log('\nπ’ Vue.js Framework Analysis:');
// Vue version and mode
if (window.Vue) {
console.log(` Version: ${window.Vue.version}`);
console.log(` Dev mode: ${window.Vue.config?.devtools || false}`);
}
// Vuex detection
if (window.$nuxt?.$store || document.querySelector('[data-v-][data-server-rendered]')) {
console.log(' β
Vuex state management');
}
// Nuxt.js detection
if (window.$nuxt || window.__NUXT__) {
console.log(' β
Nuxt.js framework');
if (window.__NUXT__?.config) {
console.log(` Mode: ${window.__NUXT__.config.mode || 'universal'}`);
}
}
// Vue Router
if (window.$nuxt?.$router || window.VueRouter) {
console.log(' β
Vue Router');
}
}
// Angular Analysis
if (window.ng || window.angular || document.querySelector('[ng-version]')) {
console.log('\nπΊ Angular Framework Analysis:');
const ngVersion = document.querySelector('[ng-version]')?.getAttribute('ng-version');
if (ngVersion) {
console.log(` Version: Angular ${ngVersion}`);
} else if (window.angular) {
console.log(` Version: AngularJS ${window.angular.version.full}`);
}
// Angular Universal (SSR)
if (document.querySelector('[ng-server-context]')) {
console.log(' β
Angular Universal (SSR)');
}
// Check for common Angular libraries
if (window.ng?.probe) {
console.log(' π§ Angular DevTools available');
}
}
// Build tool detection
console.log('\nπ οΈ Build Tools & Bundlers:');
// Webpack
if (window.webpackJsonp || window.webpackChunk) {
console.log(' π¦ Webpack');
// Check for hot module replacement
if (window.__webpack_require__?.hmr) {
console.log(' π₯ Hot Module Replacement enabled');
}
}
// Vite
if (document.querySelector('[type="module"][src*="@vite"]') || window.__vite__) {
console.log(' β‘ Vite');
}
// Parcel
if (window.parcelRequire) {
console.log(' π¦ Parcel');
}
}
analyzeFrameworks();
3. Backend Technology Detection
// Detect backend technologies from client-side clues
async function detectBackend() {
console.log('\nπ₯οΈ Backend Technology Detection\n');
const backend = {
language: null,
framework: null,
server: null,
features: []
};
try {
// Make a HEAD request to check headers
const response = await fetch(window.location.href, { method: 'HEAD' });
const headers = {};
// Collect all headers
for (let [key, value] of response.headers.entries()) {
headers[key.toLowerCase()] = value;
}
console.log('π Response Headers Analysis:');
// Server detection
if (headers.server) {
console.log(`\nServer: ${headers.server}`);
backend.server = headers.server;
// Parse server header
if (headers.server.includes('nginx')) {
console.log(' β Nginx web server');
} else if (headers.server.includes('Apache')) {
console.log(' β Apache web server');
} else if (headers.server.includes('cloudflare')) {
console.log(' β Cloudflare proxy');
} else if (headers.server.includes('Microsoft-IIS')) {
console.log(' β Microsoft IIS');
}
}
// Language/Framework detection
if (headers['x-powered-by']) {
console.log(`\nPowered By: ${headers['x-powered-by']}`);
const poweredBy = headers['x-powered-by'].toLowerCase();
if (poweredBy.includes('php')) {
backend.language = 'PHP';
console.log(' β PHP backend');
} else if (poweredBy.includes('asp.net')) {
backend.language = 'C#';
backend.framework = 'ASP.NET';
console.log(' β ASP.NET framework');
} else if (poweredBy.includes('express')) {
backend.language = 'Node.js';
backend.framework = 'Express';
console.log(' β Express.js framework');
}
}
// Session cookie analysis
console.log('\nπͺ Session Cookie Analysis:');
const cookies = document.cookie.split(';');
cookies.forEach(cookie => {
const [name] = cookie.trim().split('=');
// PHP session
if (name === 'PHPSESSID') {
backend.language = backend.language || 'PHP';
console.log(' β PHP session detected');
}
// ASP.NET session
else if (name === 'ASP.NET_SessionId') {
backend.language = backend.language || 'C#';
backend.framework = backend.framework || 'ASP.NET';
console.log(' β ASP.NET session detected');
}
// Java session
else if (name === 'JSESSIONID') {
backend.language = backend.language || 'Java';
console.log(' β Java session detected');
}
// Rails session
else if (name.includes('_session') && name.includes('rails')) {
backend.language = backend.language || 'Ruby';
backend.framework = backend.framework || 'Rails';
console.log(' β Ruby on Rails session detected');
}
// Django session
else if (name === 'sessionid' || name === 'csrftoken') {
backend.language = backend.language || 'Python';
backend.framework = backend.framework || 'Django';
console.log(' β Django session detected');
}
});
// URL patterns
console.log('\nπ URL Pattern Analysis:');
const urlPatterns = {
'.php': 'PHP',
'.asp': 'ASP Classic',
'.aspx': 'ASP.NET',
'.jsp': 'Java/JSP',
'.do': 'Java/Struts',
'.cgi': 'CGI Script',
'.pl': 'Perl',
'.py': 'Python',
'.rb': 'Ruby'
};
const currentPath = window.location.pathname;
Object.entries(urlPatterns).forEach(([ext, tech]) => {
if (currentPath.includes(ext)) {
console.log(` β ${tech} detected from URL`);
backend.language = backend.language || tech.split('/')[0];
}
});
// API endpoint patterns
console.log('\nπ API Endpoint Patterns:');
// Look for common API patterns in the page
const apiPatterns = [
{ pattern: /\/api\/v\d+/, tech: 'RESTful API versioning' },
{ pattern: /\/graphql/, tech: 'GraphQL API' },
{ pattern: /\/rest\//, tech: 'REST API' },
{ pattern: /\/_api\//, tech: 'SharePoint API' },
{ pattern: /\/odata\//, tech: 'OData API' },
{ pattern: /\/jsonrpc/, tech: 'JSON-RPC API' }
];
const pageContent = document.documentElement.innerHTML;
apiPatterns.forEach(({ pattern, tech }) => {
if (pattern.test(pageContent)) {
console.log(` β ${tech}`);
backend.features.push(tech);
}
});
} catch (error) {
console.log('β Could not fetch headers (CORS)');
}
// Error page signatures
console.log('\nβ οΈ Error Page Signatures:');
// Create a hidden iframe to test 404 page
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = '/this-page-definitely-does-not-exist-404-test';
iframe.onload = () => {
try {
const errorContent = iframe.contentDocument?.body?.innerHTML || '';
// Check for framework-specific error pages
if (errorContent.includes('Whitelabel Error Page')) {
console.log(' β Spring Boot detected');
backend.framework = 'Spring Boot';
} else if (errorContent.includes('django.core.exceptions')) {
console.log(' β Django detected');
backend.framework = 'Django';
} else if (errorContent.includes('Rails.root')) {
console.log(' β Ruby on Rails detected');
backend.framework = 'Rails';
}
} catch (e) {
// Can't access iframe content (different origin)
}
document.body.removeChild(iframe);
};
document.body.appendChild(iframe);
// Summary
setTimeout(() => {
console.log('\nπ Backend Detection Summary:');
console.log(`Language: ${backend.language || 'Unknown'}`);
console.log(`Framework: ${backend.framework || 'Unknown'}`);
console.log(`Server: ${backend.server || 'Unknown'}`);
if (backend.features.length > 0) {
console.log(`Features: ${backend.features.join(', ')}`);
}
}, 2000);
return backend;
}
detectBackend();
Security Implications
1. Version Vulnerability Scanner
// Check for known vulnerabilities in detected versions
function scanVulnerabilities() {
console.log('\nπ‘οΈ Vulnerability Scanner\n');
const vulnerabilities = [];
// jQuery version check
if (window.jQuery) {
const version = window.jQuery.fn.jquery;
const [major, minor, patch] = version.split('.').map(Number);
console.log(`jQuery ${version} detected`);
if (major < 3 || (major === 3 && minor < 5)) {
vulnerabilities.push({
component: 'jQuery',
version: version,
severity: 'HIGH',
cve: 'CVE-2020-11022',
description: 'XSS vulnerability in jQuery < 3.5.0'
});
}
}
// Angular version check
const ngVersion = document.querySelector('[ng-version]')?.getAttribute('ng-version');
if (ngVersion) {
const majorVersion = parseInt(ngVersion.split('.')[0]);
console.log(`Angular ${ngVersion} detected`);
if (majorVersion < 11) {
vulnerabilities.push({
component: 'Angular',
version: ngVersion,
severity: 'MEDIUM',
description: 'Outdated Angular version, missing security updates'
});
}
}
// WordPress detection
const wpGenerator = document.querySelector('meta[name="generator"][content*="WordPress"]');
if (wpGenerator) {
const wpVersion = wpGenerator.content.match(/WordPress ([\d.]+)/)?.[1];
if (wpVersion) {
console.log(`WordPress ${wpVersion} detected`);
const [major, minor] = wpVersion.split('.').map(Number);
if (major < 5 || (major === 5 && minor < 8)) {
vulnerabilities.push({
component: 'WordPress',
version: wpVersion,
severity: 'CRITICAL',
description: 'Multiple vulnerabilities in WordPress < 5.8'
});
}
}
}
// Check for outdated TLS
if (window.location.protocol === 'https:') {
// This would need server access to check properly
console.log('HTTPS enabled - TLS version check requires server access');
} else {
vulnerabilities.push({
component: 'Protocol',
severity: 'CRITICAL',
description: 'Site not using HTTPS'
});
}
// Report vulnerabilities
if (vulnerabilities.length > 0) {
console.log('\nβ VULNERABILITIES FOUND:');
console.log('β'.repeat(50));
vulnerabilities.forEach(vuln => {
const icon = vuln.severity === 'CRITICAL' ? 'π΄' :
vuln.severity === 'HIGH' ? 'π ' :
vuln.severity === 'MEDIUM' ? 'π‘' : 'π’';
console.log(`\n${icon} ${vuln.component} ${vuln.version || ''}`);
console.log(`Severity: ${vuln.severity}`);
if (vuln.cve) console.log(`CVE: ${vuln.cve}`);
console.log(`Details: ${vuln.description}`);
});
console.log('\nπ‘ Recommendations:');
console.log('1. Update all components to latest stable versions');
console.log('2. Enable automatic security updates where possible');
console.log('3. Subscribe to security advisories for your stack');
console.log('4. Perform regular security audits');
} else {
console.log('β
No known vulnerabilities detected');
console.log('Note: This is not a comprehensive security audit');
}
return vulnerabilities;
}
scanVulnerabilities();
2. Technology Risk Assessment
// Assess risks associated with detected technologies
function assessTechnologyRisks() {
console.log('\nβ οΈ Technology Risk Assessment\n');
const risks = {
high: [],
medium: [],
low: []
};
// Check for risky configurations
// 1. Debug mode indicators
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ ||
window.Vue?.config?.devtools ||
window.angular?.debug) {
risks.high.push({
issue: 'Debug mode enabled in production',
impact: 'Exposes internal application state and structure',
solution: 'Disable debug tools in production builds'
});
}
// 2. Source maps
const scripts = document.querySelectorAll('script[src]');
let hasSourceMaps = false;
scripts.forEach(script => {
if (script.src.includes('.map') || script.innerHTML.includes('sourceMappingURL')) {
hasSourceMaps = true;
}
});
if (hasSourceMaps) {
risks.medium.push({
issue: 'Source maps exposed',
impact: 'Original source code visible to attackers',
solution: 'Remove source maps from production'
});
}
// 3. Outdated libraries
if (window.jQuery && window.jQuery.fn.jquery.startsWith('1.')) {
risks.high.push({
issue: 'Severely outdated jQuery version',
impact: 'Multiple known security vulnerabilities',
solution: 'Upgrade to jQuery 3.x or remove dependency'
});
}
// 4. Mixed content
if (window.location.protocol === 'https:') {
const httpResources = document.querySelectorAll('[src^="http:"], [href^="http:"]');
if (httpResources.length > 0) {
risks.high.push({
issue: 'Mixed content (HTTP resources on HTTPS page)',
impact: 'Breaks security guarantees of HTTPS',
solution: 'Use HTTPS for all resources'
});
}
}
// 5. Exposed API keys
const scriptContent = Array.from(scripts).map(s => s.innerHTML).join(' ');
const apiKeyPatterns = [
/api[_-]?key['"]\s*[:=]\s*['"][^'"]{20,}/i,
/['"](AIza[0-9A-Za-z-_]{35})['"]/, // Google
/['"](sk_live_[0-9a-zA-Z]{24,})['"]/, // Stripe
/['"](pk_live_[0-9a-zA-Z]{24,})['"]/ // Stripe public
];
apiKeyPatterns.forEach(pattern => {
if (pattern.test(scriptContent)) {
risks.high.push({
issue: 'Potential API key exposed in JavaScript',
impact: 'API abuse, data theft, financial loss',
solution: 'Move API keys to server-side, use proxy endpoints'
});
}
});
// 6. Technology-specific risks
// WordPress without hardening
if (document.querySelector('link[href*="wp-content"]')) {
if (document.querySelector('link[href*="/wp-admin"]') ||
document.querySelector('link[href*="/wp-login"]')) {
risks.medium.push({
issue: 'WordPress admin URLs exposed',
impact: 'Easy target for brute force attacks',
solution: 'Hide admin URLs, implement 2FA'
});
}
}
// Exposed development frameworks
if (window.webpackHotUpdate) {
risks.high.push({
issue: 'Webpack hot reload in production',
impact: 'Development server exposed to internet',
solution: 'Use production build without dev server'
});
}
// Report risks
console.log('π΄ HIGH RISK ISSUES:');
if (risks.high.length === 0) {
console.log(' None found');
} else {
risks.high.forEach(risk => {
console.log(`\n Issue: ${risk.issue}`);
console.log(` Impact: ${risk.impact}`);
console.log(` Fix: ${risk.solution}`);
});
}
console.log('\nπ‘ MEDIUM RISK ISSUES:');
if (risks.medium.length === 0) {
console.log(' None found');
} else {
risks.medium.forEach(risk => {
console.log(`\n Issue: ${risk.issue}`);
console.log(` Impact: ${risk.impact}`);
console.log(` Fix: ${risk.solution}`);
});
}
// Best practices
console.log('\nπ‘ Security Best Practices:');
console.log('1. Keep all dependencies updated');
console.log('2. Use subresource integrity (SRI) for CDN resources');
console.log('3. Implement Content Security Policy');
console.log('4. Remove debug code and source maps');
console.log('5. Audit npm/yarn dependencies regularly');
return risks;
}
assessTechnologyRisks();
Complete Stack Analysis
Comprehensive Technology Audit
// Run complete technology stack audit
async function completeTechAudit() {
console.log('π COMPLETE TECHNOLOGY STACK AUDIT');
console.log('β'.repeat(50));
console.log(`URL: ${window.location.href}`);
console.log(`Date: ${new Date().toLocaleDateString()}\n`);
const audit = {
frontend: {},
backend: {},
infrastructure: {},
security: {},
performance: {},
score: 100
};
// Phase 1: Frontend Detection
console.log('π± PHASE 1: FRONTEND TECHNOLOGIES');
console.log('β'.repeat(40));
// Detect all frontend technologies
const frontendChecks = {
React: window.React || window.__REACT_DEVTOOLS_GLOBAL_HOOK__,
Vue: window.Vue || document.querySelector('[data-v-]'),
Angular: window.angular || document.querySelector('[ng-version]'),
jQuery: window.jQuery || window.$,
Bootstrap: window.bootstrap || document.querySelector('[class*="col-md-"]'),
Tailwind: document.querySelector('[class*="flex "][class*="items-"]')
};
Object.entries(frontendChecks).forEach(([tech, detected]) => {
if (detected) {
audit.frontend[tech] = { detected: true };
console.log(`β
${tech}`);
}
});
// Phase 2: Performance Impact
console.log('\nβ‘ PHASE 2: PERFORMANCE IMPACT');
console.log('β'.repeat(40));
const resources = performance.getEntriesByType('resource');
const jsSize = resources
.filter(r => r.name.includes('.js'))
.reduce((sum, r) => sum + (r.transferSize || 0), 0);
const cssSize = resources
.filter(r => r.name.includes('.css'))
.reduce((sum, r) => sum + (r.transferSize || 0), 0);
console.log(`JavaScript: ${(jsSize / 1024).toFixed(0)}KB`);
console.log(`CSS: ${(cssSize / 1024).toFixed(0)}KB`);
console.log(`Total resources: ${resources.length}`);
if (jsSize > 500000) {
audit.performance.jsSize = 'Too large';
audit.score -= 10;
console.log('β οΈ JavaScript bundle too large');
}
// Phase 3: Security Analysis
console.log('\nπ PHASE 3: SECURITY ANALYSIS');
console.log('β'.repeat(40));
// Check for security issues
const securityChecks = {
HTTPS: window.location.protocol === 'https:',
'Debug Mode': !!(window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || window.Vue?.config?.devtools),
'Source Maps': Array.from(document.scripts).some(s => s.src.includes('.map')),
'Console Logs': window.console.log.toString() !== 'function log() { [native code] }'
};
Object.entries(securityChecks).forEach(([check, result]) => {
audit.security[check] = result;
if (check === 'HTTPS' && !result) {
console.log('β Not using HTTPS');
audit.score -= 20;
} else if (check !== 'HTTPS' && result) {
console.log(`β οΈ ${check} detected`);
audit.score -= 5;
} else if (check === 'HTTPS' && result) {
console.log('β
HTTPS enabled');
}
});
// Phase 4: Best Practices
console.log('\nβ
PHASE 4: BEST PRACTICES');
console.log('β'.repeat(40));
const practices = {
'Compression': resources.some(r => r.encodedBodySize < r.decodedBodySize * 0.8),
'CDN Usage': resources.some(r => r.name.includes('cdn')),
'Lazy Loading': document.querySelectorAll('img[loading="lazy"]').length > 0,
'Modern Format': document.querySelectorAll('source[type="image/webp"]').length > 0
};
Object.entries(practices).forEach(([practice, implemented]) => {
console.log(`${implemented ? 'β
' : 'β'} ${practice}`);
if (!implemented) audit.score -= 5;
});
// Final Score
console.log('\nπ AUDIT SUMMARY');
console.log('β'.repeat(50));
console.log(`Technology Score: ${audit.score}/100`);
console.log(`Frontend frameworks: ${Object.keys(audit.frontend).length}`);
console.log(`Security issues: ${Object.values(audit.security).filter(v => v).length}`);
// Recommendations
console.log('\nπ‘ RECOMMENDATIONS:');
if (audit.score < 70) {
console.log('1. Address security vulnerabilities immediately');
}
if (jsSize > 500000) {
console.log('2. Implement code splitting and tree shaking');
}
if (!practices['Modern Format']) {
console.log('3. Use modern image formats (WebP, AVIF)');
}
if (!practices['CDN Usage']) {
console.log('4. Implement CDN for static assets');
}
console.log('5. Keep all dependencies updated');
console.log('6. Remove development code from production');
return audit;
}
// Run the complete audit
completeTechAudit();
The Bottom Line
Technology detection reveals more than just toolsβit exposes:
- Security posture - Outdated versions mean known vulnerabilities
- Performance characteristics - Some stacks are inherently slower
- Development practices - Debug mode in production shows poor deployment
- Business priorities - Technology choices reflect company values
- Technical debt - Mixed technologies indicate evolution over time
Know your stack. Update regularly. Remove debug code. Your technology choices are visible to everyone.
Detect any tech stack instantly: Fusebox identifies frameworks, libraries, CMSs, and infrastructure while you browse. Understand what powers any website. $29 one-time purchase.