|
1 | | -import { ImageResponse } from "next/og" |
2 | | -import { NextRequest } from "next/server" |
| 1 | +import { NextRequest, NextResponse } from "next/server" |
3 | 2 |
|
4 | 3 | export const runtime = "edge" |
5 | 4 |
|
| 5 | +/** Redirect old ?time= URLs to clean /api/og/preconfirm/[time] path */ |
6 | 6 | export async function GET(request: NextRequest) { |
7 | 7 | const raw = parseFloat(request.nextUrl.searchParams.get("time") || "0.4") |
8 | 8 | const time = !isNaN(raw) && raw >= 0 && raw <= 999 ? raw.toFixed(1) : "0.4" |
9 | | - |
10 | | - // Subsetted fonts: Clonoid digits-only (2.5KB), Sora label chars only (5KB) |
11 | | - const [clonoidFont, soraFont] = await Promise.all([ |
12 | | - fetch(new URL("./fonts/clonoid-digits.ttf", import.meta.url)).then((r) => |
13 | | - r.arrayBuffer() |
14 | | - ), |
15 | | - fetch(new URL("./fonts/sora-subset.ttf", import.meta.url)).then((r) => |
16 | | - r.arrayBuffer() |
17 | | - ), |
18 | | - ]) |
19 | | - |
20 | | - return new ImageResponse( |
21 | | - <div |
22 | | - style={{ |
23 | | - width: "100%", |
24 | | - height: "100%", |
25 | | - display: "flex", |
26 | | - flexDirection: "column", |
27 | | - alignItems: "center", |
28 | | - justifyContent: "center", |
29 | | - background: "linear-gradient(160deg, #020810 0%, #071428 35%, #0d2040 60%, #091830 100%)", |
30 | | - position: "relative", |
31 | | - overflow: "hidden", |
32 | | - }} |
33 | | - > |
34 | | - {/* Outer subtle vignette */} |
35 | | - <div |
36 | | - style={{ |
37 | | - position: "absolute", |
38 | | - inset: 0, |
39 | | - background: |
40 | | - "radial-gradient(ellipse 80% 70% at 50% 45%, transparent 30%, rgba(0,0,0,0.4) 100%)", |
41 | | - }} |
42 | | - /> |
43 | | - |
44 | | - {/* Primary blue glow — centered upper half */} |
45 | | - <div |
46 | | - style={{ |
47 | | - position: "absolute", |
48 | | - width: "800px", |
49 | | - height: "500px", |
50 | | - borderRadius: "50%", |
51 | | - background: |
52 | | - "radial-gradient(ellipse, rgba(20, 90, 200, 0.3) 0%, rgba(15, 70, 170, 0.12) 35%, transparent 65%)", |
53 | | - top: "20%", |
54 | | - left: "50%", |
55 | | - transform: "translate(-50%, -50%)", |
56 | | - }} |
57 | | - /> |
58 | | - |
59 | | - {/* Secondary smaller glow for depth */} |
60 | | - <div |
61 | | - style={{ |
62 | | - position: "absolute", |
63 | | - width: "400px", |
64 | | - height: "300px", |
65 | | - borderRadius: "50%", |
66 | | - background: |
67 | | - "radial-gradient(ellipse, rgba(40, 130, 255, 0.15) 0%, transparent 70%)", |
68 | | - top: "35%", |
69 | | - left: "50%", |
70 | | - transform: "translate(-50%, -50%)", |
71 | | - }} |
72 | | - /> |
73 | | - |
74 | | - {/* Cyan horizon line */} |
75 | | - <div |
76 | | - style={{ |
77 | | - position: "absolute", |
78 | | - width: "100%", |
79 | | - height: "1px", |
80 | | - top: "63%", |
81 | | - background: |
82 | | - "linear-gradient(90deg, transparent 5%, rgba(0, 180, 255, 0.15) 25%, rgba(0, 200, 255, 0.5) 50%, rgba(0, 180, 255, 0.15) 75%, transparent 95%)", |
83 | | - }} |
84 | | - /> |
85 | | - |
86 | | - {/* Soft glow on the line */} |
87 | | - <div |
88 | | - style={{ |
89 | | - position: "absolute", |
90 | | - width: "60%", |
91 | | - height: "40px", |
92 | | - top: "61.5%", |
93 | | - left: "20%", |
94 | | - background: |
95 | | - "radial-gradient(ellipse, rgba(0, 160, 255, 0.08) 0%, transparent 70%)", |
96 | | - }} |
97 | | - /> |
98 | | - |
99 | | - {/* Content */} |
100 | | - <div |
101 | | - style={{ |
102 | | - display: "flex", |
103 | | - flexDirection: "column", |
104 | | - alignItems: "center", |
105 | | - justifyContent: "center", |
106 | | - position: "relative", |
107 | | - zIndex: 1, |
108 | | - paddingBottom: "70px", |
109 | | - }} |
110 | | - > |
111 | | - {/* SWAP PRECONFIRMED label */} |
112 | | - <div |
113 | | - style={{ |
114 | | - fontFamily: "Sora", |
115 | | - fontSize: "22px", |
116 | | - fontWeight: 600, |
117 | | - color: "rgba(140, 190, 255, 0.45)", |
118 | | - letterSpacing: "0.35em", |
119 | | - textTransform: "uppercase" as const, |
120 | | - marginBottom: "8px", |
121 | | - }} |
122 | | - > |
123 | | - Swap Preconfirmed |
124 | | - </div> |
125 | | - |
126 | | - {/* Speed number + sec */} |
127 | | - <div style={{ display: "flex", alignItems: "baseline", gap: "16px" }}> |
128 | | - <div |
129 | | - style={{ |
130 | | - fontFamily: "Clonoid", |
131 | | - fontSize: "200px", |
132 | | - color: "#fff", |
133 | | - lineHeight: 1, |
134 | | - letterSpacing: "-0.02em", |
135 | | - }} |
136 | | - > |
137 | | - {time} |
138 | | - </div> |
139 | | - <div |
140 | | - style={{ |
141 | | - fontFamily: "Sora", |
142 | | - fontSize: "52px", |
143 | | - fontWeight: 600, |
144 | | - color: "rgba(140, 190, 255, 0.4)", |
145 | | - lineHeight: 1, |
146 | | - marginBottom: "20px", |
147 | | - }} |
148 | | - > |
149 | | - sec |
150 | | - </div> |
151 | | - </div> |
152 | | - |
153 | | - {/* Branding */} |
154 | | - <div |
155 | | - style={{ |
156 | | - fontFamily: "Sora", |
157 | | - fontSize: "22px", |
158 | | - fontWeight: 600, |
159 | | - color: "rgba(140, 190, 255, 0.3)", |
160 | | - marginTop: "24px", |
161 | | - fontStyle: "italic", |
162 | | - letterSpacing: "0.05em", |
163 | | - }} |
164 | | - > |
165 | | - fastprotocol.io |
166 | | - </div> |
167 | | - </div> |
168 | | - </div>, |
169 | | - { |
170 | | - width: 1200, |
171 | | - height: 630, |
172 | | - fonts: [ |
173 | | - { name: "Clonoid", data: clonoidFont, style: "italic", weight: 700 }, |
174 | | - { name: "Sora", data: soraFont, style: "normal", weight: 600 }, |
175 | | - ], |
176 | | - } |
| 9 | + return NextResponse.redirect( |
| 10 | + new URL(`/api/og/preconfirm/${time}`, request.url), |
| 11 | + 301 |
177 | 12 | ) |
178 | 13 | } |
0 commit comments