{"id":8548,"date":"2026-08-23T10:51:27","date_gmt":"2026-08-23T01:51:27","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=8548"},"modified":"2026-08-23T13:48:14","modified_gmt":"2026-08-23T04:48:14","slug":"nextjs-sns-server-10","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/08\/23\/nextjs-sns-server-10\/","title":{"rendered":"[nextjs]SNS Server-10(myapp20)"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \uc774\uc804 \ud504\ub85c\uc81d\ud2b8\ub294 inbox_posts\ud14c\uc774\ube14\uc758 \uac1c\ubcc4\uae00 API\ub97c \ubcf4\ub824\uba74 \ud130\ubbf8\ub110\uc744 \uc0ac\uc6a9\ud574\uc57c\ud588\uc2b5\ub2c8\ub2e4.<br>In the previous project, you had to use the terminal to view the API for individual posts in the <code>inbox_posts<\/code> table.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb myapp20 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c posts\ub098 inbox_posts\ud14c\uc774\ube14\uc758 API\uac12\ub3c4 \ubcfc \uc218 \uc788\uac8c \uc218\uc815\ud569\ub2c8\ub2e4.<br>In the myapp20 project, we are modifying the setup so that API values \u200b\u200bfrom the <code>posts<\/code> or <code>inbox_posts<\/code> tables can also be viewed in the browser.<\/p>\n\n\n\n<p>\ud83d\udcc1 \uc804\uccb4 \ud504\ub85c\uc81d\ud2b8 \uad6c\uc870 \/ Overall Project Structure<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myapp20\/  \n\u251c\u2500\u2500 app\/  (Next.js App Router)\n\u2502   \u251c\u2500\u2500 .well-known\/webfinger\/route.ts  -&gt; webfinger\n\u2502   \u251c\u2500\u2500 api\/posts\/route.ts     -&gt; Writing API\n\u2502   \u251c\u2500\u2500 api\/follow\/route.ts    -&gt; Follow API(temporary)\n\u2502   \u251c\u2500\u2500 api\/timeline\/route.ts  -&gt; Timeline API\n\u2502   \u251c\u2500\u2500 users\/&#91;username]\/\n\u2502   \u2502   \u251c\u2500\u2500 statuses\/&#91;id]\/route.ts -&gt; Indivisual Post\n\u2502   \u2502   \u251c\u2500\u2500 route.ts               -&gt; Acotr Information\n\u2502   \u2502   \u251c\u2500\u2500 followers\/route.ts     -&gt; Followers List\n\u2502   \u2502   \u251c\u2500\u2500 following\/route.ts     -&gt; Following List\n\u2502   \u2502   \u251c\u2500\u2500 inbox\/route.ts         -&gt; Inbox\n\u2502   \u2502   \u2514\u2500\u2500 outbox\/route.ts        -&gt; outbox\n\u2502   \u251c\u2500\u2500 usersui\/&#91;username]\/page.tsx  -&gt; Timeline UI\n\u2502   \u251c\u2500\u2500 layout.tsx, page.tsx, globals.css\n\u2502   \u2514\u2500\u2500 favicon.ico\n\u251c\u2500\u2500 lib\/\n\u2502   \u251c\u2500\u2500 ap.ts                  -&gt; Follow Accept\n\u2502   \u2514\u2500\u2500 db.ts                  -&gt; DB connection\n\u251c\u2500\u2500 data\/\n\u2502   \u2514\u2500\u2500 keys\/                  -&gt; private.pem, public.pem\n\u251c\u2500\u2500 data.sqlite                -&gt; Database\n\u251c\u2500\u2500 Caddyfile                  -&gt; https \n\u2514\u2500\u2500 package.json<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791(myapp20)<br>Project Start (myapp20)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npx create-next-app@latest<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 SQLite\uc124\uce58 \/ Installing SQLite<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/myapp20\nnpm install better-sqlite3\nnpm install -D @types\/better-sqlite3<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 DDNS,https\uc124\uc815 \/ DDNS,https settings<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-freelifemakers-org wp-block-embed-freelifemakers-org\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"zc48r5keUs\"><a href=\"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/08\/10\/nextjs-dns-caddy\/\">[nextjs]nextjs+domain(ddns)+https(caddy)<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"&#8220;[nextjs]nextjs+domain(ddns)+https(caddy)&#8221; &#8212; freelifemakers.org\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/08\/10\/nextjs-dns-caddy\/embed\/#?secret=rMK4yT5c3b#?secret=zc48r5keUs\" data-secret=\"zc48r5keUs\" width=\"560\" height=\"315\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83d\udcc1 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc2a4\ud0a4\ub9c8 \ud655\uc778 \ubc0f \uc218\uc815<br>Review and modify database schema<\/p>\n\n\n\n<p>\u2714\ufe0f \ub2e4\ub978 \uc11c\ubc84\uc5d0\uc11c \ubc1b\ub294 \uae00(inbox_posts) \ud14c\uc774\ube14\uc5d0\uc11c id\uac00 \ub108\ubb34 \uae38\uc5b4\uc11c \uc9e7\uac8c \uc904\uc774\uae30 \uc704\ud55c \uc791\uc5c5\uc785\ub2c8\ub2e4.<br>This task aims to shorten the <code>id<\/code> in the <code>inbox_posts<\/code> table, which stores posts received from other servers, because the current ID is too long.<\/p>\n\n\n\n<p>\u2714\ufe0f URL\ubd80\ubd84\uc744 \ud3ec\ud568\ud55c \uc804\uccb4\ub97c id\ub97c original_id \ud544\ub4dc\uc5d0 \ub530\ub85c \uc800\uc7a5\ud569\ub2c8\ub2e4.<br>The entire string, including the URL portion, is stored separately in the <code>original_id<\/code> field.<\/p>\n\n\n\n<p>\u2714\ufe0f original_id\ub294 gotosocial\uc774\ub098 mastodon\uc11c\ubc84\uc640 \ud1b5\uc2e0\ud558\uae30 \uc704\ud574\uc11c \uc0ac\uc6a9\ud558\uace0 id\ub294 \uad00\ub9ac\uc6a9\uc73c\ub85c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<br><code>original_id<\/code> is used for communication with GoToSocial or Mastodon servers, while <code>id<\/code> is used for administrative purposes.<\/p>\n\n\n\n<p>\u2714\ufe0f inbox_post\uc758 \uc2a4\ud0a4\ub9c8(\ud14c\uc774\ube14)\uac00 \ub2e4\uc74c\uacfc \uac19\uc9c0 \uc54a\ub2e4\uba74 \uc218\uc815\ud569\ub2c8\ub2e4.<br>Modify the schema (table) for <code>inbox_post<\/code> if it does not match the following.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE inbox_posts (\n  id TEXT PRIMARY KEY,\n  actor TEXT,\n  content TEXT,\n  username TEXT,\n  created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n, original_id TEXT);<\/code><\/pre>\n\n\n\n<p>&#8212; \ud14c\uc774\ube14 \uc218\uc815\ud558\uae30(\uc774\uc804\uc5d0 \uc218\uc815\ud558\uc9c0 \uc54a\uc558\ub2e4\uba74&#8230;)<br>Modify the table (if you haven&#8217;t already&#8230;)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ALTER TABLE inbox_posts ADD COLUMN original_id TEXT;<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ucf54\ub4dc \uc218\uc815 \/ Code modification<\/p>\n\n\n\n<p>\u2714\ufe0f myapp20\/app\/users\/[username]\/inbox<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    if (body.type === 'Create') {\n      const note = body.object;\n      if (note &amp;&amp; note.type === 'Note') {\n        console.log(`\ud83d\udcdd &#91;${username}] \uc0c8 \uae00 \ub3c4\ucc29 \/ New post received from ${actorId}`);\n        console.log(`\ub0b4\uc6a9\/content: ${note.content?.slice(0, 100)}`);\n\n        \/\/ \u2705 myapp20 -inbox_posts\uc8fc\uc18c \uc904\uc774\uae30 \/ Shorten inbox_posts URL\n        try {\n          const longId = note.id || `https:\/\/remote\/${Date.now()}-${Math.random()}`;\n          const shortId = longId.split('\/').pop()!; \/\/ \ub9c8\uc9c0\ub9c9 \ubd80\ubd84\ub9cc \uc798\ub77c\ub0b4\uae30 \/ Cut off only the last part\n          const content = note.content || '';\n\n          db.prepare(`\n            INSERT OR IGNORE INTO inbox_posts (id, actor, content, username, original_id, created_at) \n            VALUES (?, ?, ?, ?, ?, ?)\n          `).run(shortId, actorId, content, username, longId, note.published || new Date().toISOString());\n          console.log(`\u2705 &#91;${username}] inbox_posts \uc800\uc7a5 \uc644\ub8cc\/inbox_posts saved successfully. : ${shortId} (\uc6d0\ubcf8\/original: ${longId})`);\n\n        } catch (e) {\n          console.error(`\u274c \uae00 \uc800\uc7a5 \uc2e4\ud328 \/ Failed to save post`, e);\n        }\n\n      }\n      return new Response('', { status: 202 });\n    }<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \/myapp20\/app\/usersui\/[username]\/page.tsx<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>... ...\n\n\/\/ \u2705 myapp20\nfunction getDisplayName(actorOrUsername: string) {\n  if (!actorOrUsername) return 'unknown';\n  \/\/ https:\/\/freelifemakers.com\/users\/user1 -> user1@freelifemakers.com\n  if (actorOrUsername.startsWith('https:\/\/')) {\n    try {\n      const url = new URL(actorOrUsername);\n      const username = url.pathname.split('\/').pop() || 'user';\n      return `${username}@${url.hostname}`;\n    } catch {\n      return actorOrUsername.split('\/').pop() || actorOrUsername;\n    }\n  }\n  return actorOrUsername;\n}\n\n... ...\n\n  return (\n    &lt;div style={{ padding: 20, maxWidth: 900, margin: '0 auto' }}>\n      &lt;h1 style={{ fontSize: 24, marginBottom: 16 }}>{username} \ud0c0\uc784\ub77c\uc778 \/ Timeline&lt;\/h1>\n      &lt;ul style={{ listStyle: 'none', padding: 0 }}>\n        {timeline.map((p:any) => (\n          &lt;li key={`${p.source}-${p.id}`} style={{\n            display: 'flex',\n            alignItems: 'center',\n            gap: 6,\n            padding: '10px 0',\n            borderBottom: '1px solid #eee',\n            flexWrap: 'wrap'\n          }}>\n            &lt;span style={{ background: p.source === 'mine'? '#dbeafe' : '#fef3c7', padding: '2px 6px', borderRadius: 4, fontSize: 11 }}>\n              {p.source}\n            &lt;\/span>\n            &lt;b>{getDisplayName(p.actor)}:&lt;\/b>\n            &lt;span dangerouslySetInnerHTML={{__html: p.content}} \/>\n            &lt;span style={{ color: '#999', fontSize: 11, marginLeft: 'auto' }}>\n              {new Date(p.created_at).toLocaleString()}\n            &lt;\/span>\n          &lt;\/li>\n        ))}\n      &lt;\/ul>\n    &lt;\/div>\n  );<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ud14c\uc2a4\ud2b8 \/ Test<\/p>\n\n\n\n<p>\u2714\ufe0f inbox_posts\uc5d0 \uae30\uc874\uc758 \uae00\uc774 \uc788\ub2e4\uba74 \ub2e4 \uc9c0\uc6c1\ub2c8\ub2e4.(https:\/\/ \ub54c\ubb38\uc5d0&#8230;)<br>Delete any existing posts in <code>inbox_posts<\/code> (due to <code>https:\/\/<\/code>\u2026)<\/p>\n\n\n\n<p>&#8212; gotosocial\uc11c\ubc84(freelifemakers.com)\uc11c\ubc84\uc758 \uae00\ub3c4 \uc9c0\uc6c1\ub2c8\ub2e4.<br>Posts on the GoToSocial server (freelifemakers.com) are also being deleted.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sqlite&gt; select * from inbox_posts;\nhttps:\/\/freelifemakers.com\/users\/user1\/statuses\/01M0EJPP57WC47FAK0N395S7MB|https:\/\/freelifemakers.com\/users\/user1|&lt;p&gt;inbox_posts table test&lt;\/p&gt;|user1|2026-07-10 01:16:15|\nhttps:\/\/freelifemakers.com\/users\/user1\/statuses\/01M0KMS8K1XRFW703S32MX6V25|https:\/\/freelifemakers.com\/users\/user1|&lt;p&gt;actor test&lt;\/p&gt;|user1|2026-07-19T10:20:10+02:00|https:\/\/freelifemakers.com\/users\/user1\/statuses\/01M0KMS8K1XRFW703S32MX6V25\nsqlite&gt;<strong> delete from inbox_posts;<\/strong><\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f pinafore\uc5d0\uc11c \uc0c8\ub85c \uae00\uc744 \uc4f0\uace0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub97c \ud655\uc778\ud569\ub2c8\ub2e4.<br>Write a new post in Pinafore and check the database.<\/p>\n\n\n\n<p>&#8212; pinafore.socical<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"374\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-pinafore-jpg.jpg\" alt=\"\" class=\"wp-image-8615\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-pinafore-jpg.jpg 600w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-pinafore-jpg-300x187.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-pinafore-jpg-400x249.jpg 400w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">pinafore.social<\/figcaption><\/figure>\n\n\n\n<p>&#8212; sqlite database(aloy-horizon.duckdns.org)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sqlite&gt; select * from inbox_posts;\n<strong>01M0P8VYEQTFW28N97W6MG8PY5<\/strong>|https:\/\/freelifemakers.com\/users\/user1|&lt;p&gt;reduce inbox_posts id&lt;\/p&gt;|user1|2026-07-20T06:10:11+03:00|https:\/\/freelifemakers.com\/users\/user1\/statuses\/<strong>01M0P8VYEQTFW28N97W6MG8PY5<\/strong>\nsqlite&gt; <\/code><\/pre>\n\n\n\n<p>&#8212; gotosocial server( freelifemakers.com )<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"360\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-gotosocial-jpg.jpg\" alt=\"\" class=\"wp-image-8619\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-gotosocial-jpg.jpg 600w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-gotosocial-jpg-300x180.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-gotosocial-jpg-400x240.jpg 400w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">gotosocial<\/figcaption><\/figure>\n\n\n\n<p>\u2714\ufe0f \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c \ub2e4\uc74c \uc8fc\uc18c\ub97c \uc2e4\ud589\ud569\ub2c8\ub2e4.<br>Open the following address in your browser.<\/p>\n\n\n\n<p>&#8212; inbox_posts \ud14c\uc774\ube14\uc758 \uae00 \ubcf4\uae30<br>View posts from the inbox_posts table<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:\/\/aloy-horizon.duckdns.org\/users\/user1\/statuses\/<strong>01M0P8VYEQTFW28N97W6MG8PY5<\/strong><\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"233\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-inbox_posts-jpg.jpg\" alt=\"\" class=\"wp-image-8607\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-inbox_posts-jpg.jpg 600w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-inbox_posts-jpg-300x117.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-inbox_posts-jpg-400x155.jpg 400w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">inbox_posts table<\/figcaption><\/figure>\n\n\n\n<p>&#8212; posts \ud14c\uc774\ube14\uc758 \uae00 \ubcf4\uae30<br>View a post from the &#8216;posts&#8217; table<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:\/\/aloy-horizon.duckdns.org\/users\/user1\/statuses\/<strong>e6c99652-572f-491a-9e61-05e67b0d58fc<\/strong><\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"216\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-posts-jpg.jpg\" alt=\"\" class=\"wp-image-8604\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-posts-jpg.jpg 600w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-posts-jpg-300x108.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-api-posts-jpg-400x144.jpg 400w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">posts table<\/figcaption><\/figure>\n\n\n\n<p>&#8212; \ud0c0\uc784\ub77c\uc778UI \/ Timeline UI<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;aloy-horizon.duckdns.org\/@user1<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"414\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-timelineui-jpg.jpg\" alt=\"\" class=\"wp-image-8630\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-timelineui-jpg.jpg 600w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-timelineui-jpg-300x207.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/08\/myapp20-timelineui-jpg-400x276.jpg 400w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">TImeline UI<\/figcaption><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83d\udcc1 \uc9c0\uae08\uae4c\uc9c0 \uc791\uc5c5\ud55c \ub0b4\uc6a9\uacfc \ub77c\uc6b0\ud2b8 \uc785\ub2c8\ub2e4.<br>Here is the work done so far and the routes.<\/p>\n\n\n\n<p>\u2714\ufe0f \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \ud560 \uc218 \uc788\ub294 \ub77c\uc6b0\ud2b8<br>Routes that can be tested in a browser<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>1. WebFinger\nhttps:&#47;&#47;aloy-horizon.duckdns.org\/.well-known\/webfinger?resource=acct:user1@aloy-horizon.duckdns.org\n\n2. Actor (\ud504\ub85c\ud544 \/ Profile)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\n\n3. Followers (\ub0a8\uc774 \ub098 \ud314\ub85c\uc6b0 \/ Someone follows me)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/followers\n\n4. Following (\ub0b4\uac00 \ub0a8\uc744 \ud314\ub85c\uc6b0 \/ I follow others)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/following\n\n5. Outbox (\ub0b4 \uae00 \ubaa9\ub85d \/ My post list)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/outbox\n\n6. \ud0c0\uc784\ub77c\uc778 \/ Timeline\n\n- \ud0c0\uc784\ub77c\uc778UI \/ Timeline UI\nhttps:\/\/aloy-horizon.duckdns.org\/usersui\/user1\nor\nhttps:\/\/aloy-horizon.duckdns.org\/@user1\n\n- \ud0c0\uc784\ub77c\uc778API \/ Timeline API\nhttps:\/\/aloy-horizon.duckdns.org\/api\/timeline?username=user1\n\n7. \uac1c\ubcc4 \uae00(\uae00 \uc0c1\uc138) \/ indivisual posts(Post Details)&#91;posts, inbox_posts]\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/statuses\/&#91;ID]\n\nex)\n# posts table\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/statuses\/e6c99652-572f-491a-9e61-05e67b0d58fc\n\n# inbox_posts table\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/statuses\/01M0P8VYEQTFW28N97W6MG8PY5\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ud130\ubbf8\ub110\uc5d0\uc11c\ub9cc \ud14c\uc2a4\ud2b8 \uac00\ub2a5\ud55c \ub77c\uc6b0\ud2b8<br>Routes that can only be tested in the terminal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud314\ub85c\uc6b0 (following 1\ub85c \uc99d\uac00)\n# Follow (following increased to 1)\n\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/follow \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\"username\":\"user1\",\"target\":\"https:\/\/freelifemakers.com\/users\/user1\"}'\n\n# \uc5b8\ud314\ub85c\uc6b0 (following 0\uc73c\ub85c \uac10\uc18c)\n# Unfollow (following count reduced to 0)\n\ncurl -X DELETE https:\/\/aloy-horizon.duckdns.org\/api\/follow \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\"username\":\"user1\",\"target\":\"https:\/\/freelifemakers.com\/users\/user1\"}'\n\n# \uae00 \uc4f0\uae30 (outbox 7\ub85c \uc99d\uac00 + \ud314\ub85c\uc6cc\ub4e4\uc5d0\uac8c \ubc30\ub2ec)\n# Writing a post (added to outbox 7 + delivered to followers)\n\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/posts \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\"username\":\"user1\",\"content\":\"Hello Fediverse! #test\"}'<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\uc694\ud55c\ubcf5\uc74c 8\uc7a5 32\uc808 \/ John 8:32<\/p>\n\n\n\n<p>&#8220;\uadf8\ub9ac\uace0 \ub108\ud76c\ub294 \uc9c4\ub9ac\ub97c \uc54c\uac8c \ub420 \uac83\uc774\uba70, \uc9c4\ub9ac\uac00 \ub108\ud76c\ub97c \uc790\uc720\ub86d\uac8c \ud560 \uac83\uc774\ub2e4.&#8221;<\/p>\n\n\n\n<p>&#8220;Then you will know the truth ,and the truth will set you free&#8221;<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \uc774\uc804 \ud504\ub85c\uc81d\ud2b8\ub294 inbox_posts\ud14c\uc774\ube14\uc758 \uac1c\ubcc4\uae00 API\ub97c \ubcf4\ub824\uba74 \ud130\ubbf8\ub110\uc744 \uc0ac\uc6a9\ud574\uc57c\ud588\uc2b5\ub2c8\ub2e4.In the previous project, you had to use the terminal to view the API for individual posts in the inbox_posts table. \ud83d\udc49\ud83c\udffb myapp20 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c posts\ub098 inbox_posts\ud14c\uc774\ube14\uc758 API\uac12\ub3c4 \ubcfc \uc218 \uc788\uac8c \uc218\uc815\ud569\ub2c8\ub2e4.In the myapp20 project, we are modifying the setup so that API values \u200b\u200bfrom the posts [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,27,1,7],"tags":[],"class_list":["post-8548","post","type-post","status-publish","format-standard","hentry","category-news","category-nextjs","category-uncategorized","category-website","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/8548","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=8548"}],"version-history":[{"count":72,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/8548\/revisions"}],"predecessor-version":[{"id":8634,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/8548\/revisions\/8634"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=8548"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=8548"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=8548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}