|
| 1 | +from flask import Flask |
| 2 | +from endpoints import api_bp |
| 3 | + |
| 4 | + |
| 5 | +app = Flask(__name__) |
| 6 | + |
| 7 | + |
| 8 | +app.register_blueprint(api_bp) |
| 9 | + |
| 10 | + |
| 11 | +@app.get("/") |
| 12 | +def read_root(): |
| 13 | + return """ |
| 14 | + <!DOCTYPE html> |
| 15 | + <html lang="en"> |
| 16 | + <head> |
| 17 | + <meta charset="UTF-8"> |
| 18 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 19 | + <title>Vercel + Flask</title> |
| 20 | + <link rel="icon" type="image/svg+xml" href="/favicon.ico"> |
| 21 | + <style> |
| 22 | + * { margin: 0; padding: 0; box-sizing: border-box; } |
| 23 | + body { |
| 24 | + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; |
| 25 | + background-color: #000000; color: #ffffff; line-height: 1.6; min-height: 100vh; |
| 26 | + display: flex; flex-direction: column; |
| 27 | + } |
| 28 | + header { border-bottom: 1px solid #333333; padding: 0; } |
| 29 | + nav { max-width: 1200px; margin: 0 auto; display: flex; align-items: center; padding: 1rem 2rem; gap: 2rem; } |
| 30 | + .logo { font-size: 1.25rem; font-weight: 600; color: #ffffff; text-decoration: none; } |
| 31 | + .nav-links { display: flex; gap: 1.5rem; margin-left: auto; } |
| 32 | + .nav-links a { text-decoration: none; color: #888888; padding: 0.5rem 1rem; border-radius: 6px; transition: all 0.2s ease; font-size: 0.875rem; font-weight: 500; } |
| 33 | + .nav-links a:hover { color: #ffffff; background-color: #111111; } |
| 34 | + main { flex: 1; max-width: 1200px; margin: 0 auto; padding: 4rem 2rem; display: flex; flex-direction: column; align-items: center; text-align: center; } |
| 35 | + .hero { margin-bottom: 3rem; } |
| 36 | + .hero-code { margin-top: 2rem; width: 100%; max-width: 900px; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); } |
| 37 | + .hero-code pre { background-color: #0a0a0a; border: 1px solid #333333; border-radius: 8px; padding: 1.5rem; text-align: left; grid-column: 1 / -1; } |
| 38 | + h1 { font-size: 3rem; font-weight: 700; margin-bottom: 1rem; background: linear-gradient(to right, #ffffff, #888888); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } |
| 39 | + .subtitle { font-size: 1.25rem; color: #888888; margin-bottom: 2rem; max-width: 600px; } |
| 40 | + .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.5rem; width: 100%; max-width: 900px; } |
| 41 | + .card { background-color: #111111; border: 1px solid #333333; border-radius: 8px; padding: 1.5rem; transition: all 0.2s ease; text-align: left; } |
| 42 | + .card:hover { border-color: #555555; transform: translateY(-2px); } |
| 43 | + .card h3 { font-size: 1.125rem; font-weight: 600; margin-bottom: 0.5rem; color: #ffffff; } |
| 44 | + .card p { color: #888888; font-size: 0.875rem; margin-bottom: 1rem; } |
| 45 | + .card a { display: inline-flex; align-items: center; color: #ffffff; text-decoration: none; font-size: 0.875rem; font-weight: 500; padding: 0.5rem 1rem; background-color: #222222; border-radius: 6px; border: 1px solid #333333; transition: all 0.2s ease; } |
| 46 | + .card a:hover { background-color: #333333; border-color: #555555; } |
| 47 | + .status-badge { display: inline-flex; align-items: center; gap: 0.5rem; background-color: #0070f3; color: #ffffff; padding: 0.25rem 0.75rem; border-radius: 20px; font-size: 0.75rem; font-weight: 500; margin-bottom: 2rem; } |
| 48 | + .status-dot { width: 6px; height: 6px; background-color: #00ff88; border-radius: 50%; } |
| 49 | + pre { background-color: #0a0a0a; border: 1px solid #333333; border-radius: 6px; padding: 1rem; overflow-x: auto; margin: 0; } |
| 50 | + code { font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace; font-size: 0.85rem; line-height: 1.5; color: #ffffff; } |
| 51 | + .keyword { color: #ff79c6; } |
| 52 | + .string { color: #f1fa8c; } |
| 53 | + .function { color: #50fa7b; } |
| 54 | + .class { color: #8be9fd; } |
| 55 | + .module { color: #8be9fd; } |
| 56 | + .variable { color: #f8f8f2; } |
| 57 | + .decorator { color: #ffb86c; } |
| 58 | + @media (max-width: 768px) { |
| 59 | + nav { padding: 1rem; flex-direction: column; gap: 1rem; } |
| 60 | + .nav-links { margin-left: 0; } |
| 61 | + main { padding: 2rem 1rem; } |
| 62 | + h1 { font-size: 2rem; } |
| 63 | + .hero-code { grid-template-columns: 1fr; } |
| 64 | + .cards { grid-template-columns: 1fr; } |
| 65 | + } |
| 66 | + </style> |
| 67 | + </head> |
| 68 | + <body> |
| 69 | + <header> |
| 70 | + <nav> |
| 71 | + <a href="/" class="logo">Vercel + Flask</a> |
| 72 | + <div class="nav-links"> |
| 73 | + <a href="/api/data">API</a> |
| 74 | + </div> |
| 75 | + </nav> |
| 76 | + </header> |
| 77 | + <main> |
| 78 | + <div class="hero"> |
| 79 | + <h1>Vercel + Flask</h1> |
| 80 | + <div class="hero-code"> |
| 81 | + <pre><code><span class="keyword">from</span> <span class="module">flask</span> <span class="keyword">import</span> <span class="class">Flask</span> |
| 82 | +
|
| 83 | +<span class="variable">app</span> = <span class="class">Flask</span>(<span class="string">__name__</span>) |
| 84 | +
|
| 85 | +<span class="decorator">@app.get</span>(<span class="string">"/"</span>) |
| 86 | +<span class="keyword">def</span> <span class="function">read_root</span>(): |
| 87 | + <span class="keyword">return</span> {<span class="string">"Python"</span>: <span class="string">"on Vercel"</span>}</code></pre> |
| 88 | + </div> |
| 89 | + </div> |
| 90 | +
|
| 91 | + <div class="cards"> |
| 92 | + <div class="card"> |
| 93 | + <h3>Sample Data</h3> |
| 94 | + <p>Access sample JSON data through our REST API. Perfect for testing and development purposes.</p> |
| 95 | + <a href="/api/data">Get Data →</a> |
| 96 | + </div> |
| 97 | + </div> |
| 98 | + </main> |
| 99 | + </body> |
| 100 | + </html> |
| 101 | + """ |
0 commit comments