CODE · 6.7 KB
scripts/generate-golden-fixture.mjs
Workspace snapshot · 08/31 23:51
import { copyFile, mkdir, writeFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import { exportHtml } from "../src/export-html.js";
const item = (title, description, proof = "") => ({ title, description, proof });
const base = (id, type, title, body, contentModel, cta = "") => ({
id, type, label: id.toUpperCase(), role: "読者の判断を前へ進める", userQuestion: `${title}をどう判断するか`,
title, body, proof: "検証用固定フィクスチャ", content: `${title}の表示内容`, implementation: "PC/SPで情報優先順位を維持",
layoutVariant: "content-editorial", cta, contentModel,
});
const sections = [
{
...base("hero", "hero", "会議のあとを、仕事に戻す。", "決定・担当・期限だけを、次の一手へつなぎます。", {}, "資料を見る"),
layoutVariant: "hero-product-stage",
asset: "日本の制作チームが会議後に決定事項を整理する実写KV",
imageBrief: { subject: "日本の制作チーム", composition: "左にコピー余白、右に人物", style: "明るい自然光のeditorial photo" },
},
base("trust", "trust", "試す前に、判断材料を開く。", "対応範囲と未対応範囲を先に示します。", { items: [item("入力資料", "営業資料・サービス資料から事実を抽出"), item("確認事項", "推測した内容は確定せず、修正可能にする"), item("納品形式", "HTML・CSS・画像を同梱して出力")] }),
base("problem", "problem", "制作が止まるのは、情報がない時ではない。", "事実と仮説が混ざり、判断の順番が見えない時です。", { items: [item("要件が散らばる", "資料、会話、URLに判断材料が分散する"), item("言葉が先に走る", "根拠より先にコピーが決まり、後で作り直す"), item("WFと実装がずれる", "設計した表示部品が納品HTMLで失われる")] }),
base("mechanism", "mechanism", "文章ではなく、判断の構造をつくる。", "表示する内容をセクション型ごとのデータとして持ちます。", { beforeAfter: { before: item("本文を自動分割", "文章の句読点からカードを作り、意味が崩れる"), after: item("型付きデータ", "見出し・説明・根拠を別フィールドで保持する") } }),
base("difference", "differentiation", "制作会社の確認点を、工程に残す。", "構成・WF・トンマナ・実装を別々に確認できます。", { items: [item("構成", "読者の疑問と反論の順番を確認"), item("WF", "表示内容とレイアウトの対応を確認"), item("トンマナ", "色だけでなく写真・字・密度・動きを比較")] }),
base("process", "process", "5つの確認だけで、公開形まで進む。", "ユーザーの判断点を増やさず、内部工程を厚くします。", { steps: [item("ヒアリング", "資料から下書きし、不足だけ回答"), item("構成", "キャッチコピーとストーリーを選択"), item("WF", "位置コメントで修正"), item("トンマナ", "3方向から選択"), item("実装", "ブラウザ上で確認し納品")]}),
base("comparison", "comparison", "違いは、作る速さより戻れる場所。", "各工程の正本と修正点を比較します。", { comparison: { columns: ["本フロー", "文章生成だけ"], rows: [{ label: "資料理解", cells: ["事実・仮説・未確認を分離", "要約のみ"] }, { label: "WF", cells: ["型付き表示データ", "本文の自動分割"] }, { label: "修正", cells: ["対象箇所だけ更新", "全体がドリフト"] }] } }),
base("proof", "proof", "品質は、自己申告ではなく証跡で見る。", "固定入力を再生成し、表示と検査結果を残します。", { caseStudy: { subject: "Golden fixture", issue: "汎用レンダラーがダミー文言を出力", action: "型付きデータと出力ゲートへ変更", result: "ダミー文言を含む出力をテストで拒否", source: "自動テスト24件とブラウザQA", metrics: [] } }),
base("pricing", "pricing", "無料検証から、必要な範囲だけ。", "価格はヒアリングで確認できた条件だけを表示します。", { plans: [{ name: "社内検証", price: "無料", period: " / 検証期間", description: "生成フローと品質を社内で確認", features: ["資料入力", "構成・WF", "HTML出力"], note: "検証用", cta: "試作を始める" }] }),
base("faq", "faq", "導入前に残る疑問へ答える。", "不明点を抽象見出しで逃げず、回答まで表示します。", { faqs: [{ question: "資料だけでも始められますか?", answer: "資料から回答の下書きを作り、未確認項目だけを追加で確認します。" }, { question: "生成後に修正できますか?", answer: "構成・WF・トンマナ・実装の各段階で修正できます。" }, { question: "画像は納品後も表示されますか?", answer: "画像をZIPへ同梱し、期限付きURLへ依存しない形で出力します。" }] }),
base("fit", "fit", "初稿の壁打ちではなく、制作工程を進めたいチームへ。", "用途と対象外を先に示します。", { items: [item("向いている", "BtoBサービスLPの初稿を短期間で作りたい"), item("向いている", "構成から実装まで同じ根拠を維持したい"), item("対象外", "根拠なしの実績やレビューを自動生成したい")] }),
base("form", "form", "資料から、最初の構成をつくる。", "必要事項を送信すると制作フローを開始します。", {}, "構成を作る"),
];
const output = new URL("../output/golden/", import.meta.url);
await mkdir(output, { recursive: true });
const sourceImage = new URL("../assets/qa/hero-textless-v1.png", import.meta.url);
const images = [];
if (existsSync(sourceImage)) {
await mkdir(new URL("images/", output), { recursive: true });
await copyFile(sourceImage, new URL("images/hero.png", output));
images.push({ sectionId: "hero", src: "images/hero.png" });
}
const html = exportHtml({ name: "LP制作フロー", answers: { formalServiceName: "LP STUDIO", formalCompanyName: "QA Fixture", formFields: "会社名,お名前,メールアドレス,相談内容", formEndpoint: "https://example.com/form", privacyUrl: "https://example.com/privacy", formSuccess: "送信後に受付画面を表示", conversionDefinition: "フォーム送信" } }, sections, { palette: ["#17130f", "#ff5a36", "#f4efe7"], type: "ゴシック × 明朝" }, images);
await writeFile(new URL("index.html", output), html, "utf8");
await writeFile(new URL("fixture.json", output), JSON.stringify({ sections }, null, 2), "utf8");
console.log(new URL("index.html", output).pathname);