[{"data":1,"prerenderedAt":3236},["ShallowReactive",2],{"content-/cloudflare-workers-routes-ogp-solution":3,"all-pages-for-dir":3215,"related-/cloudflare-workers-routes-ogp-solution":3216,"og-image-/cloudflare-workers-routes-ogp-solution":3235},{"id":4,"title":5,"body":6,"category":3199,"concepts":3199,"description":3200,"extension":3201,"meta":3202,"navigation":263,"ogImage":3199,"path":3203,"project_name":3199,"published":3204,"publishedAt":3205,"seo":3206,"source":3199,"stem":3207,"tags":3208,"todo":3199,"unpublished":3204,"updatedAt":3205,"__hash__":3214},"pages/2025-12/2025-12-25/cloudflare-workers-routes-ogp-solution.md","Cloudflare Workers Routes でOGPシェアURLのSEO問題を解決",{"type":7,"value":8,"toc":3173},"minimark",[9,13,18,27,38,42,72,76,83,89,95,98,102,105,111,117,173,177,187,192,202,204,208,214,220,223,228,231,237,242,817,824,828,835,841,846,1797,1803,1808,2583,2588,2592,2595,2601,2606,2613,2660,2686,2693,2696,2717,2719,2722,2726,2777,2781,2784,2859,2864,2915,2923,2926,2946,2957,2961,2964,2984,2986,2989,3074,3077,3080,3085,3090,3098,3100,3103,3106,3132,3136,3147,3149,3152,3169],[10,11,5],"h1",{"id":12},"cloudflare-workers-routes-でogpシェアurlのseo問題を解決",[14,15,17],"h2",{"id":16},"背景もともと何をやろうとしていたか","背景：もともと何をやろうとしていたか",[19,20,21,22,26],"p",{},"SNSで日本語作文クイズの結果をシェアする際、",[23,24,25],"strong",{},"動的にOGP画像を生成","したかった。",[28,29,34],"pre",{"className":30,"code":32,"language":33},[31],"language-text","ユーザーがクイズ完了 → 「5/12問正解！」のOGP画像を動的生成 → SNSでシェア\n","text",[35,36,32],"code",{"__ignoreMap":37},"",[39,40,41],"h3",{"id":41},"課題",[43,44,45,56,62],"ol",{},[46,47,48,51,52,55],"li",{},[23,49,50],{},"Nuxt は静的サイト生成（SSG）を使用"," - OOM問題により ",[35,53,54],{},"cloudflare-pages-static"," プリセットを使用",[46,57,58,61],{},[23,59,60],{},"静的サイトではクエリパラメータを動的に処理できない"," - ビルド時に固定される",[46,63,64,71],{},[23,65,66,67,70],{},"OGP画像生成に ",[35,68,69],{},"workers-og"," を使いたい"," - Nuxt ビルドに組み込むとWASM関連でOOMが発生",[39,73,75],{"id":74},"初期の解決策workerを分離","初期の解決策：Workerを分離",[19,77,78,79,82],{},"OGP画像生成を別の Cloudflare Worker（",[35,80,81],{},"og-image-worker","）として分離してデプロイ。",[28,84,87],{"className":85,"code":86,"language":33},[31],"apps/workers/og/\n├── src/index.ts    # OGP画像生成 + シェアページHTML\n├── wrangler.toml\n└── package.json\n",[35,88,86],{"__ignoreMap":37},[19,90,91,92],{},"Worker URL: ",[35,93,94],{},"https://og-image-worker.number55number55.workers.dev",[96,97],"hr",{},[14,99,101],{"id":100},"発生した問題seo効果がメインドメインに帰属しない","発生した問題：SEO効果がメインドメインに帰属しない",[39,103,104],{"id":104},"問題のある構成",[28,106,109],{"className":107,"code":108,"language":33},[31],"シェアURL: https://og-image-worker.number55number55.workers.dev/share/japanese-quiz?...\n                    ↑ Workers.dev ドメイン\n",[35,110,108],{"__ignoreMap":37},[19,112,113,116],{},[35,114,115],{},"workers.dev"," をSNSで拡散されるリンクが指しているため：",[118,119,120,133],"table",{},[121,122,123],"thead",{},[124,125,126,130],"tr",{},[127,128,129],"th",{},"項目",[127,131,132],{},"状態",[134,135,136,145,153,163],"tbody",{},[124,137,138,142],{},[139,140,141],"td",{},"OGPカード表示",[139,143,144],{},"正常",[124,146,147,150],{},[139,148,149],{},"ユーザートラフィック",[139,151,152],{},"リダイレクトで得られる",[124,154,155,160],{},[139,156,157],{},[23,158,159],{},"被リンク評価（SEO）",[139,161,162],{},"workers.dev に帰属",[124,164,165,170],{},[139,166,167],{},[23,168,169],{},"ブランドURL認知",[139,171,172],{},"低い",[39,174,176],{"id":175},"nuxt側にシェアページを作成してみたが","Nuxt側にシェアページを作成してみたが",[19,178,179,182,183,186],{},[35,180,181],{},"pages/share/japanese-quiz.vue"," を作成し、シェアURLを ",[35,184,185],{},"log.eurekapu.com/share/..."," に変更。",[19,188,189],{},[23,190,191],{},"結果：失敗",[19,193,194,197,198,201],{},[35,195,196],{},"route.query"," がビルド時に空になる静的サイト生成では、OGPメタタグが固定値（",[35,199,200],{},"0/10問正解","）になってしまった。",[96,203],{},[14,205,207],{"id":206},"解決策cloudflare-workers-routes","解決策：Cloudflare Workers Routes",[19,209,210,213],{},[23,211,212],{},"Workers Routes"," を使って、メインドメインのURLでWorkerを実行する。",[28,215,218],{"className":216,"code":217,"language":33},[31],"設定前:\nlog.eurekapu.com/share/* → Nuxt静的ページ（クエリパラメータが空）\n\n設定後:\nlog.eurekapu.com/share/* → Worker（クエリパラメータを動的に処理）\n",[35,219,217],{"__ignoreMap":37},[39,221,222],{"id":222},"仕組み",[224,225,227],"h4",{"id":226},"step-1-ユーザーがsnsにシェア","Step 1: ユーザーがSNSにシェア",[19,229,230],{},"クイズ完了後、「結果をシェアする」ボタンを押すと、以下のURLがSNSに投稿される：",[28,232,235],{"className":233,"code":234,"language":33},[31],"https://log.eurekapu.com/share/japanese-quiz?category=punctuation&correct=5&total=12\n",[35,236,234],{"__ignoreMap":37},[19,238,239],{},[23,240,241],{},"Nuxt側の実装（ResultSummary.vue）：",[28,243,247],{"className":244,"code":245,"language":246,"meta":37,"style":37},"language-typescript shiki shiki-themes vitesse-light vitesse-light","// apps/web/app/components/japanese-quiz/ResultSummary.vue\n\n// シェアURLはメインドメインのシェアページを使用（SEO効果を最大化）\nconst shareUrl = computed(() => {\n  return `https://log.eurekapu.com/share/japanese-quiz?category=${props.category}&correct=${props.result.correctAnswers}&total=${props.result.totalQuestions}`\n})\n\nconst shareText = computed(() => {\n  const categoryName = getCategoryLabel(props.category)\n  return `「${categoryName}」クイズで${props.result.correctAnswers}/${props.result.totalQuestions}問正解しました！\\n\\nあなたも挑戦してみませんか？`\n})\n\n// シェアボタン押下時の処理\nconst shareResult = async () => {\n  if (navigator.share) {\n    // Web Share API が使える場合（主にモバイル）\n    await navigator.share({\n      title: `${getCategoryLabel(props.category)}クイズ結果`,\n      text: shareText.value,\n      url: shareUrl.value,  // ← このURLがSNSに投稿される\n    })\n  } else {\n    // Web Share APIが使えない場合はTwitterにシェア\n    shareToTwitter()\n  }\n}\n\nconst shareToTwitter = () => {\n  const tweetText = encodeURIComponent(shareText.value)\n  const tweetUrl = encodeURIComponent(shareUrl.value)\n  window.open(\n    `https://twitter.com/intent/tweet?text=${tweetText}&url=${tweetUrl}`,\n    '_blank'\n  )\n}\n","typescript",[35,248,249,258,265,271,299,369,375,380,398,424,486,491,496,502,522,544,550,566,604,621,641,647,658,664,673,679,685,690,707,730,752,766,794,806,812],{"__ignoreMap":37},[250,251,254],"span",{"class":252,"line":253},"line",1,[250,255,257],{"class":256},"sxvE3","// apps/web/app/components/japanese-quiz/ResultSummary.vue\n",[250,259,261],{"class":252,"line":260},2,[250,262,264],{"emptyLinePlaceholder":263},true,"\n",[250,266,268],{"class":252,"line":267},3,[250,269,270],{"class":256},"// シェアURLはメインドメインのシェアページを使用（SEO効果を最大化）\n",[250,272,274,278,282,286,290,293,296],{"class":252,"line":273},4,[250,275,277],{"class":276},"stQ0i","const ",[250,279,281],{"class":280},"s4oTP","shareUrl",[250,283,285],{"class":284},"shFtX"," =",[250,287,289],{"class":288},"senZ8"," computed",[250,291,292],{"class":284},"(()",[250,294,295],{"class":284}," =>",[250,297,298],{"class":284}," {\n",[250,300,302,306,310,314,317,320,323,326,329,332,334,336,338,341,343,346,348,351,353,355,357,359,361,364,366],{"class":252,"line":301},5,[250,303,305],{"class":304},"sHkkW","  return",[250,307,309],{"class":308},"sMJiu"," `",[250,311,313],{"class":312},"sdGka","https://log.eurekapu.com/share/japanese-quiz?category=",[250,315,316],{"class":304},"${",[250,318,319],{"class":312},"props",[250,321,322],{"class":284},".",[250,324,325],{"class":312},"category",[250,327,328],{"class":304},"}",[250,330,331],{"class":312},"&correct=",[250,333,316],{"class":304},[250,335,319],{"class":312},[250,337,322],{"class":284},[250,339,340],{"class":312},"result",[250,342,322],{"class":284},[250,344,345],{"class":312},"correctAnswers",[250,347,328],{"class":304},[250,349,350],{"class":312},"&total=",[250,352,316],{"class":304},[250,354,319],{"class":312},[250,356,322],{"class":284},[250,358,340],{"class":312},[250,360,322],{"class":284},[250,362,363],{"class":312},"totalQuestions",[250,365,328],{"class":304},[250,367,368],{"class":308},"`\n",[250,370,372],{"class":252,"line":371},6,[250,373,374],{"class":284},"})\n",[250,376,378],{"class":252,"line":377},7,[250,379,264],{"emptyLinePlaceholder":263},[250,381,383,385,388,390,392,394,396],{"class":252,"line":382},8,[250,384,277],{"class":276},[250,386,387],{"class":280},"shareText",[250,389,285],{"class":284},[250,391,289],{"class":288},[250,393,292],{"class":284},[250,395,295],{"class":284},[250,397,298],{"class":284},[250,399,401,404,407,409,412,415,417,419,421],{"class":252,"line":400},9,[250,402,403],{"class":276},"  const ",[250,405,406],{"class":280},"categoryName",[250,408,285],{"class":284},[250,410,411],{"class":288}," getCategoryLabel",[250,413,414],{"class":284},"(",[250,416,319],{"class":280},[250,418,322],{"class":284},[250,420,325],{"class":280},[250,422,423],{"class":284},")\n",[250,425,427,429,431,434,436,438,440,443,445,447,449,451,453,455,457,460,462,464,466,468,470,472,474,477,481,484],{"class":252,"line":426},10,[250,428,305],{"class":304},[250,430,309],{"class":308},[250,432,433],{"class":312},"「",[250,435,316],{"class":304},[250,437,406],{"class":312},[250,439,328],{"class":304},[250,441,442],{"class":312},"」クイズで",[250,444,316],{"class":304},[250,446,319],{"class":312},[250,448,322],{"class":284},[250,450,340],{"class":312},[250,452,322],{"class":284},[250,454,345],{"class":312},[250,456,328],{"class":304},[250,458,459],{"class":312},"/",[250,461,316],{"class":304},[250,463,319],{"class":312},[250,465,322],{"class":284},[250,467,340],{"class":312},[250,469,322],{"class":284},[250,471,363],{"class":312},[250,473,328],{"class":304},[250,475,476],{"class":312},"問正解しました！",[250,478,480],{"class":479},"snbK4","\\n\\n",[250,482,483],{"class":312},"あなたも挑戦してみませんか？",[250,485,368],{"class":308},[250,487,489],{"class":252,"line":488},11,[250,490,374],{"class":284},[250,492,494],{"class":252,"line":493},12,[250,495,264],{"emptyLinePlaceholder":263},[250,497,499],{"class":252,"line":498},13,[250,500,501],{"class":256},"// シェアボタン押下時の処理\n",[250,503,505,507,510,512,515,518,520],{"class":252,"line":504},14,[250,506,277],{"class":276},[250,508,509],{"class":288},"shareResult",[250,511,285],{"class":284},[250,513,514],{"class":276}," async ",[250,516,517],{"class":284},"()",[250,519,295],{"class":284},[250,521,298],{"class":284},[250,523,525,528,531,534,536,539,542],{"class":252,"line":524},15,[250,526,527],{"class":304},"  if",[250,529,530],{"class":284}," (",[250,532,533],{"class":280},"navigator",[250,535,322],{"class":284},[250,537,538],{"class":280},"share",[250,540,541],{"class":284},")",[250,543,298],{"class":284},[250,545,547],{"class":252,"line":546},16,[250,548,549],{"class":256},"    // Web Share API が使える場合（主にモバイル）\n",[250,551,553,556,559,561,563],{"class":252,"line":552},17,[250,554,555],{"class":304},"    await",[250,557,558],{"class":280}," navigator",[250,560,322],{"class":284},[250,562,538],{"class":288},[250,564,565],{"class":284},"({\n",[250,567,569,573,576,579,581,584,586,588,590,592,594,596,599,601],{"class":252,"line":568},18,[250,570,572],{"class":571},"sz8Xr","      title",[250,574,575],{"class":284},": ",[250,577,578],{"class":308},"`",[250,580,316],{"class":304},[250,582,583],{"class":288},"getCategoryLabel",[250,585,414],{"class":284},[250,587,319],{"class":312},[250,589,322],{"class":284},[250,591,325],{"class":312},[250,593,541],{"class":284},[250,595,328],{"class":304},[250,597,598],{"class":312},"クイズ結果",[250,600,578],{"class":308},[250,602,603],{"class":284},",\n",[250,605,607,610,612,614,616,619],{"class":252,"line":606},19,[250,608,609],{"class":571},"      text",[250,611,575],{"class":284},[250,613,387],{"class":280},[250,615,322],{"class":284},[250,617,618],{"class":280},"value",[250,620,603],{"class":284},[250,622,624,627,629,631,633,635,638],{"class":252,"line":623},20,[250,625,626],{"class":571},"      url",[250,628,575],{"class":284},[250,630,281],{"class":280},[250,632,322],{"class":284},[250,634,618],{"class":280},[250,636,637],{"class":284},",  ",[250,639,640],{"class":256},"// ← このURLがSNSに投稿される\n",[250,642,644],{"class":252,"line":643},21,[250,645,646],{"class":284},"    })\n",[250,648,650,653,656],{"class":252,"line":649},22,[250,651,652],{"class":284},"  }",[250,654,655],{"class":304}," else",[250,657,298],{"class":284},[250,659,661],{"class":252,"line":660},23,[250,662,663],{"class":256},"    // Web Share APIが使えない場合はTwitterにシェア\n",[250,665,667,670],{"class":252,"line":666},24,[250,668,669],{"class":288},"    shareToTwitter",[250,671,672],{"class":284},"()\n",[250,674,676],{"class":252,"line":675},25,[250,677,678],{"class":284},"  }\n",[250,680,682],{"class":252,"line":681},26,[250,683,684],{"class":284},"}\n",[250,686,688],{"class":252,"line":687},27,[250,689,264],{"emptyLinePlaceholder":263},[250,691,693,695,698,700,703,705],{"class":252,"line":692},28,[250,694,277],{"class":276},[250,696,697],{"class":288},"shareToTwitter",[250,699,285],{"class":284},[250,701,702],{"class":284}," ()",[250,704,295],{"class":284},[250,706,298],{"class":284},[250,708,710,712,715,717,720,722,724,726,728],{"class":252,"line":709},29,[250,711,403],{"class":276},[250,713,714],{"class":280},"tweetText",[250,716,285],{"class":284},[250,718,719],{"class":288}," encodeURIComponent",[250,721,414],{"class":284},[250,723,387],{"class":280},[250,725,322],{"class":284},[250,727,618],{"class":280},[250,729,423],{"class":284},[250,731,733,735,738,740,742,744,746,748,750],{"class":252,"line":732},30,[250,734,403],{"class":276},[250,736,737],{"class":280},"tweetUrl",[250,739,285],{"class":284},[250,741,719],{"class":288},[250,743,414],{"class":284},[250,745,281],{"class":280},[250,747,322],{"class":284},[250,749,618],{"class":280},[250,751,423],{"class":284},[250,753,755,758,760,763],{"class":252,"line":754},31,[250,756,757],{"class":280},"  window",[250,759,322],{"class":284},[250,761,762],{"class":288},"open",[250,764,765],{"class":284},"(\n",[250,767,769,772,775,777,779,781,784,786,788,790,792],{"class":252,"line":768},32,[250,770,771],{"class":308},"    `",[250,773,774],{"class":312},"https://twitter.com/intent/tweet?text=",[250,776,316],{"class":304},[250,778,714],{"class":312},[250,780,328],{"class":304},[250,782,783],{"class":312},"&url=",[250,785,316],{"class":304},[250,787,737],{"class":312},[250,789,328],{"class":304},[250,791,578],{"class":308},[250,793,603],{"class":284},[250,795,797,800,803],{"class":252,"line":796},33,[250,798,799],{"class":308},"    '",[250,801,802],{"class":312},"_blank",[250,804,805],{"class":308},"'\n",[250,807,809],{"class":252,"line":808},34,[250,810,811],{"class":284},"  )\n",[250,813,815],{"class":252,"line":814},35,[250,816,684],{"class":284},[19,818,819,820,823],{},"ポイント：",[35,821,822],{},"log.eurekapu.com","（メインドメイン）をシェアURLは指している。Workers Routes によって、このURLへのアクセスは Worker に転送される。",[224,825,827],{"id":826},"step-2-snsクローラーがogp情報を取得","Step 2: SNSクローラーがOGP情報を取得",[19,829,830,831,834],{},"SNS（Twitter/X、Facebook等）は投稿されたURLに対して",[23,832,833],{},"クローラー","を送り、OGPメタタグを読み取る：",[28,836,839],{"className":837,"code":838,"language":33},[31],"SNSクローラーがURLにアクセス\n        ↓\nhttps://log.eurekapu.com/share/japanese-quiz?category=punctuation&correct=5&total=12\n        ↓\nCloudflare がルートをチェック → 「/share/*」にマッチ\n        ↓\nog-image-worker に転送\n        ↓\nWorker がクエリパラメータを読んで動的にHTML生成\n        ↓\nOGPメタタグ付きHTMLを返す:\n  - og:title = \"句読点の打ち方クイズ - 5/12問正解！\"\n  - og:image = \"https://og-image-worker.../og/japanese-quiz?category=punctuation&correct=5&total=12\"\n        ↓\nSNSクローラーが og:image のURLにもアクセス\n        ↓\nWorker が動的にOGP画像を生成して返す（「5/12問正解」の画像）\n        ↓\nSNSがOGPカードを表示（タイトル + 説明 + 画像）\n",[35,840,838],{"__ignoreMap":37},[19,842,843],{},[23,844,845],{},"Worker側の実装（シェアページHTML生成）：",[28,847,849],{"className":244,"code":848,"language":246,"meta":37,"style":37},"// apps/workers/og/src/index.ts\n\n// カテゴリ名マッピング\nconst CATEGORY_NAMES: Record\u003Cstring, string> = {\n  'modification-order': '修飾語の順序',\n  'punctuation': '句読点の打ち方',\n  'particles': '助詞の使い方',\n  'all': '全問チャレンジ',\n}\n\nexport default {\n  async fetch(request: Request, env: Env): Promise\u003CResponse> {\n    const url = new URL(request.url)\n\n    // OGP画像を返す（og:image用）\n    if (url.pathname === '/og/japanese-quiz') {\n      return handleJapaneseQuizImage(url)\n    }\n\n    // シェアページ（OGタグ付きHTMLを返し、実際のページにリダイレクト）\n    if (url.pathname === '/share/japanese-quiz') {\n      return handleSharePage(url)\n    }\n\n    return new Response('Not Found', { status: 404 })\n  },\n}\n\n// シェアページ: OGタグ付きHTMLを返す\nfunction handleSharePage(url: URL): Response {\n  // クエリパラメータから値を取得（動的に処理できる！）\n  const category = url.searchParams.get('category') || 'all'\n  const correct = url.searchParams.get('correct') || '0'\n  const total = url.searchParams.get('total') || '10'\n\n  const categoryName = CATEGORY_NAMES[category] || 'クイズ'\n  const ogImageUrl = `https://og-image-worker.number55number55.workers.dev/og/japanese-quiz?category=${category}&correct=${correct}&total=${total}`\n  const redirectUrl = `https://log.eurekapu.com/japanese-writing-quiz/${category}`\n\n  // OGPメタタグを含むHTMLを動的に生成\n  const html = `\u003C!DOCTYPE html>\n\u003Chtml lang=\"ja\">\n\u003Chead>\n  \u003Cmeta charset=\"UTF-8\">\n  \u003Ctitle>${categoryName} - ${correct}/${total}問正解！ | 日本語作文クイズ\u003C/title>\n\n  \u003C!-- OGPメタタグ（SNSクローラーが読み取る） -->\n  \u003Cmeta property=\"og:title\" content=\"${categoryName}クイズ - ${correct}/${total}問正解！\">\n  \u003Cmeta property=\"og:description\" content=\"日本語作文クイズに挑戦しよう\">\n  \u003Cmeta property=\"og:image\" content=\"${ogImageUrl}\">\n  \u003Cmeta property=\"og:type\" content=\"website\">\n\n  \u003C!-- Twitter Card -->\n  \u003Cmeta name=\"twitter:card\" content=\"summary_large_image\">\n  \u003Cmeta name=\"twitter:title\" content=\"${categoryName}クイズ - ${correct}/${total}問正解！\">\n  \u003Cmeta name=\"twitter:image\" content=\"${ogImageUrl}\">\n\n  \u003C!-- 人間のユーザー用：即座にリダイレクト -->\n  \u003Cmeta http-equiv=\"refresh\" content=\"0;url=${redirectUrl}\">\n\u003C/head>\n\u003Cbody>\n  \u003Cp>リダイレクト中... \u003Ca href=\"${redirectUrl}\">こちらをクリック\u003C/a>\u003C/p>\n\u003C/body>\n\u003C/html>`\n\n  return new Response(html, {\n    headers: { 'Content-Type': 'text/html; charset=utf-8' },\n  })\n}\n",[35,850,851,856,860,865,894,916,936,956,976,980,984,994,1036,1062,1066,1071,1099,1113,1118,1122,1127,1150,1163,1167,1171,1206,1211,1215,1219,1224,1246,1251,1291,1329,1367,1371,1400,1439,1462,1467,1473,1488,1494,1500,1506,1538,1543,1549,1581,1587,1602,1608,1613,1619,1625,1655,1669,1674,1680,1694,1700,1706,1721,1727,1735,1740,1758,1786,1792],{"__ignoreMap":37},[250,852,853],{"class":252,"line":253},[250,854,855],{"class":256},"// apps/workers/og/src/index.ts\n",[250,857,858],{"class":252,"line":260},[250,859,264],{"emptyLinePlaceholder":263},[250,861,862],{"class":252,"line":267},[250,863,864],{"class":256},"// カテゴリ名マッピング\n",[250,866,867,869,872,874,878,881,884,887,889,892],{"class":252,"line":273},[250,868,277],{"class":276},[250,870,871],{"class":280},"CATEGORY_NAMES",[250,873,575],{"class":284},[250,875,877],{"class":876},"sSkh3","Record",[250,879,880],{"class":284},"\u003C",[250,882,883],{"class":876},"string",[250,885,886],{"class":284},", ",[250,888,883],{"class":876},[250,890,891],{"class":284},"> =",[250,893,298],{"class":284},[250,895,896,899,902,905,907,909,912,914],{"class":252,"line":301},[250,897,898],{"class":308},"  '",[250,900,901],{"class":312},"modification-order",[250,903,904],{"class":308},"'",[250,906,575],{"class":284},[250,908,904],{"class":308},[250,910,911],{"class":312},"修飾語の順序",[250,913,904],{"class":308},[250,915,603],{"class":284},[250,917,918,920,923,925,927,929,932,934],{"class":252,"line":371},[250,919,898],{"class":308},[250,921,922],{"class":312},"punctuation",[250,924,904],{"class":308},[250,926,575],{"class":284},[250,928,904],{"class":308},[250,930,931],{"class":312},"句読点の打ち方",[250,933,904],{"class":308},[250,935,603],{"class":284},[250,937,938,940,943,945,947,949,952,954],{"class":252,"line":377},[250,939,898],{"class":308},[250,941,942],{"class":312},"particles",[250,944,904],{"class":308},[250,946,575],{"class":284},[250,948,904],{"class":308},[250,950,951],{"class":312},"助詞の使い方",[250,953,904],{"class":308},[250,955,603],{"class":284},[250,957,958,960,963,965,967,969,972,974],{"class":252,"line":382},[250,959,898],{"class":308},[250,961,962],{"class":312},"all",[250,964,904],{"class":308},[250,966,575],{"class":284},[250,968,904],{"class":308},[250,970,971],{"class":312},"全問チャレンジ",[250,973,904],{"class":308},[250,975,603],{"class":284},[250,977,978],{"class":252,"line":400},[250,979,684],{"class":284},[250,981,982],{"class":252,"line":426},[250,983,264],{"emptyLinePlaceholder":263},[250,985,986,989,992],{"class":252,"line":488},[250,987,988],{"class":304},"export",[250,990,991],{"class":304}," default",[250,993,298],{"class":284},[250,995,996,999,1002,1004,1007,1009,1012,1014,1017,1019,1022,1025,1028,1030,1033],{"class":252,"line":493},[250,997,998],{"class":276},"  async",[250,1000,1001],{"class":288}," fetch",[250,1003,414],{"class":284},[250,1005,1006],{"class":280},"request",[250,1008,575],{"class":284},[250,1010,1011],{"class":876},"Request",[250,1013,886],{"class":284},[250,1015,1016],{"class":280},"env",[250,1018,575],{"class":284},[250,1020,1021],{"class":876},"Env",[250,1023,1024],{"class":284},"): ",[250,1026,1027],{"class":876},"Promise",[250,1029,880],{"class":284},[250,1031,1032],{"class":876},"Response",[250,1034,1035],{"class":284},"> {\n",[250,1037,1038,1041,1044,1046,1049,1052,1054,1056,1058,1060],{"class":252,"line":498},[250,1039,1040],{"class":276},"    const ",[250,1042,1043],{"class":280},"url",[250,1045,285],{"class":284},[250,1047,1048],{"class":276}," new ",[250,1050,1051],{"class":288},"URL",[250,1053,414],{"class":284},[250,1055,1006],{"class":280},[250,1057,322],{"class":284},[250,1059,1043],{"class":280},[250,1061,423],{"class":284},[250,1063,1064],{"class":252,"line":504},[250,1065,264],{"emptyLinePlaceholder":263},[250,1067,1068],{"class":252,"line":524},[250,1069,1070],{"class":256},"    // OGP画像を返す（og:image用）\n",[250,1072,1073,1076,1078,1080,1082,1085,1088,1091,1094,1096],{"class":252,"line":546},[250,1074,1075],{"class":304},"    if",[250,1077,530],{"class":284},[250,1079,1043],{"class":280},[250,1081,322],{"class":284},[250,1083,1084],{"class":280},"pathname",[250,1086,1087],{"class":276}," ===",[250,1089,1090],{"class":308}," '",[250,1092,1093],{"class":312},"/og/japanese-quiz",[250,1095,904],{"class":308},[250,1097,1098],{"class":284},") {\n",[250,1100,1101,1104,1107,1109,1111],{"class":252,"line":552},[250,1102,1103],{"class":304},"      return",[250,1105,1106],{"class":288}," handleJapaneseQuizImage",[250,1108,414],{"class":284},[250,1110,1043],{"class":280},[250,1112,423],{"class":284},[250,1114,1115],{"class":252,"line":568},[250,1116,1117],{"class":284},"    }\n",[250,1119,1120],{"class":252,"line":606},[250,1121,264],{"emptyLinePlaceholder":263},[250,1123,1124],{"class":252,"line":623},[250,1125,1126],{"class":256},"    // シェアページ（OGタグ付きHTMLを返し、実際のページにリダイレクト）\n",[250,1128,1129,1131,1133,1135,1137,1139,1141,1143,1146,1148],{"class":252,"line":643},[250,1130,1075],{"class":304},[250,1132,530],{"class":284},[250,1134,1043],{"class":280},[250,1136,322],{"class":284},[250,1138,1084],{"class":280},[250,1140,1087],{"class":276},[250,1142,1090],{"class":308},[250,1144,1145],{"class":312},"/share/japanese-quiz",[250,1147,904],{"class":308},[250,1149,1098],{"class":284},[250,1151,1152,1154,1157,1159,1161],{"class":252,"line":649},[250,1153,1103],{"class":304},[250,1155,1156],{"class":288}," handleSharePage",[250,1158,414],{"class":284},[250,1160,1043],{"class":280},[250,1162,423],{"class":284},[250,1164,1165],{"class":252,"line":660},[250,1166,1117],{"class":284},[250,1168,1169],{"class":252,"line":666},[250,1170,264],{"emptyLinePlaceholder":263},[250,1172,1173,1176,1179,1182,1184,1186,1189,1191,1194,1197,1199,1203],{"class":252,"line":675},[250,1174,1175],{"class":304},"    return",[250,1177,1178],{"class":276}," new",[250,1180,1181],{"class":288}," Response",[250,1183,414],{"class":284},[250,1185,904],{"class":308},[250,1187,1188],{"class":312},"Not Found",[250,1190,904],{"class":308},[250,1192,1193],{"class":284},", { ",[250,1195,1196],{"class":571},"status",[250,1198,575],{"class":284},[250,1200,1202],{"class":1201},"sM54T","404",[250,1204,1205],{"class":284}," })\n",[250,1207,1208],{"class":252,"line":681},[250,1209,1210],{"class":284},"  },\n",[250,1212,1213],{"class":252,"line":687},[250,1214,684],{"class":284},[250,1216,1217],{"class":252,"line":692},[250,1218,264],{"emptyLinePlaceholder":263},[250,1220,1221],{"class":252,"line":709},[250,1222,1223],{"class":256},"// シェアページ: OGタグ付きHTMLを返す\n",[250,1225,1226,1229,1231,1233,1235,1237,1239,1242,1244],{"class":252,"line":732},[250,1227,1228],{"class":276},"function",[250,1230,1156],{"class":288},[250,1232,414],{"class":284},[250,1234,1043],{"class":280},[250,1236,575],{"class":284},[250,1238,1051],{"class":876},[250,1240,1241],{"class":284},"):",[250,1243,1181],{"class":876},[250,1245,298],{"class":284},[250,1247,1248],{"class":252,"line":754},[250,1249,1250],{"class":256},"  // クエリパラメータから値を取得（動的に処理できる！）\n",[250,1252,1253,1255,1257,1259,1262,1264,1267,1269,1272,1274,1276,1278,1280,1282,1285,1287,1289],{"class":252,"line":768},[250,1254,403],{"class":276},[250,1256,325],{"class":280},[250,1258,285],{"class":284},[250,1260,1261],{"class":280}," url",[250,1263,322],{"class":284},[250,1265,1266],{"class":280},"searchParams",[250,1268,322],{"class":284},[250,1270,1271],{"class":288},"get",[250,1273,414],{"class":284},[250,1275,904],{"class":308},[250,1277,325],{"class":312},[250,1279,904],{"class":308},[250,1281,541],{"class":284},[250,1283,1284],{"class":276}," || ",[250,1286,904],{"class":308},[250,1288,962],{"class":312},[250,1290,805],{"class":308},[250,1292,1293,1295,1298,1300,1302,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324,1327],{"class":252,"line":796},[250,1294,403],{"class":276},[250,1296,1297],{"class":280},"correct",[250,1299,285],{"class":284},[250,1301,1261],{"class":280},[250,1303,322],{"class":284},[250,1305,1266],{"class":280},[250,1307,322],{"class":284},[250,1309,1271],{"class":288},[250,1311,414],{"class":284},[250,1313,904],{"class":308},[250,1315,1297],{"class":312},[250,1317,904],{"class":308},[250,1319,541],{"class":284},[250,1321,1284],{"class":276},[250,1323,904],{"class":308},[250,1325,1326],{"class":312},"0",[250,1328,805],{"class":308},[250,1330,1331,1333,1336,1338,1340,1342,1344,1346,1348,1350,1352,1354,1356,1358,1360,1362,1365],{"class":252,"line":808},[250,1332,403],{"class":276},[250,1334,1335],{"class":280},"total",[250,1337,285],{"class":284},[250,1339,1261],{"class":280},[250,1341,322],{"class":284},[250,1343,1266],{"class":280},[250,1345,322],{"class":284},[250,1347,1271],{"class":288},[250,1349,414],{"class":284},[250,1351,904],{"class":308},[250,1353,1335],{"class":312},[250,1355,904],{"class":308},[250,1357,541],{"class":284},[250,1359,1284],{"class":276},[250,1361,904],{"class":308},[250,1363,1364],{"class":312},"10",[250,1366,805],{"class":308},[250,1368,1369],{"class":252,"line":814},[250,1370,264],{"emptyLinePlaceholder":263},[250,1372,1374,1376,1378,1380,1383,1386,1388,1391,1393,1395,1398],{"class":252,"line":1373},36,[250,1375,403],{"class":276},[250,1377,406],{"class":280},[250,1379,285],{"class":284},[250,1381,1382],{"class":280}," CATEGORY_NAMES",[250,1384,1385],{"class":284},"[",[250,1387,325],{"class":280},[250,1389,1390],{"class":284},"]",[250,1392,1284],{"class":276},[250,1394,904],{"class":308},[250,1396,1397],{"class":312},"クイズ",[250,1399,805],{"class":308},[250,1401,1403,1405,1408,1410,1412,1415,1417,1419,1421,1423,1425,1427,1429,1431,1433,1435,1437],{"class":252,"line":1402},37,[250,1404,403],{"class":276},[250,1406,1407],{"class":280},"ogImageUrl",[250,1409,285],{"class":284},[250,1411,309],{"class":308},[250,1413,1414],{"class":312},"https://og-image-worker.number55number55.workers.dev/og/japanese-quiz?category=",[250,1416,316],{"class":304},[250,1418,325],{"class":312},[250,1420,328],{"class":304},[250,1422,331],{"class":312},[250,1424,316],{"class":304},[250,1426,1297],{"class":312},[250,1428,328],{"class":304},[250,1430,350],{"class":312},[250,1432,316],{"class":304},[250,1434,1335],{"class":312},[250,1436,328],{"class":304},[250,1438,368],{"class":308},[250,1440,1442,1444,1447,1449,1451,1454,1456,1458,1460],{"class":252,"line":1441},38,[250,1443,403],{"class":276},[250,1445,1446],{"class":280},"redirectUrl",[250,1448,285],{"class":284},[250,1450,309],{"class":308},[250,1452,1453],{"class":312},"https://log.eurekapu.com/japanese-writing-quiz/",[250,1455,316],{"class":304},[250,1457,325],{"class":312},[250,1459,328],{"class":304},[250,1461,368],{"class":308},[250,1463,1465],{"class":252,"line":1464},39,[250,1466,264],{"emptyLinePlaceholder":263},[250,1468,1470],{"class":252,"line":1469},40,[250,1471,1472],{"class":256},"  // OGPメタタグを含むHTMLを動的に生成\n",[250,1474,1476,1478,1481,1483,1485],{"class":252,"line":1475},41,[250,1477,403],{"class":276},[250,1479,1480],{"class":280},"html",[250,1482,285],{"class":284},[250,1484,309],{"class":308},[250,1486,1487],{"class":312},"\u003C!DOCTYPE html>\n",[250,1489,1491],{"class":252,"line":1490},42,[250,1492,1493],{"class":312},"\u003Chtml lang=\"ja\">\n",[250,1495,1497],{"class":252,"line":1496},43,[250,1498,1499],{"class":312},"\u003Chead>\n",[250,1501,1503],{"class":252,"line":1502},44,[250,1504,1505],{"class":312},"  \u003Cmeta charset=\"UTF-8\">\n",[250,1507,1509,1512,1514,1516,1518,1521,1523,1525,1527,1529,1531,1533,1535],{"class":252,"line":1508},45,[250,1510,1511],{"class":312},"  \u003Ctitle>",[250,1513,316],{"class":304},[250,1515,406],{"class":312},[250,1517,328],{"class":304},[250,1519,1520],{"class":312}," - ",[250,1522,316],{"class":304},[250,1524,1297],{"class":312},[250,1526,328],{"class":304},[250,1528,459],{"class":312},[250,1530,316],{"class":304},[250,1532,1335],{"class":312},[250,1534,328],{"class":304},[250,1536,1537],{"class":312},"問正解！ | 日本語作文クイズ\u003C/title>\n",[250,1539,1541],{"class":252,"line":1540},46,[250,1542,264],{"emptyLinePlaceholder":263},[250,1544,1546],{"class":252,"line":1545},47,[250,1547,1548],{"class":312},"  \u003C!-- OGPメタタグ（SNSクローラーが読み取る） -->\n",[250,1550,1552,1555,1557,1559,1561,1564,1566,1568,1570,1572,1574,1576,1578],{"class":252,"line":1551},48,[250,1553,1554],{"class":312},"  \u003Cmeta property=\"og:title\" content=\"",[250,1556,316],{"class":304},[250,1558,406],{"class":312},[250,1560,328],{"class":304},[250,1562,1563],{"class":312},"クイズ - ",[250,1565,316],{"class":304},[250,1567,1297],{"class":312},[250,1569,328],{"class":304},[250,1571,459],{"class":312},[250,1573,316],{"class":304},[250,1575,1335],{"class":312},[250,1577,328],{"class":304},[250,1579,1580],{"class":312},"問正解！\">\n",[250,1582,1584],{"class":252,"line":1583},49,[250,1585,1586],{"class":312},"  \u003Cmeta property=\"og:description\" content=\"日本語作文クイズに挑戦しよう\">\n",[250,1588,1590,1593,1595,1597,1599],{"class":252,"line":1589},50,[250,1591,1592],{"class":312},"  \u003Cmeta property=\"og:image\" content=\"",[250,1594,316],{"class":304},[250,1596,1407],{"class":312},[250,1598,328],{"class":304},[250,1600,1601],{"class":312},"\">\n",[250,1603,1605],{"class":252,"line":1604},51,[250,1606,1607],{"class":312},"  \u003Cmeta property=\"og:type\" content=\"website\">\n",[250,1609,1611],{"class":252,"line":1610},52,[250,1612,264],{"emptyLinePlaceholder":263},[250,1614,1616],{"class":252,"line":1615},53,[250,1617,1618],{"class":312},"  \u003C!-- Twitter Card -->\n",[250,1620,1622],{"class":252,"line":1621},54,[250,1623,1624],{"class":312},"  \u003Cmeta name=\"twitter:card\" content=\"summary_large_image\">\n",[250,1626,1628,1631,1633,1635,1637,1639,1641,1643,1645,1647,1649,1651,1653],{"class":252,"line":1627},55,[250,1629,1630],{"class":312},"  \u003Cmeta name=\"twitter:title\" content=\"",[250,1632,316],{"class":304},[250,1634,406],{"class":312},[250,1636,328],{"class":304},[250,1638,1563],{"class":312},[250,1640,316],{"class":304},[250,1642,1297],{"class":312},[250,1644,328],{"class":304},[250,1646,459],{"class":312},[250,1648,316],{"class":304},[250,1650,1335],{"class":312},[250,1652,328],{"class":304},[250,1654,1580],{"class":312},[250,1656,1658,1661,1663,1665,1667],{"class":252,"line":1657},56,[250,1659,1660],{"class":312},"  \u003Cmeta name=\"twitter:image\" content=\"",[250,1662,316],{"class":304},[250,1664,1407],{"class":312},[250,1666,328],{"class":304},[250,1668,1601],{"class":312},[250,1670,1672],{"class":252,"line":1671},57,[250,1673,264],{"emptyLinePlaceholder":263},[250,1675,1677],{"class":252,"line":1676},58,[250,1678,1679],{"class":312},"  \u003C!-- 人間のユーザー用：即座にリダイレクト -->\n",[250,1681,1683,1686,1688,1690,1692],{"class":252,"line":1682},59,[250,1684,1685],{"class":312},"  \u003Cmeta http-equiv=\"refresh\" content=\"0;url=",[250,1687,316],{"class":304},[250,1689,1446],{"class":312},[250,1691,328],{"class":304},[250,1693,1601],{"class":312},[250,1695,1697],{"class":252,"line":1696},60,[250,1698,1699],{"class":312},"\u003C/head>\n",[250,1701,1703],{"class":252,"line":1702},61,[250,1704,1705],{"class":312},"\u003Cbody>\n",[250,1707,1709,1712,1714,1716,1718],{"class":252,"line":1708},62,[250,1710,1711],{"class":312},"  \u003Cp>リダイレクト中... \u003Ca href=\"",[250,1713,316],{"class":304},[250,1715,1446],{"class":312},[250,1717,328],{"class":304},[250,1719,1720],{"class":312},"\">こちらをクリック\u003C/a>\u003C/p>\n",[250,1722,1724],{"class":252,"line":1723},63,[250,1725,1726],{"class":312},"\u003C/body>\n",[250,1728,1730,1733],{"class":252,"line":1729},64,[250,1731,1732],{"class":312},"\u003C/html>",[250,1734,368],{"class":308},[250,1736,1738],{"class":252,"line":1737},65,[250,1739,264],{"emptyLinePlaceholder":263},[250,1741,1743,1745,1747,1749,1751,1753,1756],{"class":252,"line":1742},66,[250,1744,305],{"class":304},[250,1746,1178],{"class":276},[250,1748,1181],{"class":288},[250,1750,414],{"class":284},[250,1752,1480],{"class":280},[250,1754,1755],{"class":284},",",[250,1757,298],{"class":284},[250,1759,1761,1764,1767,1769,1772,1774,1776,1778,1781,1783],{"class":252,"line":1760},67,[250,1762,1763],{"class":571},"    headers",[250,1765,1766],{"class":284},": { ",[250,1768,904],{"class":308},[250,1770,1771],{"class":312},"Content-Type",[250,1773,904],{"class":308},[250,1775,575],{"class":284},[250,1777,904],{"class":308},[250,1779,1780],{"class":312},"text/html; charset=utf-8",[250,1782,904],{"class":308},[250,1784,1785],{"class":284}," },\n",[250,1787,1789],{"class":252,"line":1788},68,[250,1790,1791],{"class":284},"  })\n",[250,1793,1795],{"class":252,"line":1794},69,[250,1796,684],{"class":284},[19,1798,819,1799,1802],{},[35,1800,1801],{},"url.searchParams.get()"," でクエリパラメータを実行時に取得できる。静的サイトと違い、リクエストごとに Worker は動的に処理できる。",[19,1804,1805],{},[23,1806,1807],{},"Worker側の実装（OGP画像生成）：",[28,1809,1811],{"className":244,"code":1810,"language":246,"meta":37,"style":37},"// apps/workers/og/src/index.ts（続き）\n\nimport { ImageResponse, loadGoogleFont } from 'workers-og'\n\n// フォントをキャッシュ（必要な文字だけサブセット化）\nlet fontDataPromise: Promise\u003CArrayBuffer> | null = null\nasync function getFontData(): Promise\u003CArrayBuffer> {\n  if (!fontDataPromise) {\n    const text = '0123456789/ -クイズ修飾語の順序句読点の打ち方助詞の使い方全問チャレンジ素晴らしいよくできましたもう少し復習しましょう日本語作文問正解！'\n    fontDataPromise = loadGoogleFont({ family: 'Noto Sans JP', weight: 400, text })\n  }\n  return fontDataPromise\n}\n\nasync function handleJapaneseQuizImage(url: URL): Promise\u003CResponse> {\n  const category = url.searchParams.get('category') || 'all'\n  const correct = parseInt(url.searchParams.get('correct') || '0')\n  const total = parseInt(url.searchParams.get('total') || '10')\n\n  const categoryName = CATEGORY_NAMES[category] || 'クイズ'\n  const percentage = Math.round((correct / total) * 100)\n\n  // スコアに応じたメッセージ\n  let gradeText = ''\n  if (percentage >= 90) gradeText = '素晴らしい！'\n  else if (percentage >= 70) gradeText = 'よくできました'\n  else if (percentage >= 50) gradeText = 'もう少し'\n  else gradeText = '復習しましょう'\n\n  // Satori用HTML（OGP画像のレイアウト）\n  const html = `\n\u003Cdiv style=\"display: flex; width: 1200px; height: 630px; align-items: center; justify-content: center; background: linear-gradient(135deg, #f7efe8 0%, #f6d7cf 45%, #f2b8b5 100%); font-family: Noto Sans JP, sans-serif; color: #3a2b2b;\">\n  \u003Cdiv style=\"display: flex; flex-direction: column; width: 900px; padding: 48px; background: rgba(255, 255, 255, 0.75); border-radius: 32px;\">\n    \u003Cdiv style=\"display: flex; font-size: 26px; opacity: 0.7;\">日本語作文クイズ\u003C/div>\n    \u003Cdiv style=\"display: flex; font-size: 52px; font-weight: 700; margin-top: 8px;\">${categoryName}\u003C/div>\n    \u003Cdiv style=\"display: flex; font-size: 80px; font-weight: 700; margin-top: 24px;\">${correct} / ${total} 問正解\u003C/div>\n    \u003Cdiv style=\"display: flex; font-size: 28px; margin-top: 8px; opacity: 0.75;\">${gradeText}\u003C/div>\n    \u003Cdiv style=\"display: flex; font-size: 20px; opacity: 0.5; margin-top: 24px; justify-content: flex-end;\">log.eurekapu.com\u003C/div>\n  \u003C/div>\n\u003C/div>`\n\n  const fontData = await getFontData()\n\n  // workers-og が HTML を PNG 画像に変換\n  return new ImageResponse(html, {\n    width: 1200,\n    height: 630,\n    fonts: [{\n      name: 'Noto Sans JP',\n      data: fontData,\n      weight: 400,\n      style: 'normal',\n    }],\n  })\n}\n",[35,1812,1813,1818,1822,1850,1854,1859,1887,1913,1928,1943,1983,1987,1994,1998,2002,2030,2066,2109,2151,2155,2179,2216,2220,2225,2238,2266,2296,2324,2339,2343,2348,2359,2364,2369,2374,2388,2410,2423,2428,2433,2440,2444,2460,2464,2469,2485,2497,2509,2517,2532,2543,2554,2570,2575,2579],{"__ignoreMap":37},[250,1814,1815],{"class":252,"line":253},[250,1816,1817],{"class":256},"// apps/workers/og/src/index.ts（続き）\n",[250,1819,1820],{"class":252,"line":260},[250,1821,264],{"emptyLinePlaceholder":263},[250,1823,1824,1827,1830,1833,1835,1838,1841,1844,1846,1848],{"class":252,"line":267},[250,1825,1826],{"class":304},"import",[250,1828,1829],{"class":284}," {",[250,1831,1832],{"class":280}," ImageResponse",[250,1834,1755],{"class":284},[250,1836,1837],{"class":280}," loadGoogleFont",[250,1839,1840],{"class":284}," }",[250,1842,1843],{"class":304}," from",[250,1845,1090],{"class":308},[250,1847,69],{"class":312},[250,1849,805],{"class":308},[250,1851,1852],{"class":252,"line":273},[250,1853,264],{"emptyLinePlaceholder":263},[250,1855,1856],{"class":252,"line":301},[250,1857,1858],{"class":256},"// フォントをキャッシュ（必要な文字だけサブセット化）\n",[250,1860,1861,1864,1867,1869,1871,1873,1876,1879,1882,1884],{"class":252,"line":371},[250,1862,1863],{"class":276},"let ",[250,1865,1866],{"class":280},"fontDataPromise",[250,1868,575],{"class":284},[250,1870,1027],{"class":876},[250,1872,880],{"class":284},[250,1874,1875],{"class":876},"ArrayBuffer",[250,1877,1878],{"class":284},"> | ",[250,1880,1881],{"class":276},"null",[250,1883,285],{"class":284},[250,1885,1886],{"class":276}," null\n",[250,1888,1889,1892,1895,1898,1901,1904,1906,1908,1911],{"class":252,"line":377},[250,1890,1891],{"class":276},"async",[250,1893,1894],{"class":276}," function",[250,1896,1897],{"class":288}," getFontData",[250,1899,1900],{"class":284},"():",[250,1902,1903],{"class":876}," Promise",[250,1905,880],{"class":284},[250,1907,1875],{"class":876},[250,1909,1910],{"class":284},">",[250,1912,298],{"class":284},[250,1914,1915,1917,1919,1922,1924,1926],{"class":252,"line":382},[250,1916,527],{"class":304},[250,1918,530],{"class":284},[250,1920,1921],{"class":276},"!",[250,1923,1866],{"class":280},[250,1925,541],{"class":284},[250,1927,298],{"class":284},[250,1929,1930,1932,1934,1936,1938,1941],{"class":252,"line":400},[250,1931,1040],{"class":276},[250,1933,33],{"class":280},[250,1935,285],{"class":284},[250,1937,1090],{"class":308},[250,1939,1940],{"class":312},"0123456789/ -クイズ修飾語の順序句読点の打ち方助詞の使い方全問チャレンジ素晴らしいよくできましたもう少し復習しましょう日本語作文問正解！",[250,1942,805],{"class":308},[250,1944,1945,1948,1950,1952,1955,1958,1960,1962,1965,1967,1969,1972,1974,1977,1979,1981],{"class":252,"line":426},[250,1946,1947],{"class":280},"    fontDataPromise",[250,1949,285],{"class":284},[250,1951,1837],{"class":288},[250,1953,1954],{"class":284},"({ ",[250,1956,1957],{"class":571},"family",[250,1959,575],{"class":284},[250,1961,904],{"class":308},[250,1963,1964],{"class":312},"Noto Sans JP",[250,1966,904],{"class":308},[250,1968,886],{"class":284},[250,1970,1971],{"class":571},"weight",[250,1973,575],{"class":284},[250,1975,1976],{"class":1201},"400",[250,1978,886],{"class":284},[250,1980,33],{"class":280},[250,1982,1205],{"class":284},[250,1984,1985],{"class":252,"line":488},[250,1986,678],{"class":284},[250,1988,1989,1991],{"class":252,"line":493},[250,1990,305],{"class":304},[250,1992,1993],{"class":280}," fontDataPromise\n",[250,1995,1996],{"class":252,"line":498},[250,1997,684],{"class":284},[250,1999,2000],{"class":252,"line":504},[250,2001,264],{"emptyLinePlaceholder":263},[250,2003,2004,2006,2008,2010,2012,2014,2016,2018,2020,2022,2024,2026,2028],{"class":252,"line":524},[250,2005,1891],{"class":276},[250,2007,1894],{"class":276},[250,2009,1106],{"class":288},[250,2011,414],{"class":284},[250,2013,1043],{"class":280},[250,2015,575],{"class":284},[250,2017,1051],{"class":876},[250,2019,1241],{"class":284},[250,2021,1903],{"class":876},[250,2023,880],{"class":284},[250,2025,1032],{"class":876},[250,2027,1910],{"class":284},[250,2029,298],{"class":284},[250,2031,2032,2034,2036,2038,2040,2042,2044,2046,2048,2050,2052,2054,2056,2058,2060,2062,2064],{"class":252,"line":546},[250,2033,403],{"class":276},[250,2035,325],{"class":280},[250,2037,285],{"class":284},[250,2039,1261],{"class":280},[250,2041,322],{"class":284},[250,2043,1266],{"class":280},[250,2045,322],{"class":284},[250,2047,1271],{"class":288},[250,2049,414],{"class":284},[250,2051,904],{"class":308},[250,2053,325],{"class":312},[250,2055,904],{"class":308},[250,2057,541],{"class":284},[250,2059,1284],{"class":276},[250,2061,904],{"class":308},[250,2063,962],{"class":312},[250,2065,805],{"class":308},[250,2067,2068,2070,2072,2074,2077,2079,2081,2083,2085,2087,2089,2091,2093,2095,2097,2099,2101,2103,2105,2107],{"class":252,"line":552},[250,2069,403],{"class":276},[250,2071,1297],{"class":280},[250,2073,285],{"class":284},[250,2075,2076],{"class":288}," parseInt",[250,2078,414],{"class":284},[250,2080,1043],{"class":280},[250,2082,322],{"class":284},[250,2084,1266],{"class":280},[250,2086,322],{"class":284},[250,2088,1271],{"class":288},[250,2090,414],{"class":284},[250,2092,904],{"class":308},[250,2094,1297],{"class":312},[250,2096,904],{"class":308},[250,2098,541],{"class":284},[250,2100,1284],{"class":276},[250,2102,904],{"class":308},[250,2104,1326],{"class":312},[250,2106,904],{"class":308},[250,2108,423],{"class":284},[250,2110,2111,2113,2115,2117,2119,2121,2123,2125,2127,2129,2131,2133,2135,2137,2139,2141,2143,2145,2147,2149],{"class":252,"line":568},[250,2112,403],{"class":276},[250,2114,1335],{"class":280},[250,2116,285],{"class":284},[250,2118,2076],{"class":288},[250,2120,414],{"class":284},[250,2122,1043],{"class":280},[250,2124,322],{"class":284},[250,2126,1266],{"class":280},[250,2128,322],{"class":284},[250,2130,1271],{"class":288},[250,2132,414],{"class":284},[250,2134,904],{"class":308},[250,2136,1335],{"class":312},[250,2138,904],{"class":308},[250,2140,541],{"class":284},[250,2142,1284],{"class":276},[250,2144,904],{"class":308},[250,2146,1364],{"class":312},[250,2148,904],{"class":308},[250,2150,423],{"class":284},[250,2152,2153],{"class":252,"line":606},[250,2154,264],{"emptyLinePlaceholder":263},[250,2156,2157,2159,2161,2163,2165,2167,2169,2171,2173,2175,2177],{"class":252,"line":623},[250,2158,403],{"class":276},[250,2160,406],{"class":280},[250,2162,285],{"class":284},[250,2164,1382],{"class":280},[250,2166,1385],{"class":284},[250,2168,325],{"class":280},[250,2170,1390],{"class":284},[250,2172,1284],{"class":276},[250,2174,904],{"class":308},[250,2176,1397],{"class":312},[250,2178,805],{"class":308},[250,2180,2181,2183,2186,2188,2191,2193,2196,2199,2201,2204,2206,2208,2211,2214],{"class":252,"line":643},[250,2182,403],{"class":276},[250,2184,2185],{"class":280},"percentage",[250,2187,285],{"class":284},[250,2189,2190],{"class":280}," Math",[250,2192,322],{"class":284},[250,2194,2195],{"class":288},"round",[250,2197,2198],{"class":284},"((",[250,2200,1297],{"class":280},[250,2202,2203],{"class":276}," / ",[250,2205,1335],{"class":280},[250,2207,541],{"class":284},[250,2209,2210],{"class":276}," * ",[250,2212,2213],{"class":1201},"100",[250,2215,423],{"class":284},[250,2217,2218],{"class":252,"line":649},[250,2219,264],{"emptyLinePlaceholder":263},[250,2221,2222],{"class":252,"line":660},[250,2223,2224],{"class":256},"  // スコアに応じたメッセージ\n",[250,2226,2227,2230,2233,2235],{"class":252,"line":666},[250,2228,2229],{"class":276},"  let ",[250,2231,2232],{"class":280},"gradeText",[250,2234,285],{"class":284},[250,2236,2237],{"class":308}," ''\n",[250,2239,2240,2242,2244,2246,2249,2252,2254,2257,2259,2261,2264],{"class":252,"line":675},[250,2241,527],{"class":304},[250,2243,530],{"class":284},[250,2245,2185],{"class":280},[250,2247,2248],{"class":284}," >=",[250,2250,2251],{"class":1201}," 90",[250,2253,541],{"class":284},[250,2255,2256],{"class":280}," gradeText",[250,2258,285],{"class":284},[250,2260,1090],{"class":308},[250,2262,2263],{"class":312},"素晴らしい！",[250,2265,805],{"class":308},[250,2267,2268,2271,2274,2276,2278,2280,2283,2285,2287,2289,2291,2294],{"class":252,"line":681},[250,2269,2270],{"class":304},"  else",[250,2272,2273],{"class":304}," if",[250,2275,530],{"class":284},[250,2277,2185],{"class":280},[250,2279,2248],{"class":284},[250,2281,2282],{"class":1201}," 70",[250,2284,541],{"class":284},[250,2286,2256],{"class":280},[250,2288,285],{"class":284},[250,2290,1090],{"class":308},[250,2292,2293],{"class":312},"よくできました",[250,2295,805],{"class":308},[250,2297,2298,2300,2302,2304,2306,2308,2311,2313,2315,2317,2319,2322],{"class":252,"line":687},[250,2299,2270],{"class":304},[250,2301,2273],{"class":304},[250,2303,530],{"class":284},[250,2305,2185],{"class":280},[250,2307,2248],{"class":284},[250,2309,2310],{"class":1201}," 50",[250,2312,541],{"class":284},[250,2314,2256],{"class":280},[250,2316,285],{"class":284},[250,2318,1090],{"class":308},[250,2320,2321],{"class":312},"もう少し",[250,2323,805],{"class":308},[250,2325,2326,2328,2330,2332,2334,2337],{"class":252,"line":692},[250,2327,2270],{"class":304},[250,2329,2256],{"class":280},[250,2331,285],{"class":284},[250,2333,1090],{"class":308},[250,2335,2336],{"class":312},"復習しましょう",[250,2338,805],{"class":308},[250,2340,2341],{"class":252,"line":709},[250,2342,264],{"emptyLinePlaceholder":263},[250,2344,2345],{"class":252,"line":732},[250,2346,2347],{"class":256},"  // Satori用HTML（OGP画像のレイアウト）\n",[250,2349,2350,2352,2354,2356],{"class":252,"line":754},[250,2351,403],{"class":276},[250,2353,1480],{"class":280},[250,2355,285],{"class":284},[250,2357,2358],{"class":308}," `\n",[250,2360,2361],{"class":252,"line":768},[250,2362,2363],{"class":312},"\u003Cdiv style=\"display: flex; width: 1200px; height: 630px; align-items: center; justify-content: center; background: linear-gradient(135deg, #f7efe8 0%, #f6d7cf 45%, #f2b8b5 100%); font-family: Noto Sans JP, sans-serif; color: #3a2b2b;\">\n",[250,2365,2366],{"class":252,"line":796},[250,2367,2368],{"class":312},"  \u003Cdiv style=\"display: flex; flex-direction: column; width: 900px; padding: 48px; background: rgba(255, 255, 255, 0.75); border-radius: 32px;\">\n",[250,2370,2371],{"class":252,"line":808},[250,2372,2373],{"class":312},"    \u003Cdiv style=\"display: flex; font-size: 26px; opacity: 0.7;\">日本語作文クイズ\u003C/div>\n",[250,2375,2376,2379,2381,2383,2385],{"class":252,"line":814},[250,2377,2378],{"class":312},"    \u003Cdiv style=\"display: flex; font-size: 52px; font-weight: 700; margin-top: 8px;\">",[250,2380,316],{"class":304},[250,2382,406],{"class":312},[250,2384,328],{"class":304},[250,2386,2387],{"class":312},"\u003C/div>\n",[250,2389,2390,2393,2395,2397,2399,2401,2403,2405,2407],{"class":252,"line":1373},[250,2391,2392],{"class":312},"    \u003Cdiv style=\"display: flex; font-size: 80px; font-weight: 700; margin-top: 24px;\">",[250,2394,316],{"class":304},[250,2396,1297],{"class":312},[250,2398,328],{"class":304},[250,2400,2203],{"class":312},[250,2402,316],{"class":304},[250,2404,1335],{"class":312},[250,2406,328],{"class":304},[250,2408,2409],{"class":312}," 問正解\u003C/div>\n",[250,2411,2412,2415,2417,2419,2421],{"class":252,"line":1402},[250,2413,2414],{"class":312},"    \u003Cdiv style=\"display: flex; font-size: 28px; margin-top: 8px; opacity: 0.75;\">",[250,2416,316],{"class":304},[250,2418,2232],{"class":312},[250,2420,328],{"class":304},[250,2422,2387],{"class":312},[250,2424,2425],{"class":252,"line":1441},[250,2426,2427],{"class":312},"    \u003Cdiv style=\"display: flex; font-size: 20px; opacity: 0.5; margin-top: 24px; justify-content: flex-end;\">log.eurekapu.com\u003C/div>\n",[250,2429,2430],{"class":252,"line":1464},[250,2431,2432],{"class":312},"  \u003C/div>\n",[250,2434,2435,2438],{"class":252,"line":1469},[250,2436,2437],{"class":312},"\u003C/div>",[250,2439,368],{"class":308},[250,2441,2442],{"class":252,"line":1475},[250,2443,264],{"emptyLinePlaceholder":263},[250,2445,2446,2448,2451,2453,2456,2458],{"class":252,"line":1490},[250,2447,403],{"class":276},[250,2449,2450],{"class":280},"fontData",[250,2452,285],{"class":284},[250,2454,2455],{"class":304}," await",[250,2457,1897],{"class":288},[250,2459,672],{"class":284},[250,2461,2462],{"class":252,"line":1496},[250,2463,264],{"emptyLinePlaceholder":263},[250,2465,2466],{"class":252,"line":1502},[250,2467,2468],{"class":256},"  // workers-og が HTML を PNG 画像に変換\n",[250,2470,2471,2473,2475,2477,2479,2481,2483],{"class":252,"line":1508},[250,2472,305],{"class":304},[250,2474,1178],{"class":276},[250,2476,1832],{"class":288},[250,2478,414],{"class":284},[250,2480,1480],{"class":280},[250,2482,1755],{"class":284},[250,2484,298],{"class":284},[250,2486,2487,2490,2492,2495],{"class":252,"line":1540},[250,2488,2489],{"class":571},"    width",[250,2491,575],{"class":284},[250,2493,2494],{"class":1201},"1200",[250,2496,603],{"class":284},[250,2498,2499,2502,2504,2507],{"class":252,"line":1545},[250,2500,2501],{"class":571},"    height",[250,2503,575],{"class":284},[250,2505,2506],{"class":1201},"630",[250,2508,603],{"class":284},[250,2510,2511,2514],{"class":252,"line":1551},[250,2512,2513],{"class":571},"    fonts",[250,2515,2516],{"class":284},": [{\n",[250,2518,2519,2522,2524,2526,2528,2530],{"class":252,"line":1583},[250,2520,2521],{"class":571},"      name",[250,2523,575],{"class":284},[250,2525,904],{"class":308},[250,2527,1964],{"class":312},[250,2529,904],{"class":308},[250,2531,603],{"class":284},[250,2533,2534,2537,2539,2541],{"class":252,"line":1589},[250,2535,2536],{"class":571},"      data",[250,2538,575],{"class":284},[250,2540,2450],{"class":280},[250,2542,603],{"class":284},[250,2544,2545,2548,2550,2552],{"class":252,"line":1604},[250,2546,2547],{"class":571},"      weight",[250,2549,575],{"class":284},[250,2551,1976],{"class":1201},[250,2553,603],{"class":284},[250,2555,2556,2559,2561,2563,2566,2568],{"class":252,"line":1610},[250,2557,2558],{"class":571},"      style",[250,2560,575],{"class":284},[250,2562,904],{"class":308},[250,2564,2565],{"class":312},"normal",[250,2567,904],{"class":308},[250,2569,603],{"class":284},[250,2571,2572],{"class":252,"line":1615},[250,2573,2574],{"class":284},"    }],\n",[250,2576,2577],{"class":252,"line":1621},[250,2578,1791],{"class":284},[250,2580,2581],{"class":252,"line":1627},[250,2582,684],{"class":284},[19,2584,819,2585,2587],{},[35,2586,69],{}," パッケージを使用。HTMLテンプレートを渡すと、Satori + Resvg で PNG 画像を動的に生成。フォントは必要な文字だけ Google Fonts からサブセット化してダウンロード。",[224,2589,2591],{"id":2590},"step-3-他のユーザーがogpカードをクリック","Step 3: 他のユーザーがOGPカードをクリック",[19,2593,2594],{},"SNSのタイムラインでOGPカードを見た人がクリックすると：",[28,2596,2599],{"className":2597,"code":2598,"language":33},[31],"OGPカードをクリック\n        ↓\nhttps://log.eurekapu.com/share/japanese-quiz?category=punctuation&correct=5&total=12\n        ↓\nCloudflare → og-image-worker に転送\n        ↓\nWorker がHTMLを返す（meta refresh 付き）\n        ↓\nブラウザが meta refresh を実行\n        ↓\nhttps://log.eurekapu.com/japanese-writing-quiz/punctuation にリダイレクト\n        ↓\n実際のクイズページが表示される\n",[35,2600,2598],{"__ignoreMap":37},[19,2602,2603],{},[23,2604,2605],{},"リダイレクトの仕組み（Worker側）：",[19,2607,2608,2609,2612],{},"Step 2 で示した ",[35,2610,2611],{},"handleSharePage"," 関数の中で、以下の部分がリダイレクトを実現している：",[28,2614,2617],{"className":2615,"code":2616,"language":1480,"meta":37,"style":37},"language-html shiki shiki-themes vitesse-light vitesse-light","\u003C!-- 人間のユーザー用：即座にリダイレクト -->\n\u003Cmeta http-equiv=\"refresh\" content=\"0;url=${redirectUrl}\">\n",[35,2618,2619,2624],{"__ignoreMap":37},[250,2620,2621],{"class":252,"line":253},[250,2622,2623],{"class":256},"\u003C!-- 人間のユーザー用：即座にリダイレクト -->\n",[250,2625,2626,2628,2631,2634,2637,2640,2643,2645,2648,2650,2652,2655,2657],{"class":252,"line":260},[250,2627,880],{"class":284},[250,2629,2630],{"class":304},"meta",[250,2632,2633],{"class":280}," http-equiv",[250,2635,2636],{"class":284},"=",[250,2638,2639],{"class":308},"\"",[250,2641,2642],{"class":312},"refresh",[250,2644,2639],{"class":308},[250,2646,2647],{"class":280}," content",[250,2649,2636],{"class":284},[250,2651,2639],{"class":308},[250,2653,2654],{"class":312},"0;url=${redirectUrl}",[250,2656,2639],{"class":308},[250,2658,2659],{"class":284},">\n",[2661,2662,2663,2672,2679],"ul",{},[46,2664,2665,2668,2669,2671],{},[35,2666,2667],{},"content=\"0;url=...\""," の ",[35,2670,1326],{}," は「0秒後にリダイレクト」を意味する",[46,2673,2674,2675,2678],{},"SNSクローラーは ",[35,2676,2677],{},"\u003Chead>"," 内のOGPメタタグを読み取って終了する（リダイレクトしない）",[46,2680,2681,2682,2685],{},"人間のブラウザは ",[35,2683,2684],{},"meta refresh"," を実行してリダイレクトする",[19,2687,2688,2689,2692],{},"これにより、",[23,2690,2691],{},"同じHTMLでクローラーと人間の両方に対応","できる。",[224,2694,2695],{"id":2695},"ポイント",[2661,2697,2698,2708,2711],{},[46,2699,2700,2703,2704,2707],{},[23,2701,2702],{},"SNSクローラー","と",[23,2705,2706],{},"人間のユーザー","が同じURLにアクセスする",[46,2709,2710],{},"どちらもWorkerが処理するが、クローラーはOGPメタタグを読み、人間はリダイレクトされる",[46,2712,2713,2714,2716],{},"OGP画像のURLは ",[35,2715,115],{}," でも問題ない（画像ホスティング先はSEOに影響しない）",[96,2718],{},[14,2720,2721],{"id":2721},"設定手順",[39,2723,2725],{"id":2724},"_1-cloudflare-ダッシュボードで設定","1. Cloudflare ダッシュボードで設定",[43,2727,2728,2733,2736,2739,2742,2769],{},[46,2729,2730,2731],{},"Cloudflare ダッシュボード → Workers & Pages → ",[35,2732,81],{},[46,2734,2735],{},"「設定」タブ → 「ドメインとルート」セクション",[46,2737,2738],{},"「+ 追加」をクリック",[46,2740,2741],{},"「ルート」を選択",[46,2743,2744,2745],{},"以下を入力：\n",[2661,2746,2747,2755,2763],{},[46,2748,2749,575,2752],{},[23,2750,2751],{},"ゾーン",[35,2753,2754],{},"eurekapu.com",[46,2756,2757,575,2760],{},[23,2758,2759],{},"ルート",[35,2761,2762],{},"log.eurekapu.com/share/*",[46,2764,2765,2768],{},[23,2766,2767],{},"失敗モード",": 失敗クローズ（ブロック）",[46,2770,2771,2772],{},"「ルートを追加」をクリック\n",[2773,2774],"img",{"alt":2775,"src":2776},"alt text","/2025-12/2025-12-25/image.png",[39,2778,2780],{"id":2779},"_2-wranglertoml-に追記推奨","2. wrangler.toml に追記（推奨）",[19,2782,2783],{},"ダッシュボードで設定した内容をコードにも反映しておくと、次回デプロイ時も設定が維持される。",[28,2785,2789],{"className":2786,"code":2787,"language":2788,"meta":37,"style":37},"language-toml shiki shiki-themes vitesse-light vitesse-light","# apps/workers/og/wrangler.toml\nname = \"og-image-worker\"\nmain = \"src/index.ts\"\ncompatibility_date = \"2024-12-01\"\ncompatibility_flags = [\"nodejs_compat\"]\naccount_id = \"your-account-id\"  # GitHub Actions で /memberships API 呼び出しをスキップするため\n\n# workers.dev ドメインを有効にする（OGP画像のURLで使用）\nworkers_dev = true\n\n# メインドメインでWorkerを実行するためのルート設定\nroutes = [\n  { pattern = \"log.eurekapu.com/share/*\", zone_name = \"eurekapu.com\" }\n]\n","toml",[35,2790,2791,2796,2801,2806,2811,2816,2821,2825,2830,2835,2839,2844,2849,2854],{"__ignoreMap":37},[250,2792,2793],{"class":252,"line":253},[250,2794,2795],{},"# apps/workers/og/wrangler.toml\n",[250,2797,2798],{"class":252,"line":260},[250,2799,2800],{},"name = \"og-image-worker\"\n",[250,2802,2803],{"class":252,"line":267},[250,2804,2805],{},"main = \"src/index.ts\"\n",[250,2807,2808],{"class":252,"line":273},[250,2809,2810],{},"compatibility_date = \"2024-12-01\"\n",[250,2812,2813],{"class":252,"line":301},[250,2814,2815],{},"compatibility_flags = [\"nodejs_compat\"]\n",[250,2817,2818],{"class":252,"line":371},[250,2819,2820],{},"account_id = \"your-account-id\"  # GitHub Actions で /memberships API 呼び出しをスキップするため\n",[250,2822,2823],{"class":252,"line":377},[250,2824,264],{"emptyLinePlaceholder":263},[250,2826,2827],{"class":252,"line":382},[250,2828,2829],{},"# workers.dev ドメインを有効にする（OGP画像のURLで使用）\n",[250,2831,2832],{"class":252,"line":400},[250,2833,2834],{},"workers_dev = true\n",[250,2836,2837],{"class":252,"line":426},[250,2838,264],{"emptyLinePlaceholder":263},[250,2840,2841],{"class":252,"line":488},[250,2842,2843],{},"# メインドメインでWorkerを実行するためのルート設定\n",[250,2845,2846],{"class":252,"line":493},[250,2847,2848],{},"routes = [\n",[250,2850,2851],{"class":252,"line":498},[250,2852,2853],{},"  { pattern = \"log.eurekapu.com/share/*\", zone_name = \"eurekapu.com\" }\n",[250,2855,2856],{"class":252,"line":504},[250,2857,2858],{},"]\n",[19,2860,2861],{},[23,2862,2863],{},"重要な設定:",[118,2865,2866,2876],{},[121,2867,2868],{},[124,2869,2870,2873],{},[127,2871,2872],{},"設定",[127,2874,2875],{},"説明",[134,2877,2878,2892],{},[124,2879,2880,2885],{},[139,2881,2882],{},[35,2883,2884],{},"account_id",[139,2886,2887,2888,2891],{},"GitHub Actions でデプロイする際、",[35,2889,2890],{},"/memberships"," API の呼び出しをスキップできる。これがないと API トークンに追加の権限が必要になる",[124,2893,2894,2899],{},[139,2895,2896],{},[35,2897,2898],{},"workers_dev = true",[139,2900,2901,2904,2905,2907,2908,2910,2911,2914],{},[35,2902,2903],{},"routes"," を設定するとデフォルトで ",[35,2906,115],{}," ドメインが無効になる。OGP画像は ",[35,2909,115],{}," ドメインで提供しているので、明示的に ",[35,2912,2913],{},"true"," にする必要がある",[19,2916,2917],{},[23,2918,2919,2920,2922],{},"なぜ ",[35,2921,2898],{}," が必要か:",[19,2924,2925],{},"Worker は2つのエンドポイントを持っている：",[2661,2927,2928,2937],{},[46,2929,2930,2933,2934,2936],{},[35,2931,2932],{},"/share/*"," → ",[35,2935,2762],{},"（routes で設定）",[46,2938,2939,2933,2942,2945],{},[35,2940,2941],{},"/og/*",[35,2943,2944],{},"og-image-worker.workers.dev/og/*","（workers.dev ドメイン）",[19,2947,2948,2950,2951,2953,2954,2956],{},[35,2949,2903],{}," を追加すると wrangler がデフォルトで ",[35,2952,115],{}," を無効にするため、OGP画像にアクセスできなくなる。両方のドメインを有効にするために ",[35,2955,2898],{}," が必要。",[39,2958,2960],{"id":2959},"_3-不要になったnuxtシェアページを削除","3. 不要になったNuxtシェアページを削除",[19,2962,2963],{},"リクエストを Worker が処理するため、Nuxt側のシェアページは不要。",[28,2965,2969],{"className":2966,"code":2967,"language":2968,"meta":37,"style":37},"language-bash shiki shiki-themes vitesse-light vitesse-light","# 削除\nrm apps/web/app/pages/share/japanese-quiz.vue\n","bash",[35,2970,2971,2976],{"__ignoreMap":37},[250,2972,2973],{"class":252,"line":253},[250,2974,2975],{"class":256},"# 削除\n",[250,2977,2978,2981],{"class":252,"line":260},[250,2979,2980],{"class":288},"rm",[250,2982,2983],{"class":312}," apps/web/app/pages/share/japanese-quiz.vue\n",[96,2985],{},[14,2987,2988],{"id":2988},"達成されたこと",[118,2990,2991,3003],{},[121,2992,2993],{},[124,2994,2995,2997,3000],{},[127,2996,129],{},[127,2998,2999],{},"改善前",[127,3001,3002],{},"改善後",[134,3004,3005,3019,3030,3043,3054,3063],{},[124,3006,3007,3010,3015],{},[139,3008,3009],{},"シェアURL",[139,3011,3012],{},[35,3013,3014],{},"workers.dev/share/...",[139,3016,3017],{},[35,3018,185],{},[124,3020,3021,3024,3026],{},[139,3022,3023],{},"被リンク評価の帰属先",[139,3025,115],{},[139,3027,3028],{},[23,3029,822],{},[124,3031,3032,3035,3038],{},[139,3033,3034],{},"ドメインオーソリティへの寄与",[139,3036,3037],{},"なし",[139,3039,3040],{},[23,3041,3042],{},"あり",[124,3044,3045,3047,3049],{},[139,3046,169],{},[139,3048,172],{},[139,3050,3051],{},[23,3052,3053],{},"高い",[124,3055,3056,3058,3060],{},[139,3057,141],{},[139,3059,144],{},[139,3061,3062],{},"正常（変化なし）",[124,3064,3065,3068,3071],{},[139,3066,3067],{},"動的OGP生成",[139,3069,3070],{},"Worker",[139,3072,3073],{},"Worker（変化なし）",[39,3075,3076],{"id":3076},"確認方法",[19,3078,3079],{},"OGPデバッガーで以下のURLをテスト：",[28,3081,3083],{"className":3082,"code":234,"language":33},[31],[35,3084,234],{"__ignoreMap":37},[19,3086,3087],{},[2773,3088],{"alt":2775,"src":3089},"/2025-12/2025-12-25/image-1.png",[2661,3091,3092,3095],{},[46,3093,3094],{},"OGP画像: 「句読点の打ち方 - 5/12問正解」と表示される",[46,3096,3097],{},"タイトル: 「句読点の打ち方クイズ - 5/12問正解！」",[96,3099],{},[14,3101,3102],{"id":3102},"まとめ",[39,3104,3105],{"id":3105},"なぜこの方法が最適か",[43,3107,3108,3114,3120,3126],{},[46,3109,3110,3113],{},[23,3111,3112],{},"コード変更が最小限"," - ResultSummary.vue のシェアURLはメインドメインのまま",[46,3115,3116,3119],{},[23,3117,3118],{},"既存のWorkerをそのまま使える"," - OGP画像生成ロジックの変更不要",[46,3121,3122,3125],{},[23,3123,3124],{},"SEO効果がメインドメインに集約"," - 被リンク評価がlog.eurekapu.comに帰属",[46,3127,3128,3131],{},[23,3129,3130],{},"設定が簡単"," - ダッシュボードで数クリック",[39,3133,3135],{"id":3134},"workers-routes-の活用ポイント","Workers Routes の活用ポイント",[2661,3137,3138,3141,3144],{},[46,3139,3140],{},"静的サイト + 動的処理が必要な部分だけWorkerで処理",[46,3142,3143],{},"メインドメインのURL体系を維持しつつ、裏側でWorkerが動く",[46,3145,3146],{},"必要なパスだけをWorkerにルーティングできる柔軟性",[96,3148],{},[14,3150,3151],{"id":3151},"関連ドキュメント",[2661,3153,3154,3162],{},[46,3155,3156,3161],{},[3157,3158,3160],"a",{"href":3159},"/og-worker-implementation-plan","動的OGP画像生成 Worker 実装"," - Worker の実装詳細",[46,3163,3164,3168],{},[3157,3165,3167],{"href":3166},"/ogp-share-url-seo-improvement","OGPシェアURL改善計画"," - SEO問題の分析",[3170,3171,3172],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sSkh3, html code.shiki .sSkh3{--shiki-default:#2E8F82;--shiki-dark:#2E8F82}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}",{"title":37,"searchDepth":260,"depth":260,"links":3174},[3175,3179,3183,3186,3191,3194,3198],{"id":16,"depth":260,"text":17,"children":3176},[3177,3178],{"id":41,"depth":267,"text":41},{"id":74,"depth":267,"text":75},{"id":100,"depth":260,"text":101,"children":3180},[3181,3182],{"id":104,"depth":267,"text":104},{"id":175,"depth":267,"text":176},{"id":206,"depth":260,"text":207,"children":3184},[3185],{"id":222,"depth":267,"text":222},{"id":2721,"depth":260,"text":2721,"children":3187},[3188,3189,3190],{"id":2724,"depth":267,"text":2725},{"id":2779,"depth":267,"text":2780},{"id":2959,"depth":267,"text":2960},{"id":2988,"depth":260,"text":2988,"children":3192},[3193],{"id":3076,"depth":267,"text":3076},{"id":3102,"depth":260,"text":3102,"children":3195},[3196,3197],{"id":3105,"depth":267,"text":3105},{"id":3134,"depth":267,"text":3135},{"id":3151,"depth":260,"text":3151},null,"Workers Routes を使って、メインドメインのURLでWorkerを実行する方法。静的サイトでも動的OGPを実現","md",{},"/cloudflare-workers-routes-ogp-solution",false,"2025-12-25T00:00:00.000Z",{"title":5,"description":3200},"2025-12/2025-12-25/cloudflare-workers-routes-ogp-solution",[3209,3210,3211,3212,3213],"cloudflare-workers","workers-routes","ogp","seo","nuxt","DgrL8OJpuwHKH4GXK1rrZgpSLz-YHTo_7TENsNPKS8w",[],[3217,3219,3223,3227,3231],{"title":3218,"path":3166,"publishedAt":3205},"OGPシェアURL改善計画 - SEO効果を最大化する設計",{"title":3220,"path":3221,"publishedAt":3222},"動的OGP画像生成の実装ガイド - Satori + Cloudflare Workers","/dynamic-ogp-image-generation-guide","2025-12-24T00:00:00.000Z",{"title":3224,"path":3225,"publishedAt":3226},"OGP画像自動生成 実装ガイド","/ogp-image-generation-plan","2025-12-23T00:00:00.000Z",{"title":3228,"path":3229,"publishedAt":3230},"移行サイトのSEO・AI-SEO改善を1日で回した — 画像altを480件、記事の要点を203本、OG画像を署名付きに","/wordpress-nuxt-ai-seo-phase-c","2026-07-27T00:00:00.000Z",{"title":3232,"path":3233,"publishedAt":3234},"Google Search Console分析から内部リンク実装へ — Nuxtブログに関連記事セクションとタグページ553枚を一日で載せた","/gsc-internal-linking-implementation","2026-07-19T00:00:00.000Z","https://log.eurekapu.com/og/blog/cloudflare-workers-routes-ogp-solution.png?v=2025-12-25T00%3A00%3A00.000Z&title=Cloudflare%20Workers%20Routes%20%E3%81%A7OGP%E3%82%B7%E3%82%A7%E3%82%A2URL%E3%81%AESEO%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E6%B1%BA&author=Kei%20Komatsu&sig=a70c1ea588f58163",1785654969082]