43号線を西へ東へ

フリーランスの備忘録、アウトプットの実験場

ズボラに作ったレアチーズケーキ

このブログはプロモーションリンクを含むときがあります


AIにレシピを聞いて、AIに買い物リストを作らせて、AIに作る手順をイラスト化させ、ネタは全てAIで作成したという、レアチーズケーキを作りました。実家のレモンを3つ使った、かなり酸っぱいレモンレアチーズケーキとなりました。

今回はゼラチンを使わない、レシピを提示されたのでその通りにやりました。

レアチーズケーキというよりかは、レアチーズソースのようになりました。途中までは美味しそうだったんですけどね。大失敗したのも良い経験です。次回はうまく作れるでしょう。

ゼラチンがいらない理由:自然の力でしっかり固まるはずだった

ゼラチンなしでも固まるのは、下記の3つの理由があるそうです。

  1. 乳タンパクが凝固
  2. 脂肪結晶化
  3. 乳化安定

実家で採れたレモンで、カッテージチーズを作ったことがあります。乳タンパクが凝固するという作用を使うわけですね。

実家のレモンで作るカッテージチーズ - 43号線を西へ東へ

料理開始

AIが作成したレシピから、その段階ごとにイラストを作成いたしました。

ビスケットを砕く

ビスケットを砕いて、バターを混ぜ込んでいきます。チーズケーキの土台となる層です。

個別包装のビスケットを買ったので、箱の大きさの割にはビスケットの数が少なかったです。

大失敗です。

薄い袋で作ったので、途中で穴が開いて、ビスケットのかけらが散乱してしまいました。

大失敗です。

クリームチーズを柔らかくします

電子レンジで20〜30秒温めて柔らかくします。

混ぜます

そこに砂糖とレモン汁を加えて、よくかき混ぜていきます。

きれいなレモンはよそ様のところに配ってるので、自宅用のレモンは皮の痛んだものが多い。

生クリーム投入

クリームチーズのダマができてしまいました。

型に入れます

写真撮り忘れましたが、ちょうど良い感じに型枠に入りました。

冷やします

3時間冷蔵で固めるとレシピにありましたが、時間がなかったので最初1時間は冷凍しました。

出来上がり

レモンカードと言うものも調べて作り、2層構造のケーキにしました、

きれいにできました。ここまでは。

誕生日会だったんですよ。私じゃないけど。

固まってないやん

本当はスポッと型から抜ける予定でしたが、ヨーグルト状のレモンチーズケーキのようなものは、自立せず崩れて行きました。

あぁ、大失敗です。

買い物リストまでAIが作った

iPhoneのリマインダーアプリで読み込める形のファイルで買い物リストを作ってもらうつもりが、買い物リストのWebアプリを作成してくれました。

買い物リスト(タップすると開く)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🛒 買い物リスト</title>
<style>
  @import url('https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic:wght@400;500;700&display=swap');

  * { box-sizing: border-box; margin: 0; padding: 0; }

  body {
    font-family: 'Zen Maru Gothic', sans-serif;
    background: #fffbec;
    min-height: 100vh;
    padding: 24px 16px 48px;
    background-image: radial-gradient(circle at 20% 10%, #fff3b0 0%, transparent 40%),
                      radial-gradient(circle at 80% 80%, #fde8c8 0%, transparent 40%);
  }

  .container {
    max-width: 480px;
    margin: 0 auto;
  }

  header {
    text-align: center;
    margin-bottom: 28px;
  }

  header .emoji {
    font-size: 52px;
    display: block;
    animation: bounce 2s ease-in-out infinite;
  }

  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-8px); }
  }

  header h1 {
    font-size: 22px;
    font-weight: 700;
    color: #5a3e1b;
    margin-top: 8px;
    letter-spacing: 0.05em;
  }

  header p {
    font-size: 12px;
    color: #a07850;
    margin-top: 4px;
  }

  .section {
    background: #fff;
    border-radius: 20px;
    padding: 18px 20px;
    margin-bottom: 16px;
    box-shadow: 0 4px 20px rgba(180,130,60,0.10);
    border: 1.5px solid #f5e6c8;
    animation: fadeUp 0.4s ease both;
  }

  @keyframes fadeUp {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: translateY(0); }
  }

  .section:nth-child(1) { animation-delay: 0.05s; }
  .section:nth-child(2) { animation-delay: 0.10s; }
  .section:nth-child(3) { animation-delay: 0.15s; }
  .section:nth-child(4) { animation-delay: 0.20s; }

  .section-title {
    font-size: 13px;
    font-weight: 700;
    color: #c98a2e;
    letter-spacing: 0.08em;
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
  }

  .section-title span {
    background: #fff8e1;
    border: 1px solid #f5d97a;
    border-radius: 30px;
    padding: 2px 10px;
  }

  .item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px dashed #f0e0c0;
    cursor: pointer;
    transition: opacity 0.2s;
    user-select: none;
  }

  .item:last-child { border-bottom: none; }

  .item.done { opacity: 0.45; }

  .item.done .item-label { text-decoration: line-through; color: #bbb; }

  .checkbox {
    width: 24px;
    height: 24px;
    border-radius: 8px;
    border: 2px solid #f0c95a;
    background: #fffdf0;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    font-size: 14px;
  }

  .item.done .checkbox {
    background: #f0c95a;
    border-color: #e0b040;
  }

  .item-info { flex: 1; }

  .item-label {
    font-size: 15px;
    color: #3a2a10;
    font-weight: 500;
    transition: color 0.2s;
  }

  .item-note {
    font-size: 11px;
    color: #b09070;
    margin-top: 2px;
  }

  .priority-badge {
    font-size: 10px;
    background: #fff0c0;
    border: 1px solid #f5d060;
    color: #a07020;
    border-radius: 20px;
    padding: 2px 8px;
    font-weight: 700;
    flex-shrink: 0;
  }

  .progress-bar-wrap {
    background: #fff;
    border-radius: 20px;
    padding: 16px 20px;
    margin-bottom: 16px;
    border: 1.5px solid #f5e6c8;
    box-shadow: 0 4px 20px rgba(180,130,60,0.08);
  }

  .progress-label {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: #a07850;
    margin-bottom: 8px;
    font-weight: 700;
  }

  .progress-bar {
    height: 10px;
    background: #f5ecd5;
    border-radius: 10px;
    overflow: hidden;
  }

  .progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #f5d060, #f0a830);
    border-radius: 10px;
    transition: width 0.5s cubic-bezier(.4,0,.2,1);
  }

  .reset-btn {
    display: block;
    margin: 0 auto 8px;
    background: none;
    border: 1.5px solid #f0c95a;
    color: #c98a2e;
    border-radius: 30px;
    padding: 8px 24px;
    font-family: 'Zen Maru Gothic', sans-serif;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.2s;
  }

  .reset-btn:hover {
    background: #fff8e1;
    transform: scale(1.04);
  }

  .complete-msg {
    text-align: center;
    font-size: 22px;
    margin: 8px 0 4px;
    display: none;
  }
</style>
</head>
<body>
<div class="container">
  <header>
    <span class="emoji">🍋</span>
    <h1>ズボラレモンレアチーズ<br>買い物リスト</h1>
    <p>タップでチェック!</p>
  </header>

  <div class="progress-bar-wrap">
    <div class="progress-label">
      <span>🛒 進捗</span>
      <span id="prog-text">0 / 0</span>
    </div>
    <div class="progress-bar"><div class="progress-fill" id="prog-fill" style="width:0%"></div></div>
    <div class="complete-msg" id="complete-msg">🎉 全部そろった!</div>
  </div>

  <div class="section" id="sec-must">
    <div class="section-title"><span>⭐ 最低限セット</span></div>
  </div>

  <div class="section" id="sec-dairy">
    <div class="section-title"><span>🥛 乳製品</span></div>
  </div>

  <div class="section" id="sec-other">
    <div class="section-title"><span>🥚 その他食材</span></div>
  </div>

  <div class="section" id="sec-opt">
    <div class="section-title"><span>✨ あれば</span></div>
  </div>

  <button class="reset-btn" onclick="resetAll()">🔄 リセット</button>
</div>

<script>
const items = [
  // 最低限セット
  { id:'cc', label:'クリームチーズ', note:'200g(1箱)', sec:'must', priority:true },
  { id:'hc', label:'生クリーム', note:'200ml(1パック)', sec:'must', priority:true },
  { id:'lemon', label:'レモン', note:'2個(強め派は3個)', sec:'must', priority:true },
  { id:'egg', label:'卵', note:'1個', sec:'must', priority:true },
  { id:'sugar', label:'砂糖', note:'家にあればOK', sec:'must', priority:true },
  // 乳製品
  { id:'butter', label:'バター', note:'20g(有塩・無塩どちらでも)', sec:'dairy' },
  // その他
  { id:'biscuit', label:'ビスケット', note:'1袋(土台用・任意)', sec:'other' },
  // オプション
  { id:'yogurt', label:'ヨーグルト', note:'クリーム一部置換OK', sec:'opt' },
  { id:'powsugar', label:'粉砂糖', note:'溶けやすい', sec:'opt' },
  { id:'lemonjuice', label:'レモン汁(瓶)', note:'レモンの代替OK', sec:'opt' },
];

const secMap = { must:'sec-must', dairy:'sec-dairy', other:'sec-other', opt:'sec-opt' };
let checked = JSON.parse(localStorage.getItem('shopping_checked') || '{}');

function save() { localStorage.setItem('shopping_checked', JSON.stringify(checked)); }

function updateProgress() {
  const mustItems = items.filter(i => i.priority);
  const done = mustItems.filter(i => checked[i.id]).length;
  const total = mustItems.length;
  document.getElementById('prog-text').textContent = `${done} / ${total}`;
  document.getElementById('prog-fill').style.width = total ? (done/total*100)+'%' : '0%';
  const msg = document.getElementById('complete-msg');
  msg.style.display = done === total ? 'block' : 'none';
}

function toggle(id) {
  checked[id] = !checked[id];
  save();
  const el = document.getElementById('item-'+id);
  el.classList.toggle('done', checked[id]);
  el.querySelector('.checkbox').textContent = checked[id] ? '✓' : '';
  updateProgress();
}

function resetAll() {
  checked = {};
  save();
  document.querySelectorAll('.item').forEach(el => {
    el.classList.remove('done');
    el.querySelector('.checkbox').textContent = '';
  });
  updateProgress();
}

// Render
items.forEach(item => {
  const sec = document.getElementById(secMap[item.sec]);
  const div = document.createElement('div');
  div.className = 'item' + (checked[item.id] ? ' done' : '');
  div.id = 'item-' + item.id;
  div.onclick = () => toggle(item.id);
  div.innerHTML = `
    <div class="checkbox">${checked[item.id] ? '✓' : ''}</div>
    <div class="item-info">
      <div class="item-label">${item.label}</div>
      ${item.note ? `<div class="item-note">${item.note}</div>` : ''}
    </div>
    ${item.priority ? '<span class="priority-badge">必須</span>' : ''}
  `;
  sec.appendChild(div);
});

updateProgress();
</script>
</body>
</html>

まとめ

レシピ考案から買い物リスト作成まで、AIに頼り切ったケーキ作りでした。

作成された手順イラストを眺めながら作業を進めました。

今回きれいなケーキの方にはならなかったですが、爽やかな酸味のレモンチーズケーキ風味は抜群に美味しかったです。また次回があるのかわかりませんが、今度はゼラチンを入れようと思います。