{"id":3065,"date":"2025-12-11T17:02:54","date_gmt":"2025-12-11T17:02:54","guid":{"rendered":"https:\/\/garyhengeveld.com\/wordpress\/?p=3065"},"modified":"2026-03-05T15:21:14","modified_gmt":"2026-03-05T15:21:14","slug":"meal-tracker","status":"publish","type":"post","link":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/","title":{"rendered":"Fork-It Meal Tracker"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n  <title>Fork-It Meal Tracker<\/title>\n  <style>\n    :root {\n      --bg: #0f172a;        \/* slate-900 *\/\n      --panel: #111827;     \/* gray-900 *\/\n      --text: #e5e7eb;      \/* gray-200 *\/\n      --muted: #9ca3af;     \/* gray-400 *\/\n      --accent: #22c55e;    \/* green-500 *\/\n      --warn: #f59e0b;      \/* amber-500 *\/\n      --danger: #ef4444;    \/* red-500 *\/\n      --card-bg: #1f2937;   \/* gray-800 *\/\n      --chip: #374151;      \/* gray-700 *\/\n      --border: #374151;\n      --link: #60a5fa;      \/* blue-400 *\/\n    }\n    html, body { height: 100%; }\n    body {\n      margin: 0;\n      background: linear-gradient(135deg, #0b1023 0%, #121a38 100%);\n      color: var(--text);\n      font-family: system-ui, -apple-system, Segoe UI, Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", sans-serif;\n    }\n    .app {\n      max-width: 1100px;\n      margin: 0 auto;\n      padding: 24px;\n    }\n    header {\n      display: grid;\n      gap: 8px;\n      margin-bottom: 16px;\n    }\n    h1 { margin: 0; font-size: 1.6rem; letter-spacing: 0.2px; }\n    .sub { color: var(--muted); font-size: 0.95rem; }\n    .grid {\n      display: grid;\n      grid-template-columns: 1fr 320px;\n      gap: 16px;\n    }\n    .panel {\n      background: rgba(17,24,39,0.85);\n      border: 1px solid var(--border);\n      border-radius: 14px;\n      backdrop-filter: blur(6px);\n    }\n    .panel > .head {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      padding: 14px 16px;\n      border-bottom: 1px solid var(--border);\n    }\n    .head h2 { margin: 0; font-size: 1.1rem; color: white }\n    .content { padding: 14px 16px; }\n    .row { display: flex; gap: 10px; flex-wrap: wrap; }\n    .group-card {\n      flex: 1 1 240px;\n      min-width: 240px;\n      background: var(--card-bg);\n      border: 1px solid var(--border);\n      border-radius: 12px;\n      padding: 12px;\n    }\n    .group-card h3 {\n      margin: 0 0 6px 0; font-size: 1rem; color: white;\n      display: flex; align-items: center; gap: 8px;\n    }\n    .chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }\n    .chip {\n      display: inline-flex; align-items: center; gap: 6px;\n      background: var(--chip); color: var(--text);\n      border-radius: 999px; padding: 6px 10px; font-size: 0.9rem;\n      border: 1px solid var(--border);\n    }\n    .chip button {\n      appearance: none; border: none; background: transparent;\n      color: var(--text); cursor: pointer; font-size: 1rem; line-height: 1;\n    }\n    .meter {\n      height: 8px; border-radius: 999px; background: #111827; border: 1px solid var(--border);\n      overflow: hidden; margin: 8px 0;\n    }\n    .meter > span { display: block; height: 100%; background: var(--accent); width: 0%; }\n    .muted { color: var(--muted); font-size: 0.9rem; }\n    .controls {\n      display: flex; gap: 8px; flex-wrap: wrap;\n    }\n    .btn {\n      appearance: none; border: 1px solid var(--border);\n      background: var(--chip); color: var(--text);\n      padding: 8px 12px; border-radius: 10px; cursor: pointer; font-weight: 600;\n    }\n    .btn.primary { background: var(--accent); color: #06290f; border-color: #16a34a; }\n    .btn.warn { background: var(--warn); color: #2b1c00; border-color: #d97706; }\n    .btn.danger { background: var(--danger); color: #2b0a0a; border-color: #dc2626; }\n    .btn.link { background: transparent; border: none; color: var(--link); text-decoration: underline; padding: 0; }\n    .inline { display: inline-flex; align-items: center; gap: 8px; }\n    .badge {\n      font-size: 0.8rem; padding: 3px 8px; border-radius: 999px;\n      border: 1px solid var(--border); background: var(--chip);\n    }\n    input, select {\n      background: var(--chip); color: black; border: 1px solid var(--border);\n      border-radius: 8px; padding: 6px 8px; font-size: 0.95rem;\n    }\n    .list { display: grid; gap: 8px; }\n    .item {\n      display: grid; grid-template-columns: 1fr auto; align-items: center;\n      background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px;\n    }\n    .item .meta { font-size: 0.9rem; color: var(--muted); }\n    .item .actions { display: inline-flex; gap: 6px; }\n    .footer { color: var(--muted); font-size: 0.85rem; text-align: center; padding: 16px; }\n    .spacer { height: 8px; }\n    \/* color bullets for groups *\/\n    .bullet { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }\n    .b-green { background: #22c55e; }\n    .b-blue { background: #60a5fa; }\n    .b-amber { background: #f59e0b; }\n    .b-pink { background: #ec4899; }\n    .b-purple { background: #a78bfa; }\n    .b-red { background: #ef4444; }\n    .b-teal { background: #14b8a6; }\n    .b-gray { background: #9ca3af; }\n    .hidden { display: none; }\n  <\/style>\n<\/head>\n<body>\n  <div class=\"app\">\n    <header>\n      <h1>Fork-It Daily Tracker<\/h1>\n      <div class=\"sub\">\n        Track balanced servings with color-coded \u201ccards.\u201d Set your plan, log meals, and \u201cdeal\u201d cards as you eat.\n      <\/div>\n    <\/header>\n\n    <div class=\"grid\">\n      <!-- Left: Food groups and logging -->\n      <section class=\"panel\">\n        <div class=\"head\">\n          <h2>Daily plan and cards<\/h2>\n          <div class=\"inline\">\n            <span class=\"badge\" id=\"dayDate\"><\/span>\n            <button class=\"btn\" id=\"newDayBtn\" title=\"Start a fresh day\">New day<\/button>\n          <\/div>\n        <\/div>\n        <div class=\"content\">\n          <div class=\"controls\">\n            <label class=\"inline\">\n              <span>Plan preset<\/span>\n              <select id=\"preset\">\n                <option value=\"balanced\">Balanced<\/option>\n                <option value=\"lowerCarb\">Lower carb<\/option>\n                <option value=\"higherProtein\">Higher protein<\/option>\n                <option value=\"custom\">Custom<\/option>\n              <\/select>\n            <\/label>\n            <button class=\"btn primary\" id=\"applyPresetBtn\">Apply preset<\/button>\n            <button class=\"btn warn\" id=\"resetAllBtn\">Reset all<\/button>\n            <button class=\"btn\" id=\"exportBtn\">Export<\/button>\n            <button class=\"btn\" id=\"importBtn\">Import<\/button>\n            <input type=\"file\" id=\"importFile\" class=\"hidden\" accept=\"application\/json\"\/>\n          <\/div>\n\n          <div class=\"spacer\"><\/div>\n\n          <div class=\"row\" id=\"groupsRow\">\n            <!-- Groups render here -->\n          <\/div>\n\n          <div class=\"spacer\"><\/div>\n\n          <div class=\"panel\" style=\"margin-top: 8px;\">\n            <div class=\"head\">\n              <h2>Quick log a serving<\/h2>\n            <\/div>\n            <div class=\"content\">\n              <div class=\"controls\">\n                <label class=\"inline\">\n                  <span>Group<\/span>\n                  <select id=\"logGroup\"><\/select>\n                <\/label>\n                <label class=\"inline\">\n                  <span>Servings<\/span>\n                  <input id=\"logServings\" type=\"number\" min=\"1\" step=\"1\" value=\"1\" \/>\n                <\/label>\n                <label class=\"inline\">\n                  <span>Note<\/span>\n                  <input id=\"logNote\" type=\"text\" placeholder=\"e.g., oatmeal, grilled chicken\"\/>\n                <\/label>\n                <button class=\"btn primary\" id=\"logBtn\">Deal cards<\/button>\n              <\/div>\n              <div class=\"muted\" style=\"margin-top: 6px;\">\n                Tip: Log each serving you eat and watch the meters fill. You can undo from the history list.\n              <\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"panel\" style=\"margin-top: 8px;\">\n            <div class=\"head\"><h2>Meal templates<\/h2><\/div>\n            <div class=\"content\">\n              <div class=\"controls\">\n                <button class=\"btn\" data-meal=\"breakfast\" id=\"tmplBreakfast\">Breakfast<\/button>\n                <button class=\"btn\" data-meal=\"lunch\" id=\"tmplLunch\">Lunch<\/button>\n                <button class=\"btn\" data-meal=\"dinner\" id=\"tmplDinner\">Dinner<\/button>\n                <button class=\"btn\" data-meal=\"snack\" id=\"tmplSnack\">Snack<\/button>\n              <\/div>\n              <div class=\"muted\" style=\"margin-top: 6px;\">\n                These add common serving combos (editable in code). Use them to \u201cdeal\u201d several cards at once.\n              <\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- Right: History and notes -->\n      <aside class=\"panel\">\n        <div class=\"head\"><h2>History and notes<\/h2><\/div>\n        <div class=\"content\">\n          <div class=\"list\" id=\"historyList\"><\/div>\n          <div class=\"spacer\"><\/div>\n          <div class=\"panel\">\n            <div class=\"head\"><h2>Daily reflections<\/h2><\/div>\n            <div class=\"content\">\n              <textarea id=\"reflection\" rows=\"6\" style=\"width: 100%; background: var(--chip); color: var(--text); border: 1px solid var(--border); border-radius: 10px; padding: 8px;\" placeholder=\"How did today feel? What worked? What needs care?\"><\/textarea>\n              <div class=\"inline\" style=\"margin-top: 8px;\">\n                <button class=\"btn\" id=\"saveReflectionBtn\">Save note<\/button>\n                <span class=\"muted\" id=\"reflectionStatus\"><\/span>\n              <\/div>\n            <\/div>\n          <\/div>\n          <div class=\"footer\">\n            Built for balance and clarity. You make the deals; this keeps score.\n          <\/div>\n        <\/div>\n      <\/aside>\n    <\/div>\n  <\/div>\n\n  <script>\n    \/\/ Core groups and default allowances (inspired by balanced, color-coded cards)\n    const GROUPS = [\n      { key: 'grains',   name: 'Grains & starches', color: 'b-amber', default: 6, tip: 'Bread, rice, pasta, oats' },\n      { key: 'fruits',   name: 'Fruits',            color: 'b-pink',  default: 3, tip: 'Fresh, frozen, unsweetened' },\n      { key: 'veggies',  name: 'Vegetables',        color: 'b-green', default: 4, tip: 'Leafy, crucifers, colorful' },\n      { key: 'protein',  name: 'Protein',           color: 'b-blue',  default: 5, tip: 'Lean meats, eggs, tofu' },\n      { key: 'dairy',    name: 'Dairy\/alt',         color: 'b-purple',default: 2, tip: 'Milk, yogurt, fortified alt' },\n      { key: 'fats',     name: 'Fats\/oils',         color: 'b-teal',  default: 3, tip: 'Nuts, seeds, olive oil' },\n      { key: 'extras',   name: 'Extras\/sweets',     color: 'b-red',   default: 1, tip: 'Treats, condiments' },\n    ];\n\n    const PRESETS = {\n      balanced: { grains: 6, fruits: 3, veggies: 4, protein: 5, dairy: 2, fats: 3, extras: 1 },\n      lowerCarb: { grains: 3, fruits: 2, veggies: 5, protein: 6, dairy: 2, fats: 3, extras: 1 },\n      higherProtein: { grains: 4, fruits: 3, veggies: 5, protein: 7, dairy: 2, fats: 3, extras: 1 },\n      custom: null \/\/ uses current state\n    };\n\n    const MEALS = {\n      breakfast: [\n        { key: 'grains', servings: 1, note: 'Oats' },\n        { key: 'protein', servings: 1, note: 'Eggs' },\n        { key: 'fruits', servings: 1, note: 'Fruit' }\n      ],\n      lunch: [\n        { key: 'protein', servings: 2, note: 'Lean protein' },\n        { key: 'veggies', servings: 2, note: 'Veg mix' },\n        { key: 'grains', servings: 1, note: 'Whole grain' }\n      ],\n      dinner: [\n        { key: 'protein', servings: 2, note: 'Lean protein' },\n        { key: 'veggies', servings: 2, note: 'Veg mix' },\n        { key: 'grains', servings: 1, note: 'Whole grain' }\n      ],\n      snack: [\n        { key: 'fruits', servings: 1, note: 'Fruit' },\n        { key: 'dairy', servings: 1, note: 'Yogurt' }\n      ]\n    };\n\n    const state = {\n      date: new Date().toISOString().slice(0,10),\n      plan: {},\n      used: {},\n      history: [],\n      reflection: ''\n    };\n\n    \/\/ Utilities\n    const fmtPct = (num) => Math.max(0, Math.min(100, Math.round(num)));\n    const el = (sel) => document.querySelector(sel);\n    const make = (tag, attrs={}, children=[]) => {\n      const node = document.createElement(tag);\n      Object.entries(attrs).forEach(([k,v]) => {\n        if (k === 'class') node.className = v;\n        else if (k === 'text') node.textContent = v;\n        else node.setAttribute(k,v);\n      });\n      children.forEach(c => node.appendChild(c));\n      return node;\n    };\n\n    function save() {\n      localStorage.setItem('dealameal_state', JSON.stringify(state));\n    }\n    function load() {\n      const raw = localStorage.getItem('dealameal_state');\n      if (!raw) return;\n      try {\n        const s = JSON.parse(raw);\n        Object.assign(state, s);\n      } catch(e) {}\n    }\n\n    function initPlanFromPreset(presetKey='balanced') {\n      const preset = PRESETS[presetKey] || PRESETS['balanced'];\n      GROUPS.forEach(g => {\n        const allowance = preset?.[g.key] ?? g.default;\n        state.plan[g.key] = allowance;\n        if (!(g.key in state.used)) state.used[g.key] = 0;\n      });\n      save(); renderAll();\n    }\n\n    function renderDate() {\n      el('#dayDate').textContent = new Date(state.date).toDateString();\n    }\n\n    function renderGroups() {\n      const row = el('#groupsRow');\n      row.innerHTML = '';\n      GROUPS.forEach(g => {\n        const allowance = state.plan[g.key] ?? g.default;\n        const used = state.used[g.key] ?? 0;\n        const remaining = Math.max(0, allowance - used);\n        const pct = allowance > 0 ? (used \/ allowance) * 100 : 0;\n\n        const card = make('div', { class: 'group-card' }, [\n          make('h3', {}, [\n            make('span', { class: 'bullet ' + g.color }),\n            make('span', { text: g.name }),\n            make('span', { class: 'badge', text: `Allowed: ${allowance}` }),\n          ]),\n          make('div', { class: 'meter' }, [\n            make('span', { style: `width: ${fmtPct(pct)}%; background: ${pct >= 100 ? 'var(--danger)' : 'var(--accent)'};` })\n          ]),\n          make('div', { class: 'inline' }, [\n            make('span', { class: 'muted', text: `Used: ${used}` }),\n            make('span', { class: 'muted', text: `Remaining: ${remaining}` })\n          ]),\n          make('div', { class: 'chips' }, [\n            make('span', { class: 'chip' }, [\n              make('span', { text: '\u22121' }),\n              make('button', { title: 'Remove one', onclick: ()=>adjust(g.key, -1) }, [ document.createTextNode('\u21ba') ])\n            ]),\n            make('span', { class: 'chip' }, [\n              make('span', { text: '+1' }),\n              make('button', { title: 'Add one', onclick: ()=>adjust(g.key, 1) }, [ document.createTextNode('\u2713') ])\n            ]),\n            make('span', { class: 'chip' }, [\n              make('span', { text: '+2' }),\n              make('button', { title: 'Add two', onclick: ()=>adjust(g.key, 2) }, [ document.createTextNode('\u27f2') ])\n            ]),\n          ]),\n          make('div', { class: 'muted', text: g.tip })\n        ]);\n        row.appendChild(card);\n      });\n    }\n\n    function renderLogControls() {\n      const sel = el('#logGroup');\n      sel.innerHTML = '';\n      GROUPS.forEach(g => {\n        const opt = make('option', { value: g.key, text: g.name });\n        sel.appendChild(opt);\n      });\n    }\n\n    function renderHistory() {\n      const list = el('#historyList');\n      list.innerHTML = '';\n      state.history.slice().reverse().forEach((h, idx) => {\n        const item = make('div', { class: 'item' }, [\n          make('div', {}, [\n            make('div', { text: `${h.servings} serving(s) of ${nameFor(h.key)}${h.note ? ' \u2014 ' + h.note : ''}` }),\n            make('div', { class: 'meta', text: `${new Date(h.time).toLocaleTimeString()} \u2022 ${new Date(h.time).toLocaleDateString()}` })\n          ]),\n          make('div', { class: 'actions' }, [\n            make('button', { class: 'btn', title: 'Undo', onclick: ()=>undo(h.id) }, [ document.createTextNode('Undo') ])\n          ])\n        ]);\n        list.appendChild(item);\n      });\n    }\n\n    function renderReflection() {\n      el('#reflection').value = state.reflection || '';\n      el('#reflectionStatus').textContent = '';\n    }\n\n    function nameFor(key) {\n      return GROUPS.find(g => g.key === key)?.name || key;\n    }\n\n    function adjust(key, delta, note='Quick adjust') {\n      const current = state.used[key] ?? 0;\n      const next = Math.max(0, current + delta);\n      state.used[key] = next;\n      if (delta > 0) {\n        addHistory({ key, servings: delta, note });\n      } else if (delta < 0) {\n        addHistory({ key, servings: delta, note: 'Removed serving(s)' });\n      }\n      save(); renderAll();\n    }\n\n    function addHistory(entry) {\n      state.history.push({\n        id: crypto.randomUUID(),\n        ...entry,\n        time: new Date().toISOString()\n      });\n    }\n\n    function undo(id) {\n      const idx = state.history.findIndex(h => h.id === id);\n      if (idx === -1) return;\n      const h = state.history[idx];\n      \/\/ reverse the servings\n      state.used[h.key] = Math.max(0, (state.used[h.key] ?? 0) - (h.servings));\n      \/\/ if it was a negative serving, undo adds back\n      if (h.servings < 0) {\n        state.used[h.key] = (state.used[h.key] ?? 0) - h.servings; \/\/ subtract negative -> add\n      }\n      state.history.splice(idx, 1);\n      save(); renderAll();\n    }\n\n    function logServing() {\n      const key = el('#logGroup').value;\n      const servings = Math.max(1, parseInt(el('#logServings').value, 10) || 1);\n      const note = el('#logNote').value.trim();\n      adjust(key, servings, note || 'Logged');\n      el('#logNote').value = '';\n    }\n\n    function applyPreset() {\n      const key = el('#preset').value;\n      if (key === 'custom') {\n        \/\/ keep current plan as-is\n        save(); renderAll();\n        return;\n      }\n      const p = PRESETS[key];\n      GROUPS.forEach(g => state.plan[g.key] = p[g.key] ?? g.default);\n      save(); renderAll();\n    }\n\n    function mealTemplate(name) {\n      const parts = MEALS[name] || [];\n      parts.forEach(p => adjust(p.key, p.servings, `${name} (${p.note})`));\n    }\n\n    function newDay() {\n      state.date = new Date().toISOString().slice(0,10);\n      state.used = {};\n      state.history = [];\n      save(); renderAll();\n    }\n\n    function resetAll() {\n      if (!confirm('Reset plan, usage, and notes? This clears all saved data.')) return;\n      localStorage.removeItem('dealameal_state');\n      state.date = new Date().toISOString().slice(0,10);\n      state.plan = {};\n      state.used = {};\n      state.history = [];\n      state.reflection = '';\n      initPlanFromPreset('balanced');\n    }\n\n    function exportData() {\n      const blob = new Blob([JSON.stringify(state, null, 2)], { type: 'application\/json' });\n      const url = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = url; a.download = `deal-a-meal-${state.date}.json`;\n      a.click();\n      setTimeout(() => URL.revokeObjectURL(url), 1000);\n    }\n\n    function importData(file) {\n      const reader = new FileReader();\n      reader.onload = (e) => {\n        try {\n          const obj = JSON.parse(e.target.result);\n          Object.assign(state, obj);\n          save(); renderAll();\n        } catch (err) {\n          alert('Invalid JSON file.');\n        }\n      };\n      reader.readAsText(file);\n    }\n\n    function saveReflection() {\n      state.reflection = el('#reflection').value.trim();\n      save();\n      el('#reflectionStatus').textContent = 'Saved';\n      setTimeout(()=> el('#reflectionStatus').textContent = '', 1500);\n    }\n\n    function renderAll() {\n      renderDate();\n      renderGroups();\n      renderLogControls();\n      renderHistory();\n      renderReflection();\n    }\n\n    \/\/ Events\n    document.addEventListener('DOMContentLoaded', () => {\n      load();\n      if (!state.plan || Object.keys(state.plan).length === 0) {\n        initPlanFromPreset('balanced');\n      } else {\n        renderAll();\n      }\n      el('#applyPresetBtn').addEventListener('click', applyPreset);\n      el('#logBtn').addEventListener('click', logServing);\n      el('#newDayBtn').addEventListener('click', newDay);\n      el('#resetAllBtn').addEventListener('click', resetAll);\n      el('#saveReflectionBtn').addEventListener('click', saveReflection);\n      el('#exportBtn').addEventListener('click', exportData);\n      el('#importBtn').addEventListener('click', () => el('#importFile').click());\n      el('#importFile').addEventListener('change', (e) => {\n        if (e.target.files?.[0]) importData(e.target.files[0]);\n        e.target.value = '';\n      });\n      \/\/ Meal templates\n      ['tmplBreakfast','tmplLunch','tmplDinner','tmplSnack'].forEach(id => {\n        const btn = el('#' + id);\n        btn.addEventListener('click', () => {\n          const meal = btn.getAttribute('data-meal');\n          mealTemplate(meal);\n        });\n      });\n    });\n  <\/script>\n<\/body>\n<\/html>\n\n\n","protected":false},"excerpt":{"rendered":"<p>Fork-It Meal Tracker Fork-It Daily Tracker Track balanced servings with color-coded \u201ccards.\u201d Set your plan, log meals, and \u201cdeal\u201d cards as you eat. Daily plan and cards New day Plan&hellip;<\/p>\n","protected":false},"author":1,"featured_media":3179,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","footnotes":""},"categories":[23,106],"tags":[],"class_list":["post-3065","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-food","category-software"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\r\n<title>Fork-It Meal Tracker - GaryHengeveld<\/title>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/\" \/>\r\n<meta property=\"og:locale\" content=\"en_US\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"Fork-It Meal Tracker - GaryHengeveld\" \/>\r\n<meta property=\"og:description\" content=\"Fork-It Meal Tracker Fork-It Daily Tracker Track balanced servings with color-coded \u201ccards.\u201d Set your plan, log meals, and \u201cdeal\u201d cards as you eat. Daily plan and cards New day Plan&hellip;\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/\" \/>\r\n<meta property=\"og:site_name\" content=\"GaryHengeveld\" \/>\r\n<meta property=\"article:published_time\" content=\"2025-12-11T17:02:54+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2026-03-05T15:21:14+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2025\/12\/forkit3.png\" \/>\r\n\t<meta property=\"og:image:width\" content=\"200\" \/>\r\n\t<meta property=\"og:image:height\" content=\"200\" \/>\r\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\r\n<meta name=\"author\" content=\"ghd796\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"ghd796\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/\"},\"author\":{\"name\":\"ghd796\",\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/#\\\/schema\\\/person\\\/a56bd109b9611da934105651f63c1988\"},\"headline\":\"Fork-It Meal Tracker\",\"datePublished\":\"2025-12-11T17:02:54+00:00\",\"dateModified\":\"2026-03-05T15:21:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/\"},\"wordCount\":114,\"publisher\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/#\\\/schema\\\/person\\\/a56bd109b9611da934105651f63c1988\"},\"image\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/forkit3.png\",\"articleSection\":[\"Food\",\"Software\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/\",\"url\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/\",\"name\":\"Fork-It Meal Tracker - GaryHengeveld\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/forkit3.png\",\"datePublished\":\"2025-12-11T17:02:54+00:00\",\"dateModified\":\"2026-03-05T15:21:14+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/#primaryimage\",\"url\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/forkit3.png\",\"contentUrl\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/forkit3.png\",\"width\":200,\"height\":200},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/meal-tracker\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fork-It Meal Tracker\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/#website\",\"url\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/\",\"name\":\"GaryHengeveld\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/#\\\/schema\\\/person\\\/a56bd109b9611da934105651f63c1988\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/#\\\/schema\\\/person\\\/a56bd109b9611da934105651f63c1988\",\"name\":\"ghd796\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/GLOGO.png\",\"url\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/GLOGO.png\",\"contentUrl\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/GLOGO.png\",\"width\":150,\"height\":150,\"caption\":\"ghd796\"},\"logo\":{\"@id\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/GLOGO.png\"},\"url\":\"https:\\\/\\\/garyhengeveld.com\\\/wordpress\\\/author\\\/ghd796\\\/\"}]}<\/script>\r\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Fork-It Meal Tracker - GaryHengeveld","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/","og_locale":"en_US","og_type":"article","og_title":"Fork-It Meal Tracker - GaryHengeveld","og_description":"Fork-It Meal Tracker Fork-It Daily Tracker Track balanced servings with color-coded \u201ccards.\u201d Set your plan, log meals, and \u201cdeal\u201d cards as you eat. Daily plan and cards New day Plan&hellip;","og_url":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/","og_site_name":"GaryHengeveld","article_published_time":"2025-12-11T17:02:54+00:00","article_modified_time":"2026-03-05T15:21:14+00:00","og_image":[{"width":200,"height":200,"url":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2025\/12\/forkit3.png","type":"image\/png"}],"author":"ghd796","twitter_card":"summary_large_image","twitter_misc":{"Written by":"ghd796","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/#article","isPartOf":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/"},"author":{"name":"ghd796","@id":"https:\/\/garyhengeveld.com\/wordpress\/#\/schema\/person\/a56bd109b9611da934105651f63c1988"},"headline":"Fork-It Meal Tracker","datePublished":"2025-12-11T17:02:54+00:00","dateModified":"2026-03-05T15:21:14+00:00","mainEntityOfPage":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/"},"wordCount":114,"publisher":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/#\/schema\/person\/a56bd109b9611da934105651f63c1988"},"image":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/#primaryimage"},"thumbnailUrl":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2025\/12\/forkit3.png","articleSection":["Food","Software"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/","url":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/","name":"Fork-It Meal Tracker - GaryHengeveld","isPartOf":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/#website"},"primaryImageOfPage":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/#primaryimage"},"image":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/#primaryimage"},"thumbnailUrl":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2025\/12\/forkit3.png","datePublished":"2025-12-11T17:02:54+00:00","dateModified":"2026-03-05T15:21:14+00:00","breadcrumb":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/#primaryimage","url":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2025\/12\/forkit3.png","contentUrl":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2025\/12\/forkit3.png","width":200,"height":200},{"@type":"BreadcrumbList","@id":"https:\/\/garyhengeveld.com\/wordpress\/meal-tracker\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/garyhengeveld.com\/wordpress\/"},{"@type":"ListItem","position":2,"name":"Fork-It Meal Tracker"}]},{"@type":"WebSite","@id":"https:\/\/garyhengeveld.com\/wordpress\/#website","url":"https:\/\/garyhengeveld.com\/wordpress\/","name":"GaryHengeveld","description":"","publisher":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/#\/schema\/person\/a56bd109b9611da934105651f63c1988"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/garyhengeveld.com\/wordpress\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/garyhengeveld.com\/wordpress\/#\/schema\/person\/a56bd109b9611da934105651f63c1988","name":"ghd796","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2026\/03\/GLOGO.png","url":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2026\/03\/GLOGO.png","contentUrl":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2026\/03\/GLOGO.png","width":150,"height":150,"caption":"ghd796"},"logo":{"@id":"https:\/\/garyhengeveld.com\/wordpress\/wp-content\/uploads\/2026\/03\/GLOGO.png"},"url":"https:\/\/garyhengeveld.com\/wordpress\/author\/ghd796\/"}]}},"_links":{"self":[{"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/posts\/3065","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/comments?post=3065"}],"version-history":[{"count":11,"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/posts\/3065\/revisions"}],"predecessor-version":[{"id":3079,"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/posts\/3065\/revisions\/3079"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/media\/3179"}],"wp:attachment":[{"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/media?parent=3065"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/categories?post=3065"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/garyhengeveld.com\/wordpress\/wp-json\/wp\/v2\/tags?post=3065"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}