<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yunus Ertürk</title>
    <description>The latest articles on DEV Community by Yunus Ertürk (@yunuserturk).</description>
    <link>https://dev.to/yunuserturk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F884617%2F54ecbf94-45e2-4f4f-87b5-39dbea0ae71c.png</url>
      <title>DEV Community: Yunus Ertürk</title>
      <link>https://dev.to/yunuserturk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yunuserturk"/>
    <language>en</language>
    <item>
      <title>How to Run Two Claude Desktop Accounts on One Mac (With Separate Dock Icons and Shared Context)</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Fri, 13 Nov 2026 07:18:39 +0000</pubDate>
      <link>https://dev.to/yunuserturk/how-to-run-two-claude-desktop-accounts-on-one-mac-with-separate-dock-icons-and-shared-context-1m2e</link>
      <guid>https://dev.to/yunuserturk/how-to-run-two-claude-desktop-accounts-on-one-mac-with-separate-dock-icons-and-shared-context-1m2e</guid>
      <description>&lt;p&gt;I run my daily operations and recurring routines inside Claude Desktop's Code tab: morning check-ins at 08:45, weekly planning, Telegram community digests, and weekly SEO and AEO checks for this blog.&lt;/p&gt;

&lt;p&gt;Running everything on a single account has a structural flaw. Paid Claude plans have a session limit that resets every five hours, plus weekly limits. When a heavy coding or video-rendering session burns through that session limit in 45 minutes, every scheduled task on that account hits the same wall and stalls.&lt;/p&gt;

&lt;p&gt;I wanted two Claude accounts running in parallel on the same Mac mini:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Account 1 (Routines):&lt;/strong&gt; my existing account, left completely untouched, so all scheduled tasks, mail connectors and morning check-ins keep running on autopilot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account 2 (Engineer):&lt;/strong&gt; a second account dedicated to hands-on coding, debugging and content work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And I needed two things most multi-account guides skip: the two accounts had to share the same project memory and skills without duplicating scheduled tasks, and they needed different icons in the macOS Dock so I wouldn't click the wrong window twenty times a day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short answer
&lt;/h2&gt;

&lt;p&gt;You don't need to log out and back in, and you don't need to migrate your existing scheduled tasks. Leave your original Claude.app untouched for routines, and launch a second instance for daily work by passing both &lt;code&gt;--user-data-dir&lt;/code&gt; (which isolates the Electron desktop app) and &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; (which isolates the Claude Code engine). To give the second window its own teal Dock icon and an "Engineer" label without breaking Apple's code signature, launch an unmodified APFS clone (&lt;code&gt;cp -cR&lt;/code&gt;) at &lt;code&gt;~/Applications/Engineer.app&lt;/code&gt; through a small launcher, and symlink only &lt;code&gt;skills&lt;/code&gt;, &lt;code&gt;agents&lt;/code&gt; and &lt;code&gt;projects&lt;/code&gt; between the two config folders.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why --user-data-dir alone isn't enough
&lt;/h2&gt;

&lt;p&gt;Most guides for running multiple Claude accounts focus either on the terminal CLI or on the chat window. If you use the Code tab inside Claude Desktop, two separate layers store your login and state:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;What it isolates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Desktop (Electron)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--user-data-dir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Desktop login, &lt;code&gt;claude_desktop_config.json&lt;/code&gt; (MCP servers), the sidebar session list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code engine&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Code tab credentials (a macOS Keychain entry), &lt;code&gt;scheduled-tasks/&lt;/code&gt;, &lt;code&gt;projects/&lt;/code&gt;, &lt;code&gt;settings.json&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Where each account keeps them:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Account 1 (Routines)&lt;/th&gt;
&lt;th&gt;Account 2 (Engineer)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Desktop&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/Library/Application Support/Claude&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/Library/Application Support/Claude-Work&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.claude&lt;/code&gt; (variable left unset)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude-work&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you only pass &lt;code&gt;--user-data-dir&lt;/code&gt;, the Desktop window opens a new account, but the Code tab inside it still uses &lt;code&gt;~/.claude&lt;/code&gt; and bills your original account. To isolate both, you have to pass both.&lt;/p&gt;

&lt;p&gt;One macOS Keychain trap: leave &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; unset for your original account. Pointing it at &lt;code&gt;~/.claude&lt;/code&gt; explicitly can make Claude Code look up a different Keychain entry than the default, so your existing login seems to disappear. Only set the variable for the second account.&lt;/p&gt;

&lt;h2&gt;
  
  
  What didn't work: editing Info.plist, and a plain AppleScript launcher
&lt;/h2&gt;

&lt;p&gt;Before landing on the working setup, I hit two dead ends that come up in almost every forum thread on this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dead end 1: editing &lt;code&gt;Info.plist&lt;/code&gt; and re-signing the app.&lt;/strong&gt; Some guides suggest duplicating &lt;code&gt;Claude.app&lt;/code&gt;, changing &lt;code&gt;CFBundleName&lt;/code&gt; and &lt;code&gt;CFBundleIdentifier&lt;/code&gt; in &lt;code&gt;Info.plist&lt;/code&gt;, replacing the binary with a wrapper script, and running &lt;code&gt;codesign&lt;/code&gt;. On recent macOS and Electron builds, modifying any file inside the signed bundle strips Anthropic's entitlements. The app crashes on launch with &lt;code&gt;EXC_BREAKPOINT (SIGTRAP)&lt;/code&gt; inside &lt;code&gt;Electron Framework&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dead end 2: a plain AppleScript launcher pointing at &lt;code&gt;/Applications/Claude.app&lt;/code&gt;.&lt;/strong&gt; An &lt;code&gt;osacompile&lt;/code&gt; applet that runs &lt;code&gt;open -n -a "/Applications/Claude.app"&lt;/code&gt; works without crashing. But even if you paste a custom icon onto the launcher in Finder, the launcher exits in a tenth of a second and &lt;code&gt;/Applications/Claude.app&lt;/code&gt; is what stays in the Dock. You end up with two identical orange Claude icons in the Dock and in window switchers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The fix: an unmodified APFS clone, a launcher and a recolored icon
&lt;/h2&gt;

&lt;p&gt;The trick is to separate the &lt;strong&gt;launcher&lt;/strong&gt; from an &lt;strong&gt;unmodified APFS clone&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy &lt;code&gt;/Applications/Claude.app&lt;/code&gt; to &lt;code&gt;~/Applications/Engineer.app&lt;/code&gt; with &lt;code&gt;cp -cR&lt;/code&gt;. On APFS this creates a clone: it finishes instantly, uses no extra disk space, and leaves every file inside &lt;code&gt;Contents/&lt;/code&gt; untouched, so Gatekeeper and Electron never complain.&lt;/li&gt;
&lt;li&gt;Attach a custom icon to the outside of the bundle with macOS's &lt;code&gt;NSWorkspace&lt;/code&gt; API. Finder stores custom icons in an extended attribute (&lt;code&gt;com.apple.FinderInfo&lt;/code&gt; and an &lt;code&gt;Icon\r&lt;/code&gt; file), outside the code-signing seal.&lt;/li&gt;
&lt;li&gt;Create a tiny launcher at &lt;code&gt;/Applications/Engineer.app&lt;/code&gt; that starts &lt;code&gt;~/Applications/Engineer.app&lt;/code&gt; with &lt;code&gt;--env "CLAUDE_CONFIG_DIR=..."&lt;/code&gt; and &lt;code&gt;--args "--user-data-dir=..."&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because the running process is &lt;code&gt;~/Applications/Engineer.app&lt;/code&gt;, the Dock shows &lt;strong&gt;its custom icon&lt;/strong&gt; and &lt;strong&gt;Engineer&lt;/strong&gt; as the tooltip.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzgjeryl19b0a8ahqj7su.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzgjeryl19b0a8ahqj7su.webp" alt="The original orange Claude app icon next to the teal Engineer clone icon, labeled routines and hands-on work" width="800" height="347"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The two icons I keep in the Dock: the original Claude app for routines, and the recolored Engineer clone for hands-on work. Both icons are taken from the apps on my Mac.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the real Dock, hovering over each icon shows its own name:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygsub1o7mpd2yjlo5c1m.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygsub1o7mpd2yjlo5c1m.webp" alt="macOS Dock with the teal Engineer icon and its Engineer tooltip, next to the orange Claude icon" width="248" height="87"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Hovering over the teal icon: Engineer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F25reqy33xqzuvo0d8rca.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F25reqy33xqzuvo0d8rca.webp" alt="macOS Dock with the orange Claude icon and its Claude tooltip, next to the teal Engineer icon" width="232" height="89"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Hovering over the orange icon: Claude.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Create the isolated Engineer app and launcher
&lt;/h3&gt;

&lt;p&gt;Open Terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkdir -p &lt;span class="s2"&gt;"$HOME/Applications"&lt;/span&gt; &lt;span class="s2"&gt;"$HOME/.claude-work"&lt;/span&gt; &lt;span class="s2"&gt;"$HOME/Library/Application Support/Claude-Work"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
rm -rf &lt;span class="s2"&gt;"$HOME/Applications/Engineer.app"&lt;/span&gt; &lt;span class="s2"&gt;"/Applications/Engineer.app"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
cp -cR &lt;span class="s2"&gt;"/Applications/Claude.app"&lt;/span&gt; &lt;span class="s2"&gt;"$HOME/Applications/Engineer.app"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
osacompile -o &lt;span class="s2"&gt;"/Applications/Engineer.app"&lt;/span&gt; \
  -e &lt;span class="s1"&gt;'do shell script "open -n -a \"$HOME/Applications/Engineer.app\" --env \"CLAUDE_CONFIG_DIR=$HOME/.claude-work\" --args \"--user-data-dir=$HOME/Library/Application Support/Claude-Work\""'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Recolor the original Claude icon to teal
&lt;/h3&gt;

&lt;p&gt;Instead of hunting for a third-party PNG, you can use macOS's built-in CoreImage (&lt;code&gt;CIHueAdjust&lt;/code&gt;) from Terminal. It takes Claude's official icon, keeps the transparent rounded corners and the white starburst, rotates the orange background 180 degrees to teal, and applies it to both &lt;code&gt;Engineer.app&lt;/code&gt; bundles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;osascript -l JavaScript -e &lt;span class="s1"&gt;'ObjC.import("Cocoa"); ObjC.import("CoreImage"); var ws = $.NSWorkspace.sharedWorkspace; var orig = ws.iconForFile("/Applications/Claude.app"); orig.setSize($.NSMakeSize(512, 512)); var ci = $.CIImage.imageWithData(orig.TIFFRepresentation); var f = $.CIFilter.filterWithName("CIHueAdjust"); f.setValueForKey(ci, "inputImage"); f.setValueForKey(3.14159, "inputAngle"); var rep = $.NSCIImageRep.imageRepWithCIImage(f.valueForKey("outputImage")); var img = $.NSImage.alloc.initWithSize($.NSMakeSize(512, 512)); img.addRepresentation(rep); ws.setIconForFileOptions(img, "/Applications/Engineer.app", 0); ws.setIconForFileOptions(img, ObjC.unwrap($.NSHomeDirectory()) + "/Applications/Engineer.app", 0);'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; killall Dock Finder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you prefer emerald green instead of blue, change &lt;code&gt;3.14159&lt;/code&gt; to &lt;code&gt;2.1&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Sign in to the second account without the deep-link mix-up
&lt;/h3&gt;

&lt;p&gt;Claude Desktop signs in through your browser and passes the login back through a &lt;code&gt;claude://&lt;/code&gt; deep link. If two Claude instances are open at the same time, macOS often hands that callback to the wrong window.&lt;/p&gt;

&lt;p&gt;For the first login only:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Quit your original Claude app (&lt;code&gt;Cmd + Q&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;Engineer&lt;/strong&gt; from &lt;code&gt;/Applications&lt;/code&gt; and sign in with your second Claude account (or use the email verification code instead of clicking the magic link).&lt;/li&gt;
&lt;li&gt;Switch to the &lt;strong&gt;Code&lt;/strong&gt; tab inside Engineer and confirm that &lt;code&gt;/status&lt;/code&gt; shows your second account.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Keeping both accounts in sync (without duplicating scheduled tasks)
&lt;/h2&gt;

&lt;p&gt;Two isolated folders mean the new account starts empty: none of your installed skills, subagents, MCP servers or conversation transcripts are there.&lt;/p&gt;

&lt;p&gt;The key is selective symlinking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ln -sfn &lt;span class="s2"&gt;"$HOME/.claude/skills"&lt;/span&gt; &lt;span class="s2"&gt;"$HOME/.claude-work/skills"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
ln -sfn &lt;span class="s2"&gt;"$HOME/.claude/agents"&lt;/span&gt; &lt;span class="s2"&gt;"$HOME/.claude-work/agents"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
ln -sfn &lt;span class="s2"&gt;"$HOME/.claude/projects"&lt;/span&gt; &lt;span class="s2"&gt;"$HOME/.claude-work/projects"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
cp &lt;span class="s2"&gt;"$HOME/Library/Application Support/Claude/claude_desktop_config.json"&lt;/span&gt; \
   &lt;span class="s2"&gt;"$HOME/Library/Application Support/Claude-Work/claude_desktop_config.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is why this split works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What stays separate (&lt;code&gt;scheduled-tasks/&lt;/code&gt; and credentials):&lt;/strong&gt; local scheduled tasks live under &lt;code&gt;~/.claude/scheduled-tasks/&amp;lt;task-name&amp;gt;/SKILL.md&lt;/code&gt;. By &lt;strong&gt;not&lt;/strong&gt; symlinking &lt;code&gt;scheduled-tasks/&lt;/code&gt;, all routines stay on Account 1. If you symlinked that folder, both open apps would fire every scheduled task twice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What is shared on disk (&lt;code&gt;skills/&lt;/code&gt;, &lt;code&gt;agents/&lt;/code&gt;, &lt;code&gt;projects/&lt;/code&gt;):&lt;/strong&gt; Claude Code stores session transcripts and per-project auto memory (&lt;code&gt;MEMORY.md&lt;/code&gt;) under &lt;code&gt;~/.claude/projects/&lt;/code&gt;, grouped by working directory, regardless of which account paid for the tokens. Symlinking &lt;code&gt;projects/&lt;/code&gt; lets either account resume or search conversations started by the other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project-level context (&lt;code&gt;CLAUDE.md&lt;/code&gt; and &lt;code&gt;AGENTS.md&lt;/code&gt;):&lt;/strong&gt; because both accounts open the same project folders on disk, shared files like &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;Now.md&lt;/code&gt; and project logs are read and updated by both accounts in real time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pairing each Claude account with its own Chrome profile
&lt;/h2&gt;

&lt;p&gt;Several of my scheduled tasks read signed-in pages in Chrome through the Claude in Chrome extension. If two Claude instances try to share a single Chrome profile, they fight over the connection.&lt;/p&gt;

&lt;p&gt;A Claude Desktop instance connects to Chrome through Anthropic's bridge and only sees Chrome extensions signed in to the &lt;strong&gt;same Claude account&lt;/strong&gt;. That makes isolating browsers straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Leave your original Chrome profile as it is.&lt;/strong&gt; Its Claude in Chrome extension is already signed in to Account 1 (Routines). Keep the web sessions your scheduled tasks read (Search Console, Bing Webmaster Tools, Telegram Web, analytics dashboards) logged in there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a second Chrome profile for Engineer.&lt;/strong&gt; Install the Claude in Chrome extension in the new profile and sign the extension in to Account 2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lock the pairing once.&lt;/strong&gt; With both Chrome profiles open, type &lt;code&gt;/chrome&lt;/code&gt; inside an Engineer Code session (or ask it to switch browser) and approve the connection in the new Chrome window. Claude remembers the paired browser for future sessions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Two gotchas to keep in mind
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Launch order matters (&lt;code&gt;Claude.app&lt;/code&gt; first, &lt;code&gt;Engineer.app&lt;/code&gt; second).&lt;/strong&gt; Both apps share the same internal &lt;code&gt;CFBundleIdentifier&lt;/code&gt;, so clicking the stock orange &lt;code&gt;Claude.app&lt;/code&gt; icon while Engineer is already running tells macOS LaunchServices to focus the running Engineer window instead of starting a new process. Always start your main &lt;code&gt;Claude.app&lt;/code&gt; first (it runs your background routines anyway, so it stays open all day), then launch &lt;code&gt;Engineer.app&lt;/code&gt;. Because the Engineer launcher passes &lt;code&gt;open -n&lt;/code&gt;, it always opens its own window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After a Claude Desktop update, refresh the clone.&lt;/strong&gt; When &lt;code&gt;/Applications/Claude.app&lt;/code&gt; auto-updates, your APFS clone at &lt;code&gt;~/Applications/Engineer.app&lt;/code&gt; stays on the previous build until you re-run the &lt;code&gt;cp -cR&lt;/code&gt; and icon commands above.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Keep Account 1 (scheduled tasks and routines) on the default &lt;code&gt;/Applications/Claude.app&lt;/code&gt; and &lt;code&gt;~/.claude&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create an unmodified APFS clone at &lt;code&gt;~/Applications/Engineer.app&lt;/code&gt; and a launcher at &lt;code&gt;/Applications/Engineer.app&lt;/code&gt; that passes both &lt;code&gt;--env "CLAUDE_CONFIG_DIR=$HOME/.claude-work"&lt;/code&gt; and &lt;code&gt;--args "--user-data-dir=$HOME/Library/Application Support/Claude-Work"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run the CoreImage one-liner to give Engineer a teal Claude icon in the Dock and window switcher.&lt;/li&gt;
&lt;li&gt;Quit the main app once, sign in to Account 2 inside Engineer, then reopen the main app.&lt;/li&gt;
&lt;li&gt;Symlink &lt;code&gt;skills&lt;/code&gt;, &lt;code&gt;agents&lt;/code&gt; and &lt;code&gt;projects&lt;/code&gt; from &lt;code&gt;~/.claude&lt;/code&gt; to &lt;code&gt;~/.claude-work&lt;/code&gt;, copy &lt;code&gt;claude_desktop_config.json&lt;/code&gt;, and leave &lt;code&gt;scheduled-tasks&lt;/code&gt; unlinked.&lt;/li&gt;
&lt;li&gt;Sign a second Chrome profile's Claude extension in to Account 2 and pair it with &lt;code&gt;/chrome&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're building AI-native workflows around your business, or want a hand setting up a system like this without breaking your existing tools, &lt;a href="https://blog.yunuserturk.com/run-two-claude-desktop-accounts-mac/" rel="noopener noreferrer"&gt;get in touch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.yunuserturk.com/run-two-claude-desktop-accounts-mac/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>macos</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Claimed My Business in ChatGPT. Here's What Actually Happens</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Thu, 12 Nov 2026 06:08:04 +0000</pubDate>
      <link>https://dev.to/yunuserturk/i-claimed-my-business-in-chatgpt-heres-what-actually-happens-3g1m</link>
      <guid>https://dev.to/yunuserturk/i-claimed-my-business-in-chatgpt-heres-what-actually-happens-3g1m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Status, November 10, 2026:&lt;/strong&gt; Claim submitted, under review. I’ll update this post as it moves, with dates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On November 10, OpenAI launched Businesses in ChatGPT. Businesses can now claim their profile in ChatGPT, update their details, add product feeds, and see how often ChatGPT mentions them. In the US, eligible ecommerce and online service businesses can also build a Business Agent that customers can chat with.&lt;/p&gt;

&lt;p&gt;I claimed my company, terspective, the same evening and took a screenshot of every step. Here’s what the process looks like, what you can and can’t do right after claiming, and the one thing I’d check before you start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short answer
&lt;/h2&gt;

&lt;p&gt;Go to Business Hub (chatgpt.com/business-hub), search for your business, and verify that you control it, either with a code to your business phone or with a DNS TXT record on your domain. With DNS it took me about fifteen minutes, and most of that was writing this down. The claim then goes into review. Editing your profile, adding your website and uploading products all need an extra identity check with a government-issued ID. And the insights start empty.&lt;/p&gt;

&lt;p&gt;Before you claim, make sure ChatGPT can actually read your website. Business Hub crawls the site you save to your profile, and if your server blocks OpenAI’s crawlers, that part won’t work. I found exactly that problem on this blog two days earlier: &lt;a href="https://blog.yunuserturk.com/can-chatgpt-read-your-website/" rel="noopener noreferrer"&gt;Can ChatGPT Read Your Website?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Businesses in ChatGPT is
&lt;/h2&gt;

&lt;p&gt;From OpenAI’s announcement and FAQ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claim and update.&lt;/strong&gt; Once verified, you can update key details and add product feeds with pricing and availability. ChatGPT may use this information when answering questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insights.&lt;/strong&gt; Mentions, profile views and website clicks, plus “discovery topics”, the common themes in conversations where your business comes up. Everything is aggregated and only shows up after a minimum amount of activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blue check.&lt;/strong&gt; A claimed profile gets a blue check in ChatGPT.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business Agents.&lt;/strong&gt; A labeled chat with your business, separate from ChatGPT’s own answer. For now, US ecommerce and online service businesses only. Agents can also be promoted as a ChatGPT Ads destination.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No ranking boost.&lt;/strong&gt; OpenAI’s FAQ says claiming does not guarantee higher placement or sales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who can claim.&lt;/strong&gt; Businesses with a website, in countries where ChatGPT is available, subject to industry, location and verification checks. You need to own the business or be authorized to represent it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I claimed my business, step by step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Search for your business
&lt;/h3&gt;

&lt;p&gt;I searched for “terspective” in Business Hub. ChatGPT already had a profile for it before I claimed anything: the name, a Directions button, and an address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5urqimc93omxxhsjb8ep.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5urqimc93omxxhsjb8ep.jpg" alt="Business Hub window offering to claim terspective in ChatGPT, noting that you need to verify you are authorized" width="417" height="605"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Searching for my company in Business Hub. ChatGPT already had a profile for it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That address is the one from my company’s registration, not where I work. Nobody at OpenAI asked me for it. ChatGPT had pulled it from somewhere public. This alone is a good reason to claim: your business may already have a profile in ChatGPT with details you never chose.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Confirm the account
&lt;/h3&gt;

&lt;p&gt;The next screen links the business to the ChatGPT account you’re logged in with. Pick the account you want to manage the profile with before you continue. Moving it later may not be simple. Continuing also accepts the Businesses in ChatGPT terms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuovb6ezam5clx3plkvp5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuovb6ezam5clx3plkvp5.jpg" alt="Claim screen that links the business to the logged-in ChatGPT account, with the existing profile card on the right" width="800" height="286"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The claim is tied to the ChatGPT account you’re logged in with. Continuing accepts the Businesses in ChatGPT terms.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My account is on the free plan. Claiming didn’t need a paid plan.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Choose how to verify
&lt;/h3&gt;

&lt;p&gt;Two options:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffguskq3nexk8hpme7g4o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffguskq3nexk8hpme7g4o.jpg" alt="Verification options in Business Hub: business phone or website domain" width="800" height="286"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Two ways to verify: a code to your business phone, or your domain.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Business phone:&lt;/strong&gt; a code by text or phone call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Website domain:&lt;/strong&gt; prove you control your domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose the domain. The option mentions “DNS or your website”, but the next screen only gave me a DNS TXT record.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Add the DNS TXT record
&lt;/h3&gt;

&lt;p&gt;Business Hub shows a TXT record:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo96h95jmieuqbll75av7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo96h95jmieuqbll75av7.jpg" alt="DNS TXT record to add, named openai-business-claim, with the token value hidden and an expiry about 24 hours later" width="800" height="286"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The TXT record Business Hub asks for. The token is hidden here.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;TXT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openai-business-claim.yourdomain.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;openai-business-claim=&lt;/code&gt; followed by a token&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The record expires after about 24 hours, so add it in one go.&lt;/p&gt;

&lt;p&gt;My domain’s DNS is on Cloudflare: DNS → Records → Add record, type TXT, name &lt;code&gt;openai-business-claim&lt;/code&gt; (Cloudflare adds the domain itself), the value pasted exactly, TTL Auto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmffz7p5k05qmau91zp3c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmffz7p5k05qmau91zp3c.jpg" alt="Cloudflare Add record dialog with a TXT record named openai-business-claim" width="665" height="393"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Adding the record in Cloudflare. Cloudflare appends the domain to the name.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To check that it’s live before you click verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig +short TXT openai-business-claim.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mine showed up within seconds on Cloudflare’s own nameserver, 1.1.1.1 and 8.8.8.8. With other DNS providers it can take longer.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Verify, then wait
&lt;/h3&gt;

&lt;p&gt;After “Verify domain” there was no instant approval. The screen showed three steps: claim received, review in progress, decision reached, and said the decision would come by email. You can withdraw the claim during the review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3pxnnjqdu5ogiiwlx164.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3pxnnjqdu5ogiiwlx164.jpg" alt="Claim status screen: claim received, review in progress, decision by email" width="800" height="286"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;No instant approval: the claim goes into review and the decision comes by email.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. What Business Hub looks like during review
&lt;/h3&gt;

&lt;p&gt;This part was confusing. The business list says “Pending”, but opening the profile shows a blue check and “You’ve claimed terspective”, with three options: start chatting with customers, manage your business, and a $500 credit for ChatGPT Ads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbs8cm338oa901j8n2qdi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbs8cm338oa901j8n2qdi.jpg" alt="Business Hub business list showing terspective as Pending" width="730" height="170"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The business list says Pending…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9gu5acakr7vq9005sivd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9gu5acakr7vq9005sivd.jpg" alt="Screen saying You've claimed terspective, with a blue check and a 500 dollar ChatGPT Ads credit offer" width="490" height="470"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;…while the profile itself says claimed, with a blue check and a $500 ads credit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So “claimed” and “verified” aren’t the same thing yet. Here’s what I could and couldn’t do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Edit business info:&lt;/strong&gt; locked. A banner asks for identity verification with a government-issued ID before editing or publishing an agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add website:&lt;/strong&gt; “Website access” shows “No website”, and Add website opens the verification prompt. Trying it during review gives “Your business verification is still being processed.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Products:&lt;/strong&gt; also needs the ID check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent builder:&lt;/strong&gt; “isn’t available yet”, rolling out gradually, even though terspective is a US company that sells online services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insights:&lt;/strong&gt; mentions, profile views and website clicks, 7 or 28 days, all empty. Discovery topics: empty until there are “enough mentions”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz3jwa06io2ohphdm61a4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz3jwa06io2ohphdm61a4.jpg" alt="Business Hub overview asking for identity verification with a government-issued ID, with empty mentions, profile views and website clicks" width="800" height="493"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Editing is locked behind an ID check, and the insights start empty.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg0xwn1dbwskvappfwmuv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg0xwn1dbwskvappfwmuv.jpg" alt="Website access showing no website, and an empty top 5 discovery topics chart" width="800" height="493"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;No website on the profile yet, and no discovery topics.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fweo9vkq918hise8mumru.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fweo9vkq918hise8mumru.jpg" alt="Verify your business prompt that opens when clicking Add website" width="800" height="493"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Add website opens the verification prompt.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnq0ii07sii3dd6umvl0f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnq0ii07sii3dd6umvl0f.jpg" alt="Products page in Business Hub asking for identity verification before uploading products" width="800" height="493"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Product uploads need the same ID check.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fknhqswmq7amivkfjtvfl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fknhqswmq7amivkfjtvfl.jpg" alt="Agent builder page saying it isn't available yet and is rolling out gradually" width="800" height="493"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Agent builder isn’t available for my business yet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The definitions in the panel are useful: data is daily in UTC, profile views count opens of your profile in ChatGPT, and website clicks count clicks on the website link in that profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you claim: can ChatGPT read your site?
&lt;/h2&gt;

&lt;p&gt;Under “Website access”, Business Hub says the status reflects the saved website URL, and that “a re-crawl also visits eligible linked pages.” In plain words: OpenAI will crawl the website you add to your profile.&lt;/p&gt;

&lt;p&gt;If your server blocks OpenAI’s crawlers, that crawl fails. You won’t see an error on your site, and your robots.txt can look perfectly fine. That’s what happened on this blog. My hosting server answered ChatGPT’s crawlers with 403 Forbidden while Google got in without a problem. I wrote up how I found it and fixed it here: &lt;a href="https://blog.yunuserturk.com/can-chatgpt-read-your-website/" rel="noopener noreferrer"&gt;Can ChatGPT Read Your Website?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The quickest check takes a minute. Open ChatGPT logged out and ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Open this exact page and summarize it in 3 bullet points. If you cannot open it, tell me exactly what error you got: &lt;a href="https://yoursite.com/" rel="noopener noreferrer"&gt;https://yoursite.com/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If it can’t open your page, fix that first. Claiming your profile won’t change it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Search for your business in Business Hub and see what ChatGPT already shows about you.&lt;/li&gt;
&lt;li&gt;Log in with the account that should own the profile before you continue.&lt;/li&gt;
&lt;li&gt;Verify by phone or with a DNS TXT record; check the record with &lt;code&gt;dig&lt;/code&gt; before you click verify.&lt;/li&gt;
&lt;li&gt;Expect a review, and an ID check before you can edit anything.&lt;/li&gt;
&lt;li&gt;Make sure ChatGPT can read your site before you add it.&lt;/li&gt;
&lt;li&gt;Correct anything wrong in your profile once editing opens up.&lt;/li&gt;
&lt;li&gt;Check insights after a few weeks, not on day one.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;November 10, 2026:&lt;/strong&gt; claim submitted with DNS verification; under review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If ChatGPT can’t read your site, or it describes your business wrong and you’d rather have someone sort it out, &lt;a href="https://blog.yunuserturk.com/claim-your-business-in-chatgpt/" rel="noopener noreferrer"&gt;get in touch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.yunuserturk.com/claim-your-business-in-chatgpt/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>seo</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Can ChatGPT Read Your Website? How I Found a Block My robots.txt Didn't Show</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Mon, 09 Nov 2026 08:02:48 +0000</pubDate>
      <link>https://dev.to/yunuserturk/can-chatgpt-read-your-website-how-i-found-a-block-my-robotstxt-didnt-show-54l8</link>
      <guid>https://dev.to/yunuserturk/can-chatgpt-read-your-website-how-i-found-a-block-my-robotstxt-didnt-show-54l8</guid>
      <description>&lt;p&gt;I wanted to know if ChatGPT ever cites my blog. So I asked it a few questions my posts answer, like "Can I host WordPress on Vercel?". &lt;a href="https://blog.yunuserturk.com/how-to-host-wordpress-for-free-on-vercel-a-step-by-step-guide/" rel="noopener noreferrer"&gt;My post on that&lt;/a&gt; ranks on the first page of Google. ChatGPT cited Vercel's docs, WordPress.org and a couple of other blogs. Not mine.&lt;/p&gt;

&lt;p&gt;Before trying to "optimize" anything, I checked something simpler: can ChatGPT read my site at all?&lt;/p&gt;

&lt;p&gt;It couldn't. And robots.txt had nothing to do with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short answer
&lt;/h2&gt;

&lt;p&gt;Ask ChatGPT to open one of your pages and summarize it. If it says it got a 403, something is blocking it. That block can be in robots.txt, a security plugin, Cloudflare, or, in my case, a rule on the hosting server that I had no access to. You can confirm it in a minute with &lt;code&gt;curl&lt;/code&gt;, and you can usually fix it without moving hosts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The easiest test: ask ChatGPT to open a page
&lt;/h2&gt;

&lt;p&gt;Open ChatGPT in a private window, logged out, so your own account doesn't change the answer. Then paste:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Open this exact page and summarize it in 3 bullet points. If you cannot open it, tell me exactly what error you got: &lt;a href="https://yoursite.com/some-post/" rel="noopener noreferrer"&gt;https://yoursite.com/some-post/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's what I got for my &lt;a href="https://blog.yunuserturk.com/run-wordpress-on-vercel-serverlesswp/" rel="noopener noreferrer"&gt;ServerlessWP post&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Failed to fetch &lt;a href="https://blog.yunuserturk.com/run-wordpress-on-vercel-serverlesswp/:" rel="noopener noreferrer"&gt;https://blog.yunuserturk.com/run-wordpress-on-vercel-serverlesswp/:&lt;/a&gt; (403) Forbidden&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffsdl8iebq0av3xrkd8ll.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffsdl8iebq0av3xrkd8ll.jpg" alt="ChatGPT answer after failing to open the page" width="800" height="917"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The end of a later 403 answer: ChatGPT couldn't open the post, so it explained the topic from other sources and said so.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's the whole test. If ChatGPT can't fetch your page when you hand it the URL, it can't use that page as a source when someone else asks a question.&lt;/p&gt;

&lt;p&gt;If you get a proper summary instead, your page is readable. Whether ChatGPT picks it as a source is a separate problem (more on that at the end).&lt;/p&gt;
&lt;h2&gt;
  
  
  Why robots.txt said everything was fine
&lt;/h2&gt;

&lt;p&gt;The first thing everyone checks is robots.txt. Mine allowed every bot. No &lt;code&gt;Disallow&lt;/code&gt; lines for GPTBot or anything else.&lt;/p&gt;

&lt;p&gt;robots.txt is a polite request. It tells well-behaved crawlers what you'd like them to skip. It doesn't block anything. A real block happens on the server: the request comes in, something looks at it, and sends back a 403 before WordPress even loads.&lt;/p&gt;

&lt;p&gt;So robots.txt can look perfect while the server is turning bots away.&lt;/p&gt;
&lt;h2&gt;
  
  
  Checking with curl
&lt;/h2&gt;

&lt;p&gt;A crawler identifies itself with a user agent string. You can send the same string yourself and see what your server does with it. Compare a normal request with ChatGPT's search crawler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -s -o /dev/null -w "%{http_code}\n" https://yoursite.com/robots.txt
curl -s -o /dev/null -w "%{http_code}\n" -A "OAI-SearchBot/1.3" https://yoursite.com/robots.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first should print 200. If the second prints 403, your server is blocking that crawler.&lt;/p&gt;

&lt;p&gt;I ran it with a few user agents. Same page, same moment:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User agent&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Normal browser, Googlebot, Bingbot&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OAI-SearchBot (ChatGPT search)&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ChatGPT-User (ChatGPT opening a link)&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPTBot (OpenAI training)&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ClaudeBot, PerplexityBot&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AhrefsBot, SemrushBot&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Google could read the site. ChatGPT, Claude and Perplexity couldn't. Neither could the two biggest SEO tools, which I hadn't noticed either.&lt;/p&gt;

&lt;p&gt;Three OpenAI names are worth knowing. OAI-SearchBot builds the index ChatGPT search uses. ChatGPT-User is what fetches a page when a user asks about it. GPTBot collects training data. Blocking one doesn't block the others, and you can allow search while blocking training if you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding where the block was
&lt;/h2&gt;

&lt;p&gt;The 403 page was the web server's generic error page, not a WordPress page. That already says WordPress isn't the one saying no. I went through the usual suspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WordPress plugins:&lt;/strong&gt; no security plugin with bot rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.htaccess:&lt;/strong&gt; only LiteSpeed Cache and the standard WordPress rewrite rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ModSecurity (the firewall in the hosting panel):&lt;/strong&gt; enabled, but its audit log was empty right after I triggered a 403. If ModSecurity had blocked the request, it would be logged there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Another site on the same server:&lt;/strong&gt; same 403 for the same bots.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one settled it. A different site, owned by someone else, on the same server, behaved the same way. The rule was on the server itself, a list of "bad bots" the host maintains. On a shared hosting account you can't see or change it.&lt;/p&gt;

&lt;p&gt;Testing more user agents showed how the list works: it matches on the name. GPTBot was blocked; a made-up "MyRandomBot" wasn't. Claude-User and Perplexity-User (the ones that fetch a page when a person asks) got through, while their crawlers didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Option 1: ask your host.&lt;/strong&gt; This is the obvious first step, and I did it. But shared hosts are often unwilling to change a server-wide rule for one customer, and you may wait days for an answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: put Cloudflare in front and pass the AI crawlers through.&lt;/strong&gt; This is what I did. The blog now sits behind Cloudflare. A small Cloudflare Worker looks at each request: normal visitors pass through untouched; requests from the AI crawlers are forwarded to my server with a neutral user agent, so the host's list doesn't match them. Everything else about the site stays where it is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukqqt5g7ke2uj44ud8ie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukqqt5g7ke2uj44ud8ie.png" alt="Cloudflare Worker code" width="800" height="509"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Worker, in the editor.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AI_AGENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/oai-searchbot|chatgpt-user|gptbot|perplexitybot|claudebot/i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ua&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;AI_AGENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mozilla/5.0 (compatible; Relay/1.0)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Worker runs on a route for the blog's hostname only, with "fail open" on. Cloudflare's free plan covers 100,000 Worker requests a day, far more than a small blog needs, and with fail open, if that limit is ever reached, requests skip the Worker and go straight to the server instead of showing an error.&lt;/p&gt;

&lt;p&gt;A few things that almost went wrong, so you can skip them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Moving DNS to Cloudflare can break your email.&lt;/strong&gt; When Cloudflare imports your records, it turns on its proxy (the orange cloud) for the root domain, &lt;code&gt;mail&lt;/code&gt;, &lt;code&gt;ftp&lt;/code&gt; and &lt;code&gt;www&lt;/code&gt; by default, and the import screen has "Proxy imported DNS records" ticked. Mail doesn't work through that proxy. I left only the blog proxied and everything else "DNS only".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check your new Cloudflare settings for bot blocking.&lt;/strong&gt; Bot Fight Mode would block the same crawlers again. I kept it off, and set the AI crawler settings to Allow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL mode:&lt;/strong&gt; Full (strict), since the server already had a valid certificate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your site is already on Cloudflare and you still see 403s for AI crawlers, look at those bot settings first. That's the most common cause I've seen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqm20mgfoaapa0razmfnb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqm20mgfoaapa0razmfnb.jpg" alt="Cloudflare DNS import with records set to Proxied" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;After the import, the root domain, ftp, mail and www were all set to Proxied.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8zws6frvvdparxu6c932.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8zws6frvvdparxu6c932.jpg" alt="Cloudflare import screen with Proxy imported DNS records ticked" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The import screen ticks "Proxy imported DNS records" for you. Untick it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdpfpu8nnnam64sy1bg9o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdpfpu8nnnam64sy1bg9o.jpg" alt="Cloudflare AI crawler policies set to Allow" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;AI crawler policies when adding the domain: all set to Allow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8h22zmxnkxus376mmdn6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8h22zmxnkxus376mmdn6.jpg" alt="Cloudflare Bot Fight Mode off" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Bot Fight Mode and AI Labyrinth off.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuma3fk9nzres6ek7td20.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuma3fk9nzres6ek7td20.jpg" alt="Cloudflare SSL/TLS Full (strict)" width="799" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;SSL/TLS set to Full (strict).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Did it work?
&lt;/h2&gt;

&lt;p&gt;Same curl test, before and after, same moment:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User agent&lt;/th&gt;
&lt;th&gt;Direct to server&lt;/th&gt;
&lt;th&gt;Through Cloudflare&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OAI-SearchBot&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ChatGPT-User&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPTBot&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PerplexityBot&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ClaudeBot&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Googlebot&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And the test that matters: I asked ChatGPT to open the same post again. This time it gave me the title, author, date and a correct summary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg7ubd230rpumudrikgww.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg7ubd230rpumudrikgww.jpg" alt="ChatGPT summarizing the post after the fix" width="800" height="917"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;After the fix: ChatGPT opens the post and summarizes it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One note if you test right after a DNS change: for a while some resolvers still point to the old server. My first ChatGPT retry still got a 403. A few minutes later it worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  While I was in there: Bing
&lt;/h2&gt;

&lt;p&gt;ChatGPT search leans on Bing's index, so I added the blog to Bing Webmaster Tools. Two surprises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My ServerlessWP post had been "Discovered but not crawled" since the day I published it.&lt;/li&gt;
&lt;li&gt;Two other posts were marked "Not indexed as this page is a redirect". The blog had a redirect problem weeks earlier, which I fixed, but Bing hadn't been back since.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21digzahuy94kj1a0few.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21digzahuy94kj1a0few.jpg" alt="Bing URL Inspection: Discovered but not crawled" width="800" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Discovered on publish day, never crawled.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3ov1hm6drk3ptpc0azk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3ov1hm6drk3ptpc0azk.jpg" alt="Bing URL Inspection: Not indexed as this page is a redirect" width="800" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Bing still thought this post was a redirect.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I requested indexing for all three. Bing Webmaster also has an "AI Performance" report that shows how often Microsoft's AI products cite your pages. Mine showed zero for the last three months.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6995u9z6m84ohhvxv7w8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6995u9z6m84ohhvxv7w8.jpg" alt="Bing AI Performance: zero citations" width="800" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;AI Performance: zero citations in three months.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you've never opened Bing Webmaster Tools, it's worth ten minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Ask ChatGPT, logged out, to open and summarize one of your pages. 403 or "couldn't access" means a block.&lt;/li&gt;
&lt;li&gt;Run curl with &lt;code&gt;OAI-SearchBot/1.3&lt;/code&gt; and compare with a normal request.&lt;/li&gt;
&lt;li&gt;Check robots.txt, but don't stop there.&lt;/li&gt;
&lt;li&gt;Check security plugins and Cloudflare bot settings (Bot Fight Mode, AI crawler settings).&lt;/li&gt;
&lt;li&gt;Check whether another site on the same server behaves the same way. If it does, the rule is your host's.&lt;/li&gt;
&lt;li&gt;Ask your host, or route the AI crawlers through Cloudflare as above.&lt;/li&gt;
&lt;li&gt;Repeat step 1 to confirm.&lt;/li&gt;
&lt;li&gt;Add the site to Bing Webmaster Tools and check that your important pages are indexed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Readable isn't the same as cited
&lt;/h2&gt;

&lt;p&gt;Fixing this didn't make ChatGPT cite my posts. It made it possible. The same day, I asked nine questions my blog answers. ChatGPT now reads the pages, but for the topic questions it still cites other sources, and for "Can I run real WordPress on Vercel?" it still says "not natively", which my own test shows isn't true.&lt;/p&gt;

&lt;p&gt;That's the second part of this experiment, and I'm measuring it every week. I'll write up what changes, with the numbers, in a follow-up post.&lt;/p&gt;

&lt;p&gt;If ChatGPT can't read your site, or it describes your business wrong and you'd rather have someone sort it out, &lt;a href="https://blog.yunuserturk.com/can-chatgpt-read-your-website/" rel="noopener noreferrer"&gt;get in touch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.yunuserturk.com/can-chatgpt-read-your-website/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>seo</category>
      <category>cloudflare</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Ran Real WordPress on Vercel with ServerlessWP. Here's What Broke.</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Sun, 08 Nov 2026 13:27:22 +0000</pubDate>
      <link>https://dev.to/yunuserturk/i-ran-real-wordpress-on-vercel-with-serverlesswp-heres-what-broke-4mil</link>
      <guid>https://dev.to/yunuserturk/i-ran-real-wordpress-on-vercel-with-serverlesswp-heres-what-broke-4mil</guid>
      <description>&lt;p&gt;In my &lt;a href="https://blog.yunuserturk.com/how-to-host-wordpress-for-free-on-vercel-a-step-by-step-guide/" rel="noopener noreferrer"&gt;guide to hosting WordPress for free on Vercel&lt;/a&gt;, WordPress never actually runs on Vercel. You build the site locally, export it to static HTML, and Vercel serves the files.&lt;/p&gt;

&lt;p&gt;That works for brochure sites. But readers who tried it have asked me a different question: &lt;em&gt;can I keep the WordPress admin online, on Vercel, and just log in and edit?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ServerlessWP says yes. It runs the real WordPress inside Vercel’s serverless functions, with the database stored as a SQLite file. So I deployed it, used it like a site owner would, and measured what happened.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short answer (tested October 2026)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, you can run real WordPress on Vercel, with PHP and the admin dashboard, using ServerlessWP. My deployment was live about 60 seconds after clicking Deploy. Publishing a post took under half a second, and admin pages loaded in about 0.4 seconds.&lt;/p&gt;

&lt;p&gt;The trade-offs: you can’t install plugins from the dashboard, contact forms need a separate mail service, simultaneous saves can fail because the database is a single SQLite file, the first visit after about 20 quiet minutes took 8 seconds, and the free Vercel Blob plan includes 2,000 write operations a month.&lt;/p&gt;

&lt;p&gt;Good for a low-traffic personal site. For a business site with several editors, a shop or busy forms, use ServerlessWP’s MySQL option or regular WordPress hosting.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is ServerlessWP?
&lt;/h2&gt;

&lt;p&gt;ServerlessWP is an open-source project that runs WordPress on serverless platforms (Vercel, Netlify or AWS Lambda) instead of an always-on server. On Vercel, each page request starts PHP in a function, loads WordPress, and returns the page.&lt;/p&gt;

&lt;p&gt;There’s no MySQL server. The database is a SQLite file kept in Vercel Blob storage, and media uploads go to the same Blob store. Vercel lists it as an official template, and the project describes itself as experimental.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Static export (my earlier guide)&lt;/th&gt;
&lt;th&gt;ServerlessWP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What runs on Vercel&lt;/td&gt;
&lt;td&gt;Plain HTML files&lt;/td&gt;
&lt;td&gt;WordPress itself (PHP 8.3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WordPress admin online&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;None on Vercel&lt;/td&gt;
&lt;td&gt;SQLite file in Vercel Blob&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit a post&lt;/td&gt;
&lt;td&gt;Edit locally, re-export, push&lt;/td&gt;
&lt;td&gt;Log in and edit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How long does the setup take?
&lt;/h2&gt;

&lt;p&gt;About a minute of waiting. The project’s README has a “Deploy with Vercel” button that does everything:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the button and pick your GitHub account. It copies the project into a new private repository.&lt;/li&gt;
&lt;li&gt;Add the Blob store Vercel asks for (private access is the default; keep it).&lt;/li&gt;
&lt;li&gt;Leave the two pre-filled environment variables as they are and click &lt;strong&gt;Deploy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open your new &lt;code&gt;.vercel.app&lt;/code&gt; address and run the normal WordPress installer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vlgqa9swqxq9xlhazl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vlgqa9swqxq9xlhazl8.png" alt="Vercel New Project screen cloning the ServerlessWP repository into a private GitHub repository" width="785" height="561"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Deploy with Vercel button copies ServerlessWP into a new private repository in your GitHub account.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My deployment was live about 60 seconds after I clicked Deploy.&lt;/p&gt;

&lt;p&gt;One thing went wrong on the first run, and it’s worth knowing about. Right after deployment, Vercel’s success page loads your site several times at once to make a preview. Those simultaneous requests all tried to create the database file, and the logs showed &lt;code&gt;This blob already exists&lt;/code&gt;. I fixed it by giving the database a new file name (the &lt;code&gt;SQLITE_BLOB_PATHNAME&lt;/code&gt; environment variable) and redeploying. After that, the installer opened normally.&lt;/p&gt;

&lt;h2&gt;
  
  
  What works
&lt;/h2&gt;

&lt;p&gt;I tested the things a small business site owner does every week.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Write and publish a post&lt;/td&gt;
&lt;td&gt;Works. Saved in under half a second and visible on the site immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upload an image&lt;/td&gt;
&lt;td&gt;Works. Took about 2.4 seconds; WordPress generated the usual thumbnail sizes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stay logged in&lt;/td&gt;
&lt;td&gt;Works. Ten admin pages in a row, no logouts, about 0.4 seconds each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redeploy the site&lt;/td&gt;
&lt;td&gt;Posts and images survive, because the database and uploads live in Blob storage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a site where one person writes a few posts a month, the admin feels like normal WordPress.&lt;/p&gt;

&lt;h2&gt;
  
  
  What doesn’t work the way you expect
&lt;/h2&gt;

&lt;h3&gt;
  
  
  You can’t install plugins from the dashboard
&lt;/h3&gt;

&lt;p&gt;There’s no Add New button on the Plugins screen. Instead, ServerlessWP shows a notice: &lt;em&gt;“Direct plugin installation is not currently possible with serverless functions.”&lt;/em&gt; Open the install page directly and WordPress answers &lt;em&gt;“Sorry, you are not allowed to access this page.”&lt;/em&gt; That’s deliberate: ServerlessWP’s &lt;code&gt;wp-config.php&lt;/code&gt; sets &lt;code&gt;DISALLOW_FILE_MODS&lt;/code&gt;, because anything written to the function’s disk disappears on the next deployment.&lt;/p&gt;

&lt;p&gt;To add a plugin, you put its folder in the repository (&lt;code&gt;wp/wp-content/plugins/&lt;/code&gt;), commit and push. Vercel redeploys automatically. I added Contact Form 7 this way, and it appeared in the plugin list about a minute after the push. Then you activate it in the dashboard as usual.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2dlxnbauw8thb0t8d676.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2dlxnbauw8thb0t8d676.png" alt="WordPress Plugins screen on ServerlessWP with a notice that direct plugin installation is not possible, and Contact Form 7 installed through Git" width="799" height="296"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;No Add New button: ServerlessWP explains that plugins go through the Git repository. Contact Form 7 here was added with a commit and push.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It works, but it means every plugin, theme and update goes through GitHub. If the person running the site has never used Git, that’s a real barrier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contact forms don’t send email
&lt;/h3&gt;

&lt;p&gt;Contact Form 7 accepted my test submission, then returned &lt;em&gt;“There was an error trying to send your message”&lt;/em&gt;. The serverless environment has no mail server for PHP to hand messages to. You need an SMTP plugin connected to a sending service (Postmark, Mailgun, Amazon SES and so on), installed through the repository like any other plugin. The sending domain also needs SPF and DKIM records, or the messages that do go out will land in spam; I covered that in &lt;a href="https://blog.yunuserturk.com/fix-emails-go-to-spam-after-domain-migration/" rel="noopener noreferrer"&gt;why emails go to spam after a domain migration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff9vp8ijqi0yiuqxam1fz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff9vp8ijqi0yiuqxam1fz.png" alt="Contact Form 7 on ServerlessWP showing the error There was an error trying to send your message" width="703" height="562"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;My test submission: the form works, the email does not.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On a business site this matters more than anything else on this list: a contact form that can’t deliver messages is a lost lead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simultaneous saves can fail
&lt;/h3&gt;

&lt;p&gt;SQLite is a single file, and ServerlessWP saves the whole file back to Blob storage after a write. I tested this directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 comments sent one after another: all 3 saved.&lt;/li&gt;
&lt;li&gt;5 comments sent at the same moment: 4 saved, 1 failed with a server error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing was lost silently: the failed request reported its error. But it confirms the project’s own advice: SQLite is fine for light activity, and sites with several editors, busy forms, shops or memberships should use the MySQL option instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first visit after a quiet period is slow
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Time to first byte&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First visit after ~20 minutes with no traffic&lt;/td&gt;
&lt;td&gt;8.0 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next visits&lt;/td&gt;
&lt;td&gt;0.9 to 1.3 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There’s no page cache by default (every visit runs PHP), and the function lives in Vercel’s Washington region unless you change it. A low-traffic site will regularly show its first visitor an 8-second wait.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch the free Blob limit
&lt;/h3&gt;

&lt;p&gt;Every time WordPress writes to the database, the SQLite file is uploaded to Blob storage again, and each upload counts as an “advanced operation”. My 15 minutes of testing used 116 of them. The free plan includes 2,000 per month, and Vercel’s documentation says that when you go over, Blob storage stays unavailable until 30 days have passed. With the database in Blob storage, the site stops working until then.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqzcn1egqaetrucyxrt0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqzcn1egqaetrucyxrt0b.png" alt="Vercel usage panel showing Blob simple and advanced operations for the ServerlessWP test project" width="799" height="337"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Blob usage on the test project after about an hour of testing, including the screenshots for this post.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you use ServerlessWP?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your site&lt;/th&gt;
&lt;th&gt;My take&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Personal blog or portfolio, one editor, you’re comfortable with GitHub&lt;/td&gt;
&lt;td&gt;Good fit. Free to run at low traffic, and the admin works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Business site with a contact form&lt;/td&gt;
&lt;td&gt;Possible, but plan for SMTP setup, Git-based plugin installs and the slow first visit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Several editors, a shop, memberships, busy forms&lt;/td&gt;
&lt;td&gt;Use the MySQL option, or regular WordPress hosting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want “WordPress, but free” and never want to touch Git&lt;/td&gt;
&lt;td&gt;Regular hosting will cost you less time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;ServerlessWP is the closest thing to real WordPress on Vercel, and for what it is, it works. The setup takes a minute. Running it as a business site takes more: a mail service, a Git workflow for plugins and updates, and an eye on usage limits.&lt;/p&gt;

&lt;p&gt;If you’ve deployed ServerlessWP or a static WordPress site on Vercel and got stuck on forms, plugins or speed, &lt;a href="https://blog.yunuserturk.com/run-wordpress-on-vercel-serverlesswp/" rel="noopener noreferrer"&gt;get in touch on my blog&lt;/a&gt;. Tell me what your site needs to do and I’ll tell you which setup fits.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>vercel</category>
      <category>serverless</category>
      <category>php</category>
    </item>
    <item>
      <title>Use Custom Domain Email On Gmail, with ImprovMX and Sendgrid</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Sun, 29 Sep 2024 09:50:16 +0000</pubDate>
      <link>https://dev.to/yunuserturk/use-custom-domain-email-on-gmail-with-improvmx-and-sendgrid-168f</link>
      <guid>https://dev.to/yunuserturk/use-custom-domain-email-on-gmail-with-improvmx-and-sendgrid-168f</guid>
      <description>&lt;p&gt;Creating a professional email address using your domain or company's domain name is crucial to publishing credibility for your business or personal brand. In this guide, we'll walk you through setting up a custom email using ImprovMX for email forwarding and SendGrid for sending emails. This approach is straightforward, cost-effective, and doesn't require you to host your own mail server. You can make it totally for free. And i will make you with this guide to my own domain&amp;nbsp;&lt;a href="http://yunuserturk.com/" rel="noopener noreferrer"&gt;yunuserturk.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use ImprovMX and SendGrid?
&lt;/h2&gt;

&lt;p&gt;ImprovMX is a fantastic tool for email forwarding. It allows you to receive emails sent to your custom domain and forward them to your existing email address, all for free. On the other hand, SendGrid provides a robust and reliable solution for sending emails, with powerful APIs that allow you to manage email sending easily. And these are not too much technical stuff to achieve.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Need
&lt;/h2&gt;

&lt;p&gt;Before we dive into the setup, here are the prerequisites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;A registered domain name&lt;/strong&gt;: If you don't have one, you can purchase one from domain registrars like Namecheap or GoDaddy.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;ImprovMX account&lt;/strong&gt;:&amp;nbsp;&lt;a href="https://improvmx.com/" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt;&amp;nbsp;for a free account.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;SendGrid account&lt;/strong&gt;:&amp;nbsp;&lt;a href="https://sendgrid.com/" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt;&amp;nbsp;for a free account.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Gmail account.&lt;/strong&gt;&amp;nbsp;I'm sure that you already have 🙂&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1: Set Up Email Forwarding with ImprovMX
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Sign in to ImprovMX&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;After signing up, log in to your ImprovMX account.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Add your domain&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Enter your domain name in the ImprovMX dashboard. ImprovMX will provide you with MX records that you'll need to add to your domain's DNS settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00d87qa6hwd5aorpib5t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00d87qa6hwd5aorpib5t.png" alt="Set Up Email Forwarding with ImprovMX" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. Update DNS records&lt;/strong&gt;:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojfhyv2w27ibnuteqcwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojfhyv2w27ibnuteqcwr.png" alt="Update DNS records" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You will see this screen on ImprovMX.&lt;/li&gt;
&lt;li&gt;  Go to your domain registrar's DNS settings (this is usually found in the domain management section).&lt;/li&gt;
&lt;li&gt;  Add the MX records provided by ImprovMX. These records should look something like:

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;MX1.improvmx.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;MX2.improvmx.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuskwowzgv56k0aohghe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuskwowzgv56k0aohghe.png" alt="Add the MX records provided by ImprovMX" width="800" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Set the priority to the values you see.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Create forwarding rules&lt;/strong&gt;:
&lt;/h4&gt;

&lt;p&gt;Back in ImprovMX, create a forwarding rule. This will typically be something like&amp;nbsp;&lt;code&gt;hello@yourdomain.com&lt;/code&gt;&amp;nbsp;forwarding to your personal email address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F493af9lqbynh1j3gnzqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F493af9lqbynh1j3gnzqz.png" alt="Create forwarding rules" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Verify your setup&lt;/strong&gt;: Once the DNS records propagate (this can take a few minutes to 48 hours), you can send a test email to your new custom address to ensure it's being forwarded correctly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2 (Easy Way): Set Up Gmail for Sending Emails
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Yo need your account 2FA enabled
&lt;/h4&gt;

&lt;p&gt;For this method to work, first enable your google accounts 2FA and follow this link to create an app password -&amp;gt; &lt;a href="https://myaccount.google.com/apppasswords" rel="noopener noreferrer"&gt;https://myaccount.google.com/apppasswords&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://security.google.com/settings/security/apppasswords" rel="noopener noreferrer"&gt;Create an app password&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Create an App Password&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Google will verify your ownership with this app password. Select "Other (Custom name)" under app, and type "My Domain" as the name. Hit "Generate". Copy and keep it in a safe place!&lt;/p&gt;

&lt;p&gt;Add your email to GmailGo to Gmail -&amp;gt; Settings -&amp;gt; Accounts and Import. Then, select "Add another email address you own" under Aliases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2t1efjcnhijdzbugbs8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2t1efjcnhijdzbugbs8j.png" alt="Create an App Password" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Fill in your sender's information
&lt;/h4&gt;

&lt;p&gt;Set your forwarded email (your alias) and your sender's name. Untick "treat as an alias".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjb6hvf95togne7g24ljy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjb6hvf95togne7g24ljy.png" alt="Fill in your sender's information" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Fill in your email informations
&lt;/h4&gt;

&lt;p&gt;SMTP:&amp;nbsp;&lt;strong&gt;smtp.gmail.com&lt;/strong&gt;, port is right already.\&lt;br&gt;
Username:&amp;nbsp;&lt;strong&gt;your gmail address&lt;/strong&gt;&amp;nbsp;(incl. @gmail.com)\&lt;br&gt;
Password: It is the password you generated on Step 2.&lt;/p&gt;

&lt;h4&gt;
  
  
  Confirm ownership
&lt;/h4&gt;

&lt;p&gt;You will receive an email from Gmail asking you to confirm ownership with a code. Open the link, click&amp;nbsp;&lt;strong&gt;Confirm&lt;/strong&gt;, and you are all set!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falc91mggckyrga14vogb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falc91mggckyrga14vogb.png" alt="Confirm ownership" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Send emails from your alias
&lt;/h4&gt;

&lt;p&gt;Now you can just select your alias in the list when you compose a new message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 (Harder but Better) : Set Up SendGrid for Sending Emails
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Sign in to SendGrid&lt;/strong&gt;&amp;nbsp;and&amp;nbsp;&lt;strong&gt;Verify your domain&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Log in to your SendGrid account.:&lt;/p&gt;

&lt;p&gt;In SendGrid, navigate to the "Sender Authentication" section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fushxgg8o0hoskos04fi1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fushxgg8o0hoskos04fi1.png" alt="SendGrid Sender Authentication" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose "Authenticate Your Domain" and follow the prompts to add the necessary DNS records to your domain.&lt;/p&gt;

&lt;p&gt;These will include CNAME, TXT, and possibly MX records depending on your setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin47w784t91hl0ash5mj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin47w784t91hl0ash5mj.png" alt="DNS Records" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you edit your DNS settings with these setup you will verify and see this message&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l9h6ekh4zf8itqyxpb4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l9h6ekh4zf8itqyxpb4.png" alt="Verify Your Domain" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Create an API key:
&lt;/h4&gt;

&lt;p&gt;Go to "API Keys" under the Settings menu in SendGrid.&lt;/p&gt;

&lt;p&gt;Click "Create API Key" and give it a name (e.g., "Custom Email API Key").&lt;/p&gt;

&lt;p&gt;Save the generated key somewhere secure; you'll need it later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabr7j9v47jr7knnz5hph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabr7j9v47jr7knnz5hph.png" alt="Create API Key" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Setup Your Custom Email on Gmail
&lt;/h3&gt;

&lt;p&gt;Now that you've set up ImprovMX for forwarding and configured SendGrid for sending emails, the final step is to add your custom email address to Gmail. This will allow you to send and receive emails using your new domain directly from your Gmail interface. You can see the images above for gmail settings.&lt;/p&gt;

&lt;h4&gt;
  
  
  Open Gmail Settings
&lt;/h4&gt;

&lt;p&gt;Log in to your Gmail account.\&lt;br&gt;
Click on the gear icon in the upper right corner and select See all settings.&lt;/p&gt;

&lt;h4&gt;
  
  
  Go to the Accounts and Import Tab
&lt;/h4&gt;

&lt;p&gt;In the settings menu, click on the Accounts and Import tab.\&lt;br&gt;
Scroll down to the Send mail as section and click Add another email address.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enter Your Custom Email Address
&lt;/h4&gt;

&lt;p&gt;A new window will pop up. Enter your name and the custom email address you set up (e.g., &lt;a href="mailto:hello@yourdomain.com"&gt;hello@yourdomain.com&lt;/a&gt;).\&lt;br&gt;
Uncheck the option to Treat as an alias if you want to keep this email separate from your primary Gmail account.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configure SMTP Settings
&lt;/h4&gt;

&lt;p&gt;In the next step, you'll need to enter your SMTP server settings:\&lt;br&gt;
SMTP Server: smtp.sendgrid.net\&lt;br&gt;
Port: 587 (or 465 for SSL)\&lt;br&gt;
Username: apikey\&lt;br&gt;
Password: Enter your SendGrid API Key here.\&lt;br&gt;
Click Add Account to save the settings.&lt;/p&gt;

&lt;h4&gt;
  
  
  Verify Your Email Address
&lt;/h4&gt;

&lt;p&gt;Gmail will send a verification email to your custom email address.\&lt;br&gt;
Since you've set up ImprovMX for forwarding, this email should arrive in your Gmail inbox.\&lt;br&gt;
Open the email and click the verification link, or enter the confirmation code provided.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bjwpq7n1k3q4w7iuc2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bjwpq7n1k3q4w7iuc2u.png" alt="Gmail Confirmation" width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Set as Default (Optional)
&lt;/h4&gt;

&lt;p&gt;If you want to use your custom email as the default sending address, go back to the Accounts and Import tab in Gmail settings.\&lt;br&gt;
Find your custom email under the Send mail as section and click Make default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Test and Verify Your Setup
&lt;/h3&gt;

&lt;p&gt;With everything set up, send a test email from your custom domain to ensure it's working correctly. You should be able to send and receive emails from your custom address directly within Gmail.&lt;/p&gt;

&lt;p&gt;Now I can both send with my custom domain using both gmail and sendgrid services. If you are not a tech guy you can use gmails service, but I recommend to go with sendgrid!&lt;/p&gt;

&lt;p&gt;Write me anything if you need! Happy good days.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>twilio</category>
      <category>gmail</category>
      <category>mail</category>
    </item>
    <item>
      <title>How to Host WordPress for Free on Vercel: A Step-by-Step Guide</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Wed, 20 Dec 2023 12:57:47 +0000</pubDate>
      <link>https://dev.to/yunuserturk/how-to-host-wordpress-for-free-on-vercel-a-step-by-step-guide-8cd</link>
      <guid>https://dev.to/yunuserturk/how-to-host-wordpress-for-free-on-vercel-a-step-by-step-guide-8cd</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update (November 2026):&lt;/strong&gt; This guide uses a static export, so forms, comments and search won't work. If you want real WordPress with PHP running on Vercel, I tested ServerlessWP here: &lt;a href="https://blog.yunuserturk.com/run-wordpress-on-vercel-serverlesswp/" rel="noopener noreferrer"&gt;Running Real WordPress on Vercel with ServerlessWP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Are you tired of the huge bills that come with hosting your WordPress website and want to host WordPress for free? The world of website hosting is evolving, and I'm here to guide you into host WordPress for free. In this comprehensive guide, I'll explore the exciting possibilities of hosting a WordPress site on Vercel using a Static Headless approach---revolutionizing your web hosting experience without denting your budget.&lt;/p&gt;

&lt;p&gt;By the way, I'm&amp;nbsp;&lt;a href="https://yunuserturk.com/" rel="noopener noreferrer"&gt;Yunus&lt;/a&gt;, a passionate tech enthusiast, I'm writing about tech, building digital products and design. for fellow enthusiasts, aspiring digital creators, and design enthusiasts.&amp;nbsp;&lt;a href="https://blog.yunuserturk.com/" rel="noopener noreferrer"&gt;Join me&lt;/a&gt;&amp;nbsp;and &lt;a href="https://twitter.com/yunuserturk" rel="noopener noreferrer"&gt;Follow me on twitter&lt;/a&gt; on this journey of exploring the intersections of technology, product development, and design, as every piece unfolds a narrative of creativity and functionality in the digital realm.&lt;/p&gt;

&lt;p&gt;Traditionally, hosting a dynamic WordPress website could burn a hole in your pocket. Due to the infrastructure needed to handle dynamic content and database queries. However, the landscape is changing, and we're about to embark on a journey that transforms your WordPress site into a lean, mean, static machine hosted on Vercel's serverless platform.&lt;/p&gt;

&lt;p&gt;Join us as we unravel the secrets of static websites, explore the concept of a Static Headless WordPress, and delve into the powerful world of Vercel. By the end of this guide, you'll not only understand the benefits of this approach but also have the knowledge to successfully host WordPress for free on Vercel without spending a dime. Let's turn the page on expensive hosting and usher in a new era of cost-effective, high-performance WordPress websites. Welcome to the future of hosting---welcome to hosting WordPress for free on Vercel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkh9avm39xz2do8893ul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkh9avm39xz2do8893ul.png" alt="How to Host WordPress for Free" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding Static Websites: Embracing Simplicity for Speed and Security&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we've set the stage for a budget-friendly WordPress hosting adventure, let's dive into the fascinating realm of static websites. Imagine a website that doesn't rely on complex server-side processing for every user request---a website that is lightning-fast, secure, and remarkably efficient. That's the essence of a static website.&lt;/p&gt;

&lt;p&gt;In simpler terms, a static website is like a snapshot of a traditional website. It consists of pre-rendered HTML, CSS, and JavaScript files, eliminating the need for on-the-fly content generation with every user interaction. This simplicity brings forth a multitude of advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Speed:&lt;/strong&gt;&amp;nbsp;Static websites load faster because there's no server-side processing delay. Your visitors experience quicker page loads, making for a smoother and more enjoyable browsing experience.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Security:&lt;/strong&gt;&amp;nbsp;With reduced dynamic functionality, static sites have a smaller attack surface, making them inherently more secure. Say goodbye to many common security vulnerabilities associated with dynamic content.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Scalability:&lt;/strong&gt;&amp;nbsp;Scaling a static website is a breeze. Whether you have ten or ten thousand visitors, the response time remains consistently high.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Is WordPress a Static Platform?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, you might be wondering, "How does this relate to WordPress?" Traditionally, WordPress relies on dynamic content, generating pages on-the-fly from a database each time a user requests them. While this approach is flexible, it can lead to slower load times and increased server loads, especially as your website grows.&lt;/p&gt;

&lt;p&gt;However, the magic lies in transforming your dynamic WordPress site into a static one. By doing so, you retain the simplicity and speed of a static website while still enjoying the familiar WordPress experience. This shift not only enhances performance but also opens the door to cost-effective hosting solutions, which we'll explore further in this guide.&lt;/p&gt;

&lt;p&gt;So, buckle up as we navigate the transformative journey of making WordPress static and unleash the full potential of a faster, more secure, and budget-friendly website hosting experience on Vercel. The days of compromise between performance and affordability are over; let's make your WordPress site truly dynamic without breaking the bank.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Making WordPress Static: Transforming Dynamism into Simplicity&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So, you're ready to embark on the journey of making your WordPress site static? Fantastic! Let's break down the process step by step, transforming your dynamic WordPress website into a sleek and efficient static version.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Setting Up a Local WordPress Environment with Local by Flywheel:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://localwp.com/" rel="noopener noreferrer"&gt;Download and Install Local&lt;/a&gt;:&lt;/strong&gt;&amp;nbsp;Download and install the Local by Flywheel application on your computer. This user-friendly tool makes it easy to create and manage local WordPress environments.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Create a New WordPress Site:&lt;/strong&gt;&amp;nbsp;Using Local, set up a new WordPress site locally on your computer. This step allows you to work on your website without affecting the live version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wquc02l8i53g10yi00c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wquc02l8i53g10yi00c.jpg" alt="Click the left green &amp;quot;Add Local site&amp;quot; button" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs44p4gojmzq1xx53p8ln.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs44p4gojmzq1xx53p8ln.jpg" alt="Create a new site with Local" width="799" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Developing Your WordPress Website Locally:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Customize Your WordPress Site:&lt;/strong&gt;&amp;nbsp;Build and customize your WordPress site according to your preferences. This is your opportunity to design, tweak, and perfect your website's look and feel.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Migrate Your WordPress Site:&lt;/strong&gt;&amp;nbsp;If your WordPress site is currently hosted elsewhere, use the "&lt;a href="https://wordpress.org/plugins/all-in-one-wp-migration/" rel="noopener noreferrer"&gt;All-in-One WP Migration&lt;/a&gt;" plugin to seamlessly migrate it to your local environment. Install the plugin on your existing WordPress site, export the site as a file, and then import it into your local environment using Local.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Get Done with Local WP&lt;/strong&gt;: I created an example WordPress website and will show you the steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxeqt3yf6ufeoiaar9n74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxeqt3yf6ufeoiaar9n74.png" alt="New Static WordPress" width="800" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Exporting Your WordPress Site to Static Files with WP2Static:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We will use the WP2Static plugin for it. There are some other plugins for it, but I will use this one in this path.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://wp2static.com/" rel="noopener noreferrer"&gt;Download and Install WP2Static Plugin&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;In your WordPress dashboard, install the WP2Static plugin. This tool is crucial for converting your dynamic site into a static one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd488plzr6khiiu2gc5rm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd488plzr6khiiu2gc5rm.png" alt="Add plugin to Host WordPress for Free" width="799" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure WP2Static:&lt;/strong&gt;&amp;nbsp;Set up WP2Static to export your WordPress site as static files. The most important thing in this step is to fill your new WordPress domain. Because we need to change the page domains to the actual domain that we will use for the WordPress website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faek3l90g7zxro5th0eli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faek3l90g7zxro5th0eli.png" alt="Static WordPress domain" width="799" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generate Static Files:&lt;/strong&gt;&amp;nbsp;Let WP2Static do its magic. It will generate static HTML files, CSS, and other assets that represent your WordPress site without the need for server-side processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Creating a GitHub Repository:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Set Up a GitHub Account:&lt;/strong&gt;&amp;nbsp;If you don't have one, create a GitHub account. This will be the platform where you store and manage the static files of your WordPress site.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Create a New Repository:&lt;/strong&gt;&amp;nbsp;Initialize a new repository on GitHub. This will serve as the central hub for your static WordPress site's files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iy4b4x4yjiitehnyoma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iy4b4x4yjiitehnyoma.png" alt="Create your WordPress github repo" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Pushing Static Files to the GitHub Repository:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Commit and Push Changes:&lt;/strong&gt;&amp;nbsp;Using Git commands or a GUI client, commit and push the static files to your GitHub repository. This step makes your static WordPress site accessible from anywhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6uxj39tv5k047a1dh2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6uxj39tv5k047a1dh2k.png" alt="Push your Static WordPress" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;6. Deploying Your WordPress Site on Vercel and Host WordPress for Free:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Create a Vercel Account:&lt;/strong&gt;&amp;nbsp;If you haven't already, sign up for a Vercel account. It's free and provides an excellent platform for hosting static sites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create A New Project:&lt;/strong&gt;&amp;nbsp;On your vercel dashboard, create a project for the WordPress website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Import Your GitHub Repository to Vercel:&lt;/strong&gt;&amp;nbsp;Connect your GitHub repository to Vercel. This establishes a link between your static WordPress files and the Vercel hosting platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprsktb9dhp44hf1nhwto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprsktb9dhp44hf1nhwto.png" alt="Deploy Static WordPress" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure Deployment Settings:&lt;/strong&gt;&amp;nbsp;Fine-tune deployment settings on Vercel according to your requirements. This includes specifying the branch to deploy and setting up custom domains if needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0zub5arv4j7pignd0yk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0zub5arv4j7pignd0yk.png" alt="Deployment Settings for Publishing WordPress on Vercel" width="799" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy Your WordPress Site:&lt;/strong&gt;&amp;nbsp;Initiate the deployment process on Vercel. Watch as your static WordPress site goes live on the Vercel platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtv6clb0wq2dlhmnvldt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtv6clb0wq2dlhmnvldt.png" alt="Host WordPress for Free" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You've successfully transformed your dynamic WordPress site into a static masterpiece and deployed it on Vercel---all without spending a penny on hosting. Now you can Host WordPress for Free. In the next sections, we'll explore the nuances of GitHub, version control, and the deployment process in more detail. Let's keep the momentum going!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;FAQ: Navigating the Host WordPress for Free Journey&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q1: Why should I consider hosting my WordPress site on Vercel?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: Hosting your WordPress site on Vercel brings tones of benefits, including speed, scalability, and cost-effectiveness. Vercel's serverless platform ensures high performance without the traditional hosting expenses. You can Host WordPress for Free on Vercel.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q2: Is the migration process complex, especially for non-tech-savvy users?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: Not at all. The migration process is designed to be user-friendly. With plugins like "All-in-One WP Migration" and step-by-step guides, even those without extensive technical knowledge can successfully navigate the transition. But still you have to knowledge of github version control and how-to make commit, push and deploy.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q3: Can I still use WordPress plugins and themes on a static site?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: While some dynamic functionality may be limited in a static environment, many plugins and themes are compatible. The key is to choose those that enhance static site performance. If you want to Host WordPress for Free on Vercel, you won't create a dynamic website, like comments, e-commerce etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q4: What happens to my database during the migration to a static site?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: The static site approach removes the need for a dynamic database. During migration, the content is pre-rendered and stored as static files, eliminating the need for constant database queries and updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q5: How does version control benefit my WordPress site on GitHub?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: Version control with GitHub allows you to track changes, collaborate efficiently, and roll back to previous versions if needed. It provides a secure and organized way to manage your WordPress site's evolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q6: Are there limitations to the types of websites that work well with Host WordPress for Free on Vercel?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: Static Headless WordPress on Vercel is versatile and suitable for various types of websites, from blogs to portfolios. However, websites heavily reliant on real-time dynamic content may need additional considerations.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q7: Is Vercel's Host WordPress for Free is sufficient for my site?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: Vercel's free hosting tier is excellent for small to medium-sized websites. For larger sites with high traffic, consider their affordable paid plans for enhanced performance and additional features.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q8: Can I still use Vercel if my WordPress site relies on e-commerce plugins?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: While certain e-commerce plugins may have limitations in a static environment, there are static-friendly alternatives. Consider evaluating plugins compatible with static sites or explore separate solutions for dynamic features.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q9: What if I encounter issues during deployment on Vercel?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: Vercel offers comprehensive documentation and a helpful community. If issues persist, their support team is responsive and ready to assist, ensuring a smooth deployment process.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Q10: Is it possible to revert to a dynamic WordPress site after migrating to static on Vercel?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;A: While the migration is generally one-way, keeping a backup of your dynamic WordPress site is advisable if you ever decide to revert. Be sure to plan and test thoroughly before making significant changes. But always the static website will be rendered by the main dynamic website of WordPress. So you need to have the dynamic website allways. In this case it will be on your own local system.&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have additional questions or need further clarification on any aspect of the Host WordPress for Free journey. I will be happy to guide you!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Kind of Websites Work Best with Static Headless WordPress?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Static Headless WordPress on Vercel is a powerful solution that suits a variety of website types, but it's essential to understand its strengths and limitations. Here's a guide on which types of websites work best and where you might encounter challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Personal Websites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ideal:&lt;/em&gt;&amp;nbsp;Static Headless WordPress is exceptionally well-suited for personal websites. The static nature enhances speed and security, providing an excellent user experience for readers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Portfolio Websites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ideal:&lt;/em&gt;&amp;nbsp;If you're showcasing your work or building a portfolio, a static site offers a fast and reliable way to display your content. Vercel's hosting ensures your portfolio loads quickly, impressing potential clients or employers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Business Websites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ideal:&lt;/em&gt;&amp;nbsp;Business websites with static content, such as service descriptions, contact information can benefit from the simplicity and speed of Static Headless WordPress.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Informational Websites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ideal:&lt;/em&gt;&amp;nbsp;Websites providing information without the need for real-time updates or user-generated content can leverage the efficiency of a static approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Landing Pages:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ideal:&lt;/em&gt;&amp;nbsp;Static sites are perfect for landing pages where quick loading times are crucial. Whether you're promoting a product, event, or service, the speed of a static site enhances user engagement.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Documentation Sites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ideal:&lt;/em&gt;&amp;nbsp;Static Headless WordPress is an excellent choice for documentation sites, providing a fast and reliable platform for users to access information.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Educational Websites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ideal:&lt;/em&gt;&amp;nbsp;Websites offering educational content, course descriptions, and general information can benefit from the speed and security of a static environment.&lt;/p&gt;

&lt;p&gt;However, there are scenarios where a static approach may not be the best fit:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;E-commerce Websites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Challenges:&lt;/em&gt;&amp;nbsp;E-commerce sites with dynamic product listings, real-time inventory updates, and interactive shopping carts might face limitations with the static approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;User-Generated Content (UGC) Websites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Challenges:&lt;/em&gt;&amp;nbsp;Websites heavily reliant on user-generated content, such as forums or social platforms, may find it challenging to implement real-time updates and dynamic interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Websites with Dynamic Comments:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Challenges:&lt;/em&gt;&amp;nbsp;If your website relies on dynamic comments on posts or pages, a static approach may not be the most suitable, as it lacks the real-time interaction required for comment sections.&lt;/p&gt;

&lt;p&gt;In summary, Static Headless WordPress on Vercel excels in scenarios where content remains relatively static and doesn't require constant updates or real-time interactions. Understanding the nature of your website's content and functionalities will help you determine whether the static approach aligns with your goals.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>vercel</category>
      <category>webdev</category>
      <category>github</category>
    </item>
    <item>
      <title>8 Best Tips for Finding Freelance Developer Jobs</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Sat, 19 Nov 2022 18:17:21 +0000</pubDate>
      <link>https://dev.to/yunuserturk/8-best-tips-for-finding-freelance-developer-jobs-6gb</link>
      <guid>https://dev.to/yunuserturk/8-best-tips-for-finding-freelance-developer-jobs-6gb</guid>
      <description>&lt;p&gt;There are a number of ways to get started in freelancing, but finding quality development jobs can be a challenge. Here are a few tips to get you started on the right track:&lt;/p&gt;

&lt;h3&gt;
  
  
  Job postings on online job boards or freelancing websites.
&lt;/h3&gt;

&lt;p&gt;Online freelancing job boards are the quickest way of finding projects. There are many different online job boards and freelancing websites available. Some popular online job boards include Indeed, Monster, and Dice. To find freelancing developer jobs on these websites, enter relevant keywords, mainly freelance, into the search bar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Network with other developers and let them know you're looking for freelancing work
&lt;/h3&gt;

&lt;p&gt;You can connect with other developers through online forums or social media platforms such as GitHub or Twitter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Search for companies that use the technology you're proficient in
&lt;/h3&gt;

&lt;p&gt;If you're skilled in a particular technology or programming language, you can search for companies that use that technology on job boards or freelancing websites. You can also search for companies that use that technology on LinkedIn.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reach out to companies or organizations directly and inquire about freelancing opportunities
&lt;/h3&gt;

&lt;p&gt;Another option is to reach out to companies or organizations directly and inquire about any freelance opportunities that may be available. This can be done by sending a cold email or LinkedIn message to the company.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attend industry events or meetups relevant to your skillset
&lt;/h3&gt;

&lt;p&gt;You can also attend developer meetups or events in your area. This is a great way to network with other developers and let them know you're available for freelance work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a solid online presence by having an up-to-date portfolio website or blog
&lt;/h3&gt;

&lt;p&gt;Ensure your portfolio or website is up-to-date and includes examples of your work. This will help you showcase your skillset and attract potential clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep your skills up-to-date.
&lt;/h3&gt;

&lt;p&gt;Use online resources such as online courses or tutorials to keep your skills up-to-date. This will make you more attractive to potential clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be active on social media.
&lt;/h3&gt;

&lt;p&gt;Make sure you're active on social media platforms such as Twitter and LinkedIn. This will help you build your online presence and attract potential clients.&lt;/p&gt;

&lt;p&gt;This post firstly published on &lt;a href="https://freelancerpath.com" rel="noopener noreferrer"&gt;freelancerpath&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>beginners</category>
      <category>career</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build Your Own Cloud Storage</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Tue, 08 Nov 2022 20:51:45 +0000</pubDate>
      <link>https://dev.to/yunuserturk/build-your-own-cloud-storage-6b3</link>
      <guid>https://dev.to/yunuserturk/build-your-own-cloud-storage-6b3</guid>
      <description>&lt;p&gt;Building a strong brand is something every business or individual needs to do. It's not just about having a memorable logo or tagline, but ensuring that you are remembered by your audience and clients for the right reasons. We're here to help you develop an effective branding strategy and create an identity that will make you stand out from the crowd.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focstsnd1wkzjcylg5p6z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focstsnd1wkzjcylg5p6z.jpg" alt="For freelancing" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your personal brand and freelancing business are only as strong as the tools you have available to communicate your value with potential clients. This makes an online storage solution like nextcloud that much more valuable, because it allows you to store, organize and share all of your files from any device and add security features such as two-factor authentication through services like Google Authenticator. Best of all, it's simple to get set up, and in this article we'll take you through all of the steps necessary to use nextcloud to build your own cloud storage on your own domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Cloud Storage?
&lt;/h3&gt;

&lt;p&gt;Cloud storage is a type of web hosting. Like traditional hosting, it involves storing files on a server and making them accessible to the public. Unlike traditional hosting, however, cloud storage enables you to store your data remotely and access it from anywhere as long as you have an internet connection. You can also create private accounts that are only accessible by the account's owner.&lt;/p&gt;

&lt;p&gt;Cloud storage is ideal for businesses because they need to store their data without having to worry about managing hardware or setting up servers. And when you communicate with your clients you always need to send big files. In this scenario, cloud systems are the only way. If you don't want to send files with google drive, onedrive, or use the systems like wetransfer you need to build your own branded cloud storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the Differences Custom Cloud Storage vs Others
&lt;/h3&gt;

&lt;p&gt;Cloud storage is the backbone of any freelancer brand's business efforts. But there are many types of cloud systems with different features and limitations that can make it difficult to decide which one is best. Some services offer limited storage space, others only allow you to upload a few files at a time, and some charge per gigabyte. DIY custom cloud storage with nextcloud offers much more flexibility, allowing you to scale your storage up or down as needed without any cost increases. And the most important point is when you send a file to a customer, you are sending it under your own domain and your own cloud system. It's a nice action to show your customers your brand's strong identity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Building Own Cloud
&lt;/h3&gt;

&lt;p&gt;Building your own cloud storage is like having your own private wetransfer -- only branded on your own domain. You'll be in complete control, and it'll cost you less money than paying for cloud systems monthly fee. To create your own cloud, you'll need the help of server and client software. There are several solutions that you can choose from the market but we'll discuss NextCloud in this post. I'm personally used this solution about 4-5 years and I like it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Cloud Solution: Nextcloud
&lt;/h3&gt;

&lt;p&gt;Nextcloud is similar to&amp;nbsp;&lt;a href="https://owncloud.com/" rel="noopener noreferrer"&gt;ownCloud&lt;/a&gt;, but with a few differences. Nextcloud is an upgraded version of ownCloud, created by duplicating (forking) it and developing the new version separately. It offers some great collaboration tools, allowing you to use one of their DIY cloud storage systems. They also have apps for smartphones on both Android and iOS -- which is perfect if you want to access your data wherever you are. It is different from other services like Google Drive and Dropbox because it's not hosted on servers outside of your direct control. For users seeking more control over how and where their data is stored, Nextcloud is a great choice.&lt;/p&gt;

&lt;h4&gt;
  
  
  Is it Free
&lt;/h4&gt;

&lt;p&gt;Yes, you can install it on your own server and can use free. It has its own premium pricing but I'm writing this post for freelancers and solo business owners. So you don't need team pricing or extra features. Just upload your files and send them to your customers. It is my usage also.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to Install
&lt;/h4&gt;

&lt;p&gt;NextCloud has a huge documentation on their website, here is the link: &lt;a href="https://docs.nextcloud.com/server/latest/admin_manual/installation/index.html" rel="noopener noreferrer"&gt;https://docs.nextcloud.com/server/latest/admin_manual/installation/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But if I make it summarize, here is the installation steps with web installer file;&lt;/p&gt;

&lt;p&gt;The Web Installer is the easiest way to install Nextcloud on a web space. It checks the dependencies, downloads Nextcloud from the official server, unpacks it with the right permissions and the right user account. Finally, you will be redirected to the Nextcloud installer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Right-click&amp;nbsp;&lt;a href="https://download.nextcloud.com/server/installer/setup-nextcloud.php" rel="noopener noreferrer"&gt;here&lt;/a&gt;&amp;nbsp;and save the file to your computer&lt;/li&gt;
&lt;li&gt;  Upload setup-nextcloud.php to your web space&lt;/li&gt;
&lt;li&gt;  Point your web browser to setup-nextcloud.php on your webspace&lt;/li&gt;
&lt;li&gt;  Follow the instructions and configure Nextcloud&lt;/li&gt;
&lt;li&gt;  Login to your newly created Nextcloud instance!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find further instructions in the&amp;nbsp;&lt;a href="https://docs.nextcloud.com/server/latest/admin_manual/" rel="noopener noreferrer"&gt;Nextcloud Admin Manual&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Installer uses the same Nextcloud version as available for the built in updater in Nextcloud. After a major release it can take up to a month before it becomes available through the web installer and the updater. This is done to spread the deployment of new major releases out over time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  Share files very quickly with your own domain.&lt;/li&gt;
&lt;li&gt;  Create folders for your different clients.&lt;/li&gt;
&lt;li&gt;  Share files with password.&lt;/li&gt;
&lt;li&gt;  Easy collaboration.&lt;/li&gt;
&lt;li&gt;  Store on your own server.&lt;/li&gt;
&lt;li&gt;  Built-in apps. (More than 100+)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Using
&lt;/h4&gt;

&lt;p&gt;I don't tell you how to use it here, but it's very easy. Just create a file, upload your file, and copy the share link. Here is a huge documentation about usage of nextcloud. &lt;a href="https://nextcloud.com/files/" rel="noopener noreferrer"&gt;https://nextcloud.com/files/&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Pros and Cons of NextCloud
&lt;/h4&gt;

&lt;p&gt;First, let me tell you that these pros and cons are just my thoughts. You can search and find your own pros and cons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Very easy to use&lt;/li&gt;
&lt;li&gt;  Quick installation&lt;/li&gt;
&lt;li&gt;  Smooth process&lt;/li&gt;
&lt;li&gt;  Security options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Enterprise pricing is too expensive.&lt;/li&gt;
&lt;li&gt;  You use your own hosting storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Nextcloud is a great solution if you want to build your own cloud storage and make your personal brand powerful. It is very easy to start and creates a huge difference to your personal brand in a positive way.&lt;/p&gt;

&lt;p&gt;If you have a different process for using cloud systems please mention it and let us talk about that.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>freelance</category>
      <category>nextcloud</category>
      <category>storage</category>
    </item>
    <item>
      <title>How to Create a Blog with NextJS, Notion, and Notion API</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Fri, 28 Oct 2022 14:41:55 +0000</pubDate>
      <link>https://dev.to/yunuserturk/how-to-create-a-blog-with-nextjs-notion-and-notion-api-4fnm</link>
      <guid>https://dev.to/yunuserturk/how-to-create-a-blog-with-nextjs-notion-and-notion-api-4fnm</guid>
      <description>&lt;p&gt;In this post, I want to try how we can create a blog management system using notion as a database. I have created a post on&amp;nbsp;&lt;a href="https://dev.to/yunuserturk/how-to-create-a-blog-with-using-airtable-as-a-database-3dfa"&gt;how to create a blog with airtable&lt;/a&gt;, I used airtable in that project. Now I'm doing it with notion.&lt;/p&gt;

&lt;p&gt;I wrote &lt;a href="https://blog.yunuserturk.com/how-to-create-a-blog-with-nextjs-notion-and-notion-api/" rel="noopener noreferrer"&gt;this post&lt;/a&gt; to my own blog first, and I want to publish it here too.&lt;/p&gt;

&lt;p&gt;At first, we can find everything about notion;&amp;nbsp;&lt;a href="https://developers.notion.com/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://developers.notion.com/" rel="noopener noreferrer"&gt;https://developers.notion.com/&lt;/a&gt;&amp;nbsp;address&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Notion Integration for Our Blog
&lt;/h3&gt;

&lt;p&gt;I have looked at the documentation and let's start. Firstly we should create an integration from&amp;nbsp;&lt;a href="https://www.notion.so/my-integrations" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.notion.so/my-integrations" rel="noopener noreferrer"&gt;https://www.notion.so/my-integrations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5llipi5eqcmekf9pvhe2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5llipi5eqcmekf9pvhe2.png" alt="notion" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a new integration on this page. I have created an integration named myblog, and these are my settings;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpgw5d0l168jy25du7f8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpgw5d0l168jy25du7f8.png" alt="basic information" width="800" height="774"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After these steps notion will give you a notion token, copy this token to a secure place, and we will use it for connecting our data.&lt;/p&gt;

&lt;p&gt;After that, we have to create a page and convert it to a database to use for our blog. I have created a notion page -- database full page. This is what I get;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyez32rlw6ru3r5hnnqr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyez32rlw6ru3r5hnnqr.png" alt="new" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is a share button top right, Click on the&amp;nbsp;&lt;code&gt;Share&lt;/code&gt;button and use the selector to find your integration by its name, then click&amp;nbsp;&lt;code&gt;Invite&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our integration has an access to our database now, last step we need the database id. It's the part of your URL;&lt;/p&gt;

&lt;p&gt;Mine is;&amp;nbsp;&lt;a href="https://www.notion.so/yunuserturk/f9dfc334e89e4c2289b9bc98884b5e80" rel="noopener noreferrer"&gt;https://www.notion.so/yunuserturk/f9dfc334e89e4c2289b9bc98884b5e80&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the database id is;&amp;nbsp;&lt;code&gt;f9dfc334e89e4c2289b9bc98884b5e80&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we have to create our app and we can use these notion access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a NextJS App
&lt;/h3&gt;

&lt;p&gt;The easiest way to get started with Next.js is by using&amp;nbsp;&lt;code&gt;create-next-app&lt;/code&gt;&amp;nbsp;.&lt;/p&gt;

&lt;p&gt;Create a project with VS Code, open the terminal and use the command;&amp;nbsp;&lt;code&gt;npx create-next-app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Install tailwindcss;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a sketchy UI, I copied the code from the airtable project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Head from "next/head";

export default function Home() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Head&amp;gt;
        &amp;lt;title&amp;gt;Create Next App&amp;lt;/title&amp;gt;
        &amp;lt;meta name="description" content="Generated by create next app" /&amp;gt;
        &amp;lt;link rel="icon" href="/favicon.ico" /&amp;gt;
      &amp;lt;/Head&amp;gt;

      &amp;lt;main&amp;gt;
        &amp;lt;div className="container mx-auto w-full sm:w-10/12 md:w-8/12 lg:w-6/12 xl:w-6/12 p-4"&amp;gt;
          &amp;lt;h1 className="font-bold text-2xl"&amp;gt;Welcome to my blog&amp;lt;/h1&amp;gt;
          &amp;lt;div className="flex flex-col p-5 rounded-lg border-2 border-gray-200 mt-10"&amp;gt;
            &amp;lt;h2 className="text-xl font-bold"&amp;gt;Post Title&amp;lt;/h2&amp;gt;
            &amp;lt;div&amp;gt;Post Content will be here&amp;lt;/div&amp;gt;
            &amp;lt;span className="text-sm mb-6"&amp;gt;Post Date&amp;lt;/span&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/main&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Use Notion API and Show the Content
&lt;/h3&gt;

&lt;p&gt;Our homepage is ready, now we have to fetch the data to show it on our page. Let's install notion client SDK with&amp;nbsp;&lt;code&gt;npm install @notionhq/client&lt;/code&gt;, run this command on terminal. Create a file&amp;nbsp;&lt;code&gt;lib&amp;gt;notion.js&lt;/code&gt;&amp;nbsp;and we will use our database here. With the help of the documentation, I created a starter code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Client } from "@notionhq/client";

const notion = new Client({
  auth: process.env.NEXT_PUBLIC_NOTION_TOKEN,
});

export const getDatabase = async (databaseId) =&amp;gt; {
  const response = await notion.databases.query({
    database_id: databaseId,
  });
  return response.results;
};

export const getPage = async (pageId) =&amp;gt; {
  const response = await notion.pages.retrieve({ page_id: pageId });
  return response;
};

export const getBlocks = async (blockId) =&amp;gt; {
  const blocks = [];
  let block;
  while (true) {
    const { results, next_block } = await notion.blocks.children.list({
      start_block: block,
      block_id: blockId,
    });
    blocks.push(...results);
    if (!next_block) {
      break;
    }
    block = next_block;
  }
  return blocks;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll import this to the index page and fetch the data and show the posts on the home page. With the notion API, getpage function only fetches the properties of the page. We can't retrieve the page blocks. We have to create another function and use API for retrieving page content. Notion called them blocks and has another function for it.&lt;/p&gt;

&lt;p&gt;My final index.js page is like that;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Head from "next/head";
import { getDatabase } from "../lib/notion";
import Link from "next/link";

export default function Home({ posts }) {

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Head&amp;gt;
        &amp;lt;title&amp;gt;Create Next App&amp;lt;/title&amp;gt;
        &amp;lt;meta name="description" content="Generated by create next app" /&amp;gt;
        &amp;lt;link rel="icon" href="/favicon.ico" /&amp;gt;
      &amp;lt;/Head&amp;gt;

      &amp;lt;main&amp;gt;
        &amp;lt;div className="container mx-auto w-full sm:w-10/12 md:w-8/12 lg:w-6/12 xl:w-6/12 p-4"&amp;gt;
          &amp;lt;h1 className="font-bold text-2xl"&amp;gt;Welcome to my blog&amp;lt;/h1&amp;gt;
          {posts.map((post) =&amp;gt; {
            const date=new Date(post.created_time).toLocaleString("en-Us",{
              month: "long",
              day: "numeric",
              year: "numeric",
              })
            return (
              &amp;lt;div className="flex flex-col p-5 rounded-lg border-2 border-gray-200 mt-10" key={post.id}&amp;gt;
                &amp;lt;h2 className="text-xl font-bold"&amp;gt;{post.properties.Name.title[0].plain_text}&amp;lt;/h2&amp;gt;
                &amp;lt;span className="text-sm"&amp;gt;{date}&amp;lt;/span&amp;gt;
                &amp;lt;Link href="/[post]" as={`/${post.id}`}&amp;gt;
                  &amp;lt;a className="text-sm"&amp;gt;Read more&amp;lt;/a&amp;gt;
                &amp;lt;/Link&amp;gt;
              &amp;lt;/div&amp;gt;
            );
          })}
        &amp;lt;/div&amp;gt;
      &amp;lt;/main&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export const getStaticProps = async () =&amp;gt; {
  const database = await getDatabase("f9dfc334e89e4c2289b9bc98884b5e80");

  return {
    props: {
      posts: database,
    },
    revalidate: 1,
  };
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notion gives us the blocks with API with plenty of properties. As you wish you can use which of them you want. But I just use the text and just for these blocks; paragraphs and headers. You can adjust the blocks you will use according to the project you are doing. (We will use it on the single post page.)&lt;/p&gt;

&lt;p&gt;Here is the single post page file;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { getDatabase, getPage, getBlocks } from "../lib/notion";
import Head from "next/head";

const renderBlock = (block) =&amp;gt; {
  const { type } = block;
  const value = block[type];

  switch (type) {
    case "paragraph":
      return &amp;lt;p className="mb-4"&amp;gt;{value.rich_text[0].plain_text}&amp;lt;/p&amp;gt;;
    case "heading_1":
      return &amp;lt;h1 className="font-bold text-3xl  mb-2"&amp;gt;{value.rich_text[0].plain_text}&amp;lt;/h1&amp;gt;;
    case "heading_2":
      return &amp;lt;h2 className="font-bold text-2xl  mb-2"&amp;gt;{value.rich_text[0].plain_text}&amp;lt;/h2&amp;gt;;
    case "heading_3":
      return &amp;lt;h3 className=" font-bold text-xl mb-2"&amp;gt;{value.rich_text[0].plain_text}&amp;lt;/h3&amp;gt;;
  }
};

export default function Post({ post, content }) {
  const date = new Date(post.created_time).toLocaleString("en-Us", {
    month: "long",
    day: "numeric",
    year: "numeric",
  });
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Head&amp;gt;
        &amp;lt;title&amp;gt;{post.properties.Name.title[0].plain_text}&amp;lt;/title&amp;gt;
        &amp;lt;link rel="icon" href="/favicon.ico" /&amp;gt;
      &amp;lt;/Head&amp;gt;

      &amp;lt;main&amp;gt;
        &amp;lt;div className="container mx-auto w-full sm:w-10/12 md:w-8/12 lg:w-6/12 xl:w-6/12 p-4"&amp;gt;
          &amp;lt;h1 className="font-bold text-2xl"&amp;gt;{post.properties.Name.title[0].plain_text}&amp;lt;/h1&amp;gt;
          &amp;lt;span className="text-sm"&amp;gt;{date}&amp;lt;/span&amp;gt;
          &amp;lt;img src="&amp;lt;https://picsum.photos/800/200&amp;gt;" alt="random image" className=" max-w-full" /&amp;gt;
          &amp;lt;div className="mt-10"&amp;gt;
            {content.map((block) =&amp;gt; {
              console.log(block);
              return &amp;lt;div key={block.id}&amp;gt;{block.type === "page_break" ? &amp;lt;hr /&amp;gt; : &amp;lt;div&amp;gt;{renderBlock(block)}&amp;lt;/div&amp;gt;}&amp;lt;/div&amp;gt;;
            })}
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/main&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export const getStaticPaths = async () =&amp;gt; {
  const database = await getDatabase("f9dfc334e89e4c2289b9bc98884b5e80");
  const paths = database.map((post) =&amp;gt; {
    return {
      params: {
        post: post.id,
      },
    };
  });
  return {
    paths,
    fallback: false,
  };
};

export const getStaticProps = async ({ params }) =&amp;gt; {
  const postId = params.post;
  const post = await getPage(postId);
  const content = await getBlocks(postId);

  return {
    props: {
      post,
      content,
    },
    revalidate: 1,
  };
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the final post page;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzogn0hsdm13goeubu3xs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzogn0hsdm13goeubu3xs.png" alt="final" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment and the result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I deployed it to vercel finally. It's a very basic use of Nation API, If you create something more different you can use it this way.&lt;/p&gt;

&lt;p&gt;You can see al the code from the github repo:&amp;nbsp;&lt;a href="https://github.com/yunuserturk/notion-blog" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://github.com/yunuserturk/notion-blog" rel="noopener noreferrer"&gt;https://github.com/yunuserturk/notion-blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the demo of final result:&amp;nbsp;&lt;a href="https://notion-blog-yunuserturk.vercel.app/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://notion-blog-yunuserturk.vercel.app/" rel="noopener noreferrer"&gt;https://notion-blog-yunuserturk.vercel.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>notion</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>How to create a blog with using airtable as a database</title>
      <dc:creator>Yunus Ertürk</dc:creator>
      <pubDate>Wed, 20 Jul 2022 17:19:22 +0000</pubDate>
      <link>https://dev.to/yunuserturk/how-to-create-a-blog-with-using-airtable-as-a-database-3dfa</link>
      <guid>https://dev.to/yunuserturk/how-to-create-a-blog-with-using-airtable-as-a-database-3dfa</guid>
      <description>&lt;p&gt;In this post, I want to try how we can create a blog management system using airtable as a database. Airtable is perfect for creating and managing your content. It’s easy to get started and the possibilities are endless! We’ll use react, NextJS as our frontend, and tailwindcss for CSS. We’ll also use git to store all our code in GitHub and deploy it to Vercel. Keep reading to learn how to create your own blog!&lt;/p&gt;

&lt;p&gt;I wrote &lt;a href="https://blog.yunuserturk.com/how-to-create-a-blog-with-airtable/" rel="noopener noreferrer"&gt;this post&lt;/a&gt; to my own blog first, and I want to publish it here too.&lt;/p&gt;

&lt;p&gt;You can see all the code from the GitHub repo: &lt;a href="https://github.com/yunuserturk/airtable-blog" rel="noopener noreferrer"&gt;https://github.com/yunuserturk/airtable-blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the demo of the final result: &lt;a href="https://airtable-blog-ruby.vercel.app/" rel="noopener noreferrer"&gt;https://airtable-blog-ruby.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Airtable?
&lt;/h2&gt;

&lt;p&gt;Airtable is a cloud-based, all-in-one platform that combines the power of a traditional database with the flexibility of a spreadsheet. You can use Airtable to store data, track projects, and collaborate with team members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why tailwindcss, react, and nextJS?
&lt;/h2&gt;

&lt;p&gt;Tailwind is a utility-first CSS framework that offers a low-level, atomic approach to building interfaces. In other words, it gives you the raw building blocks (utilities) you need to create designs, without any opinionated styles of their own.&lt;/p&gt;

&lt;p&gt;NextJS is a React framework that makes it easy to create server-side rendering React apps. It’s also lightweight and fast, and very effective for websites with lots of pages, which makes it ideal for creating static websites and blogs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a NextJS App
&lt;/h2&gt;

&lt;p&gt;The easiest way to get started with Next.js is by using &lt;code&gt;create-next-app&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a project with VS Code, open the terminal, and use the command; &lt;code&gt;npx create-next-app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6homqpjyygwov48z7oy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6homqpjyygwov48z7oy.png" alt="NextJS Project" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is our first app. First, we’ll edit index.js and create a blog home page, and after that create a post page.&lt;/p&gt;

&lt;p&gt;I’m creating a very basic UI with tailwindcss;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;main&amp;gt;
  &amp;lt;div className="container mx-auto w-full sm:w-10/12 md:w-8/12 lg:w-6/12 xl:w-6/12 p-4"&amp;gt;
    &amp;lt;h1 className="font-bold text-2xl"&amp;gt;Welcome to my blog&amp;lt;/h1&amp;gt;
    &amp;lt;div className="flex flex-col p-5 rounded-lg border-2 border-gray-200 mt-10"&amp;gt;
      &amp;lt;h2 className="text-xl font-bold"&amp;gt;Post Title&amp;lt;/h2&amp;gt;
      &amp;lt;div&amp;gt;Post Content will be here&amp;lt;/div&amp;gt;
      &amp;lt;span className="text-sm mb-6"&amp;gt;Post Date&amp;lt;/span&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/main&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yua6pbb61fa315bhm3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yua6pbb61fa315bhm3d.png" alt="Basic Blog UI" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Airtable as a database
&lt;/h2&gt;

&lt;p&gt;Our blog home page is ready, and we need the airtable as a database. I have created an airtable document named myblog and I’ll use these 3 columns; title, content, and date.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8t2arzsq5pmzjt9wy3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8t2arzsq5pmzjt9wy3o.png" alt="airtable database" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How can we fetch the data from airtable?
&lt;/h2&gt;

&lt;p&gt;Airtable has a nice documented API service. &lt;a href="https://airtable.com/api" rel="noopener noreferrer"&gt;https://airtable.com/api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, you can check the documentation and see how can you create something different. For now, we just fetch the post title, content, and date.&lt;/p&gt;

&lt;p&gt;Airtable has an npm package for development. Firstly we install it on our project. Open the terminal and run this code npm install airtable. After installing the airtable package I’ve created a file under components named getPosts.js, and this is for fetching the data from the airtable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Airtable from "airtable";

const AirtableBase = new Airtable({ apiKey: process.env.NEXT_PUBLIC_API_KEY });
const AirtableBase_ = AirtableBase.base(process.env.NEXT_PUBLIC_API_BASE);

const table = AirtableBase_.table("myblog");
let posts = [];

const getPosts = async () =&amp;gt; {
  posts = await table.select({}).all();
  const posts_ = posts.map((post) =&amp;gt; {
    return {
      id: post.id,
      title: post.fields.title,
      content: post.fields.content,
      date: post.fields.date,
    };
  });

  return posts_;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;export default getPosts;&lt;br&gt;
You must change your airtable table name and API variables.&lt;/p&gt;

&lt;p&gt;Now we have to create a post page to show a single post. Created a [posts].js in the pages folder. And created a sketchy post UI. For now, I’ve created post pages with post IDs. But it’s not the best practice, I will change this function when I’m implementing SEO functions.&lt;/p&gt;

&lt;p&gt;This is how is the [posts].js after airtable fetch codes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function post({ post }) {
  return (
    &amp;lt;main&amp;gt;
      &amp;lt;div className="container mx-auto w-full sm:w-10/12 md:w-8/12 lg:w-6/12 xl:w-6/12 p-4"&amp;gt;
        &amp;lt;h1 className="font-bold text-2xl"&amp;gt;{post.title}&amp;lt;/h1&amp;gt;
        &amp;lt;span className="text-sm"&amp;gt;{post.date}&amp;lt;/span&amp;gt;
        &amp;lt;img src="https://picsum.photos/800/200" alt="random image" className=" max-w-full" /&amp;gt;

        &amp;lt;div dangerouslySetInnerHTML={{ __html: marked(post.content) }} className="mt-10"&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  );
}

export async function getStaticPaths() {
  const posts = await getPosts();
  const paths = posts.map((post) =&amp;gt; ({
    params: {
      post: post.id,
    },
  }));

  return {
    paths,
    fallback: false,
  };
}

export async function getStaticProps({ params }) {
  const posts = await getPosts();
  const post = posts.find((post) =&amp;gt; post.id === params.post);
  return {
    props: {
      post,
    },
    revalidate: 1,
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you create a rich text cell in airtable, airtable gives you the data as markdown data. This is great for us but we have to do some specifications to show it smoothly. First I have installed a package named marked, it helps us to fix that. Open terminal and run command &lt;code&gt;npm install marked&lt;/code&gt;. As you can see in the code we should call the package and use it for the blog content data. This works great; &lt;code&gt;&amp;lt;div dangerouslySetInnerHTML={{ __html: marked(post.content) }} className="mt-10"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnnk0dlp9n2xeqc44gayl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnnk0dlp9n2xeqc44gayl.png" alt="Final result" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment and the result
&lt;/h2&gt;

&lt;p&gt;Finally, I deployed it to vercel. It’s a very basic method of using airtable. Anybody can build very different projects like these.&lt;/p&gt;

&lt;p&gt;You can see all the code from the Github repo: &lt;a href="https://github.com/yunuserturk/airtable-blog" rel="noopener noreferrer"&gt;https://github.com/yunuserturk/airtable-blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the demo of the final result: &lt;a href="https://airtable-blog-ruby.vercel.app/" rel="noopener noreferrer"&gt;https://airtable-blog-ruby.vercel.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>nextjs</category>
      <category>airtable</category>
    </item>
  </channel>
</rss>
