<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>My Blog</title>
        <link>https://fixedblog-3lz.pages.dev</link>
        <description>Welcome to the new blog. (Please modify this text in settings.)</description>
        <language>en</language>
        <atom:link href="https://fixedblog-3lz.pages.dev/en/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Thu, 03 Sep 2026 04:47:45 GMT</lastBuildDate>
        <item>
            <title><![CDATA[SKBE v1.0.0.10 Update: Multilingual Post Tabs, Hub Sync Polish, and Editor Safeguards]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/devlog/release-v1-0-0-10-post-management-tabs-and-hub-sync</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/devlog/release-v1-0-0-10-post-management-tabs-and-hub-sync</guid>
            <pubDate>Wed, 26 Aug 2026 06:12:17 GMT</pubDate>
            <description><![CDATA[Introducing v1.0.0.10: Dynamic language filter tabs for multilingual posts, refined Blog Hub federation protocols, editor data loss protection guards, and simplified deployment CLI.]]></description>
            <content:encoded><![CDATA[<h1 id="sveltekit-blog-engine-v10010-release-notes">SvelteKit Blog Engine v1.0.0.10 Release Notes</h1>
<p>Here is a summary of the updates introduced in <strong>SvelteKit Blog Engine v1.0.0.10</strong>.</p>
<p>As multilingual publishing grew, managing mixed-language articles in a single chronological list became increasingly tedious. In this update, we focused on implementing <strong>dynamic language filter tabs</strong> in the admin post management dashboard, <strong>refining the Blog Hub federation protocol</strong>, <strong>adding editor safeguards against formatting loss</strong>, and <strong>simplifying multi-account deployment commands</strong>.</p>
<hr>
<h2 id="1-dynamic-multilingual-filter-tabs-in-post-management">1. Dynamic Multilingual Filter Tabs in Post Management</h2>
<p>Previously, all posts were listed strictly in chronological order regardless of their language. Managing dozens of articles across Korean, English, and Japanese required unnecessary scrolling and searching.</p>
<p><img src="https://sveltekitblog.com/images/posts/release-v1-0-0-10-post-management-tabs-and-hub-sync/desktop/img-devlog-release-v1-0-0-10-post-management-tabs-and-hub-sync-en-002.webp" alt="img-devlog-release-v1-0-0-10-post-management-tabs-and-hub-sync-en-002"></p>
<h3 id="key-improvements">Key Improvements</h3>
<ul>
<li><strong>Dynamic Language Detection &amp; Live Count Badges</strong>: Instead of hardcoding language codes, the system queries active database languages and post entries in real time. Each tab displays live post counts (e.g., <code>[All (24)]</code>, <code>[Korean (10)]</code>, <code>[English (8)]</code>, <code>[Japanese (6)]</code>).</li>
<li><strong>Smart Empty States</strong>: Clicking a language tab with zero posts (e.g., <code>English (0)</code>) shows a helpful prompt along with a direct <code>[+ Write New Post in this language]</code> button to streamline the authoring workflow.</li>
<li><strong>Single-Language Mode Support</strong>: For blogs operating in only one language, the tab bar remains hidden to keep the interface clean and minimal.</li>
<li><strong>Language Chips &amp; Safe Pagination</strong>: Table rows now display crisp language badges (<code>KR</code>, <code>EN</code>, <code>JA</code>, etc.) next to titles, and switching tabs automatically resets the view to Page 1 to avoid blank pagination bugs.</li>
</ul>
<hr>
<h2 id="2-refined-blog-hub-hubsveltekitblogcom-integration">2. Refined Blog Hub (<code>hub.sveltekitblog.com</code>) Integration</h2>
<p>We polished several edge cases when syncing articles to the centralized feed platform, SvelteKit Blog Hub.</p>
<h3 id="improvements">Improvements</h3>
<ul>
<li><strong>1,500-Character Standard HTML Intro Extraction</strong>: Automatically parses and extracts clean 1,000–1,500 character HTML introductory excerpts from both Markdown and Visual HTML formats for feed summary cards.</li>
<li><strong>Absolute Image URL Conversion</strong>: Transforms relative image paths (<code>/images/posts/...</code>) into absolute URLs containing the canonical domain (<code>https://yourdomain.com/images/...</code>) so that thumbnails and in-article images render properly on external feeds.</li>
<li><strong>Publish Date Timeline Preservation</strong>: When updating an existing article, the original <code>published_at</code> timestamp is preserved instead of being overwritten by the edit date, keeping the Hub timeline chronological.</li>
<li><strong>Default Auto-Publish Setting</strong>: Added a toggle under Admin Settings (<code>⚙️ Settings</code>) to enable &quot;Auto-Submit to Hub&quot; by default for new posts.</li>
</ul>
<hr>
<h2 id="3-post-editor-data-loss-protection-guards">3. Post Editor Data Loss Protection Guards</h2>
<p>We added protective measures in the post editor to prevent accidental loss of content or formatting when switching modes.</p>
<ul>
<li><strong>HTML to Visual Mode Warning</strong>: Switching from raw HTML to the Visual editor can cause non-standard tags, custom tables, or inline styles to be sanitized by the editor parser. A confirmation dialog now alerts you before the switch occurs.</li>
<li><strong>Editor Format Lock</strong>: Existing saved posts have their editor type (HTML vs. Markdown) locked to prevent accidental corruption, with warning prompts if changes are attempted.</li>
</ul>
<hr>
<h2 id="4-simplified-multi-account-deployment-cli">4. Simplified Multi-Account Deployment CLI</h2>
<p>The <code>deploy-multi</code> script arguments have been streamlined for faster and more intuitive operations:</p>
<pre><code class="language-bash"># Previous format
npm run deploy:multi -- myaccount --admin-only

# New streamlined format
npm run deploy:multi -- myaccount admin   # Fast admin-only deploy
npm run deploy:multi -- myaccount blog    # Fast blog-only deploy
npm run deploy:multi -- myaccount         # Deploy both blog and admin
</code></pre>
<p><em>(Legacy flags like <code>--admin-only</code> and <code>--blog-only</code> remain 100% backward compatible.)</em></p>
<hr>
<h2 id="how-to-apply-the-update">How to Apply the Update</h2>
<p>Pull the latest repository commits and run your deployment command:</p>
<pre><code class="language-bash"># Pull latest code
git pull origin main

# Deploy admin (example)
npm run deploy:admin
# Or for multi-account deployment
npm run deploy:multi -- &lt;account_name&gt; admin
</code></pre>
<p>We will continue to refine and enhance the engine based on real-world usage. Thank you!</p>
]]></content:encoded>
            <category>DevLog</category>
            <enclosure url="https://sveltekitblog.com/images/posts/release-v1-0-0-10-post-management-tabs-and-hub-sync/desktop/img-devlog-release-v1-0-0-10-post-management-tabs-and-hub-sync-en-002.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Comprehensive Guide to SvelteKitBlog Hub Syndication and Auto-Publishing]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/detail-manual/blog-hub-integration-manual</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/detail-manual/blog-hub-integration-manual</guid>
            <pubDate>Tue, 25 Aug 2026 22:28:23 GMT</pubDate>
            <description><![CDATA[A comprehensive guide to federating your standalone blog with SvelteKitBlog Hub (hub.sveltekitblog.com) to expand traffic and safely automate the post creation, update, and deletion lifecycle.]]></description>
            <content:encoded><![CDATA[<h1 id="comprehensive-guide-to-sveltekitblog-hub-syndication-and-auto-publishing">🌐 Comprehensive Guide to SvelteKitBlog Hub Syndication and Auto-Publishing</h1>
<p>When operating a standalone personal blog, the biggest challenge is <strong>&quot;How can I introduce my articles to new readers?&quot;</strong> Unlike commercial blogging platforms, a self-hosted blog gives you complete freedom over your data and design, but attracting initial traffic and achieving search engine visibility requires considerable time and effort.</p>
<p><strong><a href="https://hub.sveltekitblog.com/">SvelteKit Blog Hub (hub.sveltekitblog.com)</a></strong> is a decentralized federated feed platform designed to overcome the discoverability limitations of independent blogs, allowing creators to share readership, statistics, and mutual growth.</p>
<p>This guide provides a detailed walkthrough of everything you need to know—from <strong>obtaining an API Key and configuring the admin settings to managing the post lifecycle and leveraging Google AdSense synergies</strong>.</p>
<hr>
<h2 id="1-key-features-and-working-principles">1. 🎯 Key Features and Working Principles</h2>
<p><img src="https://sveltekitblog.com/images/posts/blog-hub-integration-manual/desktop/img-detail-manual-blog-hub-integration-manual-en-001.webp" alt="img-detail-manual-blog-hub-integration-manual-en-001"></p>
<ol>
<li><strong>Complete Data Independence &amp; Ownership</strong>:<ul>
<li>The full article text and all database entries remain securely within your own Cloudflare D1 instance.</li>
<li>Only a <strong>standard HTML introduction (1,000–1,500 characters)</strong> and essential metadata (title, thumbnail, slug, etc.) are transmitted to the hub for feed card rendering.</li>
</ul>
</li>
<li><strong>Automatic Absolute URL Conversion for Images</strong>:<ul>
<li>Relative image paths (<code>/images/...</code>) embedded in Markdown or HTML are automatically transformed into absolute URLs (<code>https://yourdomain.com/...</code>), ensuring crystal-clear previews on the hub feed without broken links.</li>
</ul>
</li>
<li><strong>Non-blocking &amp; Fault-Tolerant Isolation</strong>:<ul>
<li>Even if the hub server experiences network latency or temporary downtime, <strong>your blog&#39;s internal post-saving transaction is guaranteed to complete normally without any interruption</strong>.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="2-step-1-obtain-a-hub-api-key-amp-configure-settings">2. 🔑 Step 1: Obtain a Hub API Key &amp; Configure Settings</h2>
<h3 id="obtain-an-api-key-from-the-hub-platform">① Obtain an API Key from the Hub Platform</h3>
<ol>
<li>Visit <strong><a href="https://hub.sveltekitblog.com/register-site">SvelteKit Blog Hub &#39;Connect Blog (Get API Key)&#39;</a></strong>.<br><img src="https://sveltekitblog.com/images/posts/blog-hub-integration-manual/desktop/img-detail-manual-blog-hub-integration-manual-en-002.webp?v=2" alt="img-detail-manual-blog-hub-integration-manual-en-002"></li>
<li>Register your blog&#39;s canonical URL (e.g., <code>https://myblog.com</code>) and copy the uniquely generated <strong>Site API Key</strong> (<code>sk_board_...</code> or <code>sk_hub_...</code>).</li>
</ol>
<h3 id="configure-blog-admin-settings-settings">② Configure Blog Admin Settings (<code>⚙️ Settings</code>)</h3>
<ol>
<li>Log in to your blog&#39;s admin dashboard and navigate to <strong>[Settings]</strong>.</li>
<li>Locate the <strong>SvelteKitBlog Hub Syndication Settings</strong> section.<br><img src="https://sveltekitblog.com/images/posts/blog-hub-integration-manual/desktop/img-detail-manual-blog-hub-integration-manual-en-003.webp?v=2" alt="img-detail-manual-blog-hub-integration-manual-en-003"></li>
</ol>
<pre><code class="language-text">[ SvelteKit Blog Hub Integration Settings ]
* Hub Platform URL : https://hub.sveltekitblog.com (Fixed)
* Hub Issued API Key : sk_hub_live_... (Enter your issued key)
* 🌐 Enable Auto-Publish to Hub by Default : [ON / OFF Toggle]
</code></pre>
<ol start="3">
<li>Enabling <code>Auto-Syndication by Default</code> will pre-check the syndication option whenever you create a new post.</li>
<li>Click <strong>[Save Settings]</strong> at the bottom to apply the configuration.</li>
</ol>
<hr>
<h2 id="3-step-2-auto-publishing-from-the-post-editor">3. ✍️ Step 2: Auto-Publishing from the Post Editor</h2>
<p>At the bottom of the metadata sidebar in the post editor (<code>New Post</code> or <code>Edit Post</code>), you will find the <strong>Hub Auto-Submission checkbox</strong>.<br><img src="https://sveltekitblog.com/images/posts/blog-hub-integration-manual/desktop/img-detail-manual-blog-hub-integration-manual-en-004.webp" alt="img-detail-manual-blog-hub-integration-manual-en-004"></p>
<pre><code class="language-text">[☑️] 🌐 Automatically submit to SvelteKit Blog Hub (hub.sveltekitblog.com)
     When checked, a summary card is automatically submitted to the Hub feed upon publishing.
     When unchecked, it is set to &quot;Hidden&quot; on the Hub to safely preserve like statistics;
     to delete completely from the Hub, you must delete the post on your blog.
</code></pre>
<ul>
<li><strong>Publishing Public Posts (<code>Status: Published</code>)</strong>:<ul>
<li>When saved with the checkbox active, the HTML intro and thumbnail are dispatched to the hub simultaneously with the D1 database write, appearing instantly on the hub feed.</li>
</ul>
</li>
<li><strong>Saving Drafts (<code>Status: Draft</code>)</strong>:<ul>
<li>Posts saved as drafts will never be exposed on the public hub feed, even if the checkbox is checked.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="4-step-3-lifecycle-management-edit-url-change-hide-delete">4. 🔄 Step 3: Lifecycle Management (Edit, URL Change, Hide, Delete)</h2>
<p>As you maintain your blog, you may update article content, reclassify categories, or hide/delete posts. The blog engine automatically detects these lifecycle events and syncs with the hub flawlessly.</p>
<table>
<thead>
<tr>
<th align="left">Scenario</th>
<th align="left">Blog Action</th>
<th align="left">Hub Synchronization Behavior</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>Content Update</strong></td>
<td align="left">Edit body and save</td>
<td align="left"><strong>Preserves the original publication date (<code>published_at</code>)</strong> while updating card content and thumbnail (avoids jumping to the top of the feed unnecessarily)</td>
</tr>
<tr>
<td align="left"><strong>Slug / Category Change</strong></td>
<td align="left">Change URL and save</td>
<td align="left">Automatically <strong>deletes the previous URL card (<code>DELETE</code>)</strong> and <strong>registers the new URL (<code>POST</code>)</strong> (prevents broken 404 links)</td>
</tr>
<tr>
<td align="left"><strong>Unpublish / Uncheck</strong></td>
<td align="left">Switch to Draft or uncheck</td>
<td align="left">Sets card status to <strong><code>hidden</code></strong> (reader <strong>upvote/like statistics are permanently preserved</strong>)</td>
</tr>
<tr>
<td align="left"><strong>Delete Post</strong></td>
<td align="left">Delete post from admin</td>
<td align="left">Completely <strong>removes the card from the hub (<code>DELETE</code>)</strong></td>
</tr>
</tbody></table>
<hr>
<h2 id="5-google-adsense-readiness-amp-synergies">5. 💰 Google AdSense Readiness &amp; Synergies</h2>
<p>Traffic driven from the hub significantly accelerates Google AdSense approval and ad revenue generation.</p>
<ol>
<li><strong>Securing Initial Active Traffic</strong>:<ul>
<li>Google crawlers index and rate websites with active, genuine reader traffic much faster than dormant sites with zero visitors.</li>
</ul>
</li>
<li><strong>Automated <code>ads.txt</code> Serving</strong>:<ul>
<li>Entering your AdSense authorization snippet (<code>google.com, pub-..., DIRECT, f08c47fec0942fa0</code>) in the admin settings serves it immediately at <code>https://yourdomain.com/ads.txt</code>.</li>
</ul>
</li>
<li><strong>Content Quality Guidelines</strong>:<ul>
<li>For primary AdSense approval, we recommend consistently publishing <strong>15–20 high-quality technical or informative articles (1,500+ characters each)</strong> syndicated to the hub.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="6-conclusion">6. 🏁 Conclusion</h2>
<p>By integrating with SvelteKitBlog Hub, you maintain 100% data sovereignty over your standalone blog while unlocking the powerful network synergy of a unified community feed!</p>
]]></content:encoded>
            <category>Detailed Manual</category>
            <enclosure url="https://sveltekitblog.com/images/posts/blog-hub-integration-manual/desktop/img-detail-manual-blog-hub-integration-manual-en-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Safely Deploying New Releases: Cloudflare Pages Multi-Account Deployment Automation]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/general-guide/cloudflare-pages-multi-account-deploy-guide</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/general-guide/cloudflare-pages-multi-account-deploy-guide</guid>
            <pubDate>Sun, 23 Aug 2026 13:12:23 GMT</pubDate>
            <description><![CDATA[How to safely verify new engine releases on a staging test account before deploying to production! A complete guide to one-click multi-account Cloudflare Pages deployment.]]></description>
            <content:encoded><![CDATA[<h1 id="safely-deploying-new-releases-cloudflare-pages-multi-account-deployment-automation">🚀 Safely Deploying New Releases: Cloudflare Pages Multi-Account Deployment Automation</h1>
<p>When a new engine release arrives in the GitHub repository and you update your codebase, one natural question arises:</p>
<blockquote>
<p><strong>&quot;Will this new core release and database migration apply smoothly to my live production blog without breaking anything?&quot;</strong></p>
</blockquote>
<p>In SvelteKit Blog Engine, all your custom design settings (layouts, colors, fonts) and published posts are <strong>safely preserved in the D1 database</strong>, meaning updating the engine codebase will never wipe out your customized blog UI.</p>
<p>However, you may still want to verify that new backend features, D1 schema migrations, and deployment scripts run properly in your Cloudflare environment. The safest approach is to <strong>deploy to a free auxiliary Cloudflare account (or staging test instance) first, verify everything visually, and then deploy to your main production account with confidence</strong>.</p>
<p>Standard Cloudflare tools (Wrangler) traditionally required tedious browser re-logins, manual ID swapping in config files, and often suffered from local cache collisions. This guide outlines the <strong>one-click multi-account deployment pipeline</strong> that makes staged release verification seamless and risk-free.</p>
<hr>
<h2 id="1-safe-release-deployment-workflow">🔄 1. Safe Release Deployment Workflow</h2>
<p>With the multi-account deployment runner, you can establish a robust release cycle:<br><img src="https://sveltekitblog.com/images/posts/cloudflare-pages-multi-account-deploy-guide/desktop/img-general-guide-cloudflare-pages-multi-account-deploy-guide-en-001.webp" alt="img-general-guide-cloudflare-pages-multi-account-deploy-guide-en-001"></p>
<hr>
<h2 id="2-prerequisites-cloudflare-api-tokens-once-per-account">🔑 2. Prerequisites: Cloudflare API Tokens (Once per Account)</h2>
<p>To deploy in the background without browser popups, create a dedicated <strong>API Token</strong> for each Cloudflare account once.</p>
<h3 id="2-1-creating-a-least-privilege-api-token">2-1. Creating a Least-Privilege API Token</h3>
<ol>
<li>Log in to the <a href="https://dash.cloudflare.com">Cloudflare Dashboard</a> ➔ Top-Right <strong>[My Profile]</strong> ➔ <strong>[API Tokens]</strong>.</li>
<li>Click <strong>[Create Token]</strong> and select <strong>[Use template]</strong> next to <strong><code>Edit Cloudflare Pages</code></strong>.</li>
<li>Under <strong>Permissions</strong>, click <strong><code>+ Add more</code></strong> to append the following two permissions:<ul>
<li><strong><code>Account</code></strong> - <strong><code>D1</code></strong> - <strong><code>Edit</code></strong> <em>(For automatic D1 database schema migrations)</em></li>
<li><strong><code>Account</code></strong> - <strong><code>Workers KV Storage</code></strong> - <strong><code>Edit</code></strong> <em>(For image storage bucket bindings)</em></li>
</ul>
</li>
</ol>
<blockquote>
<p><strong>💡 Security Tip</strong>: Instead of a Global API Key, issuing a token with <strong>only Pages, D1, and KV permissions (Principle of Least Privilege)</strong> is much safer.</p>
</blockquote>
<ol start="4">
<li>Select your target account under <strong>Account Resources</strong>, then click <strong>[Continue to summary] ➔ [Create Token]</strong>.</li>
<li>Copy the generated <strong>API Token string</strong>.</li>
</ol>
<h3 id="2-2-locating-your-32-character-account-id">2-2. Locating Your 32-Character Account ID</h3>
<p>From the browser address bar while inside your dashboard:</p>
<pre><code class="language-text">https://dash.cloudflare.com/1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d/workers-and-pages
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                             (This 32-character string is your Account ID)
</code></pre>
<hr>
<h2 id="3-instant-account-registration-via-backup-deploysync">📦 3. Instant Account Registration via Backup (<code>deploy:sync</code>)</h2>
<p>Instead of manually copying D1 UUIDs and KV IDs from the dashboard, you can register accounts instantly using the <strong>built-in backup download feature in Admin</strong>.</p>
<ol>
<li>In the target blog&#39;s Admin Dashboard ➔ <strong>[Settings] ➔ [Data Management]</strong>, click <strong>[Download Deployment Config]</strong>.</li>
<li>Rename the downloaded file to your desired account identifier and place it in the project root:<ul>
<li>Example (Test account): <code>wrangler.backup.test.json</code></li>
<li>Example (Main account): <code>wrangler.backup.main.json</code></li>
</ul>
</li>
<li>Run the sync command in your terminal:</li>
</ol>
<pre><code class="language-bash">npm run deploy:sync
</code></pre>
<pre><code class="language-text">======================================================
✅ [.deploy-accounts.json] Account Sync Completed!
======================================================
📋 [Registered Accounts]
  - main (Main Blog Account): 🟢 Ready
  - test (Test Blog Account): 🟡 token/accountId required
</code></pre>
<ol start="4">
<li>Open <code>.deploy-accounts.json</code> and fill in your <code>token</code> and <code>accountId</code>:</li>
</ol>
<pre><code class="language-json">{
  &quot;test&quot;: {
    &quot;name&quot;: &quot;Test Staging Account&quot;,
    &quot;token&quot;: &quot;YOUR_ACTUAL_API_TOKEN&quot;,
    &quot;accountId&quot;: &quot;YOUR_32_CHAR_ACCOUNT_ID&quot;,
    &quot;blogProject&quot;: &quot;test-blog-web&quot;,
    &quot;adminProject&quot;: &quot;test-blog-admin&quot;,
    &quot;d1&quot;: {
      &quot;BLOG_DB&quot;: { &quot;name&quot;: &quot;test-blog-db&quot;, &quot;id&quot;: &quot;11111111-2222-3333-4444-555555555555&quot; },
      &quot;USER_DB&quot;: { &quot;name&quot;: &quot;test-user-db&quot;, &quot;id&quot;: &quot;66666666-7777-8888-9999-000000000000&quot; }
    },
    &quot;kv&quot;: {
      &quot;IMAGES_KV&quot;: &quot;aaaaaaaaaabbbbbbbbbbccccccccccdd&quot;
    }
  }
}
</code></pre>
<blockquote>
<p><strong>Safe Merge</strong>: <code>deploy:sync</code> safely preserves existing tokens and account IDs without overwriting them.</p>
</blockquote>
<hr>
<h2 id="4-real-world-release-deployment-scenarios">🚀 4. Real-World Release Deployment Scenarios</h2>
<h3 id="scenario-a-test-staging-verification-first-recommended">Scenario A. Test Staging Verification First (Recommended)</h3>
<p>Deploy the new core code to your test account first to verify Blog (Web) and Admin operations:</p>
<pre><code class="language-bash">npm run deploy:multi -- test
</code></pre>
<h3 id="scenario-b-safe-production-deployment">Scenario B. Safe Production Deployment</h3>
<p>Once verified on staging, deploy to your main live blog:</p>
<pre><code class="language-bash">npm run deploy:multi -- main
</code></pre>
<h3 id="scenario-c-batch-upgrade-across-multiple-blogs">Scenario C. Batch Upgrade Across Multiple Blogs</h3>
<p>If you operate multiple sub-blogs alongside your main blog, upgrade all registered instances at once:</p>
<pre><code class="language-bash">npm run deploy:multi -- --all
</code></pre>
<h3 id="scenario-d-selective-deployment-blog-web-or-admin-only">Scenario D. Selective Deployment (Blog Web or Admin Only)</h3>
<pre><code class="language-bash"># Deploy only Blog frontend
npm run deploy:multi -- test --blog-only

# Deploy only Admin dashboard
npm run deploy:multi -- test --admin-only
</code></pre>
<hr>
<h2 id="5-3-stage-sandbox-isolation-architecture">🛡️ 5. 3-Stage Sandbox Isolation Architecture</h2>
<p><img src="https://sveltekitblog.com/images/posts/cloudflare-pages-multi-account-deploy-guide/desktop/img-general-guide-cloudflare-pages-multi-account-deploy-guide-en-002.webp" alt="img-general-guide-cloudflare-pages-multi-account-deploy-guide-en-002"></p>
<ol>
<li><strong>Session Sandbox</strong>: Isolates <code>APPDATA</code> to an ephemeral sandbox folder, preserving your host machine&#39;s global login session.</li>
<li><strong>Atomic Config Swap</strong>: Swaps in target <code>wrangler.json</code> bindings only during active deployment and restores originals in the <code>finally</code> block 100% reliably.</li>
<li><strong>Automated Cache Purging</strong>: Purges local <code>.wrangler</code> caches immediately after execution, allowing seamless switching between native single-account commands (<code>deploy:blog</code>, <code>deploy:admin</code>) and multi-account runs.</li>
</ol>
<hr>
<h2 id="6-command-reference">📋 6. Command Reference</h2>
<table>
<thead>
<tr>
<th align="left">Purpose</th>
<th align="left">Command</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>Auto-Sync Account Configs</strong></td>
<td align="left"><code>npm run deploy:sync</code></td>
</tr>
<tr>
<td align="left"><strong>Deploy Specific Account (Blog + Admin)</strong></td>
<td align="left"><code>npm run deploy:multi -- &lt;accountKey&gt;</code></td>
</tr>
<tr>
<td align="left"><strong>Deploy Specific Account Blog Only</strong></td>
<td align="left"><code>npm run deploy:multi -- &lt;accountKey&gt; --blog-only</code></td>
</tr>
<tr>
<td align="left"><strong>Deploy Specific Account Admin Only</strong></td>
<td align="left"><code>npm run deploy:multi -- &lt;accountKey&gt; --admin-only</code></td>
</tr>
<tr>
<td align="left"><strong>Batch Upgrade All Accounts</strong></td>
<td align="left"><code>npm run deploy:multi -- --all</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="7-conclusion">💡 7. Conclusion</h2>
<p>With your custom design settings and post contents safely isolated in D1, having an automated staging-to-production deployment pipeline turns release upgrades into a worry-free, dependable experience.</p>
]]></content:encoded>
            <category>General Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/cloudflare-pages-multi-account-deploy-guide/desktop/img-general-guide-cloudflare-pages-multi-account-deploy-guide-en-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[[Devlog] SvelteKit Blog Engine v1.0.0.9 Release & Key Updates]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/devlog/devlog-release-v1009</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/devlog/devlog-release-v1009</guid>
            <pubDate>Sun, 23 Aug 2026 12:48:53 GMT</pubDate>
            <description><![CDATA[SvelteKit Blog Engine v1.0.0.9 is out! Introducing Multi-Account One-Click Cloudflare Pages Deployment, Blog Hub Integration, Full SEO Optimization for Google AdSense Approval, and i18n Polish.]]></description>
            <content:encoded><![CDATA[<h1 id="sveltekit-blog-engine-v1009-release">🚀 SvelteKit Blog Engine v1.0.0.9 Release</h1>
<p>Following the v1.0.0.8 release, v1.0.0.9 introduces <strong>Multi-Account One-Click Cloudflare Pages Smart Deployment</strong>, <strong><a href="https://hub.sveltekitblog.com/">SvelteKit Blog Hub BLOG FEED</a> Integration</strong>, <strong>Full SEO/Sitemap Optimization with Unified RSS/Sitemap Visual Styling for Google AdSense Approval</strong>, and <strong>i18n Multi-Language Dictionary Polish &amp; Deployment Sync</strong>.</p>
<hr>
<h3 id="1-multi-account-smart-auto-sync-amp-one-click-cloudflare-pages-deployment">1. 🌐 Multi-Account Smart Auto-Sync &amp; One-Click Cloudflare Pages Deployment</h3>
<ul>
<li><strong>Auto-Sync via <code>wrangler.backup.json</code> (<code>npm run deploy:sync</code>)</strong>:<ul>
<li>Simply placing downloaded backup files (<code>wrangler.backup*.json</code>) from admin into the project root and running sync automatically extracts D1 IDs, KV IDs, and project names into <code>.deploy-accounts.json</code>.</li>
<li>Existing user-defined API tokens and account IDs are 100% safely preserved (merged) without loss.</li>
</ul>
</li>
<li><strong>One-Click Multi-Account Deployment Runner (<code>npm run deploy:multi</code>)</strong>:<ul>
<li>Automatically deploys <strong>Blog + Admin (2 CFPs per account)</strong> in sequence using <code>npm run deploy:multi -- &lt;accountKey&gt;</code>.</li>
<li>Supports <code>--blog-only</code>, <code>--admin-only</code> selective flags and full batch deployment across all registered accounts (<code>--all</code>).</li>
</ul>
</li>
<li><strong>Complete Sandbox Isolation &amp; Automated Cache Purging</strong>:<ul>
<li>Protects host global Wrangler configs via isolated <code>APPDATA: .wrangler-multi-temp</code>.</li>
<li>Performs atomic in-memory <code>wrangler.json</code> swapping during deployment and restores original configs in <code>finally</code>.</li>
<li>Automatically purges local <code>.wrangler</code> and <code>node_modules/.cache/wrangler</code> caches immediately after deployment, guaranteeing zero contamination of native single-account deployments (<code>npm run deploy:admin</code>, <code>npm run deploy:blog</code>).</li>
</ul>
</li>
<li><strong>Automated D1 Schema Migration (<code>sync-secrets.js</code>)</strong>:<ul>
<li>Automatically runs safe schema migrations (such as adding the <code>is_syndicated</code> column) during deployment pipelines.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="2-sveltekit-blog-hub-feed-amp-real-time-post-integration">2. 📡 SvelteKit Blog Hub Feed &amp; Real-Time Post Integration</h3>
<ul>
<li><strong>Real-Time Hub Client Module (<code>hub.ts</code>, <code>syndication.ts</code>)</strong>:<ul>
<li>Establishes a real-time post transmission pipeline delivering published article metadata to <strong><a href="https://hub.sveltekitblog.com/">SvelteKit Blog Hub BLOG FEED</a></strong>.</li>
</ul>
</li>
<li><strong>Admin Editor Hub Integration Toggle (<code>PostMetadataForm.svelte</code>)</strong>:<ul>
<li>Added an intuitive UI toggle for hub feed delivery (<code>is_syndicated</code>) when creating or editing posts.</li>
</ul>
</li>
<li><strong>Database Schema Expansion (<code>schema-blog-db.sql</code>)</strong>:<ul>
<li>Formally added <code>is_syndicated INTEGER DEFAULT 0</code> column to the <code>posts</code> table.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="3-google-adsense-quotlow-value-contentquot-resolution-amp-seo-optimization">3. 🔍 Google AdSense &quot;Low Value Content&quot; Resolution &amp; SEO Optimization</h3>
<ul>
<li><strong>Pure Post-Centric Search Indexing</strong>:<ul>
<li>Applied <code>noindex, follow</code> to category archive pages (<code>/[category]</code>), tag archive pages (<code>/tags/[tag]</code>), and guestbook (<code>/guestbook</code>) to eliminate thin content penalties while retaining full link traversal.</li>
<li>High-value article posts and essential legal/about CMS pages (<code>about</code>, <code>privacy</code>, <code>contact</code>) remain 100% indexed (<code>index, follow</code>) and are submitted via <code>sitemap.xml</code> with priority 0.9.</li>
</ul>
</li>
<li><strong>Sitemap &amp; RSS Query Sanitization with Unified Visual Styling (<code>sitemap.xsl</code>)</strong>:<ul>
<li>Sanitized DB queries for <code>sitemap.xml</code> and <code>rss.xml</code> to exclude CMS pages and category slugs, ensuring 100% pure published article posts are submitted.</li>
<li>Optimized published CMS page priority to 0.9 with complete multilingual alternate hreflang support.</li>
<li><strong>Introduced <code>static/sitemap.xsl</code> designed to 100% match the visual aesthetic of <code>rss.xsl</code></strong>, unifying browser rendering into clean, responsive English table layouts.</li>
<li>Adjusted <code>sitemap.xml</code> cache policy to <code>public, max-age=3600</code> for guaranteed 1-hour freshness.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="4-i18n-multi-language-dictionary-polish-amp-deployment-sync">4. 🌐 i18n Multi-Language Dictionary Polish &amp; Deployment Sync</h3>
<ul>
<li><strong>Translation Accuracy &amp; Quality Polish</strong>:<ul>
<li>Refined multilingual dictionary translations to improve UI consistency and correct translation inaccuracies (e.g., Japanese locale fixes).</li>
</ul>
</li>
<li><strong>Interactive i18n DB Sync during Admin Deployment (<code>deploy:admin</code>)</strong>:<ul>
<li>Added an interactive prompt to easily synchronize local i18n dictionary updates to the D1 database (<code>ui_dictionary</code>) during admin deployment.</li>
</ul>
</li>
<li><strong>Admin UI Localization</strong>:<ul>
<li>Localized remaining hardcoded UI elements in Hub-related dialogs and settings.</li>
</ul>
</li>
</ul>
]]></content:encoded>
            <category>DevLog</category>
        </item>
        <item>
            <title><![CDATA[[Devlog] Release History Summary (v1.0.0.4 ~ v1.0.0.8)]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/devlog/devlog-releases-v1004-to-v1008</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/devlog/devlog-releases-v1004-to-v1008</guid>
            <pubDate>Sun, 23 Aug 2026 12:38:32 GMT</pubDate>
            <description><![CDATA[SvelteKit Blog Engine Release History Summary (v1.0.0.4 ~ v1.0.0.8)]]></description>
            <content:encoded><![CDATA[<h3 id="release-v1008">🚀 Release v1.0.0.8</h3>
<ul>
<li><strong>Unified Category Widget</strong>: Completely removed the legacy <code>category_link</code> option to eliminate confusion and unified all category displays under a single <strong>Category Menu</strong> widget.</li>
<li><strong>Post Count Display Option (<code>showPostCount</code>)</strong>: Added a toggle checkbox in the admin design editor to show/hide post counts next to category names (e.g., <code>Development (5)</code>).</li>
<li><strong>Admin Design Live Preview Fix</strong>: Enhanced widget previews in the design editor so that Recent Posts, Popular Posts, and Category Menus render realistic placeholders accurately.</li>
<li><strong>Smart <code>hreflang</code> Filtering (SEO)</strong>: Generates <code>hreflang</code> alternate tags <strong>only for languages that contain published posts</strong>, effectively preventing search engines (e.g., Google AdSense / Search Console) from indexing empty fallback pages as thin content.</li>
</ul>
<hr>
<h3 id="release-v1007">🚀 Release v1.0.0.7</h3>
<ul>
<li><strong>Official Engine Version System (<code>APP_VERSION</code>)</strong>: Introduced the <code>APP_VERSION</code> constant in <code>@sveltekitblog/shared</code> and displayed active engine version badges in the admin sidebar and blog footer.</li>
<li><strong>Full Multilingual Route Metadata</strong>: Completed <code>hreflang</code> alternates and canonical URL injection across all frontend routes (Home, Category, Tag, Search, Guestbook).</li>
<li><strong>Footer Mobile Readability Polish</strong>: Optimized version badge contrast and layout padding on mobile viewport widths.</li>
</ul>
<hr>
<h3 id="release-v1006">🚀 Release v1.0.0.6</h3>
<ul>
<li><strong>Mobile Core Web Vitals &amp; Performance</strong>: Improved mobile loading performance through dynamic OG image generation, Google Fonts API caching, and asset preloading.</li>
<li><strong>Sitemap 500 Fix</strong>: Removed non-existent legacy tag table queries from the <code>sitemap.xml</code> generator to guarantee uninterrupted sitemap indexing.</li>
<li><strong>Dynamic HTML <code>lang</code> Attribute</strong>: Ensured the root <code>&lt;html&gt;</code> tag dynamically reflects the correct <code>lang</code> attribute (<code>ko</code>, <code>en</code>, <code>ja</code>) based on route context.</li>
<li><strong>i18n Key Architecture</strong>: Standardized language badge translation keys under the <code>common.lang.short_*</code> namespace.</li>
</ul>
<hr>
<h3 id="release-v1005">🚀 Release v1.0.0.5</h3>
<ul>
<li><strong>Svelte 5 Runes Warning Fix</strong>: Resolved reactive state compiler warnings in admin components.</li>
<li><strong>Default Admin Entry Route Refactor</strong>: Streamlined the admin dashboard entry point and feedback flow.</li>
<li><strong>Canonical URL Normalization</strong>: Fixed trailing slash discrepancies and multilingual canonical URL mismatches.</li>
</ul>
<hr>
<h3 id="release-v1004">🚀 Release v1.0.0.4</h3>
<ul>
<li><strong>Naver Webmaster Advisor H1 Fix</strong>: Resolved duplicate <code>&lt;h1&gt;</code> tag detection by search engine bots by implementing Mobile-First SSR layout switching in <code>LayoutRenderer</code>.</li>
<li><strong>Footer Layout Alignment</strong>: Aligned blog footer width and border styles with the header for consistent shadow rendering.</li>
<li><strong>Repository Cleanup</strong>: Removed tracked temporary <code>.bak</code> files from git tracking.</li>
</ul>
]]></content:encoded>
            <category>DevLog</category>
        </item>
        <item>
            <title><![CDATA[Two Methods to Deploy Websites on Cloudflare Pages and Core Concepts]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/general-guide/cloudflare-pages-deployment-guide</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/general-guide/cloudflare-pages-deployment-guide</guid>
            <pubDate>Fri, 21 Aug 2026 23:51:07 GMT</pubDate>
            <description><![CDATA[Learn two authentication methods for deploying websites to Cloudflare Pages (interactive browser login vs. API token) and explore how D1 database, Workers KV storage, and SvelteKit Blog Engine work together seamlessly.]]></description>
            <content:encoded><![CDATA[<h1 id="two-methods-to-deploy-websites-on-cloudflare-pages-and-core-concepts">🚀 Two Methods to Deploy Websites on Cloudflare Pages and Core Concepts</h1>
<p>After building a website or blog, the next big question is: <em>&quot;How do I deploy this to the internet so people can visit?&quot;</em></p>
<p>In the past, you typically had to pay a monthly fee for a Virtual Private Server (VPS), configure an Nginx web server, and manually manage SSL certificates. Today, <strong>Cloudflare Pages (CFP)</strong> allows you to deploy web applications effortlessly with zero server management, blazing-fast global speeds, and a generous free tier.</p>
<p>This guide explains what Cloudflare Pages is, compares <strong>two deployment authentication methods (Interactive Browser Login vs. API Token)</strong>, and introduces the core concepts of <strong>D1 Database</strong> and <strong>Workers KV Storage</strong> from an architectural perspective.</p>
<hr>
<h2 id="1-what-is-cloudflare-pages-cfp">📂 1. What is Cloudflare Pages (CFP)?</h2>
<p>In simple terms, Cloudflare Pages is a platform that <strong>hosts your website across hundreds of Cloudflare data centers worldwide, serving pages to visitors from the closest server at lightning speed.</strong></p>
<p>It supports not only static assets (HTML/CSS/Images) but also full-stack frameworks like SvelteKit and Next.js that perform real-time Server-Side Rendering (SSR) and API routing.<br><img src="https://sveltekitblog.com/images/posts/cloudflare-pages-deployment-guide/desktop/img-general-guide-cloudflare-pages-deployment-guide-en-001.webp" alt="img-general-guide-cloudflare-pages-deployment-guide-en-001"></p>
<h3 id="why-choose-cloudflare-pages-over-traditional-vps">Why Choose Cloudflare Pages Over Traditional VPS?</h3>
<ul>
<li><strong>Zero Server Maintenance</strong>: No need to worry about OS security patches, Nginx config tuning, or monitoring server health. Cloudflare manages the infrastructure 24/7.</li>
<li><strong>Global Edge Performance</strong>: User requests are served from the geographically closest data center, dramatically reducing latency.</li>
<li><strong>Cost-Effective</strong>: Standard personal blogs and portfolios run comfortably within the generous Free Tier.</li>
</ul>
<hr>
<h2 id="2-two-methods-to-deploy-to-cloudflare-from-your-machine">🔑 2. Two Methods to Deploy to Cloudflare from Your Machine</h2>
<p>When running a SvelteKit build (<code>npm run build</code>), <code>@sveltejs/adapter-cloudflare</code> outputs static assets and a server execution worker (<code>_worker.js</code>) into the <strong><code>.svelte-kit/cloudflare</code></strong> directory.</p>
<p>The standard command to deploy this build output is <strong><code>npx wrangler pages deploy .svelte-kit/cloudflare</code></strong>, and there are two primary authentication workflows:</p>
<h4 id="method-1-interactive-browser-login-workflow-wrangler-default">[Method 1] Interactive Browser Login Workflow (Wrangler Default)</h4>
<p>The most intuitive method for beginners with a single account. Running the command opens a web browser to grant permissions.<br><img src="https://sveltekitblog.com/images/posts/cloudflare-pages-deployment-guide/desktop/img-general-guide-cloudflare-pages-deployment-guide-en-002.webp" alt="img-general-guide-cloudflare-pages-deployment-guide-en-002"></p>
<pre><code class="language-bash"># Build SvelteKit and deploy to Pages (interactive browser login)
npm run build
npx wrangler pages deploy .svelte-kit/cloudflare --project-name=my-blog-web --branch=production
</code></pre>
<ul>
<li><strong>How it works</strong>: When you run the deploy command, Wrangler automatically opens your default browser and prompts you to log in to Cloudflare. Once you click [Allow], the authentication session is saved to your local machine (<code>~/.config/.wrangler</code>), and deployment proceeds.</li>
<li><strong>Advantages</strong>: No need to generate API tokens manually; it works seamlessly in a few clicks for single-account personal projects.</li>
<li><strong>Limitations</strong>:<ul>
<li>Switching between multiple Cloudflare accounts requires logging out and in via the browser each time.</li>
<li>Cannot be used in headless environments or CI/CD pipelines (e.g., GitHub Actions).</li>
</ul>
</li>
</ul>
<hr>
<h4 id="method-2-non-interactive-api-token-deployment-standard-for-cicd-amp-multi-account">[Method 2] Non-Interactive API Token Deployment (Standard for CI/CD &amp; Multi-Account)</h4>
<p>The industry standard for multi-account management and automated pipelines. You supply pre-generated tokens via environment variables without browser popups.<br><img src="https://sveltekitblog.com/images/posts/cloudflare-pages-deployment-guide/desktop/img-general-guide-cloudflare-pages-deployment-guide-en-003.webp" alt="img-general-guide-cloudflare-pages-deployment-guide-en-003"></p>
<pre><code class="language-bash"># Deploy with environment variables (PowerShell example)
$env:CLOUDFLARE_API_TOKEN=&quot;YOUR_CLOUDFLARE_API_TOKEN&quot;
$env:CLOUDFLARE_ACCOUNT_ID=&quot;YOUR_ACCOUNT_ID_32_CHARS&quot;
npx wrangler pages deploy .svelte-kit/cloudflare --project-name=my-blog-web --branch=production
</code></pre>
<ul>
<li><strong>How it works</strong>: You generate an API token with required permissions (Pages, D1, KV) in the Cloudflare dashboard. Supplying this token as an environment variable allows Wrangler to authenticate in the background without opening a browser.</li>
<li><strong>Advantages</strong>:<ul>
<li>Runs quietly in the background without popups.</li>
<li>Allows sandboxed, multi-account deployments without session conflicts.</li>
</ul>
</li>
<li><strong>Prerequisite</strong>: Requires creating an API token in the Cloudflare dashboard once beforehand.</li>
</ul>
<hr>
<h2 id="3-where-are-posts-and-images-stored-understanding-d1-and-kv">💾 3. Where Are Posts and Images Stored? (Understanding D1 and KV)</h2>
<p>A dynamic blog requires more than just frontend UI; it needs reliable storage for articles, metadata, and media. Cloudflare provides two dedicated serverless storage solutions:<br><img src="https://sveltekitblog.com/images/posts/cloudflare-pages-deployment-guide/desktop/img-general-guide-cloudflare-pages-deployment-guide-en-004.webp" alt="img-general-guide-cloudflare-pages-deployment-guide-en-004"></p>
<ol>
<li><strong>Cloudflare D1 (Relational SQLite Database)</strong>:<ul>
<li>A distributed SQL database structured into clean rows and columns.</li>
<li>Stores structured data such as post titles, markdown/HTML content, published dates, categories, tags, and site settings with full SQL query capabilities.</li>
</ul>
</li>
<li><strong>Workers KV (Ultra-Fast Key-Value Storage)</strong>:<ul>
<li>A globally distributed key-value store optimized for high-read workloads.</li>
<li>Serves uploaded thumbnails and images across global edge locations with sub-millisecond response times.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="4-architecture-showcase-sveltekit-blog-engine">🧩 4. Architecture Showcase: SvelteKit Blog Engine</h2>
<p>SvelteKit Blog Engine leverages Cloudflare&#39;s serverless infrastructure with an intelligent two-tier architecture:<br><img src="https://sveltekitblog.com/images/posts/cloudflare-pages-deployment-guide/desktop/img-general-guide-cloudflare-pages-deployment-guide-en-005.webp" alt="img-general-guide-cloudflare-pages-deployment-guide-en-005"></p>
<hr>
<h3 id="why-separate-blog-and-admin-into-two-independent-pages">Why Separate Blog and Admin into Two Independent Pages?</h3>
<p>Instead of bundling the entire application into a single monolithic app, SvelteKit Blog Engine decouples it into <strong>two standalone Cloudflare Pages projects</strong>:</p>
<ol>
<li><strong>Minimized Attack Surface</strong>: Admin login logic, markdown/rich-text editors, and management API endpoints are completely absent from the public blog bundle. Running on a separate subdomain ensures strong isolation.</li>
<li><strong>Maximum Frontend Performance</strong>: The public blog bundle is extremely lightweight, containing zero admin or editor scripts. This results in blazing-fast First Contentful Paint (FCP) on mobile and desktop devices alike.</li>
</ol>
<hr>
<h3 id="data-flow">Data Flow</h3>
<ul>
<li>When you write an article and upload images in the <strong>Admin Dashboard</strong>, the data is committed to the shared <strong>D1 Database</strong> and <strong>Workers KV</strong>.</li>
<li>When a reader accesses the <strong>Public Blog</strong>, it retrieves the latest post data and images from the same D1 and KV instances to render the page instantly.</li>
</ul>
<hr>
<h2 id="5-conclusion">🚀 5. Conclusion</h2>
<p>Cloudflare Pages empowers developers to run high-performance, full-stack web applications without the burden of server maintenance or costly hosting plans.</p>
<p>For single-site projects, starting with <strong>Interactive Browser Login (<code>wrangler login</code>)</strong> is fast and straightforward. As your infrastructure grows or requires multi-account automation, transitioning to <strong>API Token Deployment</strong> provides a scalable, conflict-free workflow.</p>
]]></content:encoded>
            <category>General Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/cloudflare-pages-deployment-guide/desktop/img-general-guide-cloudflare-pages-deployment-guide-en-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[[Dev Log] 2026-07-10]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/devlog/devlog-2026-07-10</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/devlog/devlog-2026-07-10</guid>
            <pubDate>Sun, 26 Jul 2026 04:50:21 GMT</pubDate>
            <description><![CDATA[v1.0.0.2 & v1.0.0.3 Release Notes & New Theme Adjustments]]></description>
            <content:encoded><![CDATA[<h2 id="v1002-update-details">v1.0.0.2 Update Details</h2>
<p>This release includes several enhancements to improve the usability and functionality of the admin post editor.</p>
<h3 id="key-changes">🚀 Key Changes</h3>
<ol>
<li><p><strong>Added Image Link Insertion and Editing in Post Body</strong></p>
<ul>
<li>Expanded the modal UI to allow linking custom URLs and configuring &quot;Open in new tab&quot; settings when inserting or editing images in the editor.</li>
<li>Integrated HTML pre/post-processing to prevent Tiptap editor from forcibly removing image link attributes upon loading.</li>
</ul>
</li>
<li><p><strong>Visualized Semantic Image Captions in Preview Mode</strong></p>
<ul>
<li>Synchronized body text processing utilities so that semantic image captions (<code>&lt;figcaption&gt;</code>) are rendered correctly in the post preview tab.</li>
</ul>
</li>
<li><p><strong>Integrated Real-time Character Counter with Multilingual Support</strong></p>
<ul>
<li>Added a real-time character counter UI at the bottom of the post editor/edit screen.</li>
<li>Automatically strips HTML tags and Markdown syntax to count raw text characters accurately with full multilingual support.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="v1003-update-details">v1.0.0.3 Update Details</h2>
<p>This release completely resolves structural flaws in the widget system and unifies the UI list styles for widgets.</p>
<h3 id="bug-fixes">🐛 Bug Fixes</h3>
<ol>
<li><p><strong>Fixed Rendering Crash When Placing Newly Created Widgets</strong></p>
<ul>
<li>Fixed a critical crash where placing a newly created widget directly onto a layout caused rendering failure due to a missing <code>master-</code> prefix upon saving.</li>
</ul>
</li>
<li><p><strong>Fixed Data Loss of Widget <code>config</code> Across Desktop/Mobile Layouts</strong></p>
<ul>
<li>Fixed a bug where widget configuration settings (<code>config</code>) were completely omitted during layout placement, causing placed widgets to save as empty states.</li>
</ul>
</li>
<li><p><strong>Fixed <code>config</code> Reset Bug Upon Opening Widget Edit Modal</strong></p>
<ul>
<li>Fixed a bug where opening the edit modal for a placed widget triggered a <code>SyntaxError</code> by executing duplicate <code>JSON.parse</code> calls on an already parsed <code>config</code> object, resetting all modal settings (limit, shadow, etc.) to defaults.</li>
</ul>
</li>
<li><p><strong>Strengthened Input Validation for Invalid <code>limit</code> Values</strong></p>
<ul>
<li>Blocked vulnerability where invalid <code>limit</code> values (<code>NaN</code>, less than 1) could be saved during widget creation/editing, normalizing invalid inputs to the default value of <code>5</code>.</li>
</ul>
</li>
<li><p><strong>Fixed Data Query Scope Error with Multiple Widgets of the Same Type</strong></p>
<ul>
<li>Fixed a structural bug where multiple widgets of the same type (e.g., Popular Posts) queried the database using only the first widget&#39;s <code>limit</code>, truncating data for the remaining widgets. Database queries now fetch up to the maximum <code>limit</code> among identical widgets, allowing each widget to render its data independently according to its own settings.</li>
</ul>
</li>
</ol>
<h3 id="styling">🎨 Styling</h3>
<ol>
<li><strong>Unified List Divider Styles for Widgets</strong><ul>
<li>Resolved visual inconsistencies where <code>RecentPostsWidget</code> and <code>PopularPostsWidget</code> used different item divider styles. Both widgets are now unified with a <code>border-bottom</code> divider and <code>0.5rem</code> padding.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="minor-layout-amp-design-adjustments">🎨 Minor Layout &amp; Design Adjustments</h2>
<p>Refined overall style elements including blog layout and colors so that screen components blend naturally without breaking.</p>
<h3 id="key-style-adjustments">🛠️ Key Style Adjustments</h3>
<ol>
<li><p><strong>Adjusted Theme Colors and Tones</strong></p>
<ul>
<li>Set an orange secondary color as an accent point while refining background colors, card borders, and shadow values to reduce visual fatigue.</li>
</ul>
</li>
<li><p><strong>Optimized Desktop 2-Column Layout Alignment</strong></p>
<ul>
<li>Re-adjusted the width ratio between the main content area and sidebar (categories, recent/popular posts, etc.) to ensure left/right margins and content alignment match smoothly.</li>
</ul>
</li>
<li><p><strong>Aligned Header/Footer &amp; Mobile Menu Elements</strong></p>
<ul>
<li>Cleaned up top header transparency settings alongside mobile menu icon alignment and footer layout elements for a crisp presentation.</li>
</ul>
</li>
</ol>
]]></content:encoded>
            <category>DevLog</category>
        </item>
        <item>
            <title><![CDATA[[Devlog] How I Ended Up Building an Outdated Blog Engine]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/devlog/devlog-why-i-built-a-blog-engine-in-2026</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/devlog/devlog-why-i-built-a-blog-engine-in-2026</guid>
            <pubDate>Sun, 26 Jul 2026 04:50:02 GMT</pubDate>
            <description><![CDATA[Just Wanted to Earn Coffee Money, Ended Up Building a Blog Engine]]></description>
            <content:encoded><![CDATA[<p><em>Please note: This post is written in a casual, monologue style to organize my personal thoughts.</em></p><p><strong>1.</strong><br>To be honest, YouTube is largely to blame for how things turned out(?).<br>When I decided to try my hand as a solo developer later in life, I was flooded with an overwhelming amount of information.<br>The problem is that while the quantity of information is overflowing, the quality is often terrible.</p><p><strong>2.</strong><br>If it's just basic introductory stuff, a high volume of info isn't really a problem. But the moment things get slightly specialized or require a specific niche, I encounter completely useless information that leaves me wondering why it even popped up in my search results. Or worse, the title perfectly matches what I want, but the actual content is just a meaningless sequence of text generated to form valid sentences.<br>When this happens on a YouTube video, it genuinely makes me furious.</p><p><strong>3.</strong><br>Then, like finding an oasis in the desert, the rare pieces of truly valuable information almost always came from developer blog posts.<br>I felt so relieved, grateful, and inspired. And then, my focus—which makes me suspect I might have adult ADHD—led me to a sudden decision:&nbsp;<em>"Hey, maybe I should build a dev blog too, help someone out, and maybe earn enough for a cup of coffee(?)."</em></p><p><strong>4.</strong><br>So I started evaluating existing blogging platforms, but every single one of them had a dealbreaker for me.<br>First, I ruled out anything that required hosting or maintenance costs.<br>Sure, earning a little coffee money would be nice, but I know that to actually pull that off, you have to work ridiculously hard. And I know myself—I'm just not that hard-working.<br>So right from the start, my absolute baseline rule was:&nbsp;<strong>Zero setup or recurring maintenance costs.</strong><br>My initial plan was to host WordPress on a local Proxmox server.<br>To run that safely, I figured minimum security measures like an L2 switch and a firewall like pfSense were essential.<br>After setting all that up and looking at WordPress again, I realized customization was way too hard. When I realized I'd have to properly study PHP just to customize it, I abandoned that approach.</p><p><strong>5.</strong><br>I quickly looked for alternative solutions, but every option had its own catch.<br>No matter what solution I picked, having to study something completely new just to set it up felt mentally exhausting.<br>That mental fatigue eventually led me to a reckless thought:&nbsp;<em>"Screw it, I'll just build a simple one myself."</em></p><p><strong>6.</strong><br>At the time, I was already messing around quite a bit with Svelte and SvelteKit.<br>Building a basic blog was easy enough. The real issue was that I couldn't trust my own design skills.<br>So I decided to architect it in a way that made swapping designs effortless—and that rabbit hole kept rolling until it became what it is today.</p><p><strong>7.</strong><br>In reality, I spent the vast majority of my time polishing the design editor and debugging.<br>Initially, I set out to build a "simple blogging tool" and finished about 90% of the code in just one day.<br>Then I actually built a blog with it and started running it.<br>That’s when the feature creep hit:&nbsp;<em>"Oh, I need this too," "I should add this feature," "It'd be nice to have this," "This is a must-have."</em>&nbsp;It felt like an endless flood of ideas.<br>What started as a mini-project in late November last year finally wrapped up feature implementation in March this year, and only in July did I finally open-source it on GitHub.</p><p><strong>8.</strong><br>Before I knew it, the codebase had grown way too large and complex, forcing me to modularize and refactor along the way.<br>I even overhauled the system architecture multiple times.<br>Initially, the admin panel was hosted on a Proxmox server accessible only locally, while the DB and auth relied on Supabase.<br>However, after experiencing terrible cold starts and seeing the project name exposed during auth on Supabase's free plan, I pivoted to going all-in on the Cloudflare ecosystem and integrated Better-auth, which I had used before.<br>After that, I continued making major changes to the internal logic and architecture.<br>On top of that, working in a Windows environment meant that every single code tweak required a full deployment to verify, leading to an astronomical amount of trial and error.</p><p><strong>9.</strong><br>Near the finish line, the codebase became so massive that I couldn't handle modifications alone anymore, so while I wrote a lot of it, I relied heavily on Gemini for the rest.<br>Since I hadn't documented anything, I had to compare the actual running features one by one to write the docs—and whenever I spotted a bug, I went right back into fixing code.<br>From March to July, it was an endless loop of:&nbsp;<em>Documentation ➔ Bug Discovery ➔ Bug Fixing.</em><br>Meanwhile, thoughts like&nbsp;<em>"Wait, I need this feature too!"</em>&nbsp;and&nbsp;<em>"Hold on, where did that feature I built go?"</em>&nbsp;kept popping up, driving me absolutely insane.</p><p><strong>10.</strong><br>To make matters worse, Gemini frequently lost its mind.<br>Instead of fixing a single line of code, it would tear down completely unrelated modules and rewrite them. I'm convinced that if Gemini hadn't thrown so many tantrums, I would have finished at least two months earlier.<br>Anyway, right up to the GitHub release, I was under extreme stress until I finally decided to cut out all the&nbsp;<em>"I should add this"</em>&nbsp;features and just ship whatever was already working and cleaned up.<br>That became v1.0.0.0.</p><p><strong>11.</strong><br>And right after that, v1.0.0.1 was released.<br>I thought I only shipped the "cleaned up working parts," but I immediately noticed things that hadn't been cleaned up properly.<br>I'm fairly certain there are more hidden issues like this, which makes me a bit anxious. I guess I had a hunch even before uploading, which is why I prepared the&nbsp;<code>v1.0.0.x</code>&nbsp;versioning ahead of time.</p><p><strong>12.</strong><br>And that is how the SvelteKit Blog Engine came to be!<br>Ending a post is always awkward, so I'll wrap up by sharing my PageSpeed Insights score.<br>AdSense is currently pending approval, but the code script is already embedded. Also, CDN caching is set to a 2-minute TTL, so if a test runs while the cache is purged and regenerating, it might impact performance—though I'm not 100% sure of the exact cause, the scores fluctuate quite a bit.<br>Please treat these scores as a rough reference from an average run.<br>Once AdSense gets approved, I'll post an updated PageSpeed Insights report.<br>Have a great day! :)</p><figure data-align="center"><img src="https://sveltekitblog.com/images/posts/devlog-why-i-built-a-blog-engine-in-2026/desktop/img-devlog-devlog-why-i-built-a-blog-engine-in-2026-ko-001.webp" alt="img-devlog-devlog-why-i-built-a-blog-engine-in-2026-ko-001" data-align="center" data-caption="Mobile score. (Integrated with AdSense [pending approval], GA4, Google Search Console, and Naver Search Advisor)"><figcaption>Mobile score. (Integrated with AdSense [pending approval], GA4, Google Search Console, and Naver Search Advisor)</figcaption></figure><figure data-align="center"><img src="https://sveltekitblog.com/images/posts/devlog-why-i-built-a-blog-engine-in-2026/desktop/img-devlog-devlog-why-i-built-a-blog-engine-in-2026-ko-002.webp" alt="img-devlog-devlog-why-i-built-a-blog-engine-in-2026-ko-002" data-align="center" data-caption="Desktop score. (Integrated with AdSense [pending approval], GA4, Google Search Console, and Naver Search Advisor)"><figcaption>Desktop score. (Integrated with AdSense [pending approval], GA4, Google Search Console, and Naver Search Advisor)</figcaption></figure><p></p>]]></content:encoded>
            <category>DevLog</category>
            <enclosure url="https://sveltekitblog.com/images/posts/devlog-why-i-built-a-blog-engine-in-2026/desktop/img-devlog-devlog-why-i-built-a-blog-engine-in-2026-ko-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[CMD One-Click Installation & Cloudflare Deployment Guide]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/admin-guide/admin-install-and-deploy</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/admin-guide/admin-install-and-deploy</guid>
            <pubDate>Wed, 15 Jul 2026 12:19:35 GMT</pubDate>
            <description><![CDATA[Learn how to build the Cloudflare edge infrastructure and deploy/sync both admin and blog apps simultaneously using a single interactive setup script in a terminal (CMD/PowerShell) environment.]]></description>
            <content:encoded><![CDATA[<h1 id="cmd-one-click-installation-amp-cloudflare-deployment-guide">🚀 CMD One-Click Installation &amp; Cloudflare Deployment Guide</h1>
<p>This guide explains the easiest and safest way to build the Cloudflare edge infrastructure and deploy/sync both the admin and blog apps simultaneously by running a single automation command (<code>npm run setup</code>) in a terminal (CMD or PowerShell) environment.</p>
<hr>
<h2 id="1-introduction-to-one-click-deployment-automation">🛠️ 1. Introduction to One-Click Deployment Automation</h2>
<p>The SvelteKit blog engine has fully automated the complex process of server resource creation and configuration file editing through an interactive setup tool in the terminal. </p>
<p>After unpacking the blog source code or downloading it to your computer via <code>git clone</code>, open the terminal, navigate to the project root folder, and run the following commands in sequence:</p>
<pre><code class="language-bash"># Install required packages
npm install
</code></pre>
<ul>
<li><strong>Dependency Library Installation</strong>: Enter <code>npm install</code> in the terminal to install all required packages. If a security warning (vulnerabilities) message appears in the terminal after installation is complete, it is recommended to enter the <code>npm audit fix</code> command to safely apply the latest security patches.</li>
</ul>
<p>Once the package installation is complete and you run <code>npm run setup</code>, the following processes will be handled automatically according to the terminal prompts:</p>
<ul>
<li><strong>Easy Cloudflare Account Authentication</strong>: Link your deployment account with a single click.</li>
<li><strong>Create DB and Storage Resources</strong>: Automatically create 2 D1 databases dedicated to the blog and a KV store for storing images.</li>
<li><strong>Real-time Configuration File Update</strong>: Detect the unique IDs of the created databases and automatically inject them into the monorepo configuration files (<code>wrangler.json</code>).</li>
<li><strong>Database Seed Data Injection</strong>: Create tables and automatically register sample posts and basic configuration information according to the selected default language.</li>
<li><strong>Upload Secrets and Allowed IP</strong>: Automatically transmit the deployer&#39;s current public IP address (<code>ALLOWED_IP</code>) and password environment variables to the cloud for admin access.</li>
<li><strong>Integrated Build &amp; Web Service Deployment</strong>: Bundle both the blog and admin SvelteKit projects and immediately deploy them to Cloudflare Pages.</li>
</ul>
<hr>
<h2 id="2-pre-deployment-checklist">📋 2. Pre-deployment Checklist</h2>
<p>Please make sure all of the following are prepared before starting the safe installation:</p>
<ol>
<li><strong>Install Node.js</strong>: Node.js (version 22 or higher) must be working on your computer.</li>
<li><strong>Cloudflare Account</strong>: A Cloudflare account (the free tier is sufficient) is required to host the blog site and databases.</li>
<li><strong>Create Secret Environment Variable Files (.dev.vars) (Required)</strong>:<ul>
<li>Before starting deployment, you must <strong>manually create</strong> a <code>.dev.vars</code> file in each of the <code>apps/admin/</code> and <code>apps/blog/</code> folders.</li>
<li>In the <code>apps/admin/.dev.vars</code> file, write <code>ADMIN_PASSWORD=YourAdminLoginPassword</code>.</li>
<li>In the <code>apps/blog/.dev.vars</code> file, write <code>BETTER_AUTH_SECRET=ArbitraryStringOfYourChoice</code>.</li>
<li><blockquote>
<p>[!WARNING]<br>If these environment variables are not set, the <strong>installation tool will stop</strong> immediately for correct operation upon running <code>npm run setup</code>.</p>
</blockquote>
</li>
</ul>
</li>
</ol>
<hr>
<h2 id="3-step-by-step-guide-for-npm-run-setup">⚙️ 3. Step-by-Step Guide for npm run setup</h2>
<p>Open the terminal, type <code>npm run setup</code> in the blog project root directory, and press Enter.</p>
<h3 id="step-0-secrets-pre-validation"><strong>Step 0. Secrets Pre-Validation</strong></h3>
<ul>
<li>Immediately upon execution, it checks if the <code>.dev.vars</code> files and the required secret variables (<code>ADMIN_PASSWORD</code>, <code>BETTER_AUTH_SECRET</code>) are entered in the admin and blog folders.</li>
<li>If any value is missing, the guide log is displayed and the script exits, so please make sure to fill them in advance.</li>
</ul>
<h3 id="step-1-configure-deployment-project-name-domain-url"><strong>Step 1. Configure Deployment Project Name (Domain URL)</strong></h3>
<ul>
<li>This step defines the URL that readers will use to access your blog (e.g., <code>[entered-project-name].pages.dev</code>).</li>
<li>It takes two names: one for the blog and one for the admin app. If running in restore mode (<code>--restore</code>), it automatically reads the existing names from the backup configuration file (<code>wrangler.backup.json</code>).</li>
</ul>
<h3 id="step-2-cloudflare-account-authentication"><strong>Step 2. Cloudflare Account Authentication</strong></h3>
<ul>
<li>Verifies Cloudflare authentication. If you have logged in previously, it automatically detects the session and skips this step.</li>
<li>If you are not logged in, a browser window will open showing the authentication request screen. Click <strong>[Allow]</strong> to approve the account integration.</li>
<li><em>Security Information: This automation tool only requests the minimum account API permissions required for infrastructure creation and deployment, so you can proceed with confidence.</em></li>
</ul>
<h3 id="step-3-resource-creation-amp-configuration-binding"><strong>Step 3. Resource Creation &amp; Configuration Binding</strong></h3>
<ul>
<li>This step creates the database and media storage in the cloud for the actual service to run. Look at the prompts in the terminal and enter the appropriate number.<ol>
<li><strong><code>1</code> (Fresh Install)</strong>: <strong>Completely deletes</strong> previously created databases and storage and recreates them. Please note that all existing data will be lost.</li>
<li><strong><code>2</code> (Keep Existing Data) [Recommended]</strong>: If resources already exist, it safely preserves the data and only links the connection information.</li>
</ol>
</li>
<li>Upon completion, the newly issued unique DB and KV IDs are automatically updated in each configuration file (<code>wrangler.json</code>) of the monorepo.</li>
</ul>
<h3 id="step-4-pre-create-web-projects"><strong>Step 4. Pre-create Web Projects</strong></h3>
<ul>
<li>To improve deployment reliability, it pre-registers and reserves empty web projects on Cloudflare Edge.</li>
<li>If a domain with the same name is already occupied, it <strong>reuses the existing domain</strong> and automatically transitions to the next step safely.</li>
</ul>
<h3 id="step-5-remote-sync-of-secrets"><strong>Step 5. Remote Sync of Secrets</strong></h3>
<ul>
<li>Safely uploads and synchronizes the secret values, such as the master password written locally in <code>.dev.vars</code>, to Cloudflare.</li>
<li><strong>Automatic Access IP Registration</strong>: Especially in this step, it detects the public IP address of the administrator&#39;s computer running the deployment in real-time and automatically injects it as the <code>ALLOWED_IP</code> variable. This prevents the administrator from being blocked upon accessing the login screen immediately after deployment.</li>
</ul>
<h3 id="step-6-database-table-configuration-amp-default-theme-setup"><strong>Step 6. Database Table Configuration &amp; Default Theme Setup</strong></h3>
<ul>
<li>Configure the database tables needed for the blog to function and inject default settings.</li>
<li>Following the on-screen prompts, choose your primary language (Korean, English, Japanese). This sets up the translation system, sample categories, header menu structure, and a default welcome post automatically.</li>
</ul>
<h3 id="step-7-build-web-services-amp-final-deployment"><strong>Step 7. Build Web Services &amp; Final Deployment</strong></h3>
<ul>
<li>Performs the integrated build of all monorepo apps and automatically runs the deployment command to Cloudflare servers to complete the installation process. Once deployment is complete, the Pages URLs for both the blog and admin will be displayed.</li>
</ul>
<hr>
<blockquote>
<p>[!TIP]</p>
<h3 id="automatic-secret-settings-and-immediate-connection-support">💡 Automatic Secret Settings and Immediate Connection Support</h3>
<p>The installation process of this project seamlessly handles resource creation, web project provisioning, and secret environment variable transmission.<br>Upon completion, the login password and IP permission settings are perfectly configured on the remote server, so it works immediately without any additional manual configuration.</p>
</blockquote>
<hr>
<h2 id="4-blog-update-amp-data-restore-deployment-npm-run-restore">🔄 4. Blog Update &amp; Data Restore Deployment (npm run restore)</h2>
<p>When a <strong>new patch version or a bug-fixed release code is deployed</strong> while running your blog, this process allows you to safely transfer your existing post data and URLs without data loss while replacing the screen with the new code.</p>
<h3 id="4-step-migration-procedure-for-new-versions">💡 4-Step Migration Procedure for New Versions</h3>
<p>You can safely complete the upgrade without data loss by using the admin data backup and the <strong><code>npm run restore</code></strong> command.</p>
<ol>
<li><strong>[Step 1] Backup Existing Data &amp; Deployment Settings</strong>:<ul>
<li>Access the <strong><code>Backup</code></strong> menu and the backup section at the bottom of the <strong><code>Theme Editor</code></strong> menu of your active admin app, and download the post content data and theme design settings to your computer respectively.</li>
<li>Also, click the &#39;Download Settings Backup&#39; button in the <strong><code>Backup</code></strong> menu to save the [wrangler.backup.json] file to your PC. (This is the most critical file for maintaining the link to your existing production database&#39;s unique ID.)</li>
</ul>
</li>
<li><strong>[Step 2] Isolated Testing of New Code</strong>:<ul>
<li>In the newly downloaded version&#39;s code folder, run <code>npm run setup</code> and enter a <strong>temporary DB for testing</strong> and a <strong>temporary Pages deployment name for testing</strong> to deploy it separately.</li>
<li>Log in to the newly deployed test admin, and import the backup data files saved in Step 1 to verify that the data loads successfully in advance.</li>
</ul>
</li>
<li><strong>[Step 3] Restore Bindings to Existing Production Server (<code>npm run restore</code>)</strong>:<ul>
<li>Once verification is complete, copy and paste the <code>wrangler.backup.json</code> file saved in Step 1 into the root directory of the new version&#39;s project folder.</li>
<li>Run the <strong><code>npm run restore</code></strong> command in the terminal. The tool script will read the <strong>existing production DB and KV unique ID information</strong> written in the backup file and automatically connect them to the new code&#39;s configuration files via override.</li>
</ul>
</li>
<li><strong>[Step 4] Schema Synchronization &amp; Override Deployment</strong>:<ul>
<li>The restore script safely updates only the table structure schema of the existing production DB to the latest specifications, so <strong>actual posts or data already stored will not be corrupted or deleted</strong> and will be perfectly preserved.</li>
<li>Next, run <code>npm run deploy:blog</code> and <code>npm run deploy:admin</code> respectively. The latest upgraded blog system will be safely deployed, overwriting the system while keeping the same URLs you were using.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="5-backup-file-types-and-functions">📦 5. Backup File Types and Functions</h2>
<p>Refer to the table below for the roles of individual files that can be safely imported and exported from the admin backup menu.</p>
<table>
<thead>
<tr>
<th align="left">Backup Type</th>
<th align="left">Extraction Path</th>
<th align="left">Recommended Filename Example</th>
<th align="left">Detailed Feature &amp; Preserved Content</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>1. Content DB Data</strong></td>
<td align="left"><strong><code>Backup</code></strong> Menu</td>
<td align="left"><code>blog-content-backup-[date].json</code></td>
<td align="left">Preserves all written blog post content, created category information, tag lists, and basic system settings.</td>
</tr>
<tr>
<td align="left"><strong>2. Deployment Config Backup</strong></td>
<td align="left"><strong><code>Backup</code></strong> Menu</td>
<td align="left"><code>wrangler.backup.json</code></td>
<td align="left">Safely preserves the deployment name and unique UUID information required for Cloudflare D1 DB and KV storage binding (<strong>Essential for server migration</strong>).</td>
</tr>
<tr>
<td align="left"><strong>3. Media File Backup</strong></td>
<td align="left"><code>Media Backup &amp; Restore</code> section in the <strong><code>Backup</code></strong> menu<br>or <code>[Backup / Restore]</code> button in the top right of the <strong><code>Media Library</code></strong> menu</td>
<td align="left"><code>[storage-name]-images-backup-[date].zip</code> <br>(e.g., <code>r2-images-backup-[date].zip</code>)</td>
<td align="left">Downloads and preserves all image media files uploaded to the active image storage (R2, Supabase, etc.) as a ZIP file.</td>
</tr>
<tr>
<td align="left"><strong>4. Design Settings Backup</strong></td>
<td align="left">Bottom of <strong><code>Theme Editor</code></strong> menu</td>
<td align="left"><code>blog-design-backup-[date].json</code></td>
<td align="left">Preserves blog theme color information, background types, and device-specific (desktop/mobile) widget layout structures configured in the Theme Editor.</td>
</tr>
<tr>
<td align="left"><strong>5. Full System Backup</strong></td>
<td align="left">Bottom of <strong><code>Site Settings</code></strong> menu</td>
<td align="left"><code>full-system-backup-[date].json</code></td>
<td align="left">Gathers raw data of all tables from both databases (BLOG_DB, USER_DB) into a single JSON file for a complete backup and restore.</td>
</tr>
</tbody></table>
<figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-install-and-deploy/desktop/img-admin-guide-admin-install-and-deploy-en-001.webp" alt="img-admin-guide-admin-install-and-deploy-en-001" data-align="left" data-caption="Content DB Data" /><figcaption>Content DB Data</figcaption></figure>
<figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-install-and-deploy/desktop/img-admin-guide-admin-install-and-deploy-en-002.webp" alt="img-admin-guide-admin-install-and-deploy-en-002" data-align="left" data-caption="Deployment Config Backup" /><figcaption>Deployment Config Backup</figcaption></figure>
<figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-install-and-deploy/desktop/img-admin-guide-admin-install-and-deploy-en-003.webp" alt="img-admin-guide-admin-install-and-deploy-en-003" data-align="left" data-caption="Media File Backup" /><figcaption>Media File Backup</figcaption></figure>
<figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-install-and-deploy/desktop/img-admin-guide-admin-install-and-deploy-en-004.webp" alt="img-admin-guide-admin-install-and-deploy-en-004" data-align="left" data-caption="Design Settings Backup" /><figcaption>Design Settings Backup</figcaption></figure>
<figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-install-and-deploy/desktop/img-admin-guide-admin-install-and-deploy-en-005.webp" alt="img-admin-guide-admin-install-and-deploy-en-005" data-align="left" data-caption="Full System Backup" /><figcaption>Full System Backup</figcaption></figure>]]></content:encoded>
            <category>Admin Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/admin-install-and-deploy/desktop/img-admin-guide-admin-install-and-deploy-en-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[First Access to Admin & Getting Started with Configurations]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/admin-guide/admin-getting-started</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/admin-guide/admin-getting-started</guid>
            <pubDate>Wed, 15 Jul 2026 12:19:26 GMT</pubDate>
            <description><![CDATA[Learn how to safely access the admin app, maintain login sessions, and utilize the multilingual UI dictionary to manage the blog system.]]></description>
            <content:encoded><![CDATA[<h1 id="first-access-to-admin-amp-getting-started-with-configurations">🔑 First Access to Admin &amp; Getting Started with Configurations</h1>
<p>This document guides administrators on how to safely access the admin page, maintain login sessions, and easily manage various site-wide text strings (multilingual dictionary) to control the blog system.</p>
<hr>
<h2 id="1-ip-security-control-policy-before-admin-login">🔒 1. IP Security Control Policy before Admin Login</h2>
<p>This blog engine adheres to a strict <strong>Access IP Filtering</strong> security policy to completely prevent unauthorized external access or hijacking of posting permissions. Only the administrator&#39;s public IP address detected at the time of deployment is registered in the server&#39;s allowlist (<code>ALLOWED_IP</code>) to permit access.</p>
<blockquote>
<p>[!IMPORTANT]</p>
<h3 id="safe-zone-centered-operation-principle-no-use-in-public-places">🛡️ Safe-Zone Centered Operation Principle (No Use in Public Places)</h3>
<p>Admin management of this blog must be performed only in <strong>places where physical and network security are secured, such as home or a trusted private office.</strong><br><strong>To prevent security leaks, accessing the admin page is strictly discouraged and should be avoided in public places such as PC cafes (PC bangs), libraries, or under public Wi-Fi networks, as they are exposed to high security risks.</strong></p>
</blockquote>
<p>If you encounter a <code>403 Forbidden</code> block screen because your public IP address changed due to router rebooting or network conditions within your safe zone, you must manually update the allowlist according to the following procedure.</p>
<h3 id="allowed-ip-list-renewal-procedure-redeployment-required">⚙️ Allowed IP List Renewal Procedure (Redeployment Required)</h3>
<ol>
<li>Open the terminal under the changed internet environment, and run the command to <strong>redeploy</strong> the blog service admin app once again.</li>
<li><strong>Workflow Guide</strong>: While this is safer than forcedly editing the database internals (which is a risky operation), it is a somewhat tedious and inconvenient process because it requires the build process and file upload waiting time of several minutes each time.</li>
<li>While the deployment script is running, it detects the new public IP address of your currently connected computer and replaces the remote server&#39;s allowed IP list with the latest one.</li>
<li>Once the deployment process is finalized, reconnecting to the admin URL will re-enable the normal login screen.</li>
<li>You only need to redeploy the admin page.</li>
</ol>
<hr>
<h2 id="2-admin-login-amp-session-management">🔑 2. Admin Login &amp; Session Management</h2>
<p>Once the login block is normal, enter the master password (<code>ADMIN_PASSWORD</code>) configured during setup to log in.</p>
<ul>
<li><strong>Secure Session Maintenance</strong>: By utilizing dedicated secure cookies, the admin login session remains safely maintained for 30 days.</li>
<li><strong>Prohibition of Access from Public Computers and Risky Areas</strong>:<br>The most secure practice is to never attempt logging in to the admin console on unverified public computers or PC cafes. If you must log in under public conditions, make sure to click the <strong>[Logout]</strong> button at the bottom left of the admin page immediately after completing work, and also enter <code>npx wrangler logout</code> in your terminal to completely sign out from the Cloudflare management credentials on that computer to prevent any credential leaks.</li>
</ul>
<blockquote>
<p>[!WARNING]</p>
<h3 id="minimize-exposure-of-admin-access-address-domain">🔒 Minimize Exposure of Admin Access Address (Domain)</h3>
<p>While the admin console is double-protected by the IP allowlist, minimizing the attack surface itself is the most robust security practice.</p>
<p>Therefore, we strongly recommend that you do not bind an obvious custom domain like <code>admin.myblog.com</code>, but instead use the randomized subdomain URL (e.g., <code>[project-name].pages.dev</code>) provided default by Cloudflare Pages to keep the admin entry hidden.</p>
</blockquote>
<hr>
<h2 id="3-multilingual-dictionary-i18n-settings-guide">🌐 3. Multilingual Dictionary (i18n) Settings Guide</h2>
<p>Fixed common UI text strings (menu labels, comment buttons, login prompts, etc.) outside of post contents can be modified instantly in English, Korean, or Japanese using the admin dictionary editor without editing a single line of source code.<br><figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-getting-started/desktop/img-admin-guide-admin-getting-started-en-002.webp" alt="img-admin-guide-admin-getting-started-en-002" data-align="left" /></figure></p>
<p>You can register a new language by using the <strong><code>Add Language</code></strong> feature. However, for the newly added language to display correctly on the site, you must translate all existing dictionary keys into that language.<br><figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-getting-started/desktop/img-admin-guide-admin-getting-started-en-001.webp" alt="img-admin-guide-admin-getting-started-en-001" data-align="left" /></figure></p>
<ol>
<li>Go to the <strong><code>Languages</code></strong> menu on the left sidebar of the admin console.</li>
<li>A list of all dictionary keys and their saved translations used across the site is provided in the <strong><code>UI Dictionary Editor</code></strong> section at the bottom.</li>
<li>Enter your desired text (Korean, English, Japanese) directly into the input field for the key you wish to modify, and click the <strong><code>Save</code></strong> icon on the far right of that row.</li>
<li>Changes apply to the live site immediately upon saving. When visitors switch languages on the blog, the modified texts will be displayed seamlessly in real-time.</li>
</ol>
]]></content:encoded>
            <category>Admin Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/admin-getting-started/desktop/img-admin-guide-admin-getting-started-en-002.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Admin Core Features and Dual Editor Overview]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/admin-guide/admin-core-features</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/admin-guide/admin-core-features</guid>
            <pubDate>Wed, 15 Jul 2026 12:19:17 GMT</pubDate>
            <description><![CDATA[A brief introduction to core admin features including multi-language simultaneous saving, visual and markdown dual editor switching, and device-specific widget placement.]]></description>
            <content:encoded><![CDATA[<h1 id="admin-core-features-and-dual-editor-overview">🎨 Admin Core Features and Dual Editor Overview</h1>
<p>This document provides a brief overview of the core features in the admin console, including multi-language simultaneous publishing, device-specific layout configuration, and real-time design theme settings.</p>
<hr>
<h2 id="1-multi-language-writing-and-dual-editor-support">📝 1. Multi-Language Writing and Dual Editor Support</h2>
<p>When entering the writing menu, a multi-language editor layout is provided, with multiple language tabs arranged side-by-side on a single screen.</p>
<h3 id="batch-multi-language-writing-and-saving">① Batch Multi-Language Writing and Saving</h3>
<ul>
<li><strong>Writing Flow</strong>: Switch between the language tabs (KO, EN, JA, etc.) at the top to write titles, excerpts, slugs (URL paths), and body content for each language.</li>
<li><strong>Batch Saving</strong>: Click the <strong>[Save All Tabs Simultaneously]</strong> button at the bottom to save the content of all languages to the database at once. Languages not explicitly set to <strong>Publish</strong> will be saved as <strong>Drafts</strong>, and any empty language tabs will be skipped.</li>
</ul>
<h3 id="dual-editor-support-visual-vs-markdown">② Dual Editor Support (Visual vs. Markdown)</h3>
<ul>
<li><strong>Visual HTML Editor (Visual)</strong>: A rich-text editor that allows direct formatting and media embedding. Image files can be easily uploaded and inserted via the toolbar button.</li>
</ul>
<figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-core-features/desktop/img-admin-guide-admin-core-features-en-002.webp" alt="img-admin-guide-admin-core-features-en-002" data-align="left" /></figure><ul>
<li><strong>Markdown Editor (Markdown)</strong>: Provided for users who prefer markdown syntax. Metadata such as titles, excerpts, categories, and tags are automatically managed in the header using YAML Front Matter (<code>---</code>). Both markdown source and parsed HTML are stored in the database upon saving.</li>
</ul>
<figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-core-features/desktop/img-admin-guide-admin-core-features-en-003.webp" alt="img-admin-guide-admin-core-features-en-003" data-align="left" /></figure><h3 id="automatic-thumbnail-selection">③ Automatic Thumbnail Selection</h3>
<ul>
<li>If no thumbnail image is manually specified, the system automatically analyzes the content to assign a representative image:<ul>
<li><strong>1st Priority</strong>: The first image element found in the body text.</li>
<li><strong>2nd Priority</strong>: If no images are present but a YouTube video link or iframe embed is found, the official high-resolution YouTube thumbnail URL of the video is used.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="2-device-specific-desktopmobile-independent-widget-placement">🧱 2. Device-Specific (Desktop/Mobile) Independent Widget Placement</h2>
<p>The layout editor supports drag-and-drop widget arrangement for sidebars and content areas, allowing you to configure independent widget exposure based on whether visitors are on desktop or mobile devices.<br><figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-core-features/desktop/img-admin-guide-admin-core-features-en-001.webp" alt="img-admin-guide-admin-core-features-en-001" data-align="left" data-caption="Desktop/Mobile Mode Selection Icons" /><figcaption>Desktop/Mobile Mode Selection Icons</figcaption></figure></p>
<h3 id="device-exposure-options">⚙️ Device Exposure Options</h3>
<ol>
<li>Choose the column layout and width ratio in the <strong><code>Blog Structure</code></strong> tab under the <strong><code>Design Editor</code></strong> menu.</li>
<li>Assign device exposure conditions (Device) when adding or modifying widgets:<ul>
<li><strong>Desktop</strong>: Displays the widget only on wider PC screens, preventing unnecessary resource loads on mobile devices.</li>
<li><strong>Mobile</strong>: Hides the widget on PC screens and limits visibility to mobile viewport resolutions.</li>
</ul>
</li>
<li><strong>Effect</strong>: Skipping heavy or redundant widget rendering for mobile visitors optimizes page load times and mobile scrolling performance.</li>
</ol>
<hr>
<h2 id="3-real-time-design-editor-and-theme-settings">🎨 3. Real-Time Design Editor and Theme Settings</h2>
<p>Design theme changes and background configurations apply instantly via CSS variables in the visitor&#39;s browser without requiring server rebuilds or redeployments.</p>
<ul>
<li><strong>4 Background Types</strong>: Select from Solid color, Gradient, Background Image, or interactive HTML5 Canvas animations (Canvas).</li>
<li><strong>Glassmorphism Effect</strong>: When using background images, adjust opacity and blur to ensure text readability with glassmorphism overlays.</li>
<li><strong>Interactive Canvas</strong>: Renders motion artwork (snowflakes, waves, constellations) inside a sandboxed canvas.</li>
</ul>
<blockquote>
<p>[!TIP]<br>Information on background configuration options and script templates can be found in the <strong><a href="./admin-design-editor.md">Design Editor Settings Introduction</a></strong> document.</p>
</blockquote>
<hr>
<h2 id="4-media-storage-support">💾 4. Media Storage Support</h2>
<p>You can switch the active cloud storage provider for uploading and serving media based on your needs.<br><figure data-align="left"><img src="https://sveltekitblog.com/images/posts/admin-core-features/desktop/img-admin-guide-admin-core-features-en-004.webp" alt="img-admin-guide-admin-core-features-en-004" data-align="left" /></figure></p>
<ol>
<li>Navigate to the <strong><code>Storage Settings</code></strong> area at the bottom of the <strong><code>Media Library</code></strong> menu.</li>
<li>Select your storage provider and configure the credentials:<ul>
<li><strong>Cloudflare KV</strong>: Stores assets in edge KV storage for fast global delivery.</li>
<li><strong>Cloudflare R2</strong>: Cost-effective large object storage for managing mass images.</li>
<li><strong>Supabase Storage</strong>: Securely uploads and stores media assets in Supabase storage buckets.</li>
<li><strong>ImageKit.io</strong>: Connects global image CDN platforms for real-time optimization and compressed formatting.</li>
</ul>
</li>
<li><strong>Real-time Switch</strong>: Saving changes instantly shifts the active upload engine to the chosen storage provider.</li>
</ol>
<blockquote>
<p>[!NOTE]<br><strong>Limitations of default storage (Cloudflare KV) in media explorer</strong><br>Cloudflare KV does not support directory listing (read APIs) in the image explorer to minimize Workers usage and costs. Other external storages, such as Cloudflare R2, Supabase Storage, and ImageKit.io, fully support listing and previewing uploaded images.</p>
</blockquote>
]]></content:encoded>
            <category>Admin Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/admin-core-features/desktop/img-admin-guide-admin-core-features-en-002.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Real-Time Design Editor and Background Customization Overview]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/admin-guide/admin-design-editor</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/admin-guide/admin-design-editor</guid>
            <pubDate>Wed, 15 Jul 2026 12:19:07 GMT</pubDate>
            <description><![CDATA[Instant real-time theme updates without rebuilds or redeployments.]]></description>
            <content:encoded><![CDATA[<h1 id="real-time-design-editor-and-background-customization-overview">🎨 Real-Time Design Editor and Background Customization Overview</h1>
<p>This document introduces the system that applies theme configurations in real time without requiring server rebuilds or redeployments, and outlines the 4 background settings: Solid, Gradient, Background Image, and Custom JavaScript Canvas.</p>
<hr>
<h2 id="1-real-time-design-editor-overview">🌌 1. Real-Time Design Editor Overview</h2>
<p>When you modify and save configuration values in the design editor, there is no need to rebuild or redeploy the blog server or CDN services. The database updates instantly, and the <strong>CSS variables and background rendering module reflect in the visitor&#39;s browser within seconds</strong>.<br>Before applying the design to the live blog, you can check the style changes through the preview screen inside the admin panel.</p>
<blockquote>
<p>[!WARNING]</p>
<h3 id="notice-differences-between-admin-preview-and-live-blog-design">⚠️ Notice: Differences Between Admin Preview and Live Blog Design</h3>
<p>The <strong>preview feature in the design editor does not guarantee a 100% identical environment</strong> to the live visitor page. Microscopic rendering differences (such as CSS variable evaluation or JavaScript Canvas rendering conditions) may occur between the admin preview and the actual blog.</p>
<p>Therefore, after changing any design configuration, we <strong>strongly recommend visiting your live blog directly and refreshing the page (F5)</strong> to verify the final rendering output.</p>
</blockquote>
<hr>
<h3 id="layout-amp-theme-configuration-settings">🧱 Layout &amp; Theme Configuration Settings</h3>
<h4 id="layout-customization">① Layout Customization</h4>
<ul>
<li><strong>Blog Structure</strong>: Select the base layout structure of the main page (e.g., 2-column, 3-column, etc.).</li>
<li><strong>Column Width Ratios</strong>: Fine-tune the width ratios of the main content column and sidebars (e.g., 1:2:1, 2:1:2, etc.).</li>
<li><strong>Maximum Width</strong>: Limit the maximum horizontal resolution of the entire layout container (e.g., 1200px, 1400px, etc.).</li>
<li><strong>Detailed Layout Values</strong>: Control the container side margins, card border radius, and box shadow depth effects.</li>
</ul>
<h4 id="basic-theme-colors">② Basic Theme Colors</h4>
<ul>
<li>Customize the Primary theme color, Secondary color, body Text color, Accent highlight color, Card Background (Card Bg), and Border colors.</li>
</ul>
<h4 id="typography-settings">③ Typography Settings</h4>
<ul>
<li>Apply web fonts by entering font family names from the Google Fonts directory, and set the base font size.</li>
</ul>
<h4 id="widget-arrangement-management">④ Widget Arrangement Management</h4>
<ul>
<li>Drag and drop available widgets to position them in different columns and arrange their render orders.</li>
</ul>
<hr>
<h2 id="2-device-specific-independent-widget-placement">🧱 2. Device-Specific Independent Widget Placement</h2>
<p>Configure widget positioning in the sidebar and content areas using drag-and-drop. You can customize layouts differently based on the visitor&#39;s screen size.</p>
<ul>
<li><strong>Desktop</strong>: Displays selected widgets (e.g., tag clouds, category trees) only on wider screens. For mobile access, elements are omitted at the HTML transmission stage to maintain fast loading times.</li>
<li><strong>Mobile</strong>: Hides the widget on desktop viewports and restricts exposure exclusively to smartphone-sized mobile resolutions.</li>
</ul>
<hr>
<h2 id="3-4-background-customization-options">🌈 3. 4 Background Customization Options</h2>
<p>Customize the sensory atmosphere of the blog using four supported background types:</p>
<h3 id="solid-solid-background">① Solid (Solid Background)</h3>
<ul>
<li>Choose a HEX code (e.g., <code>#3b82f6</code>) or HSL color code to create a clean, distraction-free screen that helps readers focus on the post content.</li>
</ul>
<h3 id="gradient-gradient-background">② Gradient (Gradient Background)</h3>
<ul>
<li>Create linear gradients where multiple colors blend smoothly using the <strong>Gradient Builder</strong> tool.</li>
<li>Adjust the gradient angle (Direction) slider and add or slide color stops to customize starting, intermediate, and ending colors.</li>
</ul>
<h3 id="image-background-image-amp-glassmorphism">③ Image (Background Image &amp; Glassmorphism)</h3>
<ul>
<li>Specify a remote image URL or use the upload button to add media assets to your library.</li>
<li><strong>Upload Optimization</strong>: Uploaded images are automatically converted to WebP format to prevent initial page load delays.</li>
<li><strong>Glassmorphism Overlay</strong>: Adjust the controls below to build a glassmorphism aesthetic that ensures text readability over background images.</li>
</ul>
<table>
<thead>
<tr>
<th align="left">Setting</th>
<th align="center">Recommended Range</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>Glass Blur</strong></td>
<td align="center"><code>5px ~ 15px</code></td>
<td align="left">Applies a translucent frosted-glass blur filter below the content cards.</td>
</tr>
<tr>
<td align="left"><strong>Overlay Opacity</strong></td>
<td align="center"><code>10% ~ 30%</code></td>
<td align="left">Controls the opacity of the mask overlaid behind the card container.</td>
</tr>
<tr>
<td align="left"><strong>Overlay Color</strong></td>
<td align="center"><code>#000000</code> or <code>#ffffff</code></td>
<td align="left">Selects dark or light mask colors to maintain text contrast.</td>
</tr>
</tbody></table>
<h3 id="custom-javascript-custom-javascript-amp-canvas-background">④ Custom JavaScript (Custom JavaScript &amp; Canvas Background)</h3>
<ul>
<li>Supports custom JavaScript execution to render interactive Canvas animations on the client&#39;s browser background.</li>
<li>Provides direct rendering control over the background canvas element (<code>canvas id=&quot;bg-canvas&quot;</code>). Detailed security restrictions and power-saving policies are explained in <strong>[4. Custom JavaScript Integration Specifications]</strong> below.</li>
</ul>
<hr>
<h2 id="4-custom-javascript-integration-specifications">⚡ 4. Custom JavaScript Integration Specifications</h2>
<p>To prevent security risks and conserve mobile battery life, the following sandbox environment and battery-saving systems are applied.<br><figure data-align="center"><img src="https://sveltekitblog.com/images/posts/admin-design-editor/desktop/img-admin-guide-admin-design-editor-en-001.webp" alt="img-admin-guide-admin-design-editor-en-001" data-align="center" data-caption="Custom JS Canvas animation input window with security sandbox (Before activation)" /><figcaption>Custom JS Canvas animation input window with security sandbox (Before activation)</figcaption></figure><br><figure data-align="center"><img src="https://sveltekitblog.com/images/posts/admin-design-editor/desktop/img-admin-guide-admin-design-editor-en-002.webp" alt="img-admin-guide-admin-design-editor-en-002" data-align="center" data-caption="Custom JS Canvas animation input window with security sandbox (After activation)" /><figcaption>Custom JS Canvas animation input window with security sandbox (After activation)</figcaption></figure></p>
<h3 id="security-sandbox-and-csp">🔒 Security Sandbox and CSP</h3>
<p>The following security measures protect against malicious script injections:</p>
<ol>
<li><strong>Isolated Sandbox Structure</strong>: Canvas code runs inside an isolated <code>iframe</code> with limited execution privileges. Access to the parent page DOM, session cookies, or login credentials is blocked.</li>
<li><strong>Content Security Policy (CSP)</strong>: Outbound network calls and external script injections are completely blocked. Sensitive data cannot be leaked to external servers.</li>
<li><strong>JS API Restrictions</strong>: Disallowed APIs, including <code>fetch</code>, <code>XMLHttpRequest</code>, <code>WebSocket</code>, <code>eval</code>, <code>new Function</code>, <code>document.cookie</code>, and <code>localStorage</code>, are intercepted and commented out (<code>/* f_e_t_c_h (blocked) */</code>) by the validator script (<code>jsValidator.ts</code>).</li>
</ol>
<h3 id="power-and-performance-optimization">🔋 Power and Performance Optimization</h3>
<ul>
<li><strong>Out-of-View Auto-Pause</strong>: If a visitor scrolls and the background animation leaves the viewport, the render loop <strong>enters sleep mode</strong> to conserve CPU and GPU cycles. The animation resumes instantly when scrolled back into view.</li>
<li><strong>Mobile Frame Throttling</strong>: Background scripts are paused on mobile devices by default to prevent device overheating. Enabling the <strong>&quot;Run animation on mobile devices&quot;</strong> option scales down particle counts automatically to match mobile processing thresholds.</li>
</ul>
<hr>
<h2 id="5-sample-background-script-code-3-types">📝 5. Sample Background Script Code (3 Types)</h2>
<p>Choose <strong>[Custom JavaScript]</strong> in the background settings and copy one of the templates below into the code editor.</p>
<blockquote>
<p>[!NOTE]<br>Scripts must acquire the target canvas context using <code>document.getElementById(&#39;bg-canvas&#39;)</code>.</p>
</blockquote>
<h3 id="sample-a-winter-snowfall-snowfall">❄️ Sample A. Winter Snowfall (Snowfall)</h3>
<p>A background animation where snowflakes drift slowly down the screen.</p>
<pre><code class="language-javascript">(function() {
  const canvas = document.getElementById(&#39;bg-canvas&#39;);
  if (!canvas) return;
  const ctx = canvas.getContext(&#39;2d&#39;);
  
  let width = canvas.width = window.innerWidth;
  let height = canvas.height = window.innerHeight;
  
  // Mobile throttle detection
  const divisor = (window.bgConfig &amp;&amp; window.bgConfig.mobileThrottleDivisor) || 1;
  const maxSnowflakes = Math.floor(100 / divisor);
  const snowflakes = [];
  
  class Snowflake {
    constructor() {
      this.reset();
      this.y = Math.random() * height; // Initial random altitude
    }
    
    reset() {
      this.x = Math.random() * width;
      this.y = -10;
      this.radius = Math.random() * 3 + 1;
      this.speed = Math.random() * 1 + 0.5;
      this.opacity = Math.random() * 0.6 + 0.2;
    }
    
    update() {
      this.y += this.speed;
      // Gentle swaying motion
      this.x += Math.sin(this.y / 30) * 0.5;
      
      if (this.y &gt; height || this.x &lt; 0 || this.x &gt; width) {
        this.reset();
      }
    }
    
    draw() {
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(25, 25, 255, ${this.opacity})`;
      ctx.fill();
    }
  }
  
  // Particle instantiation
  for (let i = 0; i &lt; maxSnowflakes; i++) {
    snowflakes.push(new Snowflake());
  }
  
  function animate() {
    ctx.clearRect(0, 0, width, height);
    
    for (let i = 0; i &lt; snowflakes.length; i++) {
      snowflakes[i].update();
      snowflakes[i].draw();
    }
    requestAnimationFrame(animate);
  }
  
  // Resize handler
  window.addEventListener(&#39;resize&#39;, () =&gt; {
    width = canvas.width = window.innerWidth;
    height = canvas.height = window.innerHeight;
  });
  
  animate();
})();
</code></pre>
<hr>
<h3 id="sample-b-constellation-network">🕸️ Sample B. Constellation Network</h3>
<p>An IT-inspired constellation pattern where floating node particles link with thin translucent lines when they drift close to one another.</p>
<pre><code class="language-javascript">(function() {
  const canvas = document.getElementById(&#39;bg-canvas&#39;);
  if (!canvas) return;
  const ctx = canvas.getContext(&#39;2d&#39;);
  
  let width = canvas.width = window.innerWidth;
  let height = canvas.height = window.innerHeight;
  
  const divisor = (window.bgConfig &amp;&amp; window.bgConfig.mobileThrottleDivisor) || 1;
  const particleCount = Math.floor(80 / divisor);
  const particles = [];
  const connectionDistance = 100;
  
  class Particle {
    constructor() {
      this.x = Math.random() * width;
      this.y = Math.random() * height;
      this.vx = (Math.random() - 0.5) * 0.8;
      this.vy = (Math.random() - 0.5) * 0.8;
      this.radius = Math.random() * 2 + 1.5;
    }
    
    update() {
      this.x += this.vx;
      this.y += this.vy;
      
      // Boundary collision
      if (this.x &lt; 0 || this.x &gt; width) this.vx *= -1;
      if (this.y &lt; 0 || this.y &gt; height) this.vy *= -1;
    }
    
    draw() {
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
      ctx.fillStyle = &#39;rgba(99, 102, 241, 0.4)&#39;; // Pastel indigo
      ctx.fill();
    }
  }
  
  for (let i = 0; i &lt; particleCount; i++) {
    particles.push(new Particle());
  }
  
  function drawLines() {
    for (let i = 0; i &lt; particles.length; i++) {
      for (let j = i + 1; j &lt; particles.length; j++) {
        const dx = particles[i].x - particles[j].x;
        const dy = particles[i].y - particles[j].y;
        const dist = Math.sqrt(dx * dx + dy * dy);
        
        if (dist &lt; connectionDistance) {
          const alpha = (connectionDistance - dist) / connectionDistance * 0.18;
          ctx.beginPath();
          ctx.moveTo(particles[i].x, particles[i].y);
          ctx.lineTo(particles[j].x, particles[j].y);
          ctx.strokeStyle = `rgba(99, 102, 241, ${alpha})`;
          ctx.lineWidth = 1;
          ctx.stroke();
        }
      }
    }
  }
  
  function animate() {
    ctx.clearRect(0, 0, width, height);
    for (let i = 0; i &lt; particles.length; i++) {
      particles[i].update();
      particles[i].draw();
    }
    drawLines();
    requestAnimationFrame(animate);
  }
  
  window.addEventListener(&#39;resize&#39;, () =&gt; {
    width = canvas.width = window.innerWidth;
    height = canvas.height = window.innerHeight;
  });
  
  animate();
})();
</code></pre>
<hr>
<h3 id="sample-c-fluid-sine-waves">🌊 Sample C. Fluid Sine Waves</h3>
<p>A relaxing animation showing multiple overlapping pastel wave ripples flowing smoothly near the bottom of the screen.</p>
<pre><code class="language-javascript">(function() {
  const canvas = document.getElementById(&#39;bg-canvas&#39;);
  if (!canvas) return;
  const ctx = canvas.getContext(&#39;2d&#39;);
  
  let width = canvas.width = window.innerWidth;
  let height = canvas.height = window.innerHeight;
  
  let wave1 = {
    y: height * 0.85,
    length: 0.005,
    amplitude: 25,
    frequency: 0.012
  };
  
  let wave2 = {
    y: height * 0.88,
    length: 0.008,
    amplitude: 15,
    frequency: 0.022
  };
  
  let increment = 0;
  
  function animate() {
    ctx.clearRect(0, 0, width, height);
    
    // Draw background wave (translucent teal)
    ctx.beginPath();
    ctx.moveTo(0, height);
    for (let i = 0; i &lt; width; i++) {
      ctx.lineTo(i, wave1.y + Math.sin(i * wave1.length + increment) * wave1.amplitude);
    }
    ctx.lineTo(width, height);
    ctx.fillStyle = &#39;rgba(45, 212, 191, 0.1)&#39;;
    ctx.fill();
    
    // Draw foreground wave (translucent sky-blue)
    ctx.beginPath();
    ctx.moveTo(0, height);
    for (let i = 0; i &lt; width; i++) {
      ctx.lineTo(i, wave2.y + Math.sin(i * wave2.length - increment * 1.5) * wave2.amplitude);
    }
    ctx.lineTo(width, height);
    ctx.fillStyle = &#39;rgba(56, 189, 248, 0.15)&#39;;
    ctx.fill();
    
    // Adjust speed according to device configuration
    const speedFactor = (window.bgConfig &amp;&amp; window.bgConfig.mobileThrottleDivisor) ? 0.3 : 1;
    increment += wave1.frequency * speedFactor;
    
    requestAnimationFrame(animate);
  }
  
  window.addEventListener(&#39;resize&#39;, () =&gt; {
    width = canvas.width = window.innerWidth;
    height = canvas.height = window.innerHeight;
    wave1.y = height * 0.85;
    wave2.y = height * 0.88;
  });
  
  animate();
})();
</code></pre>
<hr>
<h2 id="6-device-specific-mobile-background-configuration">📱 6. Device-Specific Mobile Background Configuration</h2>
<p>Customize your background settings depending on the user environment to optimize system performance.</p>
<ol>
<li><strong>Desktop Background</strong>: Choose <strong>Custom JavaScript</strong> on PC displays to run beautiful canvas animations.</li>
<li><strong>Enable Independent Mobile Settings</strong>: Check the <strong>&quot;Use different background for mobile devices&quot;</strong> toggle located at the bottom of the design editor.</li>
<li><strong>Mobile Optimization</strong>: Under the separate mobile configuration panel, select <strong>Solid</strong> or <strong>Gradient</strong> backgrounds to minimize processor workloads.</li>
<li><strong>Outcome</strong>: Conserves mobile batteries by running lightweight background styles on smartphones, while maintaining visually rich interactive motion rendering for desktop browsers.</li>
</ol>
]]></content:encoded>
            <category>Admin Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/admin-design-editor/desktop/img-admin-guide-admin-design-editor-en-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Admin Frequently Asked Questions (FAQ) and Troubleshooting]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/admin-guide/admin-faq</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/admin-guide/admin-faq</guid>
            <pubDate>Wed, 15 Jul 2026 12:18:57 GMT</pubDate>
            <description><![CDATA[Resolve installation and deployment errors, upgrade to the latest version, check mandatory image storage keys, and solve IP security blockages.]]></description>
            <content:encoded><![CDATA[<img src="https://sveltekitblog.com/images/posts/admin-faq/desktop/img-admin-guide-admin-faq-ko-001.webp" alt="img-admin-guide-admin-faq-ko-001" data-align="center"><h1 id="admin-frequently-asked-questions-faq-and-troubleshooting">❓ Admin Frequently Asked Questions (FAQ) and Troubleshooting</h1>
<p>This document provides solutions to common troubleshooting issues that may arise during the installation, deployment, and operation of the blog, as well as a guide to safely upgrading to the latest version.</p>
<hr>
<h2 id="q1-how-do-i-safely-upgrade-to-the-latest-version-or-restore-my-data">🗄️ Q1. How do I safely upgrade to the latest version or restore my data?</h2>
<p>To preserve database integrity and prevent unexpected build crashes, we strongly recommend following the safe upgrade procedures below.</p>
<h3 id="1-safe-upgrade-and-verification-procedure-recommended">1. Safe Upgrade and Verification Procedure (Recommended)</h3>
<p>To prevent database schema mismatches or template conflicts, do not deploy immediately to your production server. Instead, perform verification in a test environment first (applicable to non-Git users as well).</p>
<ol>
<li><strong>Preserve Settings Backup</strong>:<ul>
<li>Copy <code>wrangler.backup.json</code> and <code>.dev.vars</code> from your current development folder to a safe temporary location.</li>
<li><em>※ Note: The <code>.dev.vars</code> file contains critical credentials (passwords, OAuth keys, etc.) but is excluded from Git tracking (<code>.gitignore</code>) for security. Therefore, it is easily lost when updating or pulling source code. Be sure to back it up.</em></li>
</ul>
</li>
<li><strong>Back Up Production Data</strong>:<ul>
<li>Go to the <code>Content Backup</code> menu in your active blog admin panel and download the complete posts and settings backup file.</li>
</ul>
</li>
<li><strong>Clone/Download the New Version in an Isolated Folder</strong>:<ul>
<li>Do not overwrite the existing folder. Download or clone the latest release source code in an <strong>entirely new directory</strong>.</li>
</ul>
</li>
<li><strong>Deploy a Temporary Test Server</strong>:<ul>
<li>Navigate to the new folder, install dependencies (<code>npm install</code>), create a temporary database, and perform a test deployment.</li>
</ul>
</li>
<li><strong>Test Backup Restore</strong>:<ul>
<li>Access the newly deployed test admin panel and load the backup file downloaded in Step 2. Verify thoroughly that all posts and configurations display correctly without errors.</li>
</ul>
</li>
<li><strong>Apply Upgrade to Production Server</strong>:<ul>
<li>Only after validating that everything functions correctly on the test server, return to your original development folder, update the codebase (<code>git pull</code> or overwrite source), and run the individual app deployment commands (<code>npm run deploy:blog</code>, <code>npm run deploy:admin</code>) to complete the official upgrade.</li>
</ul>
</li>
</ol>
<h3 id="2-last-resort-for-data-loss">2. Last Resort for Data Loss</h3>
<ul>
<li><strong>Using the <code>npm run restore</code> Command</strong>:<ul>
<li>If the infrastructure settings or database are severely damaged and require a fresh restoration, use the backed-up <code>wrangler.backup.json</code> file as a <strong>last resort for data recovery</strong> to rebuild the entire infrastructure.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="q2-what-are-the-mandatory-keys-required-when-changing-image-storage-to-r2-supabase-or-imagekit">📂 Q2. What are the mandatory keys required when changing image storage to R2, Supabase, or ImageKit?</h2>
<p>Below is a checklist of mandatory environment variables and configurations required when using each external image storage provider.</p>
<table>
<thead>
<tr>
<th align="left">Storage Type</th>
<th align="left">Mandatory Input Items / Settings</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>Cloudflare R2</strong></td>
<td align="left"><code>IMAGES</code> R2 Bucket Binding</td>
<td align="left">Must be mapped with the R2 bucket information inside <code>wrangler.json</code>.</td>
</tr>
<tr>
<td align="left"><strong>Supabase Storage</strong></td>
<td align="left"><code>supabase_storage_url</code><br><code>supabase_storage_key</code><br><code>supabase_storage_bucket</code></td>
<td align="left">API URL and Service Role Key must be accurate, and the bucket&#39;s access policy in Supabase Storage must be set to <strong>Public</strong> to prevent image rendering failures.</td>
</tr>
<tr>
<td align="left"><strong>ImageKit.io</strong></td>
<td align="left"><code>imagekit_url_endpoint</code><br><code>imagekit_public_key</code><br><code>imagekit_private_key</code></td>
<td align="left">Verify the endpoint URL format and ensure Cross-Origin Resource Sharing (CORS) is configured.</td>
</tr>
</tbody></table>
<hr>
<h2 id="q3-dashboard-analytics-charts-display-only-demo-data">📊 Q3. Dashboard analytics charts display only demo data.</h2>
<ul>
<li><strong>Cause</strong>: If Google Analytics 4 (GA4) API environment variables are missing or invalid, placeholder demo data is shown to prevent dashboard crashes.</li>
<li><strong>Setup</strong>: Add the following environment variables to the Cloudflare Pages settings and redeploy:<ul>
<li><code>GA4_PROPERTY_ID</code>: Google Analytics Property ID</li>
<li><code>GA4_CLIENT_EMAIL</code>: Google Cloud Service Account Email</li>
<li><code>GA4_PRIVATE_KEY</code>: Google Service Account Private Key</li>
</ul>
</li>
<li><strong>Caution</strong>: When writing <code>GA4_PRIVATE_KEY</code> in <code>.dev.vars</code>, ensure the entire key string is enclosed in double quotes (<code>&quot;</code>) so that line break codes (<code>\n</code>) are preserved correctly during parsing.</li>
</ul>
<hr>
<h2 id="q4-i-cannot-access-the-admin-page-or-some-data-sync-seems-to-be-missing-after-the-initial-setup-deployment">⚡ Q4. I cannot access the admin page, or some data sync seems to be missing after the initial setup deployment.</h2>
<ul>
<li><strong>Cause</strong>: Even if environment variable settings are successfully guided during the one-click setup, temporary network errors or system glitches may cause some encryption keys or secret variables (Secrets) to be partially missing or corrupted during deployment.</li>
<li><strong>Solution</strong>: Double-check the values in each app&#39;s <code>.dev.vars</code> file. Then, navigate to each folder and manually execute the deployment commands (<code>npm run deploy:blog</code> and <code>npm run deploy:admin</code>) <strong>once</strong>. The secret environment variables stored in your local <code>.dev.vars</code> will overwrite the environment variables on Cloudflare, resolving the issue.</li>
</ul>
<hr>
<h2 id="q5-an-quotforbidden-ip-not-allowedquot-or-403-forbidden-error-occurs-when-accessing-the-admin-page">🔒 Q5. An &quot;Forbidden (IP Not Allowed)&quot; or 403 Forbidden error occurs when accessing the admin page.</h2>
<p>Due to the security specifications of this blog, the deployment script automatically detects the public IP address of your deployment PC and injects it as the allowed IP (<code>ALLOWED_IP</code>) into the Pages Secret.</p>
<h3 id="admin-security-recommendation">⚠️ Admin Security Recommendation</h3>
<ul>
<li>To prevent account hijacking and unauthorized access, <strong>it is strongly recommended to restrict admin access and writing operations</strong> on public networks (e.g., cafes, libraries) or untrusted public PCs.</li>
</ul>
<h3 id="situation-specific-troubleshooting">💡 Situation-Specific Troubleshooting</h3>
<ul>
<li><strong>Situation A. Change in home or office IP address (e.g., router reboot)</strong>:<ul>
<li>Execute <code>npm run deploy:admin</code> once from your main development PC in the home/office. It will automatically detect the new public IP and redeploy, restoring your access immediately.</li>
</ul>
</li>
<li><strong>Situation B. Relocating development environment to post from an external location</strong>:<ul>
<li>Clone/download the project and execute a new setup deployment using your backed-up configuration file (<code>wrangler.backup.json</code>).</li>
<li><strong>※ Note:</strong> When returning to your original home/office, <strong>you must execute <code>npm run deploy:admin</code> again from your original development PC</strong> to restore the allowed IP back to your primary fixed IP.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="q6-better-auth-social-login-or-signup-errors-or-infinite-login-loops-occur">🔐 Q6. Better Auth (social login or signup) errors or infinite login loops occur.</h2>
<ul>
<li><strong>Cause</strong>: Session verification fails and loops if authentication-related secrets are missing or incorrect.</li>
<li><strong>Solution</strong>: <ol>
<li>Check <code>apps/blog/.dev.vars</code> and ensure that <code>BETTER_AUTH_SECRET</code> is set to a <strong>secure random string of at least 32 characters</strong>.</li>
<li>After correcting it, run <code>npm run deploy:blog</code> to overwrite and sync the secrets, which will restore normal authentication functionality.</li>
</ol>
</li>
</ul>
]]></content:encoded>
            <category>Admin Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/admin-faq/desktop/img-admin-guide-admin-faq-ko-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Blog Homepage Layout and Getting Started with Login]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/blog-guide/blog-getting-started</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/blog-guide/blog-getting-started</guid>
            <pubDate>Wed, 15 Jul 2026 12:18:45 GMT</pubDate>
            <description><![CDATA[A brief introduction to the basic homepage layout and login/registration procedures of the blog app.]]></description>
            <content:encoded><![CDATA[<h1 id="blog-homepage-layout-and-getting-started-with-login">🌐 Blog Homepage Layout and Getting Started with Login</h1>
<p>This document provides a brief overview of the blog (<code>apps/blog</code>) homepage layout and basic login/registration methods.</p>
<hr>
<h2 id="1-blog-layout-and-navigation">🎨 1. Blog Layout and Navigation</h2>
<p>The blog layout is designed to help visitors locate information efficiently (Header, Sidebar, Main Content, and Footer).</p>
<ol>
<li><strong>Navigation Header (Header)</strong>:<ul>
<li><strong>Site Logo</strong>: Click to return to the homepage at any time.</li>
<li><strong>Shortcut Menu</strong>: Lists primary links configured by the administrator (e.g., categories, external channels).</li>
<li><strong>Language Selector</strong>: Click the globe icon to switch both menu languages and post translations instantly.</li>
</ul>
</li>
<li><strong>Sidebar</strong>:<ul>
<li>Displays category lists, the author profile card, and popular tags on desktop screens.</li>
<li>Automatically hidden on mobile resolutions to optimize readability and scrolling.</li>
</ul>
</li>
<li><strong>Main Content</strong>:<ul>
<li>Shows category filters and the latest published articles in card format.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="2-registration-and-login">🔑 2. Registration and Login</h2>
<p>Supports account registration and login for writing comments or guestbook entries.</p>
<h3 id="supported-login-and-sign-up-methods">⚙️ Supported Login and Sign-Up Methods</h3>
<ul>
<li><strong>Default Email Login/Sign-Up (Default)</strong>:<ul>
<li>Enabled by default post-installation. Users can sign up by providing an email address, display name (nickname), and password. Auto-login applies immediately upon successful registration.</li>
</ul>
</li>
</ul>
<figure data-align="center"><img src="https://sveltekitblog.com/images/posts/blog-getting-started/desktop/img-blog-guide-blog-getting-started-en-001.webp" alt="img-blog-guide-blog-getting-started-en-001" data-align="center" data-caption="Default email login screen" /><figcaption>Default email login screen</figcaption></figure><ul>
<li><strong>Social Login (Better-Auth)</strong>:<ul>
<li>Powered by the Better-Auth engine, supporting <strong>21 social login providers</strong> including Google, GitHub, Kakao, and Naver.</li>
<li>Social login buttons will only appear and function on the login screen after the administrator configures the respective client IDs and secrets as environment variables on the backend. (Integration details for social providers will be detailed in separate upcoming documents.)</li>
</ul>
</li>
</ul>
<figure data-align="center"><img src="https://sveltekitblog.com/images/posts/blog-getting-started/desktop/img-blog-guide-blog-getting-started-en-002.webp" alt="img-blog-guide-blog-getting-started-en-002" data-align="center" data-caption="Social + email login screen" /><figcaption>Social + email login screen</figcaption></figure><ul>
<li><strong>Login Status Display</strong>:<ul>
<li>Upon logging in, the top-right button switches to your profile image icon and a link to my-page.</li>
<li><em>Note: The user profile photo integration is currently in progress and may display a default profile icon instead.</em></li>
</ul>
</li>
</ul>
]]></content:encoded>
            <category>User Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/blog-getting-started/desktop/img-blog-guide-blog-getting-started-en-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Blog Core Features and Multi-Language Service Overview]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/blog-guide/blog-core-features</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/blog-guide/blog-core-features</guid>
            <pubDate>Wed, 15 Jul 2026 12:18:37 GMT</pubDate>
            <description><![CDATA[An introduction to the blog's core features including real-time multi-language rendering and manual translation fallback, comment/reply hierarchies, and private guestbook posts.]]></description>
            <content:encoded><![CDATA[<h1 id="blog-core-features-and-multi-language-service-overview">🌐 Blog Core Features and Multi-Language Service Overview</h1>
<p>This document introduces core features of the blog, including viewing multi-language post translations and communicating via comments and the guestbook.</p>
<hr>
<h2 id="1-real-time-multi-language-body-switching-i18n">🌐 1. Real-Time Multi-Language Body Switching (i18n)</h2>
<p>This blog features a real-time multi-language viewer that updates not just basic UI labels but the actual post content itself to the selected language.</p>
<h3 id="how-it-works-amp-key-features">⚙️ How It Works &amp; Key Features</h3>
<ul>
<li><strong>Language-Specific URL Routing</strong>: Clicking the globe icon at the top or the language buttons near the post title directs the browser to the language-specific URL (e.g., prefixing with <code>/en</code> or <code>/ja</code>). In addition to default languages (Korean, English, Japanese), administrators can expand and publish in other languages by configuring the translation dictionary.</li>
</ul>
<img src="https://sveltekitblog.com/images/posts/blog-core-features/desktop/img-blog-guide-blog-core-features-ko-001.webp" alt="img-blog-guide-blog-core-features-ko-001" data-align="center" />
<img src="https://sveltekitblog.com/images/posts/blog-core-features/desktop/img-blog-guide-blog-core-features-ko-002.webp" alt="img-blog-guide-blog-core-features-ko-002" data-align="center" />
<figure data-align="center"><img src="https://sveltekitblog.com/images/posts/blog-core-features/desktop/img-blog-guide-blog-core-features-ko-003.webp" alt="img-blog-guide-blog-core-features-ko-003" data-align="center" data-caption="For posts published in multiple languages, clicking the corresponding language button immediately redirects you to the translated page." /><figcaption>For posts published in multiple languages, clicking the corresponding language button immediately redirects you to the translated page.</figcaption></figure><ul>
<li><strong>Manually Authored Data Loading (Not Machine Translation)</strong>: The system does not automatically machine-translate text in real time. Instead, it queries and loads the specific post data manually translated and saved by the author under each language tab (such as content translated using AI or translation services and stored in the database).</li>
<li><strong>Simultaneous Content &amp; Metadata Loading</strong>: More than simple text replacement, the database-stored title, excerpt, tags, and body HTML are completely swapped with the datasets of the selected language.</li>
<li><strong>Untranslated Post Fallback</strong>: If the author has not registered a translation for a specific language, the system shows a notice stating the translation is unavailable and falls back to rendering the default authoring language (e.g., Korean text) to ensure the reader&#39;s flow is uninterrupted.</li>
</ul>
<hr>
<h2 id="2-comment-and-nested-reply-hierarchy">💬 2. Comment and Nested Reply Hierarchy</h2>
<p>A clean comment section is placed below each article to facilitate discussion for both guest visitors and registered members.</p>
<ul>
<li><strong>Sharing Thoughts</strong>: Logged-in users can write and post comments to share ideas.</li>
<li><strong>Hierarchical Replies (Nested Comments)</strong>: Users can reply to a specific comment, organizing discussions in an easy-to-read tree structure.</li>
<li><strong>Security &amp; Integrity Preservation</strong>: Users can delete their own comments. However, if a comment with active replies is deleted, the system masks the content with the text &quot;This comment has been deleted&quot; to prevent breaking the overall thread hierarchy.</li>
</ul>
<hr>
<h2 id="3-guestbook-and-private-posts">📖 3. Guestbook and Private Posts</h2>
<p>Provides communication features through the blog guestbook page.</p>
<h3 id="private-guestbook-features">⚙️ Private Guestbook Features</h3>
<ul>
<li><strong>Writing Private Posts</strong>: Checking the <strong>[🔒 Private Post]</strong> checkbox hides the message from the general public.</li>
<li><strong>Exposure Restriction</strong>: Private guestbook posts are completely excluded from the lists of third-party visitors and logged-out users.</li>
<li><strong>Secure Communication</strong>: The post body is visible only to the author (when logged in) and the site administrator, ensuring private communication.</li>
</ul>
]]></content:encoded>
            <category>User Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/blog-core-features/desktop/img-blog-guide-blog-core-features-ko-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Reader Policy and Frequently Asked Questions (FAQ)]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/blog-guide/blog-faq</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/blog-guide/blog-faq</guid>
            <pubDate>Wed, 15 Jul 2026 12:18:27 GMT</pubDate>
            <description><![CDATA[Introduces core principles regarding user data processing upon membership withdrawal and policies for service activity restrictions.]]></description>
            <content:encoded><![CDATA[<p><img src="https://sveltekitblog.com/images/posts/blog-faq/desktop/img-blog-guide-blog-faq-ko-001.webp" alt="img-blog-guide-blog-faq-ko-001"></p>
<h1 id="reader-policy-and-frequently-asked-questions-faq">❓ Reader Policy and Frequently Asked Questions (FAQ)</h1>
<p>This document introduces the basic principles of personal information and data processing upon account deletion, and the service activity restriction policy.</p>
<hr>
<h2 id="q1-what-happens-to-my-comments-and-guestbook-posts-when-i-delete-my-account">🚪 Q1. What happens to my comments and guestbook posts when I delete my account?</h2>
<p>The blog system applies an <strong>author anonymization policy</strong> to simultaneously protect the user&#39;s privacy and maintain the integrity of dialogue threads within the site.</p>
<h3 id="data-processing-principles-upon-deletion">💡 Data Processing Principles Upon Deletion</h3>
<ol>
<li><strong>Personal Identification Data Removal</strong>:<ul>
<li>When you delete your account, your active session and social login connection information are immediately and safely removed from the authentication system. However, for preventing abuse and security audits, minimal data containing the email and social ID connection information at the time of deletion is backed up in a segregated internal deletion log table (<code>deleted_users</code>). This log information is for internal administrative use only, and is completely anonymized and hidden on public pages to prevent any reverse-tracking of the author.</li>
</ul>
</li>
<li><strong>Content Data Retention</strong>:<ul>
<li>Your comments and guestbook messages remain on the screen to preserve the context of past discussions and conversations.</li>
</ul>
</li>
<li><strong>Nickname Anonymization</strong>:<ul>
<li>The link between your account and your posts is severed, and the author name automatically switches to <strong>&quot;Unknown&quot;</strong>. This prevents reverse-tracking of the actual author&#39;s identity.</li>
</ul>
</li>
</ol>
<ul>
<li><em>Note: If the administrator manually deletes your membership record entirely, your comments and guestbook entries may also be removed.</em></li>
</ul>
<hr>
<h2 id="q2-can-i-sign-up-again-immediately-after-deletion-or-withdrawal">🚪 Q2. Can I sign up again immediately after deletion or withdrawal?</h2>
<ul>
<li><strong>Voluntary Withdrawal</strong>:<ul>
<li>If you voluntarily delete your account, you can sign up again immediately using the same email or social account without any grace period.</li>
</ul>
</li>
<li><strong>Activity Ban (Ban) State</strong>:<ul>
<li>If your account is banned due to policy violations, you cannot sign up again with the same email because the email information still exists in the database.</li>
</ul>
</li>
<li><strong>Forced Deletion (Kick) State</strong>:<ul>
<li>If your account is forcibly deleted (Hard Deleted) by an administrator, the existing information is completely removed from the authentication tables, making it technically possible to sign up again with the same email immediately.</li>
<li>Although the email and social ID information from the time of the kick are preserved in the internal deletion log (<code>deleted_users</code>), there is currently no automated system block logic that compares this log at the time of registration to restrict sign-ups.</li>
<li>Therefore, to physically and completely prevent a malicious user from signing up again, the account should be kept in a <strong>&#39;Banned&#39;</strong> state rather than being forcibly deleted. (In a banned state, the email remains in the database, preventing re-registration due to the unique email constraint.)</li>
</ul>
</li>
</ul>
<hr>
<h2 id="q3-my-account-has-been-restricted-banned-or-forced-out-kicked">🚫 Q3. My account has been restricted (banned) or forced out (kicked).</h2>
<p>Checklist when your service usage is restricted (banned) or deleted (kicked) due to policy violations (such as posting spam or offensive content).</p>
<h3 id="core-checklist-for-activity-restrictions">💡 Core Checklist for Activity Restrictions</h3>
<ol>
<li><strong>Activity Ban (Ban)</strong>:<ul>
<li><strong>Status</strong>: Your login state remains active, but direct interactions such as posting comments, nested replies, or guestbook entries are temporarily or permanently restricted.</li>
<li><strong>Checking Reasons</strong>: When restricted, a notice saying <strong>&quot;Banned users cannot write comments.&quot;</strong> will appear in the comment form area, and you can view the specific reason and the expiration date of the restriction.</li>
</ul>
</li>
<li><strong>Forced Deletion (Kick/Delete)</strong>:<ul>
<li><strong>Status</strong>: The login account itself is completely deleted (Hard Deleted) from the database.</li>
<li><strong>Behavior</strong>: Once kicked, your active login session is immediately terminated. Subsequent login attempts will treat you as a new user with no registration history. Depending on the deletion behavior set by the administrator, comments you wrote may either be deleted entirely or anonymized as &#39;Unknown&#39;.</li>
</ul>
</li>
</ol>
]]></content:encoded>
            <category>User Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/blog-faq/desktop/img-blog-guide-blog-faq-ko-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Blog and Admin Feature Integration Overview]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/general-guide/general-integration-guide</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/general-guide/general-integration-guide</guid>
            <pubDate>Wed, 15 Jul 2026 12:18:01 GMT</pubDate>
            <description><![CDATA[An integration document linking layout options, communication systems, multi-language publishing, and real-time design editors of the blog and admin console.]]></description>
            <content:encoded><![CDATA[<p><img src="https://sveltekitblog.com/images/posts/general-integration-guide/desktop/img-general-guide-general-integration-guide-ko-001.webp" alt="img-general-guide-general-integration-guide-ko-001"></p>
<h1 id="blog-and-admin-feature-integration-overview">📖 Blog and Admin Feature Integration Overview</h1>
<p>This document links individual feature overview pages to provide a structured map of the blog service and administration (admin) features.</p>
<p><em>Note: Detailed connection guidelines and technical manuals for each feature will be published individually in future posts.</em></p>
<hr>
<h2 id="feature-overview-index">📂 Feature Overview Index</h2>
<ul>
<li><strong>Admin Features</strong><ul>
<li><strong><a href="../admin-guide/admin-install-and-deploy">CMD One-Click Installation and Cloudflare Deployment Guide</a></strong>: Deploying the blog edge infrastructure to Cloudflare with a single terminal command.</li>
<li><strong><a href="../admin-guide/admin-getting-started">Admin First Access and Configuration Guide</a></strong>: Master password login, IP whitelist management, and multi-language UI dictionary configuration.</li>
<li><strong><a href="../admin-guide/admin-core-features">Core Admin Features and Dual Editors</a></strong>: Introduces Visual HTML and Markdown editors, batch-saving, and column layouts for desktop/mobile viewports.</li>
<li><strong><a href="../admin-guide/admin-design-editor">Real-Time Design Editor and Background Showcase</a></strong>: Four background modes (solid, gradient, image, canvas scripts) applied in real-time without rebuilds.</li>
<li><strong><a href="../admin-guide/admin-faq">Admin FAQ and Troubleshooting</a></strong>: Version upgrades, image storage key checks, post-deployment troubleshooting, and IP security unblock procedures.</li>
</ul>
</li>
<li><strong>Blog Features</strong><ul>
<li><strong><a href="../blog-guide/blog-getting-started">Blog Homepage Layout and Login</a></strong>: Highlights homepage widgets, multi-language UI switches, and login integrations.</li>
<li><strong><a href="../blog-guide/blog-core-features">Blog Core Features and Multi-Language Service</a></strong>: Real-time multi-language content switching, translation fallback logic, nested comment threads, and private guestbook communication.</li>
<li><strong><a href="../blog-guide/blog-faq">Reader Policy and FAQ</a></strong>: Data processing upon account deletion, re-registration policies, and ban/kick restriction details.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="core-process-of-blog-management">🚀 Core Process of Blog Management</h2>
<p>An overview of the setup and authoring workflow for blog administrators.</p>
<h3 id="1-ip-whitelisting-and-master-login">1. IP Whitelisting and Master Login</h3>
<ul>
<li>The admin panel requires the user&#39;s public IP address to be registered in the <code>ALLOWED_IP</code> whitelist before access is granted. (A 403 Forbidden page is shown if unregistered.)</li>
<li>Enter the master password on the secure login screen to establish your session.</li>
</ul>
<h3 id="2-multi-language-batch-saving">2. Multi-Language Batch Saving</h3>
<ul>
<li>Switch between the translation tabs in the writing editor to write content, and click the save button to publish or draft all languages simultaneously to the database.</li>
</ul>
<h3 id="3-real-time-theme-updates">3. Real-Time Theme Updates</h3>
<ul>
<li>Configure styles, colors, and interactive canvas backgrounds in the design editor. Saving changes propagates parameters as CSS variables in visitors&#39; browsers instantly, without redeployment.</li>
</ul>
<hr>
<h2 id="closing-remarks">💬 Closing Remarks</h2>
<p>The content covered in this document is a <strong>brief overview</strong> of the features offered by the blog and admin systems. In reality, there are many more detailed features and convenience options that we couldn&#39;t cover here, and discovering them on your own as you explore the system can be quite an enjoyable experience.</p>
<p>We plan to publish in-depth guides with detailed usage instructions and tips for each feature in future posts, so please feel free to visit again whenever you need them. If you have any questions or feedback, don&#39;t hesitate to leave a message via the guestbook or comments section at any time.</p>
]]></content:encoded>
            <category>General Guide</category>
            <enclosure url="https://sveltekitblog.com/images/posts/general-integration-guide/desktop/img-general-guide-general-integration-guide-ko-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[SvelteKit Monorepo + Cloudflare: One-Click Deploy & Auto-Setup Detailed Manual]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/detail-manual/setup-guide</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/detail-manual/setup-guide</guid>
            <pubDate>Wed, 15 Jul 2026 12:17:45 GMT</pubDate>
            <description><![CDATA[Learn how to automate SvelteKit monorepo deployment on Cloudflare D1, KV, and Pages, including migrations and secrets synchronization, in a single click.]]></description>
            <content:encoded><![CDATA[<p><img src="https://sveltekitblog.com/images/posts/setup-guide/desktop/img-detail-manual-setup-guide-ko-001.webp" alt="img-detail-manual-setup-guide-ko-001"></p>
<h1 id="sveltekit-monorepo-cloudflare-one-click-deploy-amp-auto-setup-detailed-manual">🚀 SvelteKit Monorepo + Cloudflare: One-Click Deploy &amp; Auto-Setup Detailed Manual</h1>
<p>This project is built on top of a SvelteKit monorepo architecture and seamlessly integrates with serverless infrastructures like <strong>Cloudflare D1</strong>, <strong>KV Namespace</strong>, and <strong>Cloudflare Pages</strong>. </p>
<p>To prevent configuration omissions or database connection loss common in multi-app monorepos, a <strong>one-click automated setup script</strong> is built-in. This manual guides you through the local environment configuration required before running the script, and explains the terminal prompt options for each installation mode.</p>
<hr>
<h2 id="1-pre-requisites-before-running-the-script">📂 1. Pre-requisites Before Running the Script</h2>
<p>To prevent unexpected runtime halts, the setup script performs a pre-validation check (<strong>Step 0</strong>) on local secret variables (<code>.dev.vars</code>). You must complete the following configuration steps before triggering the command.</p>
<h3 id="1-1-create-and-configure-devvars-files">🔑 1-1. Create and Configure <code>.dev.vars</code> Files</h3>
<p>Duplicate <code>.dev.vars.example</code> in both app directories to create <code>.dev.vars</code> files and fill in the necessary keys.</p>
<ol>
<li><p><strong>Blog App Secrets</strong></p>
<ul>
<li><strong>Location</strong>: <code>apps/blog/.dev.vars</code></li>
<li><strong>Required Key</strong>:<pre><code class="language-env">BETTER_AUTH_SECRET=&quot;your_long_random_secret_string&quot;
</code></pre>
<em>(Provide a complex, unique secret string to encrypt authorization sessions and tokens. Leaving it empty or just double quotes will fail the validation.)</em></li>
</ul>
</li>
<li><p><strong>Admin App Secrets</strong></p>
<ul>
<li><p><strong>Location</strong>: <code>apps/admin/.dev.vars</code></p>
</li>
<li><p><strong>Required Key</strong>:</p>
<pre><code class="language-env">ADMIN_PASSWORD=&quot;your_admin_dashboard_password&quot;
</code></pre>
<p><em>(Set the password for accessing the admin panel dashboard.)</em></p>
</li>
<li><p><strong>Google Analytics 4 (GA4) &amp; Google AdSense Dummy Data</strong>:<br>If you want to test the widgets on the dashboard landing page with <strong>dummy (simulated) data</strong> instead of a live API connection, you must <strong>leave the Google integration variables (<code>GA4_PROPERTY_ID</code>, <code>ADSENSE_ACCOUNT_ID</code>, etc.) blank or completely remove them</strong> from both local <code>.dev.vars</code> and the Cloudflare Pages remote environment settings. The dashboard automatically falls back to dummy simulation mode if any of these configuration keys are missing.</p>
</li>
</ul>
</li>
</ol>
<blockquote>
<p>[!WARNING]<br>If these files do not exist or the required credentials are empty, the CLI will output an error and halt immediately:</p>
<pre><code class="language-text">❌ apps/admin/.dev.vars file does not exist.
   (Please copy apps/admin/.dev.vars.example to create it and configure ADMIN_PASSWORD.)
</code></pre>
</blockquote>
<hr>
<h2 id="2-command-reference">🛠️ 2. Command Reference</h2>
<table>
<thead>
<tr>
<th align="left">Command</th>
<th align="left">Objective</th>
<th align="left">Highlights</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><code>npm run setup</code></td>
<td align="left"><strong>Full Auto Setup &amp; Deploy</strong></td>
<td align="left">Choose the initial language, and the script handles resource provisioning, migrations, and final deployment automatically.</td>
</tr>
<tr>
<td align="left"><code>npm run setup:select</code></td>
<td align="left"><strong>Custom Interactive Setup</strong></td>
<td align="left">Allows custom overriding of project names, database initialization (Fresh vs Keep), resource labels, CDN cache purge sync, etc.</td>
</tr>
<tr>
<td align="left"><code>npm run restore</code></td>
<td align="left"><strong>Restore Infrastructure from Backup</strong></td>
<td align="left">References <code>wrangler.backup.json</code> to safely re-align bindings and redeploy without modifying existing tables.</td>
</tr>
</tbody></table>
<hr>
<h2 id="3-terminal-prompt-step-by-step-guide">💬 3. Terminal Prompt Step-by-Step Guide</h2>
<p>Here is a comprehensive breakdown of the actual prompts (English &amp; Korean) printed during execution and their corresponding impacts.</p>
<h3 id="3-1-shared-initial-prompts-common-for-both-setup-amp-setupselect">🌐 3-1. Shared Initial Prompts (Common for both setup &amp; setup:select)</h3>
<h4 id="q1-select-default-blog-language-database-seeding-language">Q1. Select Default Blog Language (Database Seeding Language)</h4>
<p>Determines the language of the default guide posts and configurations inserted into your Cloudflare D1 database.</p>
<pre><code class="language-text">  [EN] Select default blog language:
  [KO] 기본 블로그 언어를 선택하세요:
  1) Korean / 한국어 (ko) [Default]
  2) English / 영어 (en)
  3) Japanese / 日本語 (ja)
  [EN] Choose option (1/2/3) [Default: 1]
  [KO] 옵션을 선택하세요 (1/2/3) [기본값: 1]
  &gt; 
</code></pre>
<ul>
<li><strong>Guide</strong>: Press <code>1</code> for Korean, <code>2</code> for English, or <code>3</code> for Japanese. It seeds the D1 database with translated mock posts and system settings according to the selection.</li>
</ul>
<h4 id="q2-select-setup-mode-for-remaining-steps">Q2. Select Setup Mode for Remaining Steps</h4>
<p>Decide whether to execute a fully automated pipeline or customize every single bind variable.</p>
<pre><code class="language-text">  [EN] Choose setup mode for the remaining steps:
  [KO] 나머지 설정의 진행 방식을 선택하세요:
  1) Full Auto Setup &amp; Deploy / 풀 자동 설정 및 배포 [Default]
  2) Custom Interactive Setup / 사용자 지정 직접 선택 설정
  [EN] Choose option (1/2) [Default: 1]
  [KO] 옵션을 선택하세요 (1/2) [기본값: 1]
  &gt; 
</code></pre>
<ul>
<li><strong>1) Full Auto Setup &amp; Deploy (Default)</strong>: Automatically provisions Pages projects (<code>svelteblog</code> and <code>svelteadmin</code>), detects active Cloudflare sessions, runs migrations, and triggers a build-and-deploy flow without asking questions.</li>
<li><strong>2) Custom Interactive Setup</strong>: Transitions to custom configuration mode (equivalent to running <code>npm run setup:select</code> directly) and prompts you with questions Q3 through Q8.</li>
</ul>
<hr>
<h3 id="3-2-custom-interactive-prompts-npm-run-setupselect-only">🎨 3-2. Custom Interactive Prompts (<code>npm run setup:select</code> only)</h3>
<blockquote>
<p>[!TIP]<br>All prompts during the custom interactive phase can be answered by simply pressing <strong>Enter</strong> to fall back to the safe, standard defaults displayed inside the brackets <code>[Default: ...]</code>. You do not have to manually fill out every field.</p>
</blockquote>
<h4 id="q3-custom-deploy-project-names">Q3. Custom Deploy Project Names</h4>
<p>Specify unique project names to register on Cloudflare Pages. (The service URLs will default to <code>https://[project-name].pages.dev</code>.)</p>
<pre><code class="language-text">  [EN] Enter Blog project name [Default: svelteblog]
  [KO] 블로그 배포명을 입력하세요
  &gt; 

  [EN] Enter Admin project name [Default: svelteadmin]
  [KO] 어드민 배포명을 입력하세요
  &gt; 
</code></pre>
<ul>
<li><strong>Guide</strong>: Press enter to use the defaults. If you already have existing projects with these names in your Cloudflare dashboard, type a unique name to avoid conflicts. (This also updates deployment scripts inside <code>package.json</code> dynamically.)</li>
</ul>
<h4 id="q4-cloudflare-wrangler-login">Q4. Cloudflare Wrangler Login</h4>
<p>Triggers authorization checks.</p>
<pre><code class="language-text">  [EN] Run wrangler login?
  [KO] Wrangler 로그인을 진행할까요?
  [EN] (Y/n) [Default: Y]
  [KO] (Y/n) [기본값: Y]
  &gt; 
</code></pre>
<ul>
<li><strong>Guide</strong>: If no active session is detected, it redirects you to the browser. If a valid login exists, the script skips it automatically. Select <code>Y</code> if you wish to switch or re-authenticate Cloudflare accounts.</li>
</ul>
<h4 id="q5-database-initialization-mode-fresh-vs-keep">Q5. Database Initialization Mode (Fresh vs Keep)</h4>
<p>Specify whether to keep your remote database tables or clear them.</p>
<pre><code class="language-text">  [EN] Select Initialization Mode:
    1: Fresh Install (DELETE existing Cloudflare D1/KV databases and start clean)
    2: Keep Existing Data (Use existing Cloudflare databases to preserve your posts/data)
  [KO] 초기화 모드 선택:
    1: 완전 초기화 (기존 클라우드플레어의 D1/KV 데이터베이스를 모두 삭제하고 새로 생성합니다. 데이터 유실 주의!)
    2: 기존 데이터 유지 (기존에 구축된 클라우드플레어 리소스를 그대로 유지하고 연동합니다.)

  [EN] Choose an option (1/2) [Default: 2]
  [KO] 옵션을 선택하세요 (1/2) [기본값: 2]
  &gt; 
</code></pre>
<ul>
<li><strong>Fresh Install (1)</strong>: <strong>Permanently deletes</strong> existing D1 databases and KV namespaces on Cloudflare. Do not choose this unless you are setting up a test environment from scratch.</li>
<li><strong>Keep Existing Data (2, Recommended/Default)</strong>: Re-uses your active D1 tables and KV records. Your articles and visitor logs will remain intact.</li>
</ul>
<h4 id="q6-custom-cloudflare-resource-labels">Q6. Custom Cloudflare Resource Labels</h4>
<p>Customize the actual names of the D1 databases and KV namespace instances.</p>
<pre><code class="language-text">  [EN] Enter Blog DB name [Default: blog-db-xxxxxx]
  [KO] 블로그 DB 이름을 입력하세요
  &gt; 

  [EN] Enter User DB name [Default: user-db-xxxxxx]
  [KO] 유저 DB 이름을 입력하세요
  &gt; 

  [EN] Enter Images KV name [Default: blog-images-kv-xxxxxx]
  [KO] 이미지 KV 이름을 입력하세요
  &gt; 
</code></pre>
<ul>
<li><strong>Guide</strong>: Leave blank and press enter to generate unique labels with random suffixes (<code>xxxxxx</code>), or type custom names to match your naming guidelines.</li>
</ul>
<h4 id="q7-cloudflare-cdn-cache-purge-integration">Q7. Cloudflare CDN Cache Purge Integration</h4>
<p>Configure automatic edge cache invalidation when posts are modified.</p>
<pre><code class="language-text">  [EN] Configure Cloudflare CDN cache purge credentials?
  [KO] CDN 캐시 퍼지 설정을 등록하시겠습니까?
  [EN] (y/N) [Default: N]
  [KO] (y/N) [기본값: N]
  &gt; 
</code></pre>
<ul>
<li><strong>Guide</strong>: Selecting <code>y</code> triggers prompt inputs for your Cloudflare <code>Zone ID</code> and <code>API Token</code>. These credentials will be written to local <code>.dev.vars</code> files and synchronized as remote secrets automatically.</li>
</ul>
<h4 id="q8-direct-deployment-confirmation">Q8. Direct Deployment Confirmation</h4>
<p>Choose whether to immediately compile the code and ship it to Cloudflare Pages.</p>
<pre><code class="language-text">  [EN] Deploy directly?
  [KO] 지금 바로 배포하시겠습니까?
  [EN] (Y/n) [Default: Y]
  [KO] (Y/n) [기본값: Y]
  &gt; 
</code></pre>
<ul>
<li><strong>Guide</strong>: Press <code>Y</code> to trigger immediate builds and deployments. The script will output the resulting live URLs. Press <code>n</code> if you only want to update configuration files (<code>wrangler.json</code>) locally.</li>
</ul>
<hr>
<h3 id="3-3-post-build-synchronization-prompts-ip-whitelisting-amp-translations">🔒 3-3. Post-Build Synchronization Prompts (IP Whitelisting &amp; Translations)</h3>
<p>During the compilation stage (<code>sync-secrets.js</code>), you may encounter additional prompts concerning admin security and i18n synchronization.</p>
<h4 id="q9-admin-ip-mismatch-warning">Q9. Admin IP Mismatch Warning</h4>
<p>The admin panel uses a strict IP whitelist (<code>ALLOWED_IP</code>) for security. The script dynamically checks your machine&#39;s current public IP address and flags a mismatch if it is not in the whitelist:</p>
<pre><code class="language-text">  1) Keep existing allowed IPs / 기존 목록 유지 (현재 기기 미등록) [Default]
  2) Add current machine IP to list / 현재 기기 IP를 목록에 추가 (복수 허용)
  3) Replace with current machine IP / 현재 기기 IP로만 갱신 (기존 목록 제거)

  [EN] Select option (1/2/3) [Default: 1]
  [KO] 옵션을 선택하세요 (1/2/3) [기본값: 1]
  &gt; 
</code></pre>
<ul>
<li><strong>1) Keep existing allowed IPs (Default)</strong>: Keeps your whitelist configurations unchanged. You might be blocked from the dashboard if your current network environment differs from the registered one.</li>
<li><strong>2) Add current machine IP to list</strong>: Appends your current public IP using a comma separator. Recommended for admins managing the blog from multiple locations (e.g., home and office).</li>
<li><strong>3) Replace with current machine IP</strong>: Clears all registered IPs and sets only your current IP as the sole allowed address.</li>
</ul>
<h4 id="q10-force-sync-i18n-translations-to-d1-database">Q10. Force Sync i18n Translations to D1 Database</h4>
<p>Decide whether to overwrite remote translation tables with local code definitions:</p>
<pre><code class="language-text">[EN] Force sync remote D1 ui_dictionary with local index.ts? (Web changes will be lost)
[KO] D1 DB의 ui_dictionary를 로컬 index.ts 기준으로 강제 덮어쓰시겠습니까? (웹 수정본 유실 주의)
  [EN] Select option (y/N) [Default: N]
  [KO] 옵션을 선택하세요 (y/N) [기본값: N]
  &gt; 
</code></pre>
<ul>
<li><strong>Guide</strong>: Select <code>N</code> if you have edited translations directly in the admin dashboard settings page to prevent losing changes. Select <code>y</code> if you want to overwrite database values with local source code files (<code>packages/shared/src/i18n/index.ts</code>).</li>
</ul>
<hr>
<h2 id="4-backup-amp-restore-mechanism-npm-run-restore">🔄 4. Backup &amp; Restore Mechanism (<code>npm run restore</code>)</h2>
<p>Once a setup finishes successfully, a <code>wrangler.backup.json</code> configuration backup file is automatically generated in your root directory.</p>
<pre><code class="language-json">{
    &quot;d1&quot;: {
        &quot;BLOG_DB&quot;: { &quot;name&quot;: &quot;blog-db-xxxxxx&quot;, &quot;id&quot;: &quot;d1-uuid-value&quot; },
        &quot;USER_DB&quot;: { &quot;name&quot;: &quot;user-db-xxxxxx&quot;, &quot;id&quot;: &quot;d1-uuid-value&quot; }
    },
    &quot;kv&quot;: {
        &quot;IMAGES_KV&quot;: &quot;kv-namespace-id&quot;
    },
    &quot;blogProjectName&quot;: &quot;svelteblog&quot;,
    &quot;adminProjectName&quot;: &quot;svelteadmin&quot;
}
</code></pre>
<p>If you relocate or switch development environments:</p>
<ul>
<li>Running <code>npm run restore</code> reads this backup file to lock project names and restore exact resource bindings automatically.</li>
<li>It <strong>safely skips database seeding</strong> to prevent overwriting or wiping your operational articles and visitor data.</li>
</ul>
<hr>
<h2 id="5-troubleshooting">❓ 5. Troubleshooting</h2>
<h3 id="1-wrangler-whoami-session-or-authorization-failure">🚨 1. Wrangler Whoami Session or Authorization Failure</h3>
<ul>
<li><strong>Symptom</strong>: CLI prints authentication or access errors when provisioning D1/KV resources.</li>
<li><strong>Solution</strong>: Run <code>npm run setup:select</code> and enter <code>Y</code> at the <strong>Q4. Run wrangler login</strong> prompt to trigger a fresh browser authentication. The script only requests minimal account permissions (<code>account:read</code>, <code>user:read</code>, <code>workers:write</code>, <code>pages:write</code>, <code>d1:write</code>, <code>workers_kv:write</code>) for security.</li>
</ul>
<h3 id="2-windows-script-execution-policy-blocked">🚨 2. Windows Script Execution Policy Blocked</h3>
<ul>
<li><strong>Symptom</strong>: PowerShell restricts script executions due to authorization policies.</li>
<li><strong>Solution</strong>: The setup script automatically overrides paths and uses <code>npx.cmd</code> on Windows. We recommend running commands via <strong>Git Bash</strong> or <strong>CMD (Command Prompt)</strong> rather than standard PowerShell.</li>
</ul>
]]></content:encoded>
            <category>Detailed Manual</category>
            <enclosure url="https://sveltekitblog.com/images/posts/setup-guide/desktop/img-detail-manual-setup-guide-ko-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Cloudflare Wrangler Login and API Token Configuration Guide in CLI Environments]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/detail-manual/wrangler-login-guide</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/detail-manual/wrangler-login-guide</guid>
            <pubDate>Wed, 15 Jul 2026 12:17:34 GMT</pubDate>
            <description><![CDATA[Learn how to establish a non-interactive Wrangler authentication session using Cloudflare API Tokens in remote SSH servers and CI/CD environments.]]></description>
            <content:encoded><![CDATA[<p><img src="https://sveltekitblog.com/images/posts/setup-guide/desktop/img-detail-manual-setup-guide-ko-001.webp" alt="img-detail-manual-setup-guide-ko-001"></p>
<h1 id="cloudflare-wrangler-login-and-api-token-configuration-guide-in-cli-environments">🔑 Cloudflare Wrangler Login and API Token Configuration Guide in CLI Environments</h1>
<p>This project provides an automated setup script that provisions Cloudflare databases, storage, and build pipelines in a single execution.</p>
<p>While this script internally runs the Cloudflare <code>wrangler</code> CLI, local development environments typically trigger an interactive web browser login (<code>npx wrangler login</code>). However, in <strong>headless CLI-only environments (such as remote SSH Linux servers, headless virtual machines, or CI/CD build pipelines)</strong>, establishing an interactive browser session is impossible.</p>
<p>This manual explains how to bypass this limitation and safely configure a non-interactive Wrangler session using a <strong>Cloudflare API Token</strong>.</p>
<hr>
<h2 id="1-permission-scopes-before-vs-after-domain-setup">📂 1. Permission Scopes: Before vs. After Domain Setup</h2>
<p>Before issuing a token, it is crucial to understand your current deployment stage. To follow security best practices, separate your permissions based on your custom domain connection state.</p>
<h3 id="1-1-initial-deployment-before-custom-domain-setup">🔌 1-1. Initial Deployment (Before Custom Domain Setup)</h3>
<p>If you are deploying for the first time and only using the default <code>*.pages.dev</code> domains provided by Cloudflare Pages, <strong>you do not need any Zone (domain) level permissions.</strong> The setup script, database migrations, and resource bindings will function perfectly with only <strong>Account-level permissions</strong>.</p>
<ul>
<li><strong>Required Minimum Permissions</strong>:<ul>
<li><code>D1</code> — <strong>Edit</strong> (Required to create, query, and migrate D1 databases)</li>
<li><code>Workers KV Storage</code> — <strong>Edit</strong> (Required to manage KV namespaces for media uploads)</li>
<li><code>Cloudflare Pages</code> — <strong>Edit</strong> (Required to build and deploy SvelteKit applications)</li>
<li><code>Workers Scripts</code> — <strong>Edit</strong> (Required for CLI script management)</li>
</ul>
</li>
</ul>
<h3 id="1-2-custom-domain-mapping-amp-cdn-edge-cache-purging-future-setup">🌐 1-2. Custom Domain Mapping &amp; CDN Edge Cache Purging (Future Setup)</h3>
<p>When you bind a custom domain to your blog and enable edge CDN cache purging for better performance, you will then require <strong>Zone-level permissions</strong>.</p>
<ul>
<li><strong>Additional Required Permission</strong>:<ul>
<li><code>Zone: Cache Purge</code> — <strong>Edit</strong> (Required to invalidate CDN edge caches when content changes)</li>
</ul>
</li>
<li><strong>Security Best Practice</strong>: When limiting token scopes, do not set <strong>Zone Resources</strong> to &quot;All Zones&quot;. Restrict it to the specific custom domain (Zone) you are currently using.</li>
<li>*Note: The custom domain setup and edge CDN cache configuration will be discussed in detail in the upcoming <strong>&#39;Custom Domain Setup Detailed Manual&#39;</strong>. You can safely skip these settings during your initial setup.*</li>
</ul>
<hr>
<h2 id="2-cloudflare-api-token-creation-steps">🛠️ 2. Cloudflare API Token Creation Steps</h2>
<p>You can generate a token for non-interactive logins in the Cloudflare dashboard by following these steps:</p>
<ol>
<li><strong>Log in to the Cloudflare Dashboard</strong>:<ul>
<li>Navigate to the <a href="https://dash.cloudflare.com/">Cloudflare Dashboard</a> and log in.</li>
</ul>
</li>
<li><strong>Access the API Tokens Menu</strong>:<ul>
<li>Click the user icon in the top right corner of the dashboard and select <strong>My Profile</strong>.</li>
<li>In the left-hand navigation sidebar, click <strong>API Tokens</strong>.</li>
<li>Click the <strong>Create Token</strong> button on the right.</li>
</ul>
</li>
<li><strong>Select Custom Token</strong>:<ul>
<li>Under the templates list, locate the <strong>Create Custom Token</strong> section at the bottom and click <strong>Get Started</strong>.</li>
</ul>
</li>
<li><strong>Configure Permissions</strong>:<ul>
<li><strong>Token Name</strong>: Enter a descriptive name (e.g., <code>sveltekit-blog-cli-token</code>).</li>
<li><strong>Permissions</strong>:<ul>
<li><code>Account</code> -&gt; <code>D1</code> -&gt; <code>Edit</code></li>
<li><code>Account</code> -&gt; <code>Workers KV Storage</code> -&gt; <code>Edit</code></li>
<li><code>Account</code> -&gt; <code>Cloudflare Pages</code> -&gt; <code>Edit</code></li>
<li><code>Account</code> -&gt; <code>Workers Scripts</code> -&gt; <code>Edit</code></li>
</ul>
</li>
</ul>
</li>
<li><strong>Restrict Resources (Scope)</strong>:<ul>
<li><strong>Account Resources</strong>: Set to <code>Include</code> -&gt; Select your <code>Cloudflare Account</code> (Restricts the token&#39;s scope to your account only to isolate security risks).</li>
</ul>
</li>
<li><strong>Generate and Save</strong>:<ul>
<li>Click <strong>Continue to summary</strong>, then click <strong>Create Token</strong>.</li>
<li>Copy the generated API token (a long alphanumeric string) and store it in a secure location. (Note: You cannot view this token again after leaving the page. If lost, you must generate a new one.)</li>
</ul>
</li>
</ol>
<hr>
<h2 id="3-setting-the-environment-variable">💻 3. Setting the Environment Variable</h2>
<p>Since the browser login is bypassed, you must inject the token value into your system&#39;s environment variables. Wrangler will automatically detect it and establish an active session.</p>
<h3 id="3-1-terminal-command-by-operating-system">3-1. Terminal Command by Operating System</h3>
<p>Run the appropriate command in your terminal session before executing any setup script:</p>
<ul>
<li><strong>Linux / macOS / Git Bash (Bash/Zsh Shell)</strong>:<pre><code class="language-bash">export CLOUDFLARE_API_TOKEN=&quot;your_generated_api_token&quot;
</code></pre>
</li>
<li><strong>Windows Command Prompt (CMD)</strong>:<pre><code class="language-cmd">set CLOUDFLARE_API_TOKEN=your_generated_api_token
</code></pre>
</li>
<li><strong>Windows PowerShell</strong>:<pre><code class="language-powershell">$env:CLOUDFLARE_API_TOKEN=&quot;your_generated_api_token&quot;
</code></pre>
</li>
</ul>
<blockquote>
<p>[!NOTE]<br><strong>💻 Compatibility and macOS Testing Note</strong></p>
<ul>
<li>This guide has been fully verified and tested on <strong>Windows 10/11</strong> and <strong>Linux (Ubuntu 22.04 LTS)</strong> console environments.</li>
<li>Due to the author&#39;s lack of physical macOS hardware, a hands-on verification on macOS (MacBook) was not performed. However, since Node.js CLI executes cross-platform binaries identically, this will work seamlessly on macOS using the standard Zsh/Bash <code>export</code> command.</li>
</ul>
</blockquote>
<h3 id="3-2-local-development-devvars-and-cicd-integrations">3-2. Local Development (.dev.vars) and CI/CD Integrations</h3>
<ul>
<li><strong>Local Development</strong>:<br>To avoid typing the variable in every terminal session, add the token to the <code>.dev.vars</code> files in <code>apps/blog/</code> and <code>apps/admin/</code>. Wrangler will parse it automatically:<pre><code class="language-env">CLOUDFLARE_API_TOKEN=&quot;your_generated_api_token&quot;
</code></pre>
</li>
<li><strong>CI/CD Pipelines (GitHub Actions)</strong>:<br>Register the token under <code>Settings</code> -&gt; <code>Secrets and variables</code> -&gt; <code>Actions</code> -&gt; <code>Repository secrets</code> as <code>CLOUDFLARE_API_TOKEN</code> and map it in your workflow file:<pre><code class="language-yaml">- name: Build and Deploy SvelteKit Apps
  env:
    CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
  run: npm run deploy:blog
</code></pre>
</li>
</ul>
<hr>
<h2 id="4-verification-and-debugging">🔍 4. Verification and Debugging</h2>
<p>You can verify that the environment variable has been correctly injected and linked to your Cloudflare account using the following diagnostic tools.</p>
<h3 id="4-1-wrangler-whoami">4-1. wrangler whoami</h3>
<p>Run this command in your terminal:</p>
<pre><code class="language-bash">npx wrangler whoami
</code></pre>
<ul>
<li><strong>Success Output</strong>: If valid, the CLI will output your account details (Account Name, Account ID) and the list of permitted bindings (D1, KV, Pages, etc.).</li>
<li><strong>Clearing Sessions (wrangler logout)</strong>:<br>If an existing interactive browser session interferes with your token environment variable, clear the local cache and reset the state using the logout command:<pre><code class="language-bash">npx wrangler logout
</code></pre>
</li>
</ul>
<hr>
<h2 id="5-troubleshooting">⚠️ 5. Troubleshooting</h2>
<h3 id="1-authentication-error-code-10000">🚨 1. Authentication Error (Code: 10000)</h3>
<ul>
<li><strong>Symptom</strong>: The CLI prints authentication errors when executing the provisioning scripts.</li>
<li><strong>Solution</strong>: Double-check for typos or leading/trailing spaces in your <code>CLOUDFLARE_API_TOKEN</code> string. Verify that the <code>Account Resources</code> scope matches the account ID of the active project.</li>
</ul>
<h3 id="2-forbidden-access-denied">🚨 2. Forbidden (Access Denied)</h3>
<ul>
<li><strong>Symptom</strong>: D1 migrations work fine, but Pages deployments or KV namespace creations fail with access denied errors.</li>
<li><strong>Solution</strong>: Ensure your token has all four required edit permissions (<code>Pages -&gt; Edit</code>, <code>Workers KV -&gt; Edit</code>, etc.) in the Cloudflare API Tokens dashboard. If any are missing, update the token permissions and try again.</li>
</ul>
]]></content:encoded>
            <category>Detailed Manual</category>
            <enclosure url="https://sveltekitblog.com/images/posts/setup-guide/desktop/img-detail-manual-setup-guide-ko-001.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Web Font Configuration and Performance Tuning Manual]]></title>
            <link>https://fixedblog-3lz.pages.dev/en/detail-manual/admin-font-settings</link>
            <guid isPermaLink="true">https://fixedblog-3lz.pages.dev/en/detail-manual/admin-font-settings</guid>
            <pubDate>Wed, 15 Jul 2026 12:17:21 GMT</pubDate>
            <description><![CDATA[Learn how to safely configure web fonts in the blog admin and master the font proxying and caching optimization techniques implemented to enhance loading speed under Cloudflare Pages.]]></description>
            <content:encoded><![CDATA[<p><img src="https://sveltekitblog.com/images/posts/setup-guide/desktop/img-detail-manual-setup-guide-ko-001.webp" alt="img-detail-manual-setup-guide-ko-001"></p>
<h1 id="web-font-settings-and-load-optimization-architecture-in-blog-admin">✍️ Web Font Settings and Load Optimization Architecture in Blog Admin</h1>
<p>This project provides an intuitive design editing tool within the admin panel to easily customize fonts, improving the visual appeal and readability of your blog. </p>
<p>Beyond simply applying font names, a specialized performance optimization engine runs behind the scenes to maintain top loading speeds and high performance scores (Lighthouse Performance) even in mobile or bandwidth-constrained environments.</p>
<p>This manual details how to configure fonts in the admin design editor and explains the underlying concepts of how fonts are optimized and served rapidly to your visitors.</p>
<hr>
<h2 id="1-detailed-font-settings-in-the-design-editor">📂 1. Detailed Font Settings in the Design Editor</h2>
<p>In the admin design editor settings menu, you can finely tune font families, sizes, and weights to match your blog layout.</p>
<h3 id="1-1-global-web-font-settings-affects-entire-pages">✍️ 1-1. Global Web Font Settings (Affects Entire Pages)</h3>
<p>Manages the global fonts that bind as defaults across all text areas and the basic interface of the blog.</p>
<ul>
<li><strong>Base Font Family (Font Family)</strong>:<ul>
<li>Specifies the main typeface for the entire blog.</li>
<li><em>How to enter</em>: Enter the font name recognized by browsers. If left blank, the system default font <code>Inter</code> is inherited across the entire blog. (e.g., <code>&#39;Noto Serif KR&#39;, serif</code> or <code>Pretendard</code>)</li>
</ul>
</li>
<li><strong>Add Google Web Fonts (Google Font Name)</strong>:<ul>
<li>Registers the English names of Google Fonts to apply to specific areas like the logo text or key widget titles.</li>
<li><em>How to enter</em>: List multiple fonts separated by commas (<code>,</code>) or semicolons (<code>;</code>). (e.g., <code>Noto Serif KR, Newsreader</code>)</li>
<li><em>Integration effect</em>: The custom font names entered here will automatically populate as select options in the header&#39;s logo font dropdown and other individual font family options.</li>
</ul>
</li>
<li><strong>Base Font Size &amp; Base Font Size (Mobile)</strong>:<ul>
<li>Defines the base font size for the desktop and mobile views respectively.</li>
<li><em>How to enter &amp; Tips</em>: It fully supports not only absolute units (<strong>px</strong>, e.g., <code>16px</code> or <code>14px</code>) but also relative units (<strong>rem, em</strong>) that dynamically scale according to the user&#39;s browser settings. (e.g., Desktop <code>1rem</code> or <code>16px</code> / Mobile <code>0.875rem</code> or <code>14px</code>)</li>
</ul>
</li>
</ul>
<h3 id="1-2-header-and-logo-font-settings">🎨 1-2. Header and Logo Font Settings</h3>
<p>Applies independent typography to the branding logo text displayed in the top navigation header.</p>
<ul>
<li><strong>Font Family</strong>:<ul>
<li>Selects the typeface for the logo text. </li>
<li>Choosing <code>Inherit</code> will follow the global base font. Custom fonts registered in the <strong>[Add Google Web Fonts]</strong> field will automatically appear in this dropdown for individual assignment.</li>
</ul>
</li>
<li><strong>Font Size &amp; Mobile Font Size</strong>:<ul>
<li>Assigns distinct sizes for desktop and mobile views to ensure the logo text does not break layouts or lose legibility under different viewports. (e.g., Desktop <code>1.5rem</code> / Mobile <code>1.2rem</code>)</li>
</ul>
</li>
<li><strong>Logo Weight</strong>:<ul>
<li>Provides a dropdown menu with weights from <code>100</code> (thinnest) to <code>900</code> (boldest) in increments of 100 to customize the visual presence of the logo.</li>
<li><em>Caution</em>: The actual rendered thickness depends on the selected font family&#39;s capabilities. If the web font does not support a specific weight (e.g., 100 or 900), the browser will render using the closest available weight. It is best to check the font&#39;s specifications beforehand.</li>
</ul>
</li>
</ul>
<h3 id="1-3-global-widget-style-settings">🧩 1-3. Global Widget Style Settings</h3>
<p>Adjusts the text styling of individual widget titles and contents assembled in the sidebars or footer areas.</p>
<ul>
<li><strong>Global Widget Title Style</strong>: Configures the font family, size, weight, and color of the widget card headers.</li>
<li><strong>Global Widget Item Style</strong>: Sets the styling for the individual content items and links inside the widget card.</li>
<li><em>Inheritance rule</em>: If the font family field is left blank, it inherits the global font, maintaining layout consistency.</li>
</ul>
<hr>
<h2 id="2-font-loading-performance-optimization-and-mechanism">⚡ 2. Font Loading Performance Optimization and Mechanism</h2>
<p>Font loading delays are a primary cause of low performance scores on websites. To prevent this, the engine features a built-in font acceleration pipeline optimized for serverless environments.</p>
<h3 id="2-1-system-built-in-font-filtering">🛡️ 2-1. System Built-in Font Filtering</h3>
<p>Fonts likely already installed on the visitor&#39;s device (e.g., <code>Pretendard</code>, <code>Arial</code>, <code>system-ui</code>) are filtered out on the server side. This prevents the blog server from making unnecessary requests to Google Font servers, saving bandwidth.</p>
<h3 id="2-2-blocking-external-requests-and-self-proxying">🔄 2-2. Blocking External Requests and Self-Proxying</h3>
<p>If a visitor&#39;s browser connects directly to external Google Font URLs (<code>fonts.googleapis.com</code> and <code>gstatic.com</code>), DNS queries and SSL handshakes introduce several hundred milliseconds of rendering delay.</p>
<ul>
<li><strong>Proxying Stylesheets</strong>: The blog requests the stylesheet (CSS) through its own internal API rather than calling external Google servers during page render.</li>
<li><strong>Rewriting Internal Paths</strong>: The engine analyzes the font download links (.woff2) inside the CSS and replaces all external URLs with internal domain proxy paths.</li>
<li><strong>Security Filters</strong>: The proxy API restricts access exclusively to official Google Font domain hosts to prevent malicious redirection or relaying of unverified code.</li>
</ul>
<h3 id="2-3-cloudflare-pages-cdn-and-local-browser-caching">💾 2-3. Cloudflare Pages CDN and Local Browser Caching</h3>
<p>All proxy-requested font definitions and font files (.woff2) are cached on Cloudflare&#39;s global edge servers (CDN) for 24 hours.</p>
<ul>
<li>It also responds with strong browser caching headers. When a user clicks a link to another post or returns next time, the font renders instantly in 0ms from the local device memory, eliminating flashes of unstyled text (FOUT) or layout shifts (CLS).</li>
</ul>
<h3 id="2-4-pretendard-font-acceleration">🚀 2-4. Pretendard Font Acceleration</h3>
<p>When <code>Pretendard</code>, a typeface optimized for Korean readability, is set as the base font, the engine opens a dedicated bypass path to maximize rendering speed.</p>
<ul>
<li><strong>Parallel Download</strong>: It loads the font files in parallel with other scripts through a high-speed global open-source CDN (jsDelivr), bypassing Google Font proxying.</li>
<li><strong>Rendering Optimization</strong>: This ensures the heavy Korean font package is retrieved as quickly as possible, avoiding delayed text display on initial page entry.</li>
</ul>
<hr>
<h2 id="3-important-notes-for-configuration">💡 3. Important Notes for Configuration</h2>
<blockquote>
<p>[!IMPORTANT]<br><strong>💡 Key Guidelines When Modifying Admin Font Settings</strong></p>
<ol>
<li><strong>Enter Exact Google Font Names</strong>:<ul>
<li>The English font names entered in the Google Font Name field must match Google Font Library&#39;s official names exactly. Typos or incorrect spaces will cause the loader to fail, falling back to system generic fonts (Sans-serif).</li>
</ul>
</li>
<li><strong>Balance Desktop and Mobile Font Sizes</strong>:<ul>
<li>Keeping the desktop font size on mobile views degrades mobile legibility. Ensure you configure a slightly smaller value (e.g., <code>2px</code> less) for the mobile base size to maintain a responsive interface.</li>
</ul>
</li>
</ol>
</blockquote>
]]></content:encoded>
            <category>Detailed Manual</category>
            <enclosure url="https://sveltekitblog.com/images/posts/setup-guide/desktop/img-detail-manual-setup-guide-ko-001.webp" length="0" type="image/webp"/>
        </item>
    </channel>
</rss>