feat: premium landing page, Swagger UI docs, full OG meta stack

- Premium landing page with nav, hero, stats, streaming flow, endpoint cards
- Full OG meta stack (OG, Twitter Card, JSON-LD WebAPI schema)
- SVG favicon matching miruro.tv icon style
- SVG share image for social sharing (1200x630)
- Dedicated docs.html with custom header and Swagger UI styling
- Canonical URLs, theme-color, robots meta
- Apple-touch-icon and mask-icon from miruro.tv
- Responsive design (mobile-friendly)
- Font: Inter (Google Fonts)
This commit is contained in:
Sʜɪɴᴇɪ Nᴏᴜᴢᴇɴ
2026-06-09 14:38:44 +05:30
parent 4b083a9bf7
commit 18a73c324e
5 changed files with 711 additions and 210 deletions
+131
View File
@@ -0,0 +1,131 @@
<!DOCTYPE html>
<html lang="en" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ──────────────── OG Meta ──────────────── -->
<meta property="og:title" content="MiruroAPI — Swagger UI Documentation">
<meta property="og:type" content="website">
<meta property="og:url" content="https://mirurotvapi.vercel.app/docs">
<meta property="og:image" content="https://mirurotvapi.vercel.app/share.svg">
<meta property="og:description" content="Interactive Swagger UI documentation for MiruroAPI. Test all 16 endpoints directly from the browser.">
<meta property="og:site_name" content="MiruroAPI">
<meta property="og:locale" content="en_US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="MiruroAPI — Swagger UI Documentation">
<meta name="twitter:description" content="Interactive Swagger UI documentation for MiruroAPI.">
<meta name="twitter:image" content="https://mirurotvapi.vercel.app/share.svg">
<meta name="description" content="Interactive Swagger UI documentation for MiruroAPI. Test all 16 endpoints directly from the browser.">
<meta name="robots" content="index, follow">
<meta name="theme-color" content="#0b1622">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="canonical" href="https://mirurotvapi.vercel.app/docs">
<title>MiruroAPI — Swagger UI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
<style>
:root {
--bg: #0b1622;
--bg2: #0f172a;
--accent: #38bdf8;
--accent2: #818cf8;
--text: #e2e8f0;
--muted: #94a3b8;
}
/* ──────────────── BASE ──────────────── */
html { box-sizing: border-box; }
*, *::before, *::after { box-sizing: inherit; }
body {
margin: 0; padding: 0;
background: var(--bg);
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
/* ──────────────── CUSTOM HEADER ──────────────── */
.docs-header {
background: linear-gradient(135deg, var(--bg2), #1e1b4b);
border-bottom: 1px solid rgba(255,255,255,0.05);
padding: 20px 40px;
display: flex; align-items: center; justify-content: space-between;
}
.docs-brand { display: flex; align-items: center; gap: 12px; text-decoration: none; }
.docs-logo {
width: 32px; height: 32px; border-radius: 8px;
background: linear-gradient(135deg, var(--accent), var(--accent2));
display: flex; align-items: center; justify-content: center;
color: white; font-weight: 900; font-size: 16px;
}
.docs-title { color: var(--text); font-weight: 700; font-size: 1em; }
.docs-subtitle { color: var(--muted); font-size: 0.8em; margin-left: 8px; }
.docs-links { display: flex; gap: 16px; }
.docs-links a {
color: var(--muted); text-decoration: none; font-size: 0.85em;
font-weight: 500; transition: color 0.2s;
}
.docs-links a:hover { color: var(--accent); }
/* ──────────────── SWAGGER UI OVERRIDES ──────────────── */
.swagger-ui .topbar { display: none; }
.swagger-ui .info .title { color: var(--text) !important; }
.swagger-ui .info .description p { color: var(--muted) !important; }
.swagger-ui .scheme-container { background: rgba(15, 23, 42, 0.5) !important; box-shadow: none !important; }
.swagger-ui .opblock-tag { color: var(--accent) !important; border-color: rgba(255,255,255,0.05) !important; }
.swagger-ui .opblock .opblock-summary-description { color: var(--muted) !important; }
.swagger-ui .btn { box-shadow: none !important; }
.swagger-ui .btn.execute { background: linear-gradient(135deg, var(--accent), var(--accent2)) !important; }
.swagger-ui .model-box { background: rgba(15, 23, 42, 0.3) !important; }
.swagger-ui .scheme-container .schemes > select { color: var(--text); background: var(--bg2); }
/* ──────────────── BACK LINK ──────────────── */
.back-link {
display: inline-flex; align-items: center; gap: 6px;
color: var(--accent); text-decoration: none;
font-size: 0.85em; font-weight: 500;
margin-left: 12px;
}
.back-link:hover { text-decoration: underline; }
</style>
</head>
<body>
<!-- ──────────────── CUSTOM HEADER ──────────────── -->
<div class="docs-header">
<div style="display: flex; align-items: center;">
<a href="/" class="docs-brand">
<div class="docs-logo">M</div>
<span class="docs-title">MiruroAPI</span>
</a>
<span class="docs-subtitle">Swagger UI Documentation</span>
</div>
<div class="docs-links">
<a href="/">Home</a>
<a href="/openapi.json">OpenAPI Spec</a>
<a href="/api/health">Health</a>
<a href="https://github.com/Shineii86/MiruroAPI" target="_blank">GitHub</a>
</div>
</div>
<!-- ──────────────── SWAGGER UI ──────────────── -->
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
<script>
SwaggerUIBundle({
url: "/openapi.json",
dom_id: "#swagger-ui",
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "BaseLayout",
deepLinking: true,
defaultModelsExpandDepth: -1,
docExpansion: "list",
filter: true,
tryItOutEnabled: true,
});
</script>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#38bdf8"/>
<stop offset="50%" style="stop-color:#818cf8"/>
<stop offset="100%" style="stop-color:#a78bfa"/>
</linearGradient>
<linearGradient id="shine" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:rgba(255,255,255,0.3)"/>
<stop offset="100%" style="stop-color:rgba(255,255,255,0)"/>
</linearGradient>
</defs>
<rect width="512" height="512" rx="96" fill="url(#bg)"/>
<rect width="512" height="256" rx="96" fill="url(#shine)"/>
<text x="256" y="310" text-anchor="middle" fill="white" font-family="Arial Black,Helvetica Neue,sans-serif" font-size="260" font-weight="900" letter-spacing="-10">M</text>
<circle cx="390" cy="140" r="24" fill="rgba(255,255,255,0.9)"/>
<circle cx="390" cy="140" r="12" fill="url(#bg)"/>
</svg>

After

Width:  |  Height:  |  Size: 976 B

+529 -187
View File
@@ -1,206 +1,548 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" prefix="og: https://ogp.me/ns#">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- FULL OG META STACK — Every useful tag for social sharing -->
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- ──────────────── 1. Basic OG Tags ──────────────── -->
<meta property="og:title" content="MiruroAPI — Free Anime Streaming API">
<meta property="og:type" content="website">
<meta property="og:url" content="https://mirurotvapi.vercel.app">
<meta property="og:image" content="https://mirurotvapi.vercel.app/share.svg">
<meta property="og:description" content="Free RESTful API for anime streaming data. 16 endpoints, 12 providers, M3U8 streaming URLs. Powered by AniList GraphQL and Miruro.">
<!-- ──────────────── 2. Optional but Recommended OG Tags ──────── -->
<meta property="og:site_name" content="MiruroAPI">
<meta property="og:locale" content="en_US">
<!-- ──────────────── 3. Image Optimization ──────────────── -->
<meta property="og:image:secure_url" content="https://mirurotvapi.vercel.app/share.svg">
<meta property="og:image:type" content="image/svg+xml">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="MiruroAPI - Free Anime Streaming API">
<!-- ──────────────── 6. Twitter Card Tags ──────── -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="MiruroAPI — Free Anime Streaming API">
<meta name="twitter:description" content="Free RESTful API for anime streaming data. 16 endpoints, 12 providers, M3U8 streaming URLs.">
<meta name="twitter:image" content="https://mirurotvapi.vercel.app/share.svg">
<meta name="twitter:image:alt" content="MiruroAPI - Free Anime Streaming API">
<meta name="twitter:domain" content="mirurotvapi.vercel.app">
<!-- ──────────────── 9. Generic Meta ──────────────── -->
<meta name="description" content="Free RESTful API for anime streaming data. 16 endpoints, 12 providers, M3U8 streaming URLs. Powered by AniList GraphQL and Miruro.">
<meta name="robots" content="index, follow">
<meta name="author" content="Shinei Nouzen">
<meta name="theme-color" content="#0b1622">
<link rel="canonical" href="https://mirurotvapi.vercel.app">
<!-- ──────────────── 10. JSON-LD Structured Data ──────── -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebAPI",
"name": "MiruroAPI",
"description": "Free RESTful API for anime streaming data. 16 endpoints, 12 providers, M3U8 streaming URLs.",
"url": "https://mirurotvapi.vercel.app",
"documentation": "https://mirurotvapi.vercel.app/docs",
"provider": {
"@type": "Organization",
"name": "MiruroAPI",
"url": "https://github.com/Shineii86/MiruroAPI"
},
"potentialAction": {
"@type": "SearchAction",
"target": "https://mirurotvapi.vercel.app/api/search?query={search_term_string}",
"query-input": "required name=search_term_string"
}
}
</script>
<!-- ──────────────── Favicon ──────────────── -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="icon" type="image/png" sizes="512x512" href="https://miruro.tv/icon-512x512.png">
<link rel="icon" type="image/png" sizes="192x192" href="https://miruro.tv/icon-192x192.png">
<link rel="apple-touch-icon" href="https://miruro.tv/icon-512x512.png">
<link rel="mask-icon" href="/favicon.svg" color="#38bdf8">
<title>MiruroAPI — Free Anime Streaming API</title> <title>MiruroAPI — Free Anime Streaming API</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' style='stop-color:%2338bdf8'/%3E%3Cstop offset='100%25' style='stop-color:%23818cf8'/%3E%3C/linearGradient%3E%3C/defs%3E%3Ccircle cx='50' cy='50' r='45' fill='url(%23g)'/%3E%3Ctext x='50' y='62' text-anchor='middle' fill='white' font-family='Arial Black' font-size='32' font-weight='bold'%3EM%3C/text%3E%3C/svg%3E"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;500;700&display=swap" rel="stylesheet">
<style> <style>
* { margin: 0; padding: 0; box-sizing: border-box; } *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Outfit', sans-serif; background: radial-gradient(circle at top, #0f172a, #020617); color: #e2e8f0; min-height: 100vh; padding: 50px 20px; } :root {
.container { max-width: 960px; margin: 0 auto; background: rgba(30, 41, 59, 0.5); backdrop-filter: blur(10px); padding: 40px; border-radius: 24px; border: 1px solid rgba(255, 255, 255, 0.05); box-shadow: 0 20px 40px rgba(0,0,0,0.5); } --bg: #0b1622;
.header { text-align: center; margin-bottom: 50px; } --bg2: #0f172a;
.logo { width: 120px; border-radius: 20px; box-shadow: 0 0 30px rgba(56, 189, 248, 0.3); border: 1px solid rgba(255,255,255,0.1); margin-bottom: 25px; } --bg3: #1e293b;
h1 { font-size: 3em; font-weight: 700; background: linear-gradient(to right, #38bdf8, #818cf8); -webkit-background-clip: text; color: transparent; margin-bottom: 10px; } --accent: #38bdf8;
.subtitle { color: #94a3b8; font-size: 1.1em; font-weight: 300; } --accent2: #818cf8;
.version { display: inline-block; background: rgba(56, 189, 248, 0.15); color: #38bdf8; padding: 4px 14px; border-radius: 20px; font-size: 0.85em; margin-top: 10px; border: 1px solid rgba(56, 189, 248, 0.2); } --text: #e2e8f0;
.section-title { font-size: 1.3em; font-weight: 700; color: #818cf8; margin: 35px 0 15px; border-left: 3px solid #818cf8; padding-left: 12px; } --muted: #94a3b8;
.endpoint { background: rgba(15, 23, 42, 0.8); border-left: 4px solid #38bdf8; padding: 20px 25px; margin: 12px 0; border-radius: 0 16px 16px 0; border: 1px solid rgba(255,255,255,0.02); transition: all 0.3s ease; } --dim: #64748b;
.endpoint:hover { transform: translateX(5px); box-shadow: 0 10px 20px rgba(0,0,0,0.2); border-left-color: #818cf8; background: rgba(30, 41, 59, 0.9); } }
.method { color: #10b981; font-weight: 700; background: rgba(16, 185, 129, 0.1); padding: 4px 10px; border-radius: 6px; font-size: 0.9em; margin-right: 10px; } body {
.url { font-family: monospace; color: #cbd5e1; font-size: 1.05em; } font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
.desc { color: #94a3b8; font-size: 0.95em; margin-top: 8px; font-weight: 300; line-height: 1.5; } background: radial-gradient(ellipse at top, var(--bg2), var(--bg));
.badge { display: inline-block; font-size: 0.7em; padding: 2px 8px; border-radius: 6px; margin-left: 8px; font-weight: 500; vertical-align: middle; } color: var(--text);
.badge-new { background: rgba(16, 185, 129, 0.15); color: #10b981; border: 1px solid rgba(16, 185, 129, 0.3); } min-height: 100vh;
.step-num { display: inline-block; background: rgba(56, 189, 248, 0.15); color: #38bdf8; width: 26px; height: 26px; text-align: center; line-height: 26px; border-radius: 50%; font-size: 0.85em; font-weight: 700; margin-right: 8px; } overflow-x: hidden;
.note { background: rgba(250, 204, 21, 0.08); border: 1px solid rgba(250, 204, 21, 0.15); border-radius: 10px; padding: 14px 18px; margin-top: 12px; font-size: 0.88em; color: #fbbf24; line-height: 1.5; } }
.note b { color: #fde68a; }
pre.snippet { background: #020617; padding: 14px; border-radius: 10px; margin-top: 12px; color: #a5b4fc; font-family: monospace; font-size: 0.82em; border: 1px solid rgba(255,255,255,0.05); overflow-x: auto; line-height: 1.5; } /* ──────────────── NAV ──────────────── */
table.param-table { width: 100%; margin-top: 12px; border-collapse: collapse; font-size: 0.85em; } .nav {
table.param-table th { text-align: left; color: #818cf8; font-weight: 500; padding: 6px 10px; border-bottom: 1px solid rgba(255,255,255,0.08); } position: fixed; top: 0; left: 0; right: 0; z-index: 100;
table.param-table td { padding: 6px 10px; color: #94a3b8; border-bottom: 1px solid rgba(255,255,255,0.03); } background: rgba(11, 22, 34, 0.85);
table.param-table td:first-child { color: #a5b4fc; font-family: monospace; white-space: nowrap; } backdrop-filter: blur(20px);
.footer { text-align: center; margin-top: 50px; color: #475569; font-size: 0.9em; border-top: 1px solid rgba(255,255,255,0.05); padding-top: 20px; } border-bottom: 1px solid rgba(255,255,255,0.05);
a { color: #38bdf8; text-decoration: none; font-weight: 500; } padding: 16px 40px;
a:hover { color: #818cf8; text-shadow: 0 0 10px rgba(129, 140, 248, 0.5); } display: flex; align-items: center; justify-content: space-between;
.try-btn { display: inline-block; background: rgba(56, 189, 248, 0.1); color: #38bdf8; padding: 6px 14px; border-radius: 8px; font-size: 0.85em; margin-top: 10px; border: 1px solid rgba(56, 189, 248, 0.2); transition: all 0.3s; } }
.try-btn:hover { background: rgba(56, 189, 248, 0.2); transform: translateY(-1px); } .nav-brand { display: flex; align-items: center; gap: 12px; text-decoration: none; }
.nav-logo {
width: 36px; height: 36px; border-radius: 10px;
background: linear-gradient(135deg, var(--accent), var(--accent2));
display: flex; align-items: center; justify-content: center;
color: white; font-weight: 900; font-size: 18px;
}
.nav-title { color: var(--text); font-weight: 700; font-size: 1.1em; }
.nav-links { display: flex; gap: 24px; }
.nav-links a {
color: var(--muted); text-decoration: none; font-size: 0.9em;
font-weight: 500; transition: color 0.2s;
}
.nav-links a:hover { color: var(--accent); }
.nav-badge {
background: rgba(56, 189, 248, 0.12); color: var(--accent);
padding: 4px 12px; border-radius: 20px; font-size: 0.8em;
font-weight: 600; border: 1px solid rgba(56, 189, 248, 0.2);
}
/* ──────────────── HERO ──────────────── */
.hero {
padding: 160px 40px 80px;
text-align: center;
max-width: 900px;
margin: 0 auto;
}
.hero-badge {
display: inline-flex; align-items: center; gap: 8px;
background: rgba(56, 189, 248, 0.08);
border: 1px solid rgba(56, 189, 248, 0.15);
padding: 8px 20px; border-radius: 30px;
font-size: 0.85em; color: var(--accent); font-weight: 500;
margin-bottom: 32px;
}
.hero-badge .dot {
width: 8px; height: 8px; border-radius: 50%;
background: #10b981; animation: pulse 2s infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
.hero h1 {
font-size: clamp(2.5em, 6vw, 4.5em);
font-weight: 900;
background: linear-gradient(135deg, var(--accent), var(--accent2), #a78bfa);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
line-height: 1.1; margin-bottom: 20px;
letter-spacing: -0.03em;
}
.hero p {
font-size: 1.2em; color: var(--muted); max-width: 650px;
margin: 0 auto 40px; line-height: 1.7; font-weight: 400;
}
.hero-actions { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
.btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 14px 32px; border-radius: 12px;
font-size: 0.95em; font-weight: 600; text-decoration: none;
transition: all 0.3s ease;
}
.btn-primary {
background: linear-gradient(135deg, var(--accent), var(--accent2));
color: white; box-shadow: 0 4px 20px rgba(56, 189, 248, 0.3);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(56, 189, 248, 0.4); }
.btn-secondary {
background: rgba(255,255,255,0.05); color: var(--text);
border: 1px solid rgba(255,255,255,0.1);
}
.btn-secondary:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.15); }
/* ──────────────── STATS ──────────────── */
.stats {
display: flex; justify-content: center; gap: 60px;
padding: 40px; margin: 0 auto 60px;
max-width: 800px;
}
.stat { text-align: center; }
.stat-num {
font-size: 2.5em; font-weight: 900;
background: linear-gradient(135deg, var(--accent), var(--accent2));
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
}
.stat-label { color: var(--dim); font-size: 0.9em; margin-top: 4px; }
/* ──────────────── SECTIONS ──────────────── */
.section {
max-width: 1100px; margin: 0 auto; padding: 60px 40px;
}
.section-title {
font-size: 1.8em; font-weight: 800; margin-bottom: 12px;
letter-spacing: -0.02em;
}
.section-sub { color: var(--muted); margin-bottom: 40px; font-size: 1.05em; }
/* ──────────────── ENDPOINT CARDS ──────────────── */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.card {
background: rgba(15, 23, 42, 0.6);
border: 1px solid rgba(255,255,255,0.04);
border-radius: 16px; padding: 24px;
transition: all 0.3s ease;
}
.card:hover {
border-color: rgba(56, 189, 248, 0.2);
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(0,0,0,0.3);
}
.card-method {
display: inline-block; font-size: 0.75em; font-weight: 700;
padding: 3px 10px; border-radius: 6px; margin-bottom: 12px;
}
.get { background: rgba(16, 185, 129, 0.12); color: #10b981; }
.card-path {
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 0.9em; color: var(--accent); font-weight: 500;
margin-bottom: 8px; word-break: break-all;
}
.card-desc { color: var(--muted); font-size: 0.9em; line-height: 1.5; }
/* ──────────────── STREAMING FLOW ──────────────── */
.flow {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px;
margin-top: 40px;
}
.flow-step {
background: rgba(15, 23, 42, 0.6);
border: 1px solid rgba(255,255,255,0.04);
border-radius: 16px; padding: 32px 24px; text-align: center;
position: relative;
}
.flow-step::before {
content: attr(data-step);
position: absolute; top: -14px; left: 50%; transform: translateX(-50%);
width: 28px; height: 28px; border-radius: 50%;
background: linear-gradient(135deg, var(--accent), var(--accent2));
display: flex; align-items: center; justify-content: center;
color: white; font-size: 0.8em; font-weight: 700;
}
.flow-step h3 { margin: 12px 0 8px; font-weight: 700; }
.flow-step p { color: var(--muted); font-size: 0.9em; }
.flow-step code {
display: block; margin-top: 12px; padding: 12px;
background: rgba(0,0,0,0.3); border-radius: 8px;
font-size: 0.8em; color: var(--accent); text-align: left;
overflow-x: auto;
}
/* ──────────────── CODE BLOCK ──────────────── */
.code-block {
background: rgba(0,0,0,0.4); border-radius: 16px;
border: 1px solid rgba(255,255,255,0.05);
margin-top: 40px; overflow: hidden;
}
.code-header {
padding: 12px 20px; background: rgba(255,255,255,0.03);
border-bottom: 1px solid rgba(255,255,255,0.05);
font-size: 0.85em; color: var(--dim); font-weight: 500;
}
.code-block pre {
padding: 20px; margin: 0; overflow-x: auto;
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 0.85em; line-height: 1.6;
color: #a5b4fc;
}
/* ──────────────── PROVIDERS ──────────────── */
.providers {
display: flex; flex-wrap: wrap; gap: 10px;
justify-content: center; margin-top: 32px;
}
.provider {
background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.06);
padding: 8px 18px; border-radius: 10px;
font-size: 0.85em; color: var(--muted); font-weight: 500;
font-family: monospace;
}
/* ──────────────── FOOTER ──────────────── */
.footer {
text-align: center; padding: 60px 40px;
border-top: 1px solid rgba(255,255,255,0.05);
color: var(--dim); font-size: 0.9em;
}
.footer a { color: var(--accent); text-decoration: none; }
.footer a:hover { text-decoration: underline; }
/* ──────────────── RESPONSIVE ──────────────── */
@media (max-width: 768px) {
.nav { padding: 12px 20px; }
.nav-links { display: none; }
.hero { padding: 120px 20px 60px; }
.stats { gap: 30px; flex-wrap: wrap; }
.flow { grid-template-columns: 1fr; }
.section { padding: 40px 20px; }
}
</style> </style>
</head> </head>
<body> <body>
<div class="container">
<div class="header"> <!-- ──────────────── NAV ──────────────── -->
<svg class="logo" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg"> <nav class="nav">
<defs> <a href="/" class="nav-brand">
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%"> <div class="nav-logo">M</div>
<stop offset="0%" style="stop-color:#38bdf8"/> <span class="nav-title">MiruroAPI</span>
<stop offset="100%" style="stop-color:#818cf8"/> </a>
</linearGradient> <div class="nav-links">
</defs> <a href="/docs">Swagger UI</a>
<rect width="120" height="120" rx="24" fill="url(#grad)"/> <a href="/openapi.json">OpenAPI Spec</a>
<text x="60" y="75" text-anchor="middle" fill="white" font-family="Arial Black,sans-serif" font-size="48" font-weight="900">M</text> <a href="/api/health">Health</a>
</svg> <a href="https://github.com/Shineii86/MiruroAPI" target="_blank">GitHub</a>
<span class="nav-badge">v1.1.0</span>
</div>
</nav>
<!-- ──────────────── HERO ──────────────── -->
<section class="hero">
<div class="hero-badge">
<span class="dot"></span>
All systems operational
</div>
<h1>MiruroAPI</h1> <h1>MiruroAPI</h1>
<div class="subtitle">Decrypted, bypassed, and reverse-engineered anime streaming API</div> <p>Free RESTful API for anime streaming data. 16 endpoints, 12 providers, M3U8 streaming URLs with subtitles and skip timestamps. Powered by AniList GraphQL and Miruro.</p>
<div class="version">v1.1.0 — Full Data, Streaming &amp; Pagination</div> <div class="hero-actions">
<a href="/docs" class="btn btn-primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
Swagger UI Docs
</a>
<a href="/api/search?query=naruto&per_page=3" class="btn btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Try Search API
</a>
<a href="https://github.com/Shineii86/MiruroAPI" class="btn btn-secondary" target="_blank">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
GitHub
</a>
</div> </div>
</section>
<div class="note" style="background: rgba(16, 185, 129, 0.08); border-color: rgba(16, 185, 129, 0.2); color: #10b981;"> <!-- ──────────────── STATS ──────────────── -->
<b>16 Endpoints</b> — Powered by AniList GraphQL + Miruro streaming pipe. M3U8 URLs, subtitles, intro/outro timestamps. <div class="stats">
<div class="stat">
<div class="stat-num">16</div>
<div class="stat-label">API Endpoints</div>
</div> </div>
<div class="stat">
<!-- SEARCH & DISCOVERY --> <div class="stat-num">12</div>
<div class="section-title">Search &amp; Discovery</div> <div class="stat-label">Providers</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/search?query={name}</span></div>
<div class="desc">Full-text anime search with rich metadata — title, cover, genres, studios, scores, airing status. 20+ fields per result.</div>
<a class="try-btn" href="/api/search?query=naruto&per_page=3" target="_blank">Try it</a>
</div> </div>
<div class="stat">
<div class="endpoint"> <div class="stat-num">5000+</div>
<div><span class="method">GET</span> <span class="url">/api/suggestions?query={name}</span> <span class="badge badge-new">NEW</span></div> <div class="stat-label">Anime Indexed</div>
<div class="desc">Lightweight autocomplete for dropdowns — id, title, poster, format, status, year. Max 8 results.</div>
<a class="try-btn" href="/api/suggestions?query=one+piece" target="_blank">Try it</a>
</div> </div>
<div class="stat">
<div class="endpoint"> <div class="stat-num">M3U8</div>
<div><span class="method">GET</span> <span class="url">/api/filter</span> <span class="badge badge-new">NEW</span></div> <div class="stat-label">Stream Format</div>
<div class="desc">Advanced filter by genre, tag, year, season, format, status, sort. All params optional.</div>
<table class="param-table">
<tr><th>Param</th><th>Values</th></tr>
<tr><td>genre</td><td>Action, Romance, Comedy, Drama, Fantasy, Sci-Fi, etc.</td></tr>
<tr><td>tag</td><td>Isekai, Time Skip, Reincarnation, etc.</td></tr>
<tr><td>year</td><td>2025, 2024, etc.</td></tr>
<tr><td>season</td><td>WINTER · SPRING · SUMMER · FALL</td></tr>
<tr><td>format</td><td>TV · MOVIE · OVA · ONA · SPECIAL</td></tr>
<tr><td>status</td><td>RELEASING · FINISHED · NOT_YET_RELEASED · CANCELLED</td></tr>
<tr><td>sort</td><td>SCORE_DESC · POPULARITY_DESC · TRENDING_DESC · START_DATE_DESC</td></tr>
</table>
<a class="try-btn" href="/api/filter?genre=Action&format=TV&sort=SCORE_DESC&per_page=3" target="_blank">Try it</a>
</div>
<!-- COLLECTIONS -->
<div class="section-title">Collections (All Paginated)</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/trending</span></div>
<div class="desc">Currently trending anime across the community.</div>
<a class="try-btn" href="/api/trending?per_page=3" target="_blank">Try it</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/popular</span></div>
<div class="desc">Most popular anime of all time by total user count.</div>
<a class="try-btn" href="/api/popular?per_page=3" target="_blank">Try it</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/upcoming</span></div>
<div class="desc">Most anticipated anime that haven't aired yet.</div>
<a class="try-btn" href="/api/upcoming?per_page=3" target="_blank">Try it</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/recent</span></div>
<div class="desc">Currently airing / this season's anime.</div>
<a class="try-btn" href="/api/recent?per_page=3" target="_blank">Try it</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/spotlight</span> <span class="badge badge-new">HOT</span></div>
<div class="desc">Top 10 trending + popular anime. Perfect for hero banners.</div>
<a class="try-btn" href="/api/spotlight" target="_blank">Try it</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/schedule</span></div>
<div class="desc">Upcoming episodes with UNIX timestamps and full anime metadata.</div>
<a class="try-btn" href="/api/schedule?per_page=3" target="_blank">Try it</a>
</div>
<!-- ANIME DETAILS -->
<div class="section-title">Anime Details</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/info/{anilist_id}</span></div>
<div class="desc">Complete anime page — everything AniList has to offer. Characters (25), staff, relations, recommendations, trailer, stats, external links.</div>
<a class="try-btn" href="/api/info/21" target="_blank">Try it (One Piece)</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/anime/{id}/characters</span></div>
<div class="desc">Paginated character list with Japanese voice actors, images, roles.</div>
<a class="try-btn" href="/api/anime/20/characters" target="_blank">Try it (Naruto)</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/anime/{id}/relations</span></div>
<div class="desc">Sequels, prequels, side stories, spin-offs, source material.</div>
<a class="try-btn" href="/api/anime/20/relations" target="_blank">Try it</a>
</div>
<div class="endpoint">
<div><span class="method">GET</span> <span class="url">/api/anime/{id}/recommendations</span></div>
<div class="desc">Community recommendations sorted by highest rating.</div>
<a class="try-btn" href="/api/anime/20/recommendations" target="_blank">Try it</a>
</div>
<!-- STREAMING -->
<div class="section-title">Streaming (3-Step Flow)</div>
<div class="note">
<b>How streaming works:</b> To get a video URL, follow these 3 steps in order. Each step's output feeds into the next.
</div>
<div class="endpoint" style="border-left-color: #10b981;">
<div><span class="step-num">1</span><span class="method">GET</span> <span class="url">/api/episodes/{anilist_id}</span></div>
<div class="desc">Get all episodes from multiple providers (kiwi, bee, bonk, ally, moo, etc.) organized by sub/dub. Returns episode IDs for Step 2.</div>
<pre class="snippet">{
"providers": {
"kiwi": { "episodes": { "sub": [{ "id": "watch/kiwi/20/sub/animepahe-1", "number": 1, ... }] } },
"bee": { ... },
"bonk": { ... }
}
}</pre>
<a class="try-btn" href="/api/episodes/20" target="_blank">Try it (Naruto)</a>
</div>
<div class="endpoint" style="border-left-color: #10b981; background: rgba(16, 185, 129, 0.05);">
<div><span class="step-num">2</span> <span class="url">/api/watch/{provider}/{anilistId}/{category}/{slug}</span> <span class="badge badge-new">RECOMMENDED</span></div>
<div class="desc">Take the <b>id</b> from Step 1 and use it as the URL. Returns M3U8 streams, subtitles, intro/outro timestamps.</div>
<pre class="snippet">{
"streams": [
{ "url": "https://.../master.m3u8", "type": "hls", "quality": "1080p" }
],
"subtitles": [ { "file": "...", "label": "English" } ],
"intro": { "start": 0, "end": 90 },
"outro": { "start": 1300, "end": 1420 }
}</pre>
<a class="try-btn" href="/api/watch/kiwi/20/sub/animepahe-1" target="_blank">Try it</a>
</div>
<div class="endpoint" style="border-left-color: #818cf8;">
<div><span class="step-num">3</span> <span style="color: #818cf8; font-weight: 500;">Play the stream</span></div>
<div class="desc">Feed <code>streams[0].url</code> into any HLS player (Video.js, hls.js, VLC, mpv). Use intro/outro timestamps for skip buttons.</div>
</div>
<div class="footer">
All collection endpoints return: <code style="color: #a5b4fc;">{ page, perPage, total, hasNextPage, results[] }</code>
<br><br>
<a href="/api/health">Health</a> · <a href="/openapi.json">OpenAPI Spec</a> · <a href="https://github.com/Shineii86/MiruroAPI" target="_blank">GitHub</a>
</div> </div>
</div> </div>
<!-- ──────────────── STREAMING FLOW ──────────────── -->
<section class="section">
<h2 class="section-title">Streaming in 3 Steps</h2>
<p class="section-sub">Get M3U8 streaming URLs for any anime episode in 3 simple API calls.</p>
<div class="flow">
<div class="flow-step" data-step="1">
<h3>Get Episodes</h3>
<p>Fetch all episodes from multiple providers</p>
<code>GET /api/episodes/{anilistId}</code>
</div>
<div class="flow-step" data-step="2">
<h3>Get Sources</h3>
<p>Get M3U8 URL from episode ID</p>
<code>GET /api/watch/{provider}/{id}/{cat}/{slug}</code>
</div>
<div class="flow-step" data-step="3">
<h3>Play</h3>
<p>Feed M3U8 URL to any HLS player</p>
<code>hls.js / Video.js / VLC / mpv</code>
</div>
</div>
</section>
<!-- ──────────────── SEARCH ENDPOINTS ──────────────── -->
<section class="section">
<h2 class="section-title">Search & Discovery</h2>
<p class="section-sub">Full-text search, autocomplete, and advanced filtering powered by AniList GraphQL.</p>
<div class="grid">
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/search?query={name}</div>
<div class="card-desc">Full-text anime search with 20+ fields per result. Paginated.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/suggestions?query={name}</div>
<div class="card-desc">Lightweight autocomplete for dropdowns. Max 8 results.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/filter?genre=Action&format=TV</div>
<div class="card-desc">Advanced filter by genre, tag, year, season, format, status, sort.</div>
</div>
</div>
</section>
<!-- ──────────────── COLLECTIONS ──────────────── -->
<section class="section">
<h2 class="section-title">Collections</h2>
<p class="section-sub">Browse trending, popular, upcoming, and currently airing anime. All paginated.</p>
<div class="grid">
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/trending</div>
<div class="card-desc">Currently trending anime across the community.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/popular</div>
<div class="card-desc">Most popular anime of all time by user count.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/upcoming</div>
<div class="card-desc">Most anticipated anime that haven't aired yet.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/recent</div>
<div class="card-desc">Currently airing / this season's anime.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/spotlight</div>
<div class="card-desc">Top 10 trending + popular. Perfect for hero banners.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/schedule</div>
<div class="card-desc">Upcoming episodes with UNIX timestamps.</div>
</div>
</div>
</section>
<!-- ──────────────── ANIME DETAILS ──────────────── -->
<section class="section">
<h2 class="section-title">Anime Details</h2>
<p class="section-sub">Complete anime metadata — characters, staff, relations, recommendations, trailer, stats.</p>
<div class="grid">
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/info/{anilistId}</div>
<div class="card-desc">Everything AniList has to offer. 25 characters, staff, relations, recommendations, trailer, stats.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/anime/{id}/characters</div>
<div class="card-desc">Paginated characters with Japanese voice actors.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/anime/{id}/relations</div>
<div class="card-desc">Sequels, prequels, side stories, spin-offs.</div>
</div>
<div class="card">
<span class="card-method get">GET</span>
<div class="card-path">/api/anime/{id}/recommendations</div>
<div class="card-desc">Community recommendations sorted by rating.</div>
</div>
</div>
</section>
<!-- ──────────────── PROVIDERS ──────────────── -->
<section class="section" style="text-align: center;">
<h2 class="section-title">Streaming Providers</h2>
<p class="section-sub">12 providers with different strengths — sub, dub, download, skip times, thumbnails.</p>
<div class="providers">
<div class="provider">kiwi</div>
<div class="provider">pewe</div>
<div class="provider">bee</div>
<div class="provider">bonk</div>
<div class="provider">bun</div>
<div class="provider">ally</div>
<div class="provider">nun</div>
<div class="provider">twin</div>
<div class="provider">cog</div>
<div class="provider">moo</div>
<div class="provider">hop</div>
<div class="provider">telli</div>
</div>
</section>
<!-- ──────────────── QUICK START ──────────────── -->
<section class="section">
<h2 class="section-title">Quick Start</h2>
<p class="section-sub">Get started in seconds. No API key required.</p>
<div class="code-block">
<div class="code-header">JavaScript — Fetch search results</div>
<pre>const res = await fetch("https://mirurotvapi.vercel.app/api/search?query=naruto");
const { success, results } = await res.json();
console.log(results.total); // 5000+
console.log(results.results[0].title.romaji); // "NARUTO"</pre>
</div>
<div class="code-block" style="margin-top: 16px;">
<div class="code-header">JavaScript — Get streaming sources</div>
<pre>// Step 1: Get episodes
const eps = await fetch("https://mirurotvapi.vercel.app/api/episodes/20");
const { results } = await eps.json();
const firstEp = results.providers.kiwi.episodes.sub[0];
// Step 2: Get M3U8 URL
const stream = await fetch(`https://mirurotvapi.vercel.app${firstEp.id}`);
const { results: sources } = await stream.json();
console.log(sources.streams[0].url); // "https://.../master.m3u8"</pre>
</div>
<div class="code-block" style="margin-top: 16px;">
<div class="code-header">cURL — Quick test</div>
<pre>curl "https://mirurotvapi.vercel.app/api/search?query=one+piece&per_page=3"</pre>
</div>
</section>
<!-- ──────────────── FOOTER ──────────────── -->
<footer class="footer">
<p>
<a href="/docs">Swagger UI</a> ·
<a href="/openapi.json">OpenAPI Spec</a> ·
<a href="/api/health">Health</a> ·
<a href="https://github.com/Shineii86/MiruroAPI" target="_blank">GitHub</a>
</p>
<p style="margin-top: 12px; color: #475569;">
Powered by <a href="https://anilist.co" target="_blank">AniList GraphQL</a> + <a href="https://miruro.to" target="_blank">Miruro</a> streaming providers
</p>
<p style="margin-top: 8px; color: #334155; font-size: 0.8em;">
v1.1.0 · MIT License · Built by <a href="https://github.com/Shineii86" target="_blank">Shinei Nouzen</a>
</p>
</footer>
</body> </body>
</html> </html>
+34
View File
@@ -0,0 +1,34 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630">
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#0b1622"/>
<stop offset="50%" style="stop-color:#0f172a"/>
<stop offset="100%" style="stop-color:#1e1b4b"/>
</linearGradient>
<linearGradient id="accent" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#38bdf8"/>
<stop offset="100%" style="stop-color:#818cf8"/>
</linearGradient>
<linearGradient id="icon" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#38bdf8"/>
<stop offset="100%" style="stop-color:#a78bfa"/>
</linearGradient>
</defs>
<rect width="1200" height="630" fill="url(#bg)"/>
<rect x="0" y="580" width="1200" height="50" fill="url(#accent)" opacity="0.3"/>
<rect x="60" y="180" width="6" height="200" rx="3" fill="url(#accent)"/>
<text x="90" y="270" fill="white" font-family="Arial Black,Helvetica Neue,sans-serif" font-size="80" font-weight="900">MiruroAPI</text>
<text x="90" y="340" fill="#94a3b8" font-family="Arial,Helvetica Neue,sans-serif" font-size="32">Free Anime Streaming API</text>
<text x="90" y="390" fill="#64748b" font-family="Arial,Helvetica Neue,sans-serif" font-size="24">AniList GraphQL + Miruro Streaming Providers + M3U8</text>
<rect x="60" y="430" width="280" height="50" rx="25" fill="url(#accent)" opacity="0.15"/>
<text x="200" y="462" text-anchor="middle" fill="#38bdf8" font-family="Arial,sans-serif" font-size="20" font-weight="600">16 Endpoints</text>
<rect x="360" y="430" width="280" height="50" rx="25" fill="url(#accent)" opacity="0.15"/>
<text x="500" y="462" text-anchor="middle" fill="#38bdf8" font-family="Arial,sans-serif" font-size="20" font-weight="600">12 Providers</text>
<rect x="660" y="430" width="280" height="50" rx="25" fill="url(#accent)" opacity="0.15"/>
<text x="800" y="462" text-anchor="middle" fill="#38bdf8" font-family="Arial,sans-serif" font-size="20" font-weight="600">M3U8 Streaming</text>
<rect x="960" y="430" width="200" height="50" rx="25" fill="url(#accent)" opacity="0.15"/>
<text x="1060" y="462" text-anchor="middle" fill="#38bdf8" font-family="Arial,sans-serif" font-size="20" font-weight="600">v1.1.0</text>
<rect x="900" y="120" width="200" height="200" rx="40" fill="url(#icon)" opacity="0.15"/>
<text x="1000" y="255" text-anchor="middle" fill="white" font-family="Arial Black,sans-serif" font-size="120" font-weight="900">M</text>
<text x="600" y="580" text-anchor="middle" fill="#475569" font-family="Arial,sans-serif" font-size="18">mirurotvapi.vercel.app</text>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+1 -25
View File
@@ -76,31 +76,7 @@ app.use(express.static(path.join(__dirname, "public"), { redirect: false }));
// ---- FEATURE: Interactive Swagger UI documentation at /docs ---- // ---- FEATURE: Interactive Swagger UI documentation at /docs ----
app.get("/docs", (req, res) => { app.get("/docs", (req, res) => {
res.send(`<!DOCTYPE html> res.sendFile(path.join(__dirname, "public", "docs.html"));
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MiruroAPI — Swagger UI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
<style>body{margin:0;background:#0b1622;}</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
<script>
SwaggerUIBundle({
url: "/openapi.json",
dom_id: "#swagger-ui",
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
layout: "BaseLayout",
deepLinking: true,
defaultModelsExpandDepth: -1,
docExpansion: "list",
});
</script>
</body>
</html>`);
}); });
// ══════════════════════════════════════════════════════════════ // ══════════════════════════════════════════════════════════════